How to Auto-start MQTT Scala Program at System Boot using SBT-Native-Packager
June 02, 2017
In this tutorial, we will use sbt-native-packager to autostart MQTT Scala program at system boot with Ubuntu OS. Then we will publish MQTT data to test whether the program is actually running in the background. Let’s look more detail.
The Complete Project
You can also look the working example from my github repo. I had tested on both Raspberry Pi 3 and Ubuntu OS.
Prerequisites
Please follow my tutorial post here to install Scala and SBT. This is applicable for both Raspberry Pi or any Linux system.
Install MQTT Message Broker
$ sudo apt-get install mosquitto mosquitto-clients
Once the installation is done, you can start testing MQTT alone.
First, we start the subscriber.
$ mosquitto_sub -h localhost -t test
At another terminal, type in the following line to publish a message to the subscriber.
$ mosquitto_pub -h localhost -t test -m "hello world"
You should see the “hello world” message at the subscriber terminal.
Install Systemd
Now Debian is adopting systemd
to manage the services. So we will install systemd in the system.
$ sudo apt-get update
$ sudo apt-get install systemd
$ apt-get install systemd-sysv
Now reboot
your system.
Note: More info about systemd can be found here.
SBT Native Packager
At build.sbt
add this line to support autostart.
enablePlugins(JavaServerAppPackaging, SystemdPlugin)
Create a file called plugins.sbt
under <your_project_name/project>
and add this line.
addSbtPlugin("com.typesafe.sbt" %% "sbt-native-packager" % "1.2.0-M8")
MQTT
We also need to add in MQTT dependency in build.sbt
So final build.sbt
file will be like this.
enablePlugins(JavaServerAppPackaging, SystemdPlugin)
name := "mqtt-sbt"
version := "1.0"
mainClass in Compile := Some("MainApp")
// package settings
maintainer in Linux := "aknay <aknay@outlook.com>"
packageDescription := "Mqtt SBT Message Exchanger"
libraryDependencies += "org.eclipse.paho" % "mqtt-client" % "0.4.0"
resolvers += "MQTT Repository" at "https://repo.eclipse.org/content/repositories/paho-releases/"
Main Program
Create a main program called MainApp.scala
under <your_project_name/src/main/scala>
. Copy the following block of code and paste it. This will act like at message exchanger to test our idea.
import java.util.Calendar
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
import org.eclipse.paho.client.mqttv3.{IMqttDeliveryToken, MqttCallback, MqttClient, MqttMessage}
object MainApp {
val SEND_ME = "SendMe"
val RECEIVED_IT = "ReceivedIt"
def main(args: Array[String]) {
val brokerUrl = "tcp://localhost:1883"
//Set up persistence for messages
val persistence = new MemoryPersistence
//Initializing Mqtt Client specifying brokerUrl, clientID and MqttClientPersistance
val client = new MqttClient(brokerUrl, MqttClient.generateClientId, persistence)
//Connect to MqttBroker
client.connect
//Subscribe to Mqtt topic
client.subscribe(SEND_ME)
//Callback automatically triggers as and when new message arrives on specified topic
val callback = new MqttCallback {
override def messageArrived(topic: String, message: MqttMessage): Unit = {
println("Receiving Data, Topic : %s, Message : %s".format(topic, message))
topic match {
case SEND_ME =>
sendTopic(client, RECEIVED_IT, "I received this: " + message.toString + " at " + Calendar.getInstance().getTime )
case _ =>
}
}
override def connectionLost(cause: Throwable): Unit = {
println(cause)
}
override def deliveryComplete(token: IMqttDeliveryToken): Unit = {
}
}
//Set up callback for MqttClient
client.setCallback(callback)
}
def sendTopic(client: MqttClient, topic: String, msg: String): Unit = {
val msgTopic = client.getTopic(topic)
val messageToPublish = new MqttMessage(msg.getBytes("utf-8"))
msgTopic.publish(messageToPublish)
println("Publishing Data, Topic : %s, Message : %s".format(msgTopic.getName, messageToPublish))
}
}
Build SBT package
Now Go to your project folder then type the following line to build a package.
$ sbt debian:packageBin
Once the package is built, it can be found under <your_project_name/target>
folder.
Now type the next following line to install
$ sudo dpkg -i target/mqtt-sbt_1.0_all.deb
Make sure there is no error during the installation. We should check again whether the service is already running automatically.
$ systemctl
You should see on the list that mqtt-sbt.service
is running
Test with MQTT
Tt one terminal, type in to run the subscriber.
$ mosquitto_sub -h localhost -t ReceivedIt
And at another terminal, type in to publish a message.
$ mosquitto_pub -h localhost -t SendMe -m "hello"
You should see the following kind of message at the subscriber terminal.
I received this: hello at Fri Jun 02 14:37:52 CXT 2017
Note: you can reboot and type in all those MQTT command lines again. It should still work. You can also remove the install package by typing
$ sudo dpkg --purge mqtt-sbt