Skip to content

Add ThinQ2 device handler for LG WT7300CW washer (T1789EFH_F)#77

Open
brystmar wants to merge 2 commits into
anszom:masterfrom
brystmar:feature/washer-T1789EFH_F
Open

Add ThinQ2 device handler for LG WT7300CW washer (T1789EFH_F)#77
brystmar wants to merge 2 commits into
anszom:masterfrom
brystmar:feature/washer-T1789EFH_F

Conversation

@brystmar

@brystmar brystmar commented Jun 22, 2026

Copy link
Copy Markdown

Adds support for the LG WT7300CW top-load washer (internal model T1789EFH_F, deviceType 201, ThinQ2/LCW-007 Wi-Fi module).

What this adds

A new device handler that parses the AA/BB-framed status packets (0xEC dual-record and 0xEB single-record) to expose the following Home Assistant sensors:

Sensor Type Notes
Phase sensor (enum) Off, Fill/Sense, Paused, Wash (initial), Wash (main), Rinse/Drain, Spin
Remaining minutes sensor (duration) Byte 3 of current record
Remaining seconds sensor (duration) Byte 4 of current record
Power binary_sensor Derived: on when phase ≠ 0
Start time sensor (timestamp) Derived: recorded when phase transitions from 0
Stop time sensor (timestamp) Derived: recorded when phase transitions back to 0

Bug Fix

This PR also fixes a bug in the original byte offsets: remaining_time_min was reading rec[3], which is always 0x00 in practice. I believe the actual minutes field is rec[4], confirmed by cross-referencing real captures against the ThinQ app. The running/paused bracketing sequence shows rec[4]=43 frozen across all three packets, and the heavy-duty capture's rec[4]=24 matches the corroborating 0xE2 packet's "~24 min remaining" reading.

Notes

  • The 0xEC packet carries two back-to-back 27-byte records (current + previous); only the current (first) record is used.
  • This washer's Wi-Fi module reboots itself at end-of-cycle (ECONNRESET → POWER_ON reconnect) — this is normal device behavior, not a network issue.
  • A companion PR for the LG DLE7300WE dryer (RV13U6AM8W_D_US_WIFI) will follow once additional cycle data is captured.
  • This is my first PR to a community project, so please be kind :)

@anszom anszom left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Please see the attached review comments.

I would also ask you to add a unit test containing some data packets captured from your device for validation. See other devices' implementations for reference.

)
}

private processRecord(rec: Buffer) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the remaining bytes? Take a look at other washers' implementations - I expect that many fields would carry over.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a PM by trade, so I decided to cut scope and get an MVP in place to validate the approach first. Plan was to fill in the other elements as I do more laundry cycles at home. Does that work for you, or do I need to decipher all the bytes first?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that sounds reasonable.

Comment thread cloud/devices/T1789EFH_F.ts Outdated
Comment on lines +87 to +94
if (this.lastPhase === 0 && phase !== 0) {
this.startTime = new Date().toISOString()
this.publishProperty('start_time', this.startTime)
} else if (this.lastPhase !== 0 && phase === 0) {
this.stopTime = new Date().toISOString()
this.publishProperty('stop_time', this.stopTime)
}
this.lastPhase = phase

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really convinced that rethink should be doing this kind of processing. We are exposing raw data to HomeAssistant, and the user can do any processing they like on that side.

Also, If we wanted to do any post-processing, it should be implemented uniformly for all washers (and maybe other devices).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, fixed in eab7a67.

Comment thread cloud/devices/T1789EFH_F.ts Outdated
Comment on lines +47 to +62
remaining_time_min: {
platform: 'sensor',
unique_id: '$deviceid-remaining_time_min',
state_topic: '$this/remaining_time_min',
name: 'Remaining minutes',
device_class: 'duration',
unit_of_measurement: 'min',
},
remaining_time_sec: {
platform: 'sensor',
unique_id: '$deviceid-remaining_time_sec',
state_topic: '$this/remaining_time_sec',
name: 'Remaining seconds',
device_class: 'duration',
unit_of_measurement: 's',
},

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a single remaining_time field.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated as requested in eab7a67.

…s, add tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@brystmar brystmar left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the start/stop sensors, consolidated remaining_time fields, and added tests for LG WT7300CW (T1789EFH_F).

Removed the start_time and stop_time sensors along with the lastPhase tracking logic. These were derived from phase transitions rather than device-reported values, making them unreliable across reconnects.

Replaced remaining_time_min and remaining_time_sec with a single remaining_time field (minutes, device_class: duration), consistent with other device implementations.

I also fixed what appeared to be a bug in the original byte offsets: remaining_time_min was reading rec[3], which is always 0x00 in practice. The actual minutes field is rec[4]. I confirmed this by cross-referencing real captures against the ThinQ app: the running/paused bracketing sequence shows rec[4]=43 frozen across all three packets, and the heavy-duty capture's rec[4]=24 matches the corroborating 0xE2 packet's "~24 min remaining" reading.

Added 16 unit tests covering synthetic packets (Off, Wash main, unknown phase fallback) and 8 real validated captures from a live LG WT7300CW, including the full running > paused > resumed sequence confirming that remaining_time stays frozen during a pause. Also confirms that 0xE2 settings-echo, 0xD8 idle/ack, and 0x31 identity packets are silently ignored without errors.

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