Using the internal MQTT functionality of the SARA 410 modem

Due to poor stabilty with mqtt libs over regular TCP connections i try to examine the use the internal mqqt stack of the SARA modem. This would be a VERY convenient way to do mqtt.

With the serial passtrough sketch and manual commands it works:

AT+UMQTT=0, "3527530xxxxxxx" // Define the client id (Use your IMEI, with characters it fails!)
AT+UMQTT=1, 1883 // Set the port
AT+UMQTT=2, "mqtt.broker.com" // Define the broker server name
AT+UMQTT=4, "username", "password" // Set username and password
AT+UMQTTC=1 // Open connection to the mqtt broker
AT+UMQTTC=2,0,0,"topic", "message: hello world"

So far so good.

Remarks :

  • The connection persists over a sketch upload
  • Useful commands :
    AT+UMQTT? = Print the mqtt configuration
    AT+UMQTTER = Print the last mqtt error (Error codes in the u-blox manual)
    AT+CGPADDR = Print your own IP adress (To chek if you are online)

Questions:
I tried to rebuild the process with SerialSARA.println("AT commad"); and MODEM.sen("AT command"); but everything reacts very strange. To read the serial response i use for example:

 SerialSARA.println("AT+UMQTT=1, 1883");
  while (SerialSARA.available()) {
    Serial.write(SerialSARA.read());
  }

Now some commands go smooth:
09:26:51.742 -> AT+UMQTT=1, 1883
09:26:51.742 -> +UMQTT: 1,1
09:26:51.742 ->
09:26:51.742 -> OK

And the some commands don't even get trough, some have reaction times of over 30 sec etc.
while with manual commands everything goes fast and fine.

ERGO : i'm not able to code a sketch but i can do it with manual commands. Why?

Questions:

  • What is wrong with my approach?
  • Have someone ever tried this with success?
  • Does someone knows of a library for the mqqt stack of the SARA 410
    Thx for ideas, help or hints

After some changes it works. I do a SerialSARA.write and .avaiable>0, as an example:

  // Broker
  //Port AT+UMQTT=1, 1883
  SerialSARA.write("AT+UMQTT=1,1883\r");
  while (SerialSARA.available() > 0) {
    Serial.write(SerialSARA.read());
  }

On the serial monitor the 64 bytes buffer is the maximum to see, sometimes even less, don't kno why, but it works even when it does not look so.
I push a mqqt message of 310 bytes, on the serial monitor is just the beginning to see.
When i don't read outthe buffer, so only ```
SerialSARA.write("AT+UMQTT=1,1883\r");

It does not work.
In general it's very slow, it takes about a minute to set up everything while entering the AT command manually the modem answers very fast. 

Questions:
- I don't get the reason for this behaviour in general. 
- Why is the answering time of the modem soo different?
- I expanded the serial buffer without any change.
- Why does it cut the answer? 
- Am i totaly on the wrong train in general?

Ups: The connection is very reliable

Hi, I have the same question as you. When I am using AT command in the serial monitor it runs fast, but when I am using MODEM.sendf() it always needs more time. You said you have to use

  SerialSARA.write("AT+UMQTT=1,1883\r");
  while (SerialSARA.available() > 0) {
    Serial.write(SerialSARA.read());
  }

rather than it will not work.
Could you use MODEM.sendf("AT+UMQTT=1,1883\r") to instead?
I don't know if this will work either, but it's worth a try.

And I try your AT commands above to connect with an MQTT server, but I failed, could you tell me where I get a mistake?

AT+UMQTT=0,"352753090888437"



+UMQTT: 0,1


OK

AT+UMQTT=1,15458



+UMQTT: 1,1


OK

AT+UMQTT=2,"m11224f1.eu-central-1.emqx.cloud"



+UMQTT: 2,1


OK

AT+UMQTT=4,"*****","*****"



+UMQTT: 4,1


OK

AT+UMQTT?



+UUMQTT0: "352753090888437"

+UUMQTT1: 15458

+UUMQTT2: "m11224f1.eu-central-1.emqx.cloud"

+UUMQTT4: "yifan"

+UUM

+UMQTT:


OK
QTT6: 0

+UUMQTT7: 0

+UUMQTT10: 0

+UUMQTT11: 0

+UUMQTT12: 1

+UUMQTT14: 1


AT+UMQTTC=1



+UMQTTC: 1,0


OK

AT+UMQTTC=2,0,0,"TOPIC","HELLO"



+CME ERROR: Operation not allowed

Here is my server's information

And the mqtt error results is

AT+UMQTTER



+UMQTTER: 28,28


OK

Meanwhile i rewrote everything. Just forget everything i wrote before :crazy_face:

To my great surprise there is no library for the internal mqtt stack of the R410 modem, so i decided to start one! Actually not ready yet but your question can be clarified best with it and maybe some people here want to code?

It's a class as a library extension for the MKRNB lib, i will suggest a merge later.

You can find my library extension under:

Attention: It's UNDER CONSTRUCTION, so everyone is very welcome to contribute...

Here's the work done so far this afternoon..:

Done:

Constructor: Example: NBMqtt mqtt;
getMQTTerror() Get the last MQTT error from the modem.Example : mqtt.getMQTTerror();
setMQTTClientID Set the MQTT client ID : Use your SIM IMEI. Example: mqtt.setMQTTClientID("352753090834234");
setMQTTPort(Int): Set the MQTT Port (Normal is 1883, SSL is 8883(not yet implemented). Example : mqtt.setMQTTPort(1883);
setMQTTUserPassword(String, String): Set Username / Password for the MQTT broker. Example: mqtt.setMQTTUserPassword("username", "password");
setMQTTbrokerURL(String): Set the MQTT broker URL (DNS is made automatic). Example: mqtt.setMQTTBrokerURL("public.cloud.shiftr.io");
setMQTTbrokerIP(String): Set the MQTT broker IP (not necessary in general, provide a broker URL!)
setMQTTBrokerConnect(bool): Connect / Disconnect to the MQTT broker. Example: mqtt.setMQTTBrokerConnect(true); to connect, mqtt.setMQTTBrokerConnect(false); to disconnect

sendMQTTMsg(String, String): Send a MQTT message to a topic. Example: mqtt.sendMQTTMsg("/TestTopic", "TestMessage");

setMQTTSubscribe(String): Subscribe to a topic. Example: setMQTTSubscribe("TestTopic");

To do:

Read out MQTT messages

Set Timeouts

Set last will

Save/restore settings

There you can see what i did wrong before :stuck_out_tongue_closed_eyes:

The problem was the String to *char conversion, so in general correct is, for example:

MODEM.sendf("AT+UMQTT=3,\"%s\"", brokerIP);
  MODEM.waitForResponse(10000);

If you want to try out my lib, you just have to copy the files NBMQTT.h NBQTT.cpp, MKRNB.h and keywords.txt to your library/MKRNB folder or clone the whole repo.

Your specific problem:
You do not establish a connection to the mqtt broker.
Then you try to send a message. Because of the missing connection the "Operation is not allowed"
I think you set the server port wrong.

The AT+UMQTTC=1 (Connect to broker) is sucessfull when you receive two answers, like:

19:56:21.066 -> AT+UMQTTC=1
19:56:21.645 -> +UMQTTC: 1,1
19:56:21.645 ->
19:56:21.645 -> OK
19:56:21.681 ->
19:56:21.681 -> +UUMQTTC: 1,0

Meanwhile i fixed some bugs in my NBMQTT class draft. If you like to test it, please download the new files.

PS: Your port numbers are strange but possible. If true, your settings were right.
PS2: You better anonymisize username password in a public forum.

Thanks for your reply and reminder. The server manager said what I send is "non-standard MQTT protocol messages", I am trying to figure out where I have a mistake. And I will try your code.

I tested it but keep in mind that the modem is a diva. In doubt, load serialSARApasstrough and do a AT+CFUN=15, wait, do a ATI. If the modem answer, it works.

Don't forget to provide the correct SIM PIN in the sample sketch.

I use the public channel of shiftr.io so you can check eveything working under

https://public.cloud.shiftr.io/

Here's the output of the sample sketch (Check the speed of everything):

10:48:33.543 -> AT+CEREG?
10:48:33.543 -> +CEREG: 0,1
10:48:33.543 ->
10:48:33.543 -> OK
10:48:33.543 -> NB initialized
10:48:33.582 -> AT+UMQTT=0,"352753090834234"
10:48:33.582 -> +UMQTT: 0,1
10:48:33.582 ->
10:48:33.582 -> OK
10:48:33.617 -> AT+UMQTT=1,1883
10:48:33.617 -> +UMQTT: 1,1
10:48:33.617 ->
10:48:33.617 -> OK
10:48:33.617 -> AT+UMQTT=2,"public.cloud.shiftr.io"
10:48:33.654 -> +UMQTT: 2,1
10:48:33.654 ->
10:48:33.654 -> OK
10:48:33.654 -> AT+UMQTT=4,"public","public"
10:48:33.654 -> +UMQTT: 4,1
10:48:33.654 ->
10:48:33.654 -> OK
10:48:33.691 -> AT+UMQTTNV=2
10:48:33.724 -> +UMQTTNV: 2,1
10:48:33.724 ->
10:48:33.724 -> OK
10:48:33.762 -> AT+UMQTTC=1
10:48:34.165 -> +UMQTTC: 1,1
10:48:34.165 ->
10:48:34.165 -> OK
10:48:34.199 ->
10:48:34.199 -> +UUMQTTC: 1,0
10:48:34.199 -> AT+UMQTTC=2,0,0,"/TestTopic","TestMessage"
10:48:34.199 -> +UMQTTC: 2,1
10:48:34.199 ->
10:48:34.199 -> OK
10:48:34.236 -> AT+UMQTTER
10:48:34.236 -> +UMQTTER: 0,0
10:48:34.236 ->
10:48:34.236 -> OK
10:48:34.236 -> Last MQTT Error (See page 408 of the u-blox AT Manual): 0
10:48:39.218 -> Done
10:48:39.218 -> AT+UMQTTC=2,0,0,"/TestTopic","TestMessage"
10:48:39.256 -> +UMQTTC: 2,1
10:48:39.256 ->
10:48:39.256 -> OK
10:48:39.256 -> AT+UMQTTER
10:48:39.256 -> +UMQTTER: 0,0

AT+CEREG?


+CEREG: 0,5

OK



AT+UMQTT=0,"352753090888437"



+UMQTT: 0,1


OK

AT+UMQTT=1,1883



+UMQTT: 1,1


OK

AT+UMQTT=2,"public.cloud.shiftr.io"



+UMQTT: 2,1


OK

AT+UMQTT=4,"public","public"



+UMQTT: 4,1


OK

AT+UMQTTNV=2



+UMQTTNV: 2,1


OK

AT+UMQTTC=1



+UMQTTC: 1,0


OK

AT+UMQTTER



+UMQTTER: 704,-10


OK

Here is my new try, still cannot work...
By the way, do you use NB-IoT mode or LTE-M?

The error is for 704:"DNS Name Resolution Fail Error", for -10:"Out of bounds (QAPI)"
I will check what is this meaning

I had the same errors and the next run was a hit. The modem is a diva.
Check if you are registered with AT+CREG=? and if you have a IP with AT+CGPADDR
Then check the settings with AT+UMQTT?
Then ```
AT+UMQTTC=0

to disconnect (Even when not connected)
Then again ```
AT+UMQTTC=1

say a little prayer..

AT+CGREG?

AT+CGREG?

+CGREG: 2,4

OK

AT+CREG?

AT+CREG?

+CREG: 2,0

OK

AT+CEREG?

AT+CEREG?

+CEREG: 2,5,"6481","2F6815",9

OK

It seems i am not roaming?
It's strange, I can use grpsudpntpclient sketch...

I use LTE-M.

You can do the register manualy.
Start Passtrough, then just provide you SIM PIN with AT+CPIN="PINNUMBER".
Then check the registration status with AT+CEREG? untilyou got +CEREG: 0,1 or 0,5
then check your ip, do the mqtt setting, then connect. Should work for f....s sake.

Yes, my +CEREG: 0,5 but CREG:2,0

AT+CEREG?


+CEREG: 0,5

OK

AT+CGATT?


+CGATT: 1

OK



AT+CREG=2


OK

AT+CREG?


+CREG: 2,0

OK
AT+CGPADDR


+CGPADDR: 1,10.218.127.1

OK

My SIM card backend can find I am online... and I have an IP address..

0,5 means you are roaming and not in your home network.
From here you can log in mqtt broker manually or you take my example sketch and delete the GSM log in part

Yes, in fact, I did that before (manually). It didn't work out. I am now contacting my SIM card provider to ask if there is a problem with the SIM card. Or maybe NB-IoT can not use MQTT? (couldn't believe)

I have successfully connected with the server which I used yesterday now by using ip address to connect. But i can not upload a topic.


[15:37:08.481] AT+UMQTTC=1
[15:37:10.103] 
[15:37:10.103] 
[15:37:10.103] 
[15:37:10.103] +UMQTTC: 1,1
[15:37:10.103] 
[15:37:10.103] 
[15:37:10.103] OK
[15:37:10.103] 
[15:37:10.103] 
[15:37:10.103] +UUMQTTC: 1,0
[15:37:10.118] 
[15:37:22.420] 
[15:37:22.420] AT+UMQTTC=2,0,0,"topic","10cm"
[15:37:22.435] 
[15:37:22.435] 
[15:37:22.435] 
[15:37:22.435] +UMQTTC: 2,1
[15:37:22.435] 
[15:37:22.435] 
[15:37:22.435] OK
[15:37:28.685] 
[15:37:28.685] AT+UMQTTER
[15:37:28.701] 
[15:37:28.701] 
[15:37:28.701] 
[15:37:28.701] +UMQTTER: 390,-1
[15:37:28.701] 
[15:37:28.701] 
[15:37:28.701] OK

Finally, I can send a message. But it still error...
I used IP address
mqtt.setMQTTBrokerIP("3.122.54.81",15458);
instead of setMQTTbrokerURL(String)
In addition, if anyone need use mqtt.setMQTTBrokerIP("3.122.54.81",15458); should fix the .h and .cpp because there is only one input, you need another one for brokerport.

You're right..i never tested it...
If i get you right, the syntax
mqtt.setMQTTBrokerIP("3.122.54.81",15458);
worked?

Yes, it is

So did you change something on mqtt.cpp or mqtt.h to make it work? If so,please do a push request om github.

I have uploaded a pull request. I am from China, and I have never used Github before. I don't know if I succeeded. I'm sorry for the trouble I caused.
Here is the two files. Perhaps you can download it from here.
NBMqtt.cpp (1.8 KB)
NBMqtt.h (1.1 KB)

You made everything right on github! I merged your changes and now you are the first contributor! And first user! :sunglasses: