-
Notifications
You must be signed in to change notification settings - Fork 5
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
Provide ability to send a status msg via MQTT #14
base: main
Are you sure you want to change the base?
Conversation
Currently used for a couple of basic purposes: 1) to send count of connection attempts on connection (somewhat useful for determining if a connection is a reboot/physical issue or network). 2) Log start of OTA updates. Neither are super-important, mostly just to demo/test the functionality - more concretely, I plan to follow this up for more completed OTA status reporting (e.g. error cases), but that requires chrisjoyce911/esp32FOTA#87 to be addressed first. Outside of OTA status, I have a few other features planned that would also benefit from being able to report this type of status back.
src/mqtt.cpp
Outdated
void sendStatus(const char *newmsg) { | ||
MqttMessage msg; | ||
msg.cmd = X_CMD_PUBLISH_STATUSMSG; | ||
sprintf(statusmsg, "%s", newmsg); |
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
src/mqtt.cpp
Outdated
@@ -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); |
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.
Do you mind passing the reconnect count as a separate property instead of injecting it into the string?
I've got a mqtt_client->publish(buf, "{\"online\":false}");
message in the (so far unpublished) branch for the portable monitor to signal the device going to disconnect before sleep.
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.
OK, see what you think about this reworked code... allows an arbitrary JSON doc to be provided as the status message (as a pointer, which the queue takes ownership of to free after serialization).
This allows sending structured data (like offline:false, and connectionAttempts) but still makes it pretty simple to provide a nice wrapper for sending a simple message.
Only 4 more bytes on the queue in the general case (e.g. other messages), but when providing a doc, the caller has control over how much memory to allocate.
xQueueCreate takes the size of the item to store on the queue, which is used by xQueueSendToBack to copy that number of bytes from the provided pointer at queing time. So this should be sizeof(MqttMessage) not the size of a pointer to MqttMessage (we can't store a pointer, because the queued object is on the stack, not the heap)... Despite the bug, this currently works because sizeof(MqttMessage) == sizeof(MqttMessgae *) atm - both are 4 bytes. But that won't be true if/when more fields are added... (in the next commit).
With a helper to enable the simple usecase of just publishing a status string (OTA use-case), but also allowing other use-cases (e.g. reconnection) to send structured data rather than embedding # of reconnects in a string. This also avoids a race condition/potential loss of data if sendStatus is called consecutively before the queue is processed.
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.
Good find (oops) sizeof(struct MqttMessage*)
src/mqtt.cpp
Outdated
void sendStatus(const char *newmsg) { | ||
MqttMessage msg; | ||
msg.cmd = X_CMD_PUBLISH_STATUSMSG; | ||
sprintf(statusmsg, "%s", newmsg); |
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
(can't reply directly on your comment above since I pushed the latest commit... weird)
Yes, the issue was simply the size argument, so we could pass whatever we like.
I don't have any other use-cases (other than the reconnection count that uses it here, which I do want) for structured data other than a string message immediately in mind. I don't feel strongly about reverting back to only a string, but then we have to put the reconnection count back into a string, etc. |
aeaec2a doesn't quite preserve the same semantics that were intended here - specifically it doesn't take ownership of the passed status message and does not free it after it is sent, so you're options are either to:
None of those are very attractive... I tink given the asynchronous nature of the queue, there isn't an alternative for this API other than for it to take ownership of the string and free it itself. |
Currently used for a couple of basic purposes:
to send count of connection attempts on connection (somewhat useful
for determining if a connection is a reboot/physical issue or
network).
Log start of OTA updates.
Neither are super-important, mostly just to demo/test the functionality
status reporting (e.g. error cases), but that requires
Reporting status during the update process chrisjoyce911/esp32FOTA#87 to be addressed
first. Outside of OTA status, I have a few other features planned that
would also benefit from being able to report this type of status back.