-
Notifications
You must be signed in to change notification settings - Fork 9
Provide ability to send a status msg via MQTT #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,6 +28,7 @@ namespace mqtt { | |
|
|
||
| const uint8_t X_CMD_PUBLISH_SENSORS = bit(0); | ||
| const uint8_t X_CMD_PUBLISH_CONFIGURATION = bit(1); | ||
| const uint8_t X_CMD_PUBLISH_STATUSMSG = bit(2); | ||
|
|
||
| TaskHandle_t mqttTask; | ||
| QueueHandle_t mqttQueue; | ||
|
|
@@ -45,6 +46,8 @@ namespace mqtt { | |
| getSPS30StatusCallback_t getSPS30StatusCallback; | ||
|
|
||
| uint32_t lastReconnectAttempt = 0; | ||
| uint32_t connectionAttempts = 0; | ||
| char statusmsg[512]; | ||
|
|
||
| void publishSensors(uint16_t mask) { | ||
| if (!WiFi.isConnected() || !mqtt_client->connected()) return; | ||
|
|
@@ -255,12 +258,42 @@ namespace mqtt { | |
| } | ||
| } | ||
|
|
||
| void sendStatus(const char *newmsg) { | ||
| MqttMessage msg; | ||
| msg.cmd = X_CMD_PUBLISH_STATUSMSG; | ||
| sprintf(statusmsg, "%s", newmsg); | ||
| if (strlen(statusmsg) > 0) { | ||
| if (mqttQueue) xQueueSendToBack(mqttQueue, (void*)&msg, pdMS_TO_TICKS(100)); | ||
| } | ||
| } | ||
|
|
||
| void publishStatusInternal() { | ||
| if (!mqtt_client->connected()) { | ||
| return; | ||
mattbnz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| char msg[1024]; | ||
| StaticJsonDocument<1024> json; | ||
| json["online"] = true; | ||
| if (strlen(statusmsg) > 0) { | ||
| json["status"] = statusmsg; | ||
| } | ||
| if (serializeJson(json, msg) == 0) { | ||
| ESP_LOGW(TAG, "Failed to serialise status payload"); | ||
| return; | ||
mattbnz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| char buf[256]; | ||
| sprintf(buf, "%s/%u/up/status", config.mqttTopic, config.deviceId); | ||
| mqtt_client->publish(buf, msg); | ||
| sprintf(statusmsg, ""); | ||
| } | ||
|
|
||
| void reconnect() { | ||
| if (millis() - lastReconnectAttempt < 60000) return; | ||
| char buf[256]; | ||
| sprintf(buf, "CO2Monitor-%u-%s", config.deviceId, WifiManager::getMac().c_str()); | ||
| if (!WiFi.isConnected()) return; | ||
| lastReconnectAttempt = millis(); | ||
| connectionAttempts++; | ||
| if (!mqtt_client->connected()) { | ||
| ESP_LOGD(TAG, "Attempting MQTT connection..."); | ||
| if (mqtt_client->connect(buf, config.mqttUsername, config.mqttPassword)) { | ||
|
|
@@ -269,8 +302,8 @@ namespace mqtt { | |
| mqtt_client->subscribe(buf); | ||
| sprintf(buf, "%s/down/#", config.mqttTopic); | ||
| mqtt_client->subscribe(buf); | ||
| sprintf(buf, "%s/%u/up/status", config.mqttTopic, config.deviceId); | ||
| mqtt_client->publish(buf, "{\"online\":true}"); | ||
| sprintf(statusmsg, "connected after %d attempts", connectionAttempts); | ||
|
||
| publishStatusInternal(); | ||
| } else { | ||
| ESP_LOGW(TAG, "MQTT connection failed, rc=%i", mqtt_client->state()); | ||
| vTaskDelay(pdMS_TO_TICKS(1000)); | ||
|
|
@@ -347,6 +380,8 @@ namespace mqtt { | |
| publishConfigurationInternal(); | ||
| } else if (msg.cmd == X_CMD_PUBLISH_SENSORS) { | ||
| publishSensorsInternal(msg.mask); | ||
| } else if (msg.cmd == X_CMD_PUBLISH_STATUSMSG) { | ||
| publishStatusInternal(); | ||
| } | ||
| } | ||
| if (!mqtt_client->connected()) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a rare chance that a sendStatusInteral call is in progress while a sentStatus call is made from another thread which then overwrites/corrupts the
statusmsg. Can we avoid that e.g. by passing the status string (or a constant that gets resolved to a string) with the message? How long do you anticipate the statue message to get?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there is a much better solution, and if its worth increasing the queue message size which would reserve a larger chunk of memory. If we could keep the status message short then adding it to the queue message could work, otherwise not so sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I originally was storing the string in the message, but couldn't make it work through the queue, so fell back to the global object, but you're right it's messy... I took another look and found the bug that was breaking the queue passing (wrong size being passed to the createQueue method).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering - wouldn't the same approach of sending a pointer to the JsonDocument have worked for a String pointer as well as long as the publishStatusInternal method deleted it to free the memory?
I do like the idea of having an option to publish structured data, but it feels a little over kill for publishing a simple status message. What do you think, and do you have future changes that would make use of a generic publish for structured data