All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sigusr.mqtt.examples.LocalPublisher.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 Frédéric Cabestre
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITTaskNS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.sigusr.mqtt.examples

import cats.effect.{ExitCode, IO, IOApp}
import cats.effect.std.Console
import cats.implicits._
import com.comcast.ip4s.{Host, Port}
import fs2.Stream
import net.sigusr.mqtt.api.QualityOfService.{AtLeastOnce, AtMostOnce, ExactlyOnce}
import net.sigusr.mqtt.api._

import scala.concurrent.duration._
import scala.util.Random

object LocalPublisher extends IOApp {

  private val random: Stream[IO, Int] = Stream.eval(IO(Math.abs(Random.nextInt()))).repeat
  private val topics =
    Stream(("AtMostOnce", AtMostOnce), ("AtLeastOnce", AtLeastOnce), ("ExactlyOnce", ExactlyOnce)).repeat

  override def run(args: List[String]): IO[ExitCode] =
    if (args.nonEmpty) {
      val messages = args.toVector
      val transportConfig =
        TransportConfig[IO](
          Host.fromString("localhost").get,
          Port.fromString("1883").get,
          // TLS support looks like
          // 8883,
          // tlsConfig = Some(TLSConfig(TLSContextKind.System)),
          traceMessages = true
        )
      val sessionConfig =
        SessionConfig(s"$localPublisher", user = Some(localPublisher), password = Some("yala"), keepAlive = 5)
      implicit val console: Console[IO] = Console.make[IO]
      Session[IO](transportConfig, sessionConfig).use { session =>
          val sessionStatus = session.state.discrete
            .evalMap(logSessionStatus[IO])
            .evalMap(onSessionError[IO])
            .compile
            .drain
          val publisher = (for {
            m <- ticks().zipRight(randomMessage(messages).zip(topics))
            message = m._1
            topic = m._2._1
            qos = m._2._2
            _ <- Stream.eval(
              putStrLn[IO](
                s"Publishing on topic ${scala.Console.CYAN}$topic${scala.Console.RESET} with QoS " +
                  s"${scala.Console.CYAN}${qos.show}${scala.Console.RESET} message ${scala.Console.BOLD}$message${scala.Console.RESET}"
              )
            )
            _ <- Stream.eval(session.publish(topic, payload(message), qos))
          } yield ()).compile.drain

          for {
            _ <- IO.race(publisher, sessionStatus)
          } yield ExitCode.Success
        }.handleErrorWith(_ => IO.pure(ExitCode.Error))
    } else
      putStrLn[IO](s"${scala.Console.RED}At least one or more « messages » should be provided.${scala.Console.RESET}")
        .as(ExitCode.Error)

  private def ticks(): Stream[IO, Unit] =
    random.flatMap { r =>
      val interval = r % 2000 + 1000
      Stream.sleep[IO](interval.milliseconds)
    }

  private def randomMessage(messages: Vector[String]): Stream[IO, String] =
    random.flatMap(r => Stream.emit(messages(r % messages.length)))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy