Использование 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
Благодарим за любую помощь
Парень
@Guy . D, 👍0
2 ответа
Лучший ответ:
Вы забыли установить завершающий ноль в c-ctring incoming_msg
.
добавить incoming_msg[длина] = 0;
В языке 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
- Как подключиться к MQTT брокеру с помощью TLS?
- Преобразование byte* в int в Arduino
- esp32-cam публикует изображение в mqtt
- ESP8266 глубокий сон и MQTT
- ESP-01 неправильно просыпается после глубокого сна
- Приведение от 'char*' к 'char' теряет точность
- Публиковать данные json в mqtt
- Не удалось подключиться к брокеру MQTT через esp8266/32 и pub/sub client
пожалуйста, посмотрите мой комментарий в ответе Majenko, @Guy . D
incoming_msg[длина] = 0;
, @JurajПолучилось с первого раза :), @Guy . D
Хорошо, это работает. Можете ли вы объяснить, почему последний символ не рассматривается как обычный 0 ?, а рассматривается как
\0
?, @Guy . D0 действителен только в памяти как терминатор для c-строки. Он недействителен для передачи по сети. Вы получаете байты
полезной нагрузки
идлину
. Вы преобразуетеполезную нагрузку
в строку длинойдлина
, поэтому вы должны установить завершающий ноль в правой позиции массива символов., @Juraj