Repository navigation
fix(levoit): Core 200S display and panel reset across MCU firmware versions - #83
Merged
Merged
Conversation
…rsions Byte-level data from issue #60 on a Core 200S Plus (lap-c201s-musw, MCU 4.0.34) does not match what my captures showed on MCU 2.0.11. The version bytes decode to exactly the firmware the reporter names, so the indices line up and the difference is real: display on, 2.0.11 : 0B 00 02 01 00 03 | 64 01 | 00 00 01 00 display on, 4.0.34 : 22 00 04 01 00 03 | 01 64 | 01 00 00 00 display off, both : .. .. .. 01 00 03 | 00 00 | .. .. .. .. Bytes 6 and 7 are a pair - one holds the display brightness, the other a transient flag that goes 0x01 for a few seconds after any command - and the two swap between firmware versions. That also explains why they appeared locked together in my display capture: toggling the display writes the brightness and trips the flag in the same frame, and the capture ended before the flag expired. Reading display from a fixed byte 6 would have reported the display ON for a few seconds after every command on 4.0.34. The decoder now matches on the value 0x64 across both bytes, since that is exactly what 01 05 A1 writes, which handles either layout without sniffing the version. Same class of problem on the panel filter reset: the MCU's push carries payload 0x01 on 2.0.11 and 0x00 on 4.0.34, so my payload check would have missed it on the Plus - which is what the reporter saw, the component acking the message and publishing nothing. Direction alone identifies the event, because our own reset leaves as a 0x22 and the MCU answers 0x12, so any inbound 0x22 of this type is from the unit's button. Keyed on that instead. Also confirms the 0.0%/1.0% filter readings several people hit on 1.5.0: byte 6 on 4.0.34 is the transient flag, so publishing it as a percentage produced exactly 0 or 1. The revert in this branch removes that. The thread independently confirms both CADR fixes too - Current CADR read 125/83/41 m3/h at speeds 3/2/1, which is 167 x speed / 4, so a 3-speed unit was using a 4-speed divisor and speed 1's 41 m3/h truncated to zero per minute. Documented both layouts, the firmware mapping and a symptom-to-cause table in the device README. Compile tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Follow-up to #71 — this commit was pushed minutes after #71 merged, so it did not make it in. It addresses the byte-level data posted in #60 by @Manichee, from a Core 200S Plus on MCU 4.0.34.
Bytes 6 and 7 swap between MCU firmware versions
Their frames do not match what my captures showed on MCU 2.0.11. The version bytes decode to exactly the firmware they report, so the indices line up and the difference is real:
The two bytes are a pair — one holds display brightness, the other a transient flag that goes
0x01for a few seconds after any command — and which is which depends on the firmware.This also resolves a loose end from #71. My
display_on_off.txtshowed both bytes moving together, whilefilter_from_device.txtshowed byte 6 moving alone. Both are explained: toggling the display writes the brightness and trips the flag in the same frame, and the capture ended before the flag expired.#71 as merged would misbehave on 4.0.34 — reading display from a fixed byte 6 reports the display ON for a few seconds after every command. The decoder now matches on the value
0x64across both bytes, which is exactly what01 05 A1writes, so either layout works with no version detection.Same problem in the panel-reset handler
The MCU's push carries payload
0x01on 2.0.11 but0x00on 4.0.34, so the payload check added in #71 would miss it on the Plus — which is what @Manichee observed: the component acks the message and publishes nothing.Direction alone identifies the event: our own reset leaves as a
0x22and the MCU answers with a0x12, so any inbound0x22of this type came from the unit's button. Keyed on that instead.Independent confirmation of the CADR fixes in #71
From the same thread, Current CADR = 125 / 83 / 41 m³/h at speeds 3 / 2 / 1. That is
167 × speed ÷ 4— confirming both the 4-speed divisor on a 3-speed unit, and that speed 1's 41 m³/h truncates to zero when divided by 60. Measured on someone else's hardware.Docs
The device README now carries both layouts with the firmware mapping, plus a symptom-to-cause table covering every report in #60: stuck 100%, the "downward staircase", 0.0%/1.0% readings, Filter Low showing "Problem" on a new filter, panel reset doing nothing in HA, and the red light not clearing.
Testing
All three levoit compile tests pass on top of current main. Not verified on hardware — @Manichee (4.0.34) and @Scags104 (1.1.23) are the right people to confirm, since my own unit is 2.0.11.
🤖 Generated with Claude Code