In previous question in this forum - I asked about updating clock on an ESP8266, using MQTT broker to send a time stamp on demand, in following manner:
1) ESP8266 sends a publish containing the payload :"sync",
2) broker answers in string format ( this part is python )
def on_message(self, client, obj, msg):
self.arrived_msg = msg.payload.decode()
if self.arrived_msg == "sync":
a = datetime.datetime.now()
b = "%d,%d,%d,%d,%d,%d,%d" % (a.year, a.month, a.day, a.hour, a.minute, a.second, a.microsecond) . <------ here a string time format is created
self.client.publish(topic=self.topics[0], payload=b, qos=self.topic_qos)
3) on a terminal (MAC OS), subscribed to relevant topic- cant see publish results. which are OK:
sync <----- ESP sends request
2018,9,18,12,44,18,903242 <----- string answer from broker
4) BUT when Arduino code get this time stamp:
void callback(char* topic, byte* payload, unsigned int length) {
char incoming_msg[50];
// ledBlink(30, 5);
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]); <----- print #1
incoming_msg[i] = (char)payload[i]; <----- generate incoming msg
}
Serial.println("");
if (strcmp(topic,clockTopic)==0) { <------- detect relvant topic for clock sync
Serial.print(incoming_msg); <------ Print #2
}
5) I get this result on serial monitor :
Message arrived [HomePi/Dvir/Clock] 2018,9,18,13,48,5,230009 <---- here time stamp is OK , Print #1
2018,9,18,13,48,5,230009$��?O: @ . <----- Print #2
EDIT1:
6) I tried adding a null termination in time stamp, but it just added 0円
to time stamp
Appreciate any help
Guy
2 Answers 2
You forgot to set the terminating zero of the c-ctring incoming_msg
.
add incoming_msg[length] = 0;
-
please see my comment in Majenko's answerguyd– guyd2018年09月18日 11:13:34 +00:00Commented Sep 18, 2018 at 11:13
-
1
incoming_msg[length] = 0;
2018年09月18日 11:14:58 +00:00Commented Sep 18, 2018 at 11:14 -
-
OK- it works. Can you please explain why last char does not regarded as a plain 0 ? and regarded as
0円
?guyd– guyd2018年09月18日 11:22:22 +00:00Commented Sep 18, 2018 at 11:22 -
the 0 is valid only in memory as a terminator for the c-string. it is not valid for transport over a network. you get the
payload
bytes and thelength
. you convert thepayload
to a string of lengthlength
so you must set the terminating zero at the right position of the char array2018年09月18日 11:25:34 +00:00Commented Sep 18, 2018 at 11:25
In C a string is "null terminated". That means that the very last character of every string must be character 0 (or NULL).
You need to ensure that you add that NULL character to the end of your incoming_msg
string to terminate it, or force the entire string to be cleared to NULLs before you populate it.
The simplest way is to zero the string:
bzero(incoming_string, 50);
Or you can force a 0 to be appended after each byte is added:
incoming_msg[i] = (char)payload[i];
incoming_msg[i+1] = 0;
Or just add one at the end:
incoming_msg[length] = 0;
There's many ways of doing it - as long as you get that NULL in there somehow.
-
thank you for your answer, as a matter of fct I tried to send time stamp with null termination ( but with no luck ), I did like :` ('%d,%d,%d,%d,%d,%d,%d,%s)` which last parameter was
'0円'
. perhaps I didn;t do it right ? or this is impossible ?guyd– guyd2018年09月18日 11:13:02 +00:00Commented Sep 18, 2018 at 11:13 -
It's not the sending. It's the copying into your internal array. You discard the null.Majenko– Majenko2018年09月18日 11:14:30 +00:00Commented Sep 18, 2018 at 11:14
-
OK, what is the pupose of adding
0
every loop ( as you wrote ) ?guyd– guyd2018年09月18日 11:24:17 +00:00Commented Sep 18, 2018 at 11:24 -
It's just one of the many ways of ensuring that there is a null after the last character.Majenko– Majenko2018年09月18日 11:25:07 +00:00Commented Sep 18, 2018 at 11:25