I believe I have discovered a bug in the SLM firmware. I am using SDK v2.6.1.
When running the nRF9160 in MQTT datamode, we are encountering an issue where the slm_quit_string
has been appearing in the payload. The slm_quit_string
appears in the data if the last character of the data payload is the first character of the slm_quit_string
. For example, if we trying to send 12345h
, and our termination string is hello
, the resulting payload sent will appear as 12345hhello
. Furthermore, if the last character of the payload is the first character of the termination string, the device will not exit data mode.
I performed the following steps to recreate this (Note: this assumes the termination string is hello)
- Connect the device to a serial terminal
- Turn on device modem with
AT+CFUN=1
- Connect to MQTT broker using
AT#XMQTTCONN=<MQTT credentials>
- Set datamode timeout to 20 seconds using
AT#XDATACTRL=20000
(this is just so I have time to send my messages) - Enter data mode using
AT#XMQTTPUB=<MQTT pub message>
- Send
12345h
- Send
hello\r\n
- In this case data mode does not exit, so I must send
hello\r\n
again. - I check the what is sent over MQTT, and see that it is
12345hhello
Also note that it does not matter if the ending of the payload is the first character of the termination string, but it can be any amount of characters as long as it is in the correct order eg. 12345hel
also triggers this bug and the resulting sent payload would read 12345helhello
.
The reason this occurs is due to the way the termination string is check within slm_at_host.c raw_rx_handler();
from lines 239 to 251. In these lines there is a check for the partial termination string. We can use our current example of sending 12345h and hello. The first messages sees that the last character of the payload, "h", is a possible candidate for the termination string. So when "hello" is sent (this is our termination string), this message now checks for the second character of the termination string, "e". Because the first character of the second message is "h", the FW skips this and moves on to check for the first character of the termination string, but does not re-check if the current character is the first character of the termination string.
The reason we have run into this issue because we are sending a a payload of random data that has often conflicted with our termination string.
It appears this issue is still prevalent on the main branch of the SLM FW. Please let me know if this issue is correct and if you can recreate it. Also if there are any fixes available.
Update:
Here's a fix that addresses this edge case. I retested the issue above and it seems to be working. Hopefully you guys may find an officially tested update.
/* Find quit_str or partial match at the end of the buffer. */ for (processed = 0; processed < len && quit_str_match == false; processed++) { if (buf[processed] == slm_quit_str[quit_str_match_count]) { quit_str_match_count++; if (quit_str_match_count == strlen(slm_quit_str)) { quit_str_match = true; } } else { /* No match. Possible previous partial quit_str match is data. */ if (buf[processed] == slm_quit_str[0]) { quit_str_match_count = 1; // Check if the first value is okay } else { quit_str_match_count = 0; } prev_quit_str_match = false; } }
Thank you,
Ben