Use loop() to receive and send messages immediately, and set and process changed settings appropriately - #168
Open
kchen wants to merge 9 commits into
Open
Use loop() to receive and send messages immediately, and set and process changed settings appropriately #168kchen wants to merge 9 commits into
kchen wants to merge 9 commits into
Conversation
* Add loop() function to handle UART reading so that messages from the mini-split can be read and handled immediately. * Drop messages that are incomplete after a 150 millisecond timeout. Since each byte takes about 96 milliseconds to transmit, this quick timeout allows incomplete messages to be dropped right away to prevent message framing problems. * Remove had_error functionality to better handle messages with invalid checksums. The mini-split system often sends two copies of the same message, and if the first copy is corrupted, the second copy should still be processed if not corrupted.
* Send messages immediately when the line is available, removing tight loops to avoid blocking. * Verify sent messages 2 seconds after sending.
Rather than sending a settings message every time a status message is sent every 20 seconds, only send the settings change as needed.
* To protect against mini-split units that often send corrupted messages, when processing status messages, only accept settings changes if the settings changed bit is set (or the status message is the first valid status message received). * If the status message is invalid, ignore the entire message, and do not partially apply updates. * Fix potential floating point comparison errors.
In outgoing status messages, rather than always setting the changed settings bit, only set it when settings have changed. This should help protect against corrupted outgoing messages.
kchen
force-pushed
the
handle-corrupted-messages
branch
from
June 17, 2026 14:24
4b7495f to
13fb253
Compare
kchen
force-pushed
the
handle-corrupted-messages
branch
from
July 17, 2026 02:23
13fb253 to
966ae61
Compare
Accept a status message if the identical message has arrived in consecutive status messages, even if the changed settings bit is not set. This avoids getting stuck if the original status message with the changed settings bit set was corrupted.
kchen
force-pushed
the
handle-corrupted-messages
branch
from
July 18, 2026 00:02
966ae61 to
176e5e5
Compare
This was referenced Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The big thing this PR does is that it rearchitects the update() function, and moves much of the functionality to loop(). update() currently polls for new bytes to process and messages to send every 6 seconds. By using loop(), which is called regularly (and exits quickly if there is nothing to process), we can handle incoming bytes in approximately real-time.
The pre-existing code has a 15 second timeout if a message is incomplete. If a partial message is received, and many seconds later, a full 13-byte message is received, the pre-existing code will incorrectly drop the message because the first half of the full message will be considered the end of the partial message. The move to the real-time loop() and dropping the timeout to 150 milliseconds allows the code to quickly drop partial messages, allowing later full messages to be properly handled. (It takes 96 milliseconds for a byte to be received.)
Using loop() also allows outgoing messages to be sent right away, rather than waiting for the 6 second update() cycle. This rearchitecture of sending outgoing messages eliminates the tight loop of up to 500 milliseconds waiting for the data line to become available, which was previously blocking general ESP32 operation, and causing warnings to be logged.
This PR also includes improvements to protect against corrupted messages:
There are also a few miscellaneous changes:
This PR consists of several commits, and it may be worth reviewing the commits one by one, rather than the entire diff as a whole. I've tried to keep each commit reasonably self-contained, although there are a few things where it's not as clean as it could be.