Skip to content

WIN_056905_WW: validate LW1022FVSM through unified RAC - #89

Draft
gonkey42 wants to merge 5 commits into
anszom:masterfrom
gonkey42:codex/lw1022fvsm-rac-live-validated
Draft

WIN_056905_WW: validate LW1022FVSM through unified RAC#89
gonkey42 wants to merge 5 commits into
anszom:masterfrom
gonkey42:codex/lw1022fvsm-rac-live-validated

Conversation

@gonkey42

@gonkey42 gonkey42 commented Jul 6, 2026

Copy link
Copy Markdown

Summary

This draft follows the unified RAC direction from #73. It uses sanitized LW1022FVSM / WIN_056905_WW fixtures as regression coverage and only changes the shared RAC path for fixture-proven gaps. I also live-tested the patched RAC path locally against an installed LG LW1022FVSM reporting ThinQ model id WIN_056905_WW, then restored my local runtime.

  • Route WIN_056905_WW through RAC_056905_WW.
  • Add sanitized LW1022FVSM fixture coverage against the unified RAC implementation.
  • Teach RAC the fixture-proven LW1022FVSM / observed WIN_056905_WW differences: capability-derived modes/fan modes/temperature limits, raw fan values 2/4/6, raw mode 8 Energy Saver, power-off behavior, the tested off-to-fan-only write path, and manual whole-hour timer controls/readback with protocol-minute writes.
  • Replay the initial raw TLV state after RAC builds dynamic discovery config so the first values response publishes Home Assistant state.

Evidence Level

Fixture coverage plus live validation against an installed LG LW1022FVSM / WIN_056905_WW through rethink, MQTT, and Home Assistant.

Validation

  • node --import tsx --test --test-reporter=spec tests/cloud/devices/RAC_056905_WW.LW1022FVSM.test.ts
  • node --import tsx --test --test-reporter=spec tests/cloud/devices/RAC_056905_WW.test.ts tests/cloud/devices/RAC_056905_WW.LW1022FVSM.test.ts
  • npm run test
  • npm run build
  • npm exec -- prettier . --check --ignore-path .gitignore
  • git diff --check
  • Live validation against LG LW1022FVSM / WIN_056905_WW through local rethink runtime, MQTT, and Home Assistant

Result: LW1022FVSM RAC fixture test passed 18/18, RAC plus LW1022FVSM fixture tests passed 24/24, full suite passed 248/248, build passed, formatting passed, and diff whitespace check passed.

Live result: discovery, modes (dry, fan_only, cool, off), fan speeds (low, medium, high), target temperature, Energy Saver, Sleep Timer, Turn-off Timer, Turn-on Timer, focused 0x1f7 A/B behavior, and rollback were tested through the live path. Manual-backed timer behavior is Sleep 1h to 12h, Turn-off 1h to 24h while running, and Turn-on 1h to 24h while off. Turn-on Timer is accepted/read back when the unit is off; the unit ignores that command while already running.

Focused 0x1f7 A/B result: already-on Energy Saver mode writes worked with or without 0x1f7=1; the tested off-to-fan-only mode write required 0x1f7=1 to power the unit on.

Notes

  • The unit under validation is LG LW1022FVSM with ThinQ model id WIN_056905_WW.
  • The sanitized fixture expects modes off, cool, dry, and fan_only; fan modes low, medium, and high; no heat or swing fields for the observed capability packet; Energy Saver represented by raw mode 8; and Sleep / Turn-on / Turn-off timers exposed as whole-hour controls matching the owner's manual.
  • Turn-on Timer was live-validated as a turn-on timer: when the unit was off, a 1h command was accepted, published back as starttimer- 1, and the physical unit showed the timer; clearing it published starttimer- 0.

Technickly90 and others added 3 commits June 14, 2026 12:01
Implements full HA climate integration for the WIN_056905_WW family of
LG window air conditioners, confirmed working on:
- LG LW6023IVSM (6,000 BTU)
- LG LW1522IVSM (14,000 BTU)

Protocol findings (via live packet capture):
- Frame discriminator: buf[6]=0xa7 (vs 0x87 on RAC/POT units)
- Tag 0x1f7: power (0=off, 1=on)
- Tag 0x1f9: mode (0=cool, 1=dry, 2=fan_only, 8=eco/Energy Saver)
- Tag 0x1fa: fan speed (2=low, 4=medium, 6=high)
- Tag 0x1fd: current temperature (raw/2 = °C)
- Tag 0x1fe: set temperature (raw/2 = °C, clamped 16–30°C)
- Tag 0x21a: sleep timer (raw value in minutes)

Features implemented:
- HVAC modes: off, cool, dry, fan_only
- Fan modes: low, medium, high
- Eco/Energy Saver mode via HA preset_mode (maps to mode wire value 8)
- Sleep timer as a number entity (0-7 hours, slider)
- Current and target temperature

Notes:
- Eco mode (mode=8) is exposed as a climate preset rather than an
  hvac_mode, since HA only accepts standard hvac_mode values
- Off is handled by writing tag 0x1f7 (power) rather than mode
- Sleep timer write_xform converts hours to minutes for the wire value
- tlv_device.ts: accept 0xa7 as a valid frame kind alongside 0x87

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

Copy link
Copy Markdown
Collaborator

That's a significant change to RAC_056905_WW.ts - let me have a look at this when I have a bit of spare time - probably on weekend.

@anszom

anszom commented Jul 6, 2026

Copy link
Copy Markdown
Owner

@gonkey42 it seems you got several steps ahead of me. My intention was to first gather information on the differences between the two models. From what I can tell from your code, the differences are quite extensive:

  • energy saver mode
  • sleep timer
  • climate modes
  • fan modes
  • swing modes
  • 0x1f7 power mode handling

Perhaps @maciejsszmigiero will be able to identify if these differences could be mapped down to the capability bits. Then we can decide if making a unified implementation actualy makes sense.

@gonkey42
gonkey42 force-pushed the codex/lw1022fvsm-rac-live-validated branch from 72282f8 to 8fa9de4 Compare July 6, 2026 23:15
@gonkey42

gonkey42 commented Jul 7, 2026

Copy link
Copy Markdown
Author

Yeah, I got ahead of the information-gathering step here...

I cleaned up the draft, and then again after I decided to do some more after doing more testing on the 0x1f7 stuff, and then the screen on/off and self-cleaning functions mentioned in the manual. So, now it is focused on evidence from my LW1022FVSM / WIN_056905_WW only.

Here’s what I can say from my actual LW1022FVSM / WIN_056905_WW unit:

  • Energy Saver is present. The manual shows it in the mode cycle, and the TLV state I captured reports it as raw mode 8. I mapped it separately in HA because HA does not really have an Energy Saver HVAC mode.

  • Sleep Timer is present. The manual says Sleep Mode is 1 to 12 hours. I tested setting, reading back, and clearing the timer while the unit was running. I did not test the sleep-mode side effects like temperature changes or fan/noise behavior.

  • Delay ON and Delay OFF are state-dependent. The manual says Delay ON is for when the unit is off, and Delay OFF is for when it is on, both 1 to 24 hours. That matched live testing: ON worked while off and was ignored while already running; OFF worked while running and was ignored while off.

  • Modes on this unit are Energy Saver / Cool / Fan / Dry from the manual/control panel. Through HA/MQTT/rethink I observed cool, dry, fan_only, and off, with Energy Saver represented separately in HA from raw mode 8.

  • Fan speeds are Low / Medium / High. In the captured TLV values I saw those as raw fan values 2, 4, and 6.

  • 0x1f7: I did a focused live A/B test on my LW1022FVSM. While the unit was already on, an Energy Saver mode write worked both with and without 0x1f7=1. From off, a fan-only mode write without 0x1f7 left the unit off; the same write with 0x1f7=1 powered it on to fan-only. So for my unit, 0x1f7=1 is required for the tested off-to-on mode write, but not for the tested already-on mode write. I still would not claim from one unit that this is capability-derived or cross-model behavior.

  • The manual also documents Light Off and Auto Clean. I tested those locally too, but I did not observe a stable ThinQ/rethink TLV state change for either one. Light Off works physically from the remote/panel, while Auto Clean appeared only as a remote icon in my test.

I'm fine treating PR #89 as a draft evidence branch / possible implementation while you decide how you want to map this down to capability bits, just happy to help! :)

@gonkey42

gonkey42 commented Jul 7, 2026

Copy link
Copy Markdown
Author

I also found some more sensor data exposed by my LW1022FVSM. I added a small fork-only mapper in my fork so I can experiment with my own setup without adding churn to upstream. I’m only exposing room/indoor temperature, outdoor-side air temperature, and estimated power draw right now, but there are other diagnostic values visible too. Let me know if you want me to post captures, field IDs, or more details here.

@gonkey42

gonkey42 commented Jul 8, 2026

Copy link
Copy Markdown
Author

I just did testing for a few hours and dug a lot further into the data from my LW1022FVSM after getting it working locally.

I put a small fork-only mapper in my fork so I can experiment with my own setup without adding churn here. I’m only exposing three normal Home Assistant sensors right now, because those are the ones I actually want on dashboards/automations:

  • 0x1fd - room/current temperature, decoded as raw / 2 C
  • 0x332 - ODU/outdoor-side air temperature, decoded through the RAC air temp table; I would not call this a weather outdoor temp, more like the AC’s outdoor-side/condenser-side air reading
  • 0x2b3 - estimated instantaneous power draw, using the existing RAC-style max(5, raw - 60) W formula; definitely an estimate, not revenue-grade energy data

I also did some live testing with mode changes, fan speed, setpoint changes, Energy Saver, and real Dry mode. A few more TLVs are pretty clear now:

  • 0x228 - compressor/load-stage scalar. It is 0 when the compressor/load is stopped, ramps during startup, and sits around 21..24 under active cooling/dry load. I do not know the unit.
  • 0x229 - humidity. It looks offset/scaled compared with a portable hygrometer, so it needs calibration if you want exact room RH, but it moved downward during a real Dry-mode run while the external hygrometer also dropped.
  • 0x232 + 0x233 - big-endian active-cooling/load-work accumulator, so (0x232 << 8) + 0x233. It rises while compressor/load is active, freezes when load stops, and resumes when load restarts. I do not know the unit or reset behavior yet.
  • 0x32b - likely indoor coil / evaporator temperature, using the RAC pipe-temp style transform. It cools quickly when cooling/dry load starts and warms when load stops.
  • 0x303 - always 0 in the states I tested; probably reserved/unused.
  • 0x356 - always 250 in the states I tested; probably fixed/reserved/sentinel.

The only changing TLV from my original mystery list that I still would not name is:

  • 0x355 - I saw it move 41 -> 40 -> 39, but I still do not know what it means.

Mode mapping also got clearer on this unit:

  • 0x1f9=0 - Cool
  • 0x1f9=1 - Dry
  • 0x1f9=2 - Fan-only
  • 0x1f9=8 - Energy Saver

One Home Assistant detail that confused me at first: both Energy Saver and true Dry can show hvac_action=drying in the middle of the HA climate tile, but the actual HA mode differs. Energy Saver shows mode cool with action drying; true Dry shows mode dry with action drying.

Some other RAC-ish fields that line up with the existing path / captures:

  • 0x221 - error code
  • 0x32e - nominal capacity; looks like raw kBTU/h, converted to kW with roughly raw * 0.293
  • 0x330 - EEV opening
  • 0x32c - ODU HEX / outdoor coil temperature, through the RAC pipe temp table
  • 0x22a / 0x32f - compressor Hz-ish/load values; on this unit they seem to cap around 15
  • 0x225 - auto dry remaining
  • 0x323 - jet mode
  • 0x21a, 0x21b, 0x21c - sleep / off / on timers
  • 0x321, 0x322 - vertical / horizontal swing positions, where supported by capability bits

In my fork I intentionally only expose the three useful normal sensors and suppress the rest so my HA install does not fill up with diagnostics. But if any of this is useful upstream, I can post raw captures / example values / decoded notes here.

The fork branch I’m playing with is gonkey42/rethink:hal/release-lw1022fvsm.

-Peace


/**
* LG Air Conditioner Model LW1823HRSM
* LG Window Air Conditioner (e.g. LW6023IVSM, LW1522IVSM)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why this file is still here and even getting patched if this PR was to support WIN_056905_WW via RAC_056905_WW.ts?

@maciejsszmigiero maciejsszmigiero left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I did a quick glance at these changes, left a few comments.
It looks like supporting these units through RAC_056905_WW may have some sense indeed.

These new capability bits still need cross-checking however.
@gonkey42 do you have the model JSON file from ThinQ API for your unit?

Some other RAC-ish fields that line up with the existing path / captures:

I don't quite understand that sentence - does it mean that these tags also contain values values for Win units? Do they have EEVs instead of fixed metering and export ODU temperatures?

readable: false,
write_xform: (val) => (val === 'ON' ? 1 : 0),
/* 0x1f7 is not necessary for ON but does not seem to hurt either */
/* Direct power ON uses the generic RAC attach behavior; WIN-family mode writes add 0x1f7 separately. */

@maciejsszmigiero maciejsszmigiero Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This comment should not get overwritten.

'sleeptimer',
'Sleep timer',
'mdi:bed-clock',
this.isWinFamily() ? 12 : 15,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What happens on Win family if sleep time is programmed to 15 hours?

}

addTimerField(config: DeviceDiscovery, id: number, name: string, desc: string, icon: string, max: number) {
const step = this.isWinFamily() ? 1 : 0.25

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What happens on Win family if timers are programmed in 15 minute steps?

fan_modes: ['auto', 'very low', 'low', 'medium', 'high', 'very high'],
/* TODO: get allowed op modes from 0x2c1 */
} satisfies ClimateComponent,
min_temp: this.raw_clip_state[0x2e1] != null ? this.raw_clip_state[0x2e1] / 2 : 18,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

That's definitely not a complete support for these temperature tags so the TODO comment should stay.

config['components']['energysaver'] = allowExtendedType({
platform: 'switch',
unique_id: '$deviceid-energysaver',
name: 'Energy Saver',

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It might make more sense to export this as eco preset mode for the HA climate component instead of dedicated switch.

write_xform: (val) => {
const modes2clip: Record<string, number> = { cool: 0, dry: 1, fan_only: 2, heat: 4, auto: 6 }
if (val === 'off') {
if (this.isWinFamily()) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why just using the existing RAC code for turning the power off is not enough for Win family?

this.setProperty('climate-power', 'OFF')
return null
}
if (this.isWinFamily()) this.raw_clip_state[0x1f7] = 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Isn't attaching both temperature and fan speed to mode setting enough to power on this unit like on RAC? Note that it may need them sent in different order than RAC (the tag order sometimes matters here).

}

this.setConfig(config)
this.publishKnownState()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why this is necessary? RAC will send the current values response multiple times on query so if the initial response sets config the next ones will publish these values.

@variousred

Copy link
Copy Markdown

Independent validation and a new WIN_056905_WW variant: LG LW1224IVSM.

I tested an installed LW1224IVSM end-to-end against a fully local rethink deployment (stock Wi-Fi module, no LG app/account/cloud): appliance provisioning, MQTT discovery, telemetry, physical-control readback, and commands from Home Assistant. Identifying household data has been removed from the details below.

Device details:

  • Product model: LW1224IVSM
  • ThinQ model ID: WIN_056905_WW
  • Device type: 401
  • Appliance software: 487100
  • Wi-Fi module: clip_ble_v1.9.225 / RTK_RTL8720cm
  • Device-to-cloud TLV frames use marker byte 0xA7

The 0xA7 compatibility in this PR is required. With the current master WIN_056905_WW parser, the capability retry loop never ends; accepting 0xA7 immediately yields the capability response and initial values.

Decoded capability differences versus the LW1022FVSM fixture in this PR include:

tag     LW1224IVSM   LW1022 fixture
0x2c4   67 (0x43)    3 (0x03)
0x2d3   16390        20502
0x2f5   16391        7

The most important newly observed difference is the room-temperature scale:

  • 0x1fd=210 and 212 tracked an independently measured room temperature of about 71.4 F (21.9 C). On this unit these decode plausibly as 21.0 C and 21.2 C, i.e. raw / 10. raw / 2 produces impossible 105-106 C readings.
  • 0x1fe still uses half-degrees: raw 40 matched a panel setpoint of 68 F (20 C), and raw 37 matched about 65 F (18.5 C).
  • The capability difference 0x2c4: 0x03 -> 0x43 makes bit 0x40 a plausible discriminator for high-resolution current temperature, but this needs confirmation from another model/capture before treating it as proven.

Observed control mapping agrees with this PR:

0x1f9=0  Cool
0x1f9=8  Energy Saver (HA: cool + eco)
0x1fa=6  High fan

One synchronization detail: temperature changes were pushed asynchronously, but a physical panel/remote change from Energy Saver / 68 F to Cool / about 65 F was not accompanied by mode/setpoint TLVs. A full values query (01010400000065020201027D425A6E) returned the new state immediately. The base 15-minute refresh can therefore leave HA stale after physical controls. Matching the unified RAC driver's active 28 s refresh cadence kept state synchronized; I verified multiple scheduled refreshes and readbacks live.

Sanitized capability response from the LW1224IVSM:

000004000000A702013367B009B0600107B09054D400B0C1B11043B300B340B4E04006B55060B6A003F6B6F0487100B85020B8903CB8D020B9103CBC600201BD30080000B5A08000D3C0DD04BD604007FB0F64406480FA01B5C0B61020B646B5C1B600B646B5C2B600B646B5C8B61028B6461BF6

Sanitized values response while in Energy Saver / 68 F / High:

000004000000A7020436557E487DC17E867F50D47F90288180C8C083408380868086C0870088407C8089408A10228A50608A8F8C905C8CD026ACE00311D550E4D590FA87C0E800CAD055CB10ABCB8CCBCFCC00CC908C1B01C0C0A040FA80EE4076F4

Sanitized queried values response after changing the physical controls to Cool / about 65 F / High:

000004000000A7020470567E407DC17E867F50D27F90258180C8C083408380868086C0870088407C8089408A10218A505E8A8F8CA0015F8CD055ACE0030FD550E4D590FA87C0E800CAD053CB10A8CB8CCBCFCC00CC90881B01C0C0A040FA80EE40DF47

The Wi-Fi indicator on the appliance remained dark despite a stable local TLS/MQTT connection, strong RSSI, continuous telemetry, and successful commands. This appears cosmetic and may reflect LG-app/cloud registration state rather than actual Wi-Fi association.

Happy to provide additional controlled captures or test a proposed capability-based temperature transform on the live unit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants