Following on from my earlier article describing use of the SIMCom y7080 CAT-NB (NB-IoT) module, which ended with me “running into the sand” with MQTT and having to update the firmware, here is the report of success!
For reference, see the SIMCom Y70XX Series MQTT(S) Application note.
In this article, I will be using the mosquitto test broker, which has listeners on several ports according to different scenarios for SSL/TLS and authentication.
Preliminaries
I’m assuming a mobile/cellular connection has already been made (see earlier article). I’m also going to jump straight in with encrypted communications, i.e. MQTTS aka MQTT with SSL/TLS. In the cases given below I am not, however, concerned with either: a) verification of the server certificate or b) using a client certificate to authenticate to the server. Since the server is one I control and trust, (a) is not necessary, and conventional user/password authentication will be sufficient instead of (b) since the connection is encrypted. Only using encryption makes the setup of the modem somewhat easier but it still involves the modem and server undertaking some behind-the-scenes communications to transfer the encryption keys. This means using our limited bandwidth and takes quite a bite out of a typical NB-IoT subscription data allowance; the payload for a single simple MQTT message is likely to be very much smaller than the connection data cost.
Initial set-up is straight-forward, involving starting the modem’s MQTT service and one client within it (the 0 is the handle for the MQTT service):
AT+CMQTTSTART AT+CMQTTACCQ=0,"client_123",1
Note that client id in AT+CMQTTACCQ is what will appear to the broker and that the final parameter must be 1 for a MQTTS (TLS) connection. Note also that for the encryption-only use case, it is not necessary to do any additional SSL configuration, as described in the Y70XX SSL Application Note. That 1 is all you need!
DNS
Using domain name servers to look up an IP address is nice but it does introduce an additional communication overhead; while this is rarely noticeable in most scenarios, the low bandwidth of NB-IoT makes using numerical IP addresses an attractive option. Things get a bit messy if you use a cloud service; I’ve noticed that the IP address for my Azure IoT Hub has changed (see my other article on talking MQTT with Azure IoT Hub).
It is easy to look up the IP address using nslookup (same command on linux and windows – yay!). For test.mosquitto.org it is 91.121.93.94 .
The Y7080 can also query DNS, using either servers whose addresses are provided by the mobile network operator or falling back on factory-defined servers (in China?).
Check the servers with:
AT+QIDNSCFG?
I got two Class A private addresses, so these must belong to the mobile network operator:
PrimaryDns:10.105.16.254
SecondaryDns:10.105.144.254
Querying DNS is as simple as:
AT+CMDNS=test.mosquitto.org
This is an asynchronous operation, so it returns “OK” very quickly and then provides the IP address as a separate message +CMDNS:91.121.93.94. Bad news comes in the form of +CMDNS:QUERY_DNS_FAILED; on the Vodafone platform this will happen if you query a domain name which is not listed in your APN Access List (see my previous article).
Repeating the CMDNS command straight-away will give a much faster response, so there must be caching somewhere (given the speed, I suppose this is internal to the modem). I’ve not found the cache duration documented anywhere but it is only of the order of a few minutes.
Making a Connection
Although using authentication will be essential for any in-service data logging, it makes sense to get a more simple situation working first. The connection to the simple MQTTS service of test.mosquitto.org without authentication uses port 8883:
AT+CMQTTCONNECT=0,"tcp://91.121.93.94:8883",60,1
Note that the Y7080 does require the “tcp://” and that the port is not a separate parameter.
This is another asynchronous command. Be prepared to wait several seconds, hoping for the successful message: +CMQTTCONNECT: 0,0. If you forget to make the last parameter of AT+CMQTTACCQ be 1 then the modem will very quickly follow that with +CMQTTCONNLOST: 0,2. This can also happen with test.mosquitto.org at quite frequent and seemingly-random times; the price of a free public service.
You can check whether the modem is connected with:
AT+CMQTTCONNECT?
A bare +CMQTTCONNECT: 0 tells of no connection, whereas a live connection will give a response containing the server URL etc.
Now the simple case works, it is a simple matter to add a username and password, using port 8885. The test.mosquitto.org documentation indicates we can use username=”rw” and password “readwrite” for a user with read and write access, so simply connect using:
AT+CMQTTCONNECT=0,"tcp://91.121.93.94:8885",60,1,rw,readwrite
Publishing Some Data
For each message, three steps are required (even if the topic stays the same). First declare the topic in two states, with the first stage declaring the length of the topic, e.g. for a five character long topic:
AT+CMQTTTOPIC=0,5
The Y7080 will respond with a prompt of “>” and wait for the topic string. I found that providing too few characters caused a broker disconnect when publishing. Conversely, providing too many characters simply caused the modem to use the first 5. Unlike the AT+MQPUB described in my previous article, the topic is provided using normal characters, without the need to convert to hexadecimal.
The payload is declared in similar fashion, with a “>” prompt to enter the payload string:
AT+CMQTTPAYLOAD=0,8
The payload string can be either shorter or longer than the length declared in AT+CMQTTPAYLOAD; the modem quietly does the right thing, sending shorter if shorter and truncating if longer.
And finally send it with (I am using QoS of 1 here):
AT+CMQTTPUB=0,1,60
The final command is, as you might by now expect, asynchronous. A short time after “OK”, success is indicated by +CMQTTPUB=0,0.
Tidy-up
Tidy-up is a three-stage process. These must be done in the correct order otherwise error responses are given:
AT+CMQTTDISC=0,120 AT+CMQTTREL=0 AT+CMQTTSTOP