Использование MQTT для отправки отметки времени — в Arduino

В предыдущем вопросе на этом форуме я спрашивал об обновлении часов на ESP8266 с использованием брокера MQTT для отправки отметки времени по требованию следующим образом:

1) ESP8266 отправляет публикацию, содержащую полезную нагрузку: «sync»,

2) брокер отвечает в строковом формате (эта часть — 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) на терминале (MAC OS), подписан на соответствующую тему — не вижу результатов публикации. что нормально:

sync                           <----- ESP sends request
2018,9,18,12,44,18,903242      <----- string answer from broker

4) НО, когда код Arduino получает эту отметку времени:

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) Я получаю такой результат на последовательном мониторе:

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

РЕДАКТИРОВАТЬ1:

6) Я попробовал добавить нулевое завершение в отметку времени, но к отметке времени просто добавился \0 Благодарим за любую помощь

Парень

, 👍0


2 ответа


Лучший ответ:

1

Вы забыли установить завершающий ноль в c-ctring incoming_msg.

добавить incoming_msg[длина] = 0;

,

пожалуйста, посмотрите мой комментарий в ответе Majenko, @Guy . D

incoming_msg[длина] = 0;, @Juraj

Получилось с первого раза :), @Guy . D

Хорошо, это работает. Можете ли вы объяснить, почему последний символ не рассматривается как обычный 0 ?, а рассматривается как \0 ?, @Guy . D

0 действителен только в памяти как терминатор для c-строки. Он недействителен для передачи по сети. Вы получаете байты полезной нагрузки и длину. Вы преобразуете полезную нагрузку в строку длиной длина, поэтому вы должны установить завершающий ноль в правой позиции массива символов., @Juraj


1

В языке C строка завершается нулем. Это означает, что самый последний символ каждой строки должен быть символом 0 (или NULL).

Вам необходимо добавить этот NULL-символ в конец строки incoming_msg, чтобы завершить ее, или принудительно очистить всю строку до NULL перед ее заполнением.

Самый простой способ — обнулить строку:

bzero(incoming_string, 50);

Или вы можете принудительно добавлять 0 после добавления каждого байта:

incoming_msg[i] = (char)payload[i];
incoming_msg[i+1] = 0;

Или просто добавьте его в конце:

incoming_msg[length] = 0;

Есть много способов сделать это - главное, чтобы вы каким-то образом вставили туда NULL.

,

спасибо за ответ, на самом деле я пытался отправить временную метку с нулевым завершением (но безуспешно), я сделал так: ('%d,%d,%d,%d,%d,%d,%d,%s), где последний параметр был '\0'. Возможно, я сделал это неправильно? Или это невозможно?, @Guy . D

Это не отправка. Это копирование в ваш внутренний массив. Вы отбрасываете нуль., @Majenko

Хорошо, какова цель добавления 0 в каждом цикле (как вы написали)?, @Guy . D

Это всего лишь один из многих способов убедиться, что после последнего символа есть ноль., @Majenko