Are there any examples out there for a host application in C that is using AT commands via serial to the nRF9160 running the Serial LTE Modem for a MQTT TLS connection?

I'm currently working on a POC for the nRF9160 with an external host processor. I have the Serial LTE Modem example running on the nRF9160 and have the serial comms between the host and the nRF9160 working well with the AT commands so far. My issue is that I'm new to AT commands and cellular in general. So I've been piecing together a C program to run on our host processor running Debian for managing a MQTT connection to the cloud. Right now I'm able to get my system to connect to the Nordic test.mosquitto.com broker and sub/pub to the topics I've created. But my next step is to add TLS and then move it to our AWS cloud.

I was able to find a sequence for bringing up the LTE and MQTT connection via hit or miss trials of different sequences I saw in other examples using the nRFConnect Link Monitor and the IoT Introduction course for the nRF9160. But I'm not 100% certain I have the sequence correct. It works but I would love to have an example from the host side in C to make sure I haven't missed something that will become important once I start really getting into the functionality. I know there are examples out there for the nRF9160 that do everything I'm trying to do but the ones I've found are all intended to run solely on the nRF9160 without the host processor. So I'm guessing which AT command would take care of that functionality because the nRF9160 code uses the libraries pretty heavily.

With trying to add TLS to my system, I've run into a few questions in addition to my concerns with the basic LTE and MQTT functionality. From looking at the Serial LTE Modem code, it looks to be set up to handle the sockets. But do I need to issue the AT command to establish one via the host or does the Serial LTE Modem code know that sockets are needed and take care of it for me? Do I need to change any of the Serial LTE Modem configurations if I want the certs and keys handled by the nRF9160? If the host processor needs to setup the socket, does the socket come before the MQTT connection or after?

Any C code, documentation, or even just a nice sequence diagram with the AT commands would be a HUGE help!!! But I will take any help I can get. Slight smile

Using VSCode for both processors, 2.2.0 nRF Connect Tool chain, and Debian Buster or Bullseye.

  • Hi,

    We have the slm_shell sample in NCS v2.3.0, which shows one possible host implementation. However, it only exposed the SLM AT commands in a shell, and show how you can send the commands over UART, it doesn't really show how to actually use the commands.

    You have probably already found this, but for reference, her is the documentation for the MQTT related AT commands in the SLM: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.2.0/nrf/applications/serial_lte_modem/doc/MQTT_AT_commands.html

    When using the MQTT commands, the SLM will handle the sockets automatically. This means that to connect to an MQTT broker, you only need to connect the device to the network, and then connect to the MQTT broker. E.g.:

    (Before we start: Parameters inside <> should be replaced with their actual values. If I end a command or response with ... it means that there are more fields in the command or response, I am just too lazy to write them all out, and their values are not important/relevant at the time)

    1. AT+CEREG=5

    Not strictly necessary, but this will enable registration event notifications from the modem, which will let us know that we have connected to the network. At this point, you might want to enable other notifications from the modem, or do other configurations of the modem as well. You can find the full list of AT commands supported by the modem here: https://infocenter.nordicsemi.com/topic/ref_at_commands/REF/at_commands/intro.html

    One command to pay extra attention to is AT%XSYSTEMMODE. In this case, I assume that the modem is already configured to use the correct system mode(s).

    2. AT+CFUN=1

    Turn on the modem, and start connecting to the network.

    When the modem has connected to a network, it will send a +CEREG: 1,... or +CEREG: 5,... status.

    3. AT#XMQTTCON=1,"<client ID>","<user name>","<password>","<URL>",<port>,<sec_tag>

    If you are using IPv6 instead of IPv4, the first parameter will be 2 instead of 1. In the case of AWS, the client ID will be the device ID in AWS and the username and password will be empty. The sec_tag is an integer and must mach the sec_tag (security tag) where you have written the device credentials.

    Writing the credentials should probably be done as part of production of the device, and not happen when the device is actually running. To write credentials to the modem, you use the %CMNG AT command. The sec_tag can be chosen arbitrarily. I like to think of it as a file name. The name doesn't matter, it is just used to refer to the file later. Similarly, the value of the sec_tag doesn't matter, you just have to refer to the same sec_tag later, when using the #XMQTTCON AT command. In the case of AWS, you must write the AWS Root CA certificate (type 0), and the client certificate and private key to the sec_tag (types 1 and 2). You should also make sure that there are no unrelated credentials on the sec_tag that you use.

    At this point, the SLM will do the DNS lookup, TLS handshake and MQTT connection. When you get a #XMQTTEVT=0,0 response, you are connected to the broker.


    Hopefully, this answers your questions.

    However, there is one more thing that is useful to note: To send JSON, you need to use data_mode. To enter data_mode when using the #XMQTTPUB command, leave the msg parameter empty (see examples 2 and 4 here). At this point the SLM will respond with OK, and any bytes sent over UART will be interpreted as part of the message, until you send the escape sequence (by default "+++"). Note that the escape sequence does not contain any <CR> or <LF> characters, which means that you cannot use the LTE Link Monitor to exit data_mode, as it will always end a line with <CR><LF>. Instead, you will need to use a terminal emulator that let you control the line endings manually.

    Best regards,

    Didrik

  • Thank you so much for the information!!! I don't know how but I missed the <sec_tag> as part of the AT#XMQTTCON command! However, the situation I find myself in now is quite confusing. I verified that I get this same response whether I manage the XSSOCKET or let the SLM take care of it. But it seems that I need to issue a connect to the non-secure port (1883) before I can successfully connect to the secure port (8883). But even if I connect to the 1883 and then to 8883, I still receive an error. If I check the connection after the error, it shows that it connected ok after all and I'm able to publish messages successfully on the secure port, which I'm verifying using the MQTT Explorer with one window connected to 1883 and another to 8883.

    So my question now is why do I need to connect to the 1883 port first? And why am I seeing an error response with the AT#XMQTTCON command for the 8883 port? See my terminal output below - note I used the ... for the messages that get returned and aren't relevant to the questions.

    AT#XMQTTCON=1,"MQTT Client ID","","","test.mosquitto.org",8883,16842753
    ERROR
    +CSCON: 1
    %CESQ: 42,2,7,1
    +CSCON: 0%CESQ: 42,2,12,1
    AT#XMQTTCON?
    #XMQTTCON: 0,"MQTT Client ID","test.mosquitto.org",8883,16842753
    OK
    AT#XMQTTPUB="devacademy/publish/topic","BLEH!",2,0
    ERROR
    AT#XMQTTCON?
    #XMQTTCON: 0,"MQTT Client ID","test.mosquitto.org",8883,16842753
    OK
    AT#XMQTTCON=1,"MQTT Client ID","","","test.mosquitto.org",8883,16842753
    ERROR
    +CSCON: 1%CESQ: 42,2,7,1
    +CSCON: 0
    AT#XMQTTCON=1,"MQTT Client ID","","","test.mosquitto.org",1883
    OK
    +CSCON: 1
    #XMQTTEVT: 0,0
    #XMQTTMSG: 26,0 ....
    
    #XMQTTEVT: 2,0
    +CSCON: 0
    AT#XMQTTCON?
    #XMQTTCON: 1,"MQTT Client ID","test.mosquitto.org",1883
    OK
    AT#XMQTTCON=1,"MQTT Client ID","","","test.mosquitto.org",8883,16842753
    ERROR
    AT#XMQTTCON?
    #XMQTTCON: 1,"MQTT Client ID","test.mosquitto.org",8883,16842753
    OK
    AT#XMQTTPUB="devacademy/publish/topic","BLEH!",2,0
    OK
    +CSCON: 1
    #XMQTTEVT: 4,0
    #XMQTTEVT: 6,0
    +CSCON: 0

  • The sec_tag you are using is used for connecting to nRF Cloud. Assuming you have not changed the credentials at that sec_tag, you will not be able to connect to test.mosquitto.org with those credentials as test.mosquitto.org uses a different CA certificate.

    What happens in your log is that you first try to connect with TLS using the wrong credentials, which causes an error. You then connect without TLS. Then, you try to connect with TLS again, but because you already have a connection open (and the SLM only supports one MQTT connection at a time), it returns an error. You then publish using the un-encrypted connection you set up previously.

  • I thought the Nordic creds were under type 10 and type 11? I chose the sec_tag that had type 1 and 2 when I ran the AT%CMNG=1?

  • Ah ha! I see now. I was able to load the mosquitto CA and my XMQTTCON worked. At least for a bit. It disconnected after my second publish. But I'm at least able to connect successfully. Thank you so much for all your help!!!!

Related