0

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

1

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 answer – Guy . D Sep 18 '18 at 11:13
  • 1
    incoming_msg[length] = 0; – Juraj Sep 18 '18 at 11:14
  • got it the first time :) – Guy . D Sep 18 '18 at 11:16
  • OK- it works. Can you please explain why last char does not regarded as a plain 0 ? and regarded as \0 ? – Guy . D Sep 18 '18 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 the length. you convert the payload to a string of length length so you must set the terminating zero at the right position of the char array – Juraj Sep 18 '18 at 11:25
1

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 ? – Guy . D Sep 18 '18 at 11:13
  • It's not the sending. It's the copying into your internal array. You discard the null. – Majenko Sep 18 '18 at 11:14
  • OK, what is the pupose of adding 0 every loop ( as you wrote ) ? – Guy . D Sep 18 '18 at 11:24
  • It's just one of the many ways of ensuring that there is a null after the last character. – Majenko Sep 18 '18 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.