Skip to content

feat(dishwasher): Add LG Dishwasher (H11) support - #139

Open
asata wants to merge 4 commits into
anszom:masterfrom
asata:feat/lg-dishwasher-h11
Open

feat(dishwasher): Add LG Dishwasher (H11) support#139
asata wants to merge 4 commits into
anszom:masterfrom
asata:feat/lg-dishwasher-h11

Conversation

@asata

@asata asata commented Aug 15, 2026

Copy link
Copy Markdown

This PR adds support for the LG Dishwasher to the local AABB packet parser.

  • Actual Model Name: DUE2BG.AKOR
  • LG ThinQ / Rethink Internal Model ID: H11

It includes read-only sensors for monitoring the dishwasher's state and full remote control capabilities reverse-engineered from the ThinQ app, including comprehensive auxiliary settings.

Features Added

  • State Monitoring: state, course, remain_time
  • Basic Control: Power switch, Pause button, Resume button, Cancel / Drain Stop button
  • Remote Start Options:
    • Allows selecting Target Course (Auto, 1 Hour, Normal, Download Cycle, etc.)
    • Delay Start Hour (1~12 hours)
    • Washing Options: High Temp (0x08), Extra Dry (0x04), Extra Rinse (1~3 levels)
    • start_course button dynamically constructs the f0 26 10 control payload based on the selected virtual entities.
  • Comprehensive Settings Control:
    • Added 7 entities for configuring auxiliary device settings directly from HA: salt_level, rinse_level, buzzer_level, end_alarm_sound, clean_reminder, auto_dry, and brightness.
    • Added remote_start_mode (Permanent, One-Time, Off) to configure the machine's behavior after cycles.

🔍 Complete Packet Analysis & Protocol Structure (For Reviewers)

During the development of this parser, we successfully decoded the complete structure of the AABB local protocol for both status reporting and appliance control. Here is the full breakdown of the protocol for the H11 Dishwasher:

1. Status Payload (32 ec -> 00 18 Tag Block)

The machine reports its current state using 32 ec packets. The second half of the payload contains a 00 18 tag block followed by 24 bytes of data. Key offsets (starting at 0):

  • [0] (State): 01 (INITIAL), 02 (RUNNING), 03 (PAUSE), 04 (STANDBY)
  • [3] & [4] (Initial Time): Initial Course Time (Hour, Minute)
  • [5] (Course): Base Course Code (e.g., 01: Auto, 12: 1 Hour, 0b: Download Cycle)
  • [7] & [8] (Remain Time): Remaining Time (Hour, Minute)
  • [9] (Delay Start): Delay start time in hours (0 means disabled)
  • [11] (Opt1 & Door): 0x40 (Clean Reminder LED ON), 0x10 (Auto Dry ON), 0x02 (Door Open)
  • [12] (Wash Options): 0x04 (Extra Dry ON), 0x08 (High Temp ON)
  • [13] (Rinse Level): Rinse dispenser level (0x00 ~ 0x04)
  • [14] (Salt Level): Salt dispenser level (0x00 ~ 0x04)
  • [15] (Buzzer & Btn): 0x80 (Buzzer HIGH), 0x40 (Buzzer LOW), 0x00 (Buzzer OFF). (Note: 0x02 represents the physical Remote Start button state)
  • [16] (Opt2): 0x80 (Remote Control: PERMANENT), 0x40 (ONE-TIME), 0xc0 (OFF). 0x04 (End Alarm Sound ON)
  • [19] (Opt3): 0x40 (Display Brightness HIGH)
  • [20] (Smart Course): Specific Downloaded Course ID (e.g., 0x0f: Plastic, 0x0d: Tub Clean)
  • [21] (Extra Rinse): 00 (0), 10 (1 level), 20 (2 levels), 30 (3 levels)

2. Control Commands (f0 26)

Unlike washing machines (32 0a), the dishwasher uses f0 26 packets for control.

  • Power On / Wake Up: f0 26 16
  • Power Off (Immediate): f0 26 12
  • Pause / Resume: f0 26 13 / f0 26 14
  • Cancel Course & Drain: f0 26 11 (Pumps for 1 min, then powers off)
  • Start Course: f0 26 10 [Course] [DelayHour] [Opt2=0x00] [Opt3] [Opt4] [Opt5=0x00]
    • [Opt3] (Wash Options): 0x08 (High Temp), 0x04 (Extra Dry). Both = 0x0c.
    • [Opt4] (Rinse Levels): 0x08 (1), 0x10 (2), 0x18 (3). (Note: The 0x40 flag must be added if the course is 0b Download Cycle)
  • Settings Control: f0 26 [Rinse] [Salt] [Opt1] [Opt2] [Opt3] 00 00 00 00
    • Overwrites all auxiliary settings at once. Our implementation caches existing user preferences and applies bitwise operations to update only the requested setting without altering others.

3. Note on "Downloaded Courses"

Changing the specific "Downloaded Course" assignment (e.g., changing from Tub Clean to Pots & Pans) cannot be executed via the local network. When changed via the app, the machine downloads the cycle algorithm payload directly from LG Cloud (HTTPS/MQTT). We can monitor the active course ID by reading byte [20], but we cannot push a new assignment locally.

asata added 3 commits August 15, 2026 18:30
- Add local AABB parser for LG Dishwasher (H11)
- Map dishwasher states, courses, and options to Home Assistant sensors
- Support power control commands (Wake Up / Power Off)
- Exclude fake local energy/cycle count data (LG Cloud only)
- Register H11 in ha_bridge
- Add Pause, Resume, Cancel/Drain Stop commands
- Add remote start parameters (Course, Delay, High Temp, Extra Dry, Extra Rinse)
- Add start course button that dynamically builds f0 26 10 packet
* Add 7 new entities to control auxiliary settings (salt, rinse, buzzer, clean reminder, auto dry, brightness, remote start mode).
* Update status payload (`00 18` block) parsing logic to map setting flags from bytes `[11]`, `[13]`, `[14]`, `[15]`, `[16]`, and `[19]`.
* Implement `sendSettings` logic to safely overwrite a single setting by caching previous states and using bitwise operations for the `f0 26` control packet.
* Convert `rinse_level` from a read-only sensor to a configurable number entity.
@asata asata changed the title feat(dishwasher): Add LG Dishwasher (H11) support with full remote control feat(dishwasher): Add LG Dishwasher (H11) support Aug 16, 2026
- Add support for parsing the `323e` energy statistics packet.
- Extract the 2-byte accumulated energy consumption value (Wh).
- Implement sequence-based deduplication logic to ignore redundant burst packets.
- Expose the `energy_consumption` sensor via MQTT Discovery (`state_class: total_increasing`).
@anszom

anszom commented Aug 20, 2026

Copy link
Copy Markdown
Owner

Thank you for the PR. I've just returned from vacation and I'm slowly working through the PR & issue backlog. I'd appreciate your patience :)

jmhufford pushed a commit to jmhufford/rethink that referenced this pull request Aug 21, 2026
Deployed to a real instance and read the service log back. The handler binds
(no more "thinq2 device type N17 unknown"), publishes its discovery config, and
decodes energy_consumption 0 -> 2 Wh from real frames. Three things I wrote from
the bench capture were wrong, and one open question is answered.

Wrong: 0x3E is not wash-only and 0x0A does not stop during a wash. Both types
interleave in the same burst with the appliance idle at 2 Wh. The appliance does
not stream continuously at all — it goes quiet for minutes, then bursts for
about a minute (0x0A every 1-5s, 0x3E every 4-6s).

Wrong: the 0x0A length byte is not a length. It reads 0xFF while the frame is
87 or 88 bytes, and 0x0A is the only type here that fails this repo's AABB
checksum — 0x31, 0x72 and 0x3E all pass. Neither matters, because AABBDevice
keys off the 0xAA/0xBB delimiters, but it explains the checksum failures seen
earlier and it means the length byte cannot be trusted for this type.

Answered: the statistics layout. The bench capture only ever saw all-zero
payloads, so nothing distinguished delta from accumulated. A live change gives
32 3E 0002 0002 01 against 32 3E 0000 0000 00 — consistent with PR anszom#139's
"delta, accumulated, sequence", and the sequence byte moved with the value and
then held across six identical frames, so on this appliance it behaves as a
change counter rather than the burst counter PR anszom#139 describes.

0x32 0xEC still never appears — zero occurrences across the whole deployment
log, corroborating the bench capture on independent firmware. So state, course,
remaining time and door remain unpublished and start() still sends nothing.

Test fixtures now use real captured frames for 0x0A, 0x31, 0x72 and both
statistics readings; the synthetic 0x72 stand-in is gone. The only synthetic
fixtures left are the 0xEC ones, which have nothing real to draw on, and the
sequence-wrap case, which is labelled as not-yet-observed behaviour.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants