send() after receive()
I would like to ask for an advice: I am working on some autonomous watering gizmo built on barebone Atmel328p, HomeAssistant and MySensors. As my units run on batteries, I use long smartSleep()s to save power.
The release water command is initiated by controller. After the specific amount of water is released, I would like to send some information back to the controller (remaining amount of water in the tank and the fact that the pump was switched off after the watering was done). Sending this information from within receive() is a no-no, as I learned recently (a lots of !MCO:PRO:RC=1), so instead of sending the outbound messages directly, I put them into a linked queue which is flushed in the loop(). This works, somewhat.
But due to the fact that the receive() is called just before smartSleep(), my messages must wait in the queue till the smartSleep() is finished and they get out only after the unit wakes up again (say, after 30 minutes).
It's not the end of the world, but I have quite a strong feeling I am trying to reinvent the wheel here. Is there some "proper" way how to send out message to controller in a reaction to some received() data? I tried to play with wait() after waking up, but it did not work as I hoped it would.
Many thanks in advance,
rejoe2 last edited by
This reminds me on a discussion some time ago which lead to this feature request: https://github.com/mysensors/MySensors/pull/1271
Perhaps you might check out if that would help.
Hmm, interesting idea, I will try to pursue it further.
However, I've noticed that there are some "official" examples out there with send() within receive() - namely https://github.com/mysensors/MySensors/blob/development/examples/DimmableLEDActuator/DimmableLEDActuator.ino
Is there any rule to follow under which it would be possible to send() from receive() without any radio conflicts? Maybe I am just doing it wrong.
@Honza-Liška there is, but it is too complicated for me to understand.
https://github.com/mysensors/MySensors/issues/1289 has some discussion
Thank you for the information! From the linked discussion I somewhat feel that you understand it quite well.
To perform the send() from within receive() indiscriminately and hope that the controller will be prescient enough not to send any further messages while MySensors perform their I_PRE_SLEEP_NOTIFICATION wait() surely is a recipe for some pretty interesting problems down the line.
I try to add some pre-sleep evaluation callback to _sleep() in the similar manner to the solution described by @tmandel in the discussion linked above. Or I just accept the fact that it can't be done.
However it still feels kind of weird that there is no "proper" way how to deal with this scenario...
rejoe2 last edited by
I've no deep knowledge in these things, but imo the proposal from @tmandel leads in the right direction. Just looping once more (and perhaps having the info that the smartSleep-command has been skipped to avoid unnecessary additional measuring and so on) imo is the cleanest solution to this kind of trouble.
Honza Liška last edited by Honza Liška
From what I understood, the solution from @tmandel was meant to revoke sleep based on incoming message. I needed to delay sleep due to messages waiting in the outgoing queue.
At the end, I just got my fork of MySensors and added additional extern callback to MySensorsCore.cpp/_sleep just after the pre-sleep wait(MY_SMART_SLEEP_WAIT_DURATION_MS). The callback is then implemented in my source, where I check whether the oubound queue is empty. If not, MY_SLEEP_NOT_POSSIBLE is returned and the queue is flushed immediately in the next loop().
It may be crude but... hey, it keeps my flowers watered.
Many thanks for the advice and the direction provided!