serial2mqtt

For a complete view : with UML sequence diagrams
Arduino Sample program to communicate with the serial2mqtt gateway , see : Arduino device code

Most simple example : publish uptime to MQTT via serial line.

#include  <Arduino.h>
void  setup() {
Serial.begin(115200);
}
void  loop() {
Serial.println("[1,\"src/myTopic/time\","+String(millis())+"]");
delay(100);
}

MQTT for all micro-controllers ! The purpose is to offer MQTT publisher/subscriber functionality to all small micro controllers. Those with just a UART or USB interface.
Example : some cheap STM32 board on eBay.


I know the ESP32 is capable of Wifi and MQTT on TCP/IP , but in my case it was used for its PWM capabilities and enclosed in a metal box.

This program will act as a full MQTT Client gateway and make integration as simple as possible.
This was created because Ethernet or WiFi is still absent in most ( cheap ) controllers .
Also the concept behind is that a central PC or Raspberry PI can act as the intelligent mind behind commodity components.

enter image description here

Working assumptions and features

– JSON will be text delimited by newlines

Optional

The serial2mqtt should be able to reset the device ( hard reset )

Protocol

JSON TEXT

JSON ARRAY

Example : [1,“mytopic”,“3.141592653”]

[<COMMAND>,<TOPIC>,<MESSAGE>,<QOS>,<RETAIN>,<CRC>] 
* QOS ,RETAIN, CRC  retain are optional
<CRC> : can be checked or not, is calculated on the total JSON string based on the message containing "0000" as temporary CRC. When calculated is in HEX format.
* COMMAND 0:SUBSCRIBE,1:PUBLISH
* publish : [1,"dst/topic1","message1",0,0]
* subscribe : [0,"dst/myTopic/#"]
* QOS : 0,1,2 : for QOS, default 0
* RETAIN : 0 or 1 for true or false, default 0

JSON OBJECT

    Example : { "cmd":"MQTT-PUB","topic":"src/device/service/property","message":"1234.66","qos":0,"retained":false }\n

TEXT JSON

{ "cmd":"MQTT-PUB","topic":"src/device/service/property","message":"1234.66","qos":0,"retained":false }\n

CONNECTION SETUP

µCserial2mqttMQTT Brokeropen serial port ttyconnect(broker,port)connAck[0,"dst/DEVICE/+"][1,"dst/DEVICE/system/loopback","true"]subscribe("dst/DEVICE/publish("dst/DEVICE/system/loopback","true")publish("dst/DEVICE/system/loopback","true")[1,"dst/DEVICE/system/loopback","true"][1,"dst/DEVICE/system/loopback","true"]publish("dst/DEVICE/system/loopback","true")publish("dst/DEVICE/system/loopback","true")[1,"dst/DEVICE/system/loopback","true"]no more messages after 5 sec,serial2mqtt disconnects serial port and tries to reconnect. MQTT connection always open.close serial port ttyopen serial portµCserial2mqttMQTT Broker

Programming through serial2mqtt

A command line utility will send a single mqtt request to the serial2mqtt gateway to program the microcontroller.

µCserial2mqttMQTT Brokerprogrammer CLIPUBLISH("dst/drive/serial2mqtt/flash",flash image binary)PUBLISHprogram flash imagePUBLISH(logs)logsstartup logslogslogsMQTT PubµCserial2mqttMQTT Brokerprogrammer CLI

Logging through serial2mqtt

Everything that serial2mqtt receives on the serial port is also send on a topic.The micrcontroller will also log to the central logging system

Build instructions

Or just deploy the pre-build versions from the Debug directory , 2 versions available : Linux 64bits Intel and Raspberry Pi ARM. The armv6l also runs on raspberry pi 3. Watch out for the arch command below.

wget https://github.com/vortex314/serial2mqtt/raw/master/Debug/serial2mqtt.`arch`.zip
wget https://github.com/vortex314/serial2mqtt/raw/master/serial2mqtt.json
unzip serial2mqtt.`arch`.zip
mv Debug/serial2mqtt.`arch` serial2mqtt

Tested

Still to do

Code design

Per serial port there is a main thread and mqtt threads for callback
The main thread waits for events and handle these primarily. 2 timers in this thread are checked for expiry ( not time critical ) : serial-watchdog and mqtt-connect.

To avoid concurrency issues , the callbacks of the mqtt threads are communicated back by writing an event code on a pipe.
The main threads waits on events : timeout of 1 sec, data on serial file-descriptor or pipe file-descriptor.
The mqtt event of received message is handled directly by writing the message on the serial port.