- OpenThread with MQTT-SN client support
- Trying MQTT-SN client with CLI application example
- MQTT-SN source files
- Code samples
This project contains fork of OpenThread SDK which implements MQTT-SN protocol on Thread network. MQTT-SN implementation is part of OpenThread library build. MQTT-SN implementation allows user to send MQTT messages from Thread network to regular MQTT broker in external IP network. This is not official OpenThread project. OpenThread code may be outdated and there can be some bugs or missing features. If you want to use latest OpenThread project please go to official repository.
-
MQTT-SN over Thread network uses UDP as transport layer. UDP MQTT-SN packets are tranformed and forwarded to MQTT broker by Eclipse Paho MQTT-SN Gateway.
-
There is introduced C API for custom applications and CLI commands which can be used for basic client functions evaluation.
Provided MQTT-SN client implements most important features specified by protocol MQTT-SN v1.2:
- Publish and subscribe with QoS level 0, 1, 2
- Easy publish with QoS level -1 without maintaining connection
- Periodic keepalive requests
- Multicast gateway search and advertising
- Sleep mode for sleeping devices
OpenThread released by Google is an open-source implementation of the Thread networking protocol. Google Nest has released OpenThread to make the technology used in Nest products more broadly available to developers to accelerate the development of products for the connected home.
MQTT-SN v1.2 is formerly known as MQTT-S. MQTT for Sensor Networks is aimed at embedded devices on non-TCP/IP networks, such as Zigbee. MQTT-SN is a publish/subscribe messaging protocol for wireless sensor networks (WSN), with the aim of extending the MQTT protocol beyond the reach of TCP/IP infrastructure for Sensor and Actuator solutions. More informations can be found in MQTT-SN specification.
- Linux device such as Raspberry Pi acting as border router with installed Docker - Docker install guide, guide for Raspberry
- 2 Thread devices compatible with OpenThread - check here
- Environment for building firmware with GNU Arm Embedded Toolchain
OpenThread Border Router runs on an RCP design. Select a supported OpenThread platform to use as an RCP and follow the official building instructions. For example for KW41Z platform run following commands:
git clone https://github.com/openthread/ot-kw41z.git --recursive
cd ot-kw41z
./script/bootstrap
./script/build -DOT_BORDER_AGENT=ON -DOT_BORDER_ROUTER=ON -DOT_COMMISSIONER=ON -DOT_UDP_FORWARD=ON
After a successful build, the elf files are found in output/kw41z/bin. You can convert them to bin files using arm-none-eabi-objcopy:
cd /output/kw41z/bin
arm-none-eabi-objcopy -O binary ot-rcp ot-rcp.bin
Then flash the binary and connect RCP device to border router device.
Border router device provides functionality for routing and forwarding communication from Thread subnet to other IP networks. In this example border router consists of OpenThread Border Router (OTBR) which is capable of routing communication with Thread network and Eclipse Paho MQTT-SN Gateway which transforms MQTT-SN UDP packets to MQTT.
All applications for border router are provided as Docker images. First step is to install docker on your platform (Docker install guide). On Raspberry Pi platform just run following script:
curl -sSL https://get.docker.com | sh
In real application it is best practice to use DNS server for resolving host IP address. In this example are used simple static addresses for locating services. Create custom docker network test
for this purpose:
sudo docker network create --subnet=172.18.0.0/16 test
Run new OTBR container from official image:
sudo docker run -d --name otbr --sysctl "net.ipv6.conf.all.disable_ipv6=0 \
net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1" -p 8080:80 \
--dns=127.0.0.1 -v /dev/ttyACM0:/dev/ttyACM0 --net test --ip 172.18.0.6 \
--privileged openthread/otbr --radio-url spinel+hdlc+uart:///dev/ttyACM0"
Container will use test
network with static IP address 172.18.0.6. If needed replace /dev/ttyACM0
in -v
and --radio-url
parameter with name under which appear RCP device in your system (/dev/ttyS0
, /dev/ttyUSB0
etc.).
In latest OTBR image it may be necessary to manually activate NAT64 feature by running following command in running container (after the network is setup and up).
# ot-ctl nat64 enable
Done
You can check if NAT64 is enabled:
# ot-ctl nat64 state
PrefixManager: Active
Translator: Active
Done
NAT-64 prefix is set automatically by OpenThread. It allows address translation and routing to local addresses. Border Router web GUI is bound to port 8080.
Next step is to run Mosquitto container as MQTT broker for sample test. Broker IP address in test
network will be 172.18.0.7:
sudo docker run -d --name mosquitto --net test --ip 172.18.0.7 kyberpunk/mosquitto
As last step run container with MQTT-SN Gateway:
sudo docker run -d --name paho --net test --ip 172.18.0.8 kyberpunk/paho \
--broker-name 172.18.0.7 --broker-port 1883
MQTT-SN gateway service address is 172.18.0.8 which can be translated to IPv6 as 2018:ff9b::ac12:8. See more information here.
IMPORTANT NOTICE: In this network configuration MQTT-SN network does not support SEARCHGW and ADVERTISE messages in Thread network until you configure multicast forwarding. Alternativelly you can use UDPv6 version of gateway (kyberpunk/paho:udp6 image) and attach it to OTBR container interface wpan0 (--net "container:otbr"
).
Build the CLI example firmware accordingly to your platform. Original openthread submodule must be replaced by kyberpunk/openthread. For example for KW41Z platform run:
git clone https://github.com/openthread/ot-kw41z.git
cd ot-kw41z
git submodule remove openthread
rm -rf openthread
echo "" > .gitmodules
git submodule add https://github.com/kyberpunk/openthread.git openthread
git submodule update --init --recursive
./script/bootstrap
./script/build -DOT_MQTT=ON -DOT_JOINER=ON
Convert fimware to binary and flash your device with ot-cli-ftd.bin
.
cd /output/kw41z/bin
arm-none-eabi-objcopy -O binary ot-cli-ftd ot-cli-ftd.bin
Firs of all the CLI device must be commisioned into the Thread network. Follow the the OTBR commissioning guide. When device joined the Thread network you can start MQTT-SN service and connect to gateway which is reachable on NAT-64 translated IPv6 address e.g. 2018:ff9b::ac12:8.
> mqtt start
Done
> mqtt connect 2018:ff9b::ac12:8 10000
Done
connected
You will see connected
message when client successfully connected to the gateway. Client stays connected and periodically sends keepalive messages. See more information about connect
command in CLI reference.
You can also see log of messages forwarded by MQTT-SN gateway:
docker logs paho
CLI also supports automatic IPv4 address translation using preferred NAT64 prefix. You can then use MQTT-SN gateway IPv4 address directly in command:
> mqtt connect 172.18.0.8 10000
Done
connected
After successful connection can CLI device subscribe to MQTT topic with subscribe
command.
> mqtt subscribe sensors
Done
subscribed topic id: 1
You can test subscription by sending test message with mosquitto_pub
from mosquitto Docker container.
$ sudo docker exec -it mosquitto mosquitto_pub -h 127.0.0.1 -t sensors -m "{\"temperature\":24.0}"
Following output should appean on CLI device:
received publish from topic id 1:
{"temperature":24.0}
See more information about subscribe
command in CLI reference.
Publish a message with publish command
. To determine the topic id register
command should be used:
> mqtt register sensors
registered topic id:1
> mqtt publish 1 {"temperature":24.0}
Done
published
published
message should be written to CLI output when publish succeeded. You can test reception of PUBLISH message with mosquitto_sub
command from mosquitto Docker container.
$ sudo docker exec -it mosquitto mosquitto_sub -h 127.0.0.1 -t sensors
{"temperature":24.0}
See more information about publish
command in CLI reference.
third_party/paho
src/core/mqttsn/mqttsn_client.cpp
src/core/mqttsn/mqttsn_client.hpp
src/core/mqttsn/mqttsn_gateway_list.cpp
src/core/mqttsn/mqttsn_gateway_list.hpp
src/core/mqttsn/mqttsn_serializer.cpp
src/core/mqttsn/mqttsn_serializer.hpp
include/openthread/mqttsn.h
src/core/api/mqttsn_api.cpp
src/cli/cli_mqtt.cpp
src/cli/cli_mqtt.hpp
tests/unit/test_mqttsn.cpp
You can find code samples how to use MQTT-SN client with OpenThread in separate repository here.