iAchieved.it

Software Development Tips and Tricks

By

MQTT Last Will and Testament

This is another post in a series on writing MQTT clients using Swift on Linux.

In this post we’ll look at the MQTT Last Will and Testament message. Essentially the LWT message is predefined by a client connecting to the broker. In the event the client abnormally disconnects, the broker will then broadcast the LWT to any subscribers of the LWT message topic.

For example, let’s say you are building a chat application where each client connects to a broker and then subscribes to the topic /chat/hottub. Messages then published to /chat/hottub are received by all of the subscribers. A simple but effective way to join a “chat room” (i.e., MQTT topic).

When a client leaves the chat under normal conditions we might expect a message like “Joe has left /chat/hottub.” This would be easy to do; when the user types /exit then publish an appropriate message and then terminate the client. If a client abnormally disconnects (loss of network, client crash, etc.), then what was given to the broker as the Last Will and Testament message is used instead.

Here’s how we set up the Last Will message for our MQTT client:

willMessage is a MQTTWill property of the MQTT class. MQTTWill is constructed with a topic and message. In our example here the topic will be our chat channel /chat/hottub, and the message will be a JSON string that contains our client’s ID and a simple Abnormal Disconnect string.

Get the Code

We’ve been building Swift 3.0 directly from the latest in the Apple repositories and continually upgrade our code. To use these examples you’ll need to install Swift 3.0 from our apt-get repository.

An example of our MQTT HotTub is in GitHub.

# git clone https://github.com/iachievedit/MQTTHotTub
# cd MQTTHotTub
# swift build

To test things out you’ll want to run the MQTTHotTub twice, so open a second terminal.

1__clear_____build_debug_MQTTHotTub__ssh__and_9__clear_____build_debug_MQTTHotTub__ssh_

Run the clients with .build/debug/MQTTHotTub.

Prisencolinensinainciusol

Our MQTTHotTub client simulates a chat of gibberish. Each published message is delivered as JSON:

{"client":"octxktfo", "message":"Gyxswhz nsoxfnj gz."}
{"client":"ajyhyjic", "message":"Cmr w bzwubzv mwfhtklz."}

When a client receives a message that it did not send it gets filtered out:

Remember, if we are listening to messages published to a given topic, and we publish to that topic, the client will also receive that message back as an echo. This is the purpose of filtering with cid != clientId.

You can see each client logging what they are receiving from other clients:

Received "Wlfu zrqyj tady obxnjl lupihobi nph oapplt nyidmja." from octxktfo
Received "Cmr w bzwubzv mwfhtklz." from ajyhyjic

Now, CTRL-C one of the clients, and notice what is received by the remaining client(s):

Received "Abnormal Disconnect" from octxktfo
Abnormal Disconnect

Abnormal Disconnect

This is the MQTT Last Will and Testament message in action; the aborted client had no opportunity to broadcast that it was unavailable so instead the broker sent out the client’s Last Will on the /chat/hottub topic:

{"client":"\(clientId)","message":"Abnormal Disconnect"}

Do I Need to Have a Last Will?

Need is a strong word, and the answer is no, your MQTT client does not need to supply a Last Will message. There are plenty of additional examples that provide guidance on when you might want to use one.

What’s Next?

We’re continuing to work hard on our MQTT implementation for Swift on Linux. With Last Will and Testament now working our attention will turn to implementing secure MQTT connections (MQTT SSL). Stay tuned!

By

Handling MQTT Subscriptions with Swift on Linux

In our last post we looked at a Swift MQTT client which published information to a HiveMQ broker. Now let’s turn our attention to writing an MQTT client that subscribes to a topic.

Again, we’ll be using MQTT, code that aims to provide a solid MQTT client library implementation in Swift. If you haven’t yet read the tutorial on building an MQTT publisher with it, I suggest you do so before proceeding!

There are two basic components to writing an MQTT client that subscribes to a topic:

  • subscribing to a topic
  • handling a published message from the broker

Ignoring the boilerplate connection logic for a moment, let’s look at subscribing:

There’s nothing earth shattering here: upon receiving a ConnectedNotification a call is made to subscribe to the topic /hostname/cpu/temperature/value (where hostname is obtained from the OS). Now when the broker receives a message published to this topic it will broadcast it to our client. This is the pub-sub pattern in action.

This Transmission is Coming To You

To receive an MQTT message we need to handle the MQTTDelegate method func mqtt(mqtt: MQTT, didReceiveMessage message: MQTTMessage, id: UInt16 ). This can be readily accomplished using an NSNotification with accompanying userInfo:

Unfortunately for us much the userInfo dictionary remains grounded in using NSObjects as keys, so care must taken to cast String as an NSString when assembling.

In the main.swift implementation we listen for a MessageNotification:

For details on the MQTTMessage class, see the source, but we can gather from the above that two properties are of interest here:

  • topic:String – the topic to which the message was delivered
  • string:String? – the message contents, if any, delivered as a String

Get the Code

MQTTSub is an example implementation of an MQTT client that subscribes to our CPU temperature topic. Obtain it and compile with:

# git clone https://github.com/iachievedit/MQTTSub
# cd MQTTSub
# swift build
# .build/debug/MQTTSub

You will, of course, want to be running the publishing client as well:

# git clone https://github.com/iachievedit/PubSysTemp
# cd PubSysTemp
# swift build
# .build/debug/PubSysTemp

If your publishing client is running, you’ll see something like:

2016-06-13 02:55:43 +0000 - INFO    - Connecting to broker
2016-06-13 02:55:43 +0000 - INFO    - MQTT client has connected to broker.hivemq.com:1883
2016-06-13 02:55:43 +0000 - INFO    - Subscribe to topic
2016-06-13 02:55:43 +0000 - INFO    - didConnectAck
2016-06-13 02:55:43 +0000 - INFO    - didSubscribeTopic /darthvader/cpu/temperature/value
2016-06-13 02:55:44 +0000 - INFO    - Received 33.0 for topic /darthvader/cpu/temperature/value

If you want to have fun, try stress testing your system while running the publisher and subscriber. After stress -c 8 was started up:

PubSysTemp

2016-06-13 03:04:55 +0000 - INFO    - Published temperature to 34.0
2016-06-13 03:05:05 +0000 - INFO    - Published temperature to 37.0
2016-06-13 03:05:15 +0000 - INFO    - Published temperature to 42.0
2016-06-13 03:05:25 +0000 - INFO    - Published temperature to 45.0
2016-06-13 03:05:35 +0000 - INFO    - Published temperature to 47.0

MQTTSub

2016-06-13 03:04:55 +0000 - INFO    - Received 34.0 for topic /darthvader/cpu/temperature/value
2016-06-13 03:05:05 +0000 - INFO    - Received 37.0 for topic /darthvader/cpu/temperature/value
2016-06-13 03:05:15 +0000 - INFO    - Received 42.0 for topic /darthvader/cpu/temperature/value
2016-06-13 03:05:25 +0000 - INFO    - Received 45.0 for topic /darthvader/cpu/temperature/value
2016-06-13 03:05:35 +0000 - INFO    - Received 47.0 for topic /darthvader/cpu/temperature/value

What’s Next?

If you peruse the MQTT library you’ll notice it is lacking SSL support. That’s what’s next! In addition, we’ll be looking at writing additional MQTT tutorials that explore constructing topic hierarchies, using MQTT with real-world sensors, home automation devices, and more.

By

MQTT Clients With Swift on Linux

Swift 3.0 Swift 3.0

Over the past few years I’ve made a living managing Internet of Things (IoT) software development projects. In that time I’ve come to learn a number of protocols for communicating sensor and telemetry information back to “the cloud”. Among the most popular in the IoT space is MQTT, a lightweight protocol that allows for publishing messages to topics, as well as the ability to subscribe to topics. This model is frequently refer to as “pub-sub“.

In addition to working with IoT and MQTT, I am passionate about Swift and the inroads it is making into the server space since being open-sourced and ported to Linux. Naturally it made sense to combine the two areas and start working on an MQTT client implementation in Swift! We’ve taken the liberty to port an iOS implementation of an MQTT client over to Swift 3.0 on a Linux platform. In general this is an example that, indeed, Swift will be making inroads into both the server and IoT domains.

A disclaimer before we get started: the code below is based upon Swift 3.0 which is going through developer previews on Linux right now. To get started with Swift 3.0 on your Ubuntu 14.04 or 15.10 system go here. Or, if you have an armv7 device such as BeagleBone Black, try the ARM port of Swift 3.0!

Sample Application

My first idea was to put together a cool BeagleBone MQTT client that was reading one of the ADC inputs and sending it up to the broker. The input was going to be from a Microchip MCP9700 temperature sensor IC. The sensor IC maximum output voltage is 5.5V so I knew a voltage divider would be involved to keep the voltage input to the BeagleBone under 1.8V. I had the voltage divider all sketched out and everything!

Don't Want to Blow Up the BeagleBone!

Don’t Want to Blow Up the BeagleBone!

Unfortunately while testing the sensor IC with a standard match I got the flame a little too close to the IC package and well, Project Icarus came to an end. Our replacement example is a bit less ambitious, but serves the role of learning how to build an MQTT client with Swift. And it doesn’t involve matches.

MQTT

Our application is built around a port of a client MQTT library (yay open source!). We’ve named it simply MQTT and posted it to GitHub. The library is meant to be used in a Swift application that you can create as follows:

Running swift package init --type executable is going to give you a Swift project shell (think npm init) that you can begin customizing for your purposes. We’re going to edit Package.swift and add our MQTT library dependency:

MQTT Client Delegate

The design of the MQTT library is such that you will create a client class that inherits from MQTT and MQTTDelegate. A very basic implementation looks like this:

As you can probably guess the functions above are delegate methods that are called when the underlying MQTT client connects, publishes a message, subscribes to a topic, etc. It is up to you, the client writer, to fill out the implementation to suit your needs. In our case we’re going to implement the mqttDidDisconnect method as follows:

I’ve mentioned in previous posts that I appreciate the flexibility of posting a notification and having it acted upon by whoever was listening for it. DisconnectedNotification will be handled in our main.swift routine.

main.swift

Let’s turn our attention to main.swift which will instantiate an MQTT-based client. At a fundamental level here is all that’s required:

We want our client to be a bit more robust, so we’ll add in the ability to automatically reconnect if our connection is dropped by doing something like this:

Now, one could argue that we don’t want to exit if the connection to the broker fails. What we could do is set a timer and then rebroadcast our DisconnectedNotification. This will be our approach in the working code detailed further below.

We should publish something useful to the broker, so let’s set up an NSTimer to wake up every ten seconds and obtain the CPU temperature and then post that.

It should be noted here that we set the timer up and then fire() it immediately (so we’re not waiting ten seconds for that first post). Also, you will notice that we’re posting to the topic /<i>clientid</i>/cpu/temperature/value. This is one example of an MQTT topic naming convention and meant strictly as such. As you delve further into designing IoT applications it will become apparent that your naming convention is of considerable importance.

Getting the CPU Temperature

I love working with Linux and the wealth of information that is available in the /sys and /proc filesystems. Unfortunately when you’re dealing with hardware you have to frequently tailor your code to the specific hardware it’s running on. For example, on my x86 server the temperature of the CPU can be obtained by reading /sys/class/hwmon/hwmon0/temp1_input. On the BeagleBoard X15 it is at /sys/class/hwmon/hwmon1/temp1_input. That’s aggravating.

We won’t bother with writing portable code for now, but you should be able to take this example and suit it to your own system’s needs:

Putting it All Together

Let’s put everything together to build a working MQTT client that posts our CPU temperature to broker.hivemq.com. As a bonus, we’ll provide a web page that shows the CPU temperature displayed as a gauge.

We have three files that make up our client:

  • Client.swift
  • CPU.swift
  • main.swift

Each of these files should go in the Sources directory. Let’s look at a complete implementation of each:

Client

Client.swift

CPU

CPU.swift

main

Our main.swift appears to be complicated but it’s not really. The key things to recognize is that we wait for notifications and then set timers based upon those notifications to put our client into motion. For example, nothing good will come of trying to publish if we don’t have an MQTT connection established, so we wait for that notification (from our delegate) before attempting. Once a connection is established we set a 10 second timer and then update the temperature if we are still connected.

Note also the use of a heartbeat timer. Runloops will exit if there are no input sources or timers attached to it, so we use a simple repeating timer to keep a heartbeat (and thus, the runloop) going.

Your Package.swift file should look like:

To make life easier you can grab our code from GitHub. Build with swift build and then run it:

# git clone https://github.com/iachievedit/PubSysTemp
# cd PubSysTemp
# swift build
# .build/debug/PubSysTemp

Remember: this code is written in Swift 3.0! For more information see our post on obtaining Swift 3.0 for Linux.

What’s this Broker Thing Again?

Think of an MQTT broker as an NSNotificationCenter. In iOS one typically obtains a reference to the NSNotificationCenter.defaultCenter() and then posts messages to it. Likewise, to receive a message you register to be called when a named notification is posted (topic anyone?).

With MQTT you need to communicate with a broker. If you’re building an IoT gateway you might run your own broker using Mosquitto or HiveMQ. If you’re writing a tutorial on MQTT you might take advantage of a public broker such as test.mosquitto.org or broker.hivemq.com rather than running your own (like we did!).

In our example above we wrote an MQTT client that publishes data. What about subscribing to that data? This is also the purview of MQTT clients. For our example we’ll use a nice temperature gauge widget to power our temperature display.

Compiling Swift Heats Things Up

Compiling Swift Heats Things Up

What’s important to realize here is that the temperature gauge is actually an (JavaScript-based) MQTT client that has subscribed to receive events published to the /darthvader/cpu/temperature/value topic on broker.hivemq.com. (darthvader is our client’s hostname.)

What’s Next

There’s much more to be done with the MQTT library. As of June 11, 2016 it successfully connects and publishes, but subscribing to a topic is another story. That’s our next issue to tackle.

This is just the beginning, however, for Swift on the server. Organizations such as Zewo are working hard to develop libraries that can be used to develop server-side software on Linux with Swift. In fact, our MQTT library uses Zewo’s VeniceX TCP routines for network IO. Time will tell, but I’m convinced Swift has a bright future ahead of it in more than just iOS development.

Postscript: Please don’t comment on my lousy voltage divider. I nearly failed EE classes and do the best I can.