Skip to content

Commit bec4d4f

Browse files
authored
Merge pull request #37 from AndrewDemsDS/docs/re-attribute-table
docs(re): record the cloud attribute table, load base, and the fault namespace
2 parents b7273de + 0ce7900 commit bec4d4f

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

reverse-engineering/docs/10-stock-fw-init-and-comms.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,3 +476,106 @@ and the full loop closes end-to-end — commissioned onto the Matter fabric, `Lo
476476
Standalone setpoint writes (`OccupiedCooling/HeatingSetpoint`) return IM `0x86` (a cluster
477477
deadband/limit constraint); the setpoint also rides the mode `0x65` at byte19. Build-by-build
478478
v3→v4→v5 debugging detail is in git history.
479+
480+
## 7. Cloud attribute table (`t_*` / `f_*` / `f_e_*`) [PROVEN location, 2026-07-19]
481+
482+
The module carries the full Hisense **cloud attribute** namespace as a name blob plus a
483+
lookup table. This is the vocabulary the ConnectLife app speaks, and it is the source of the
484+
app's "Self diagnostics" screen. Found by string+pointer analysis of `dumps/w41h1_dump1.bin`
485+
(local-only, gitignored); no bus tap required.
486+
487+
### 7.1 Load base [PROVEN]
488+
489+
**`base = 0x9b6d0000`**, so `address = 0x9b6d0000 + file_offset`.
490+
491+
Derived by taking every attribute-name string offset, scanning the image for 32-bit LE words
492+
that could be pointers to them, and keeping the base with the most consistent hits:
493+
**77 of 77** names are referenced under this base and no other. Cross-checks against the
494+
addresses already in §5a hold: the `ac_8heat` getter `0x9b6f0ee6` maps to file `0x20ee6`,
495+
inside the code region.
496+
497+
This base was not previously written down. It is what makes any further static RE on this
498+
dump reproducible, so record it before anything else.
499+
500+
### 7.2 Name blob and lookup table [PROVEN]
501+
502+
| item | file offset | address |
503+
|---|---|---|
504+
| attribute-name string blob | `0x13730a` .. `0x137700` | `0x9b80730a` .. |
505+
| attribute lookup table | starts `0x137e34` | `0x9b807e34` |
506+
507+
Table entries are **12 bytes**: `[meta0: u32 LE][meta1: u32 LE][name_ptr: u32 LE]`, where
508+
`name_ptr` points into the blob. Walking the table yields 66 entries before the name-pointer
509+
sanity check fails.
510+
511+
**The `meta0` encoding is NOT yet decoded.** See §7.5 before assuming anything about it.
512+
513+
### 7.3 The fault namespace: what "Self diagnostics" reads [PROVEN names]
514+
515+
27 `f_e_*` (fault/error) attributes exist. The app's four categories are a bucketing of these:
516+
517+
| app category | attributes |
518+
|---|---|
519+
| Sensors | `f_e_intemp` `f_e_incoiltemp` `f_e_outtemp` `f_e_outcoiltemp` `f_e_outgastemp` `f_e_tubetemp` `f_e_inhumidity` `f_e_wetsensor` `f_e_temp` |
520+
| Communications | `f_e_incom` `f_e_inwifi` `f_e_push` |
521+
| Motors | `f_e_infanmotor` `f_e_pump` `f_e_arkgrille` `f_e_upmachine` `f_e_dwmachine` |
522+
| Others | `f_e_ineeprom` `f_e_outeeprom` `f_e_inkeys` `f_e_indisplay` `f_e_inele` `f_e_invzero` `f_e_filterclean` `f_e_waterfull` `f_e_over_cold` `f_e_over_hot` `f_e_dwmachine` |
523+
524+
(The category mapping is inferred from the names, not read out of the firmware. The names
525+
themselves are `[PROVEN]`.)
526+
527+
These are almost certainly bit-packed into the 160-byte status frame we already receive once
528+
per second, which means **no new polling is needed to build a diagnostics feature**, only the
529+
bit map.
530+
531+
### 7.4 Settable attributes worth noting [PROVEN names]
532+
533+
The `t_` prefix marks a settable attribute. Two matter for open issues:
534+
535+
* **`t_8heat`** and **`t_8c_heater_onoff`** both exist. 8 °C frost-guard heat therefore **is**
536+
commandable by the stock module. An earlier note in this session claimed no command verb
537+
existed for it; that was wrong, and the absence of an 8 °C control in the ConnectLife app is
538+
a UI choice, not a protocol limit.
539+
* `t_dimmer` exists alongside the display on/off control, which is the likely path to the
540+
panel-brightness *level* (the 2-bit `ac_power_display`), currently out of scope.
541+
542+
The table also names capabilities this unit probably does not implement: `t_fresh_air`,
543+
`f_co2_value`, `f_co2_level`, `t_onekey_selfclean`, `t_indoor_selfclean`,
544+
`t_outdoor_selfclean`, `t_hp_lock_onoff`, `t_ht_lock_onoff`, `t_heat_control_logic`,
545+
`t_interlock_onoff`, `t_demand_response`. Per the design rule in `docs/11 §5.1`, gate on the
546+
capability flags at runtime rather than deleting these paths.
547+
548+
### 7.5 What is NOT established, and the trap in it
549+
550+
`meta0` is **not** a plain (byte, bit) frame position. The tempting read is that byte 2 is an
551+
offset and byte 3 a bit index, because the fault entries look orderly:
552+
553+
```
554+
f_e_incoiltemp 00 00 18 0f f_e_inkeys 00 00 19 0f
555+
f_e_inhumidity 00 00 18 0e f_e_inwifi 00 00 19 0e
556+
f_e_infanmotor 00 00 18 0d f_e_inele 00 00 19 0d
557+
```
558+
559+
Three things block that reading:
560+
561+
1. **Duplicates.** `f_e_arkgrille` and `f_e_dwmachine` are both `00 00 18 0b`;
562+
`f_e_invzero` and `f_e_over_cold` are both `00 00 18 0a`. Two faults cannot share one bit.
563+
2. **Non-uniform layout.** Entries such as `t_temp` (`03 03 03 0b`) and `t_fan_speed`
564+
(`08 01 0b 09`) use bytes 0 and 1, which every `f_e_*` entry leaves zero. So `meta0` is at
565+
least two different shapes, probably keyed by type.
566+
3. **Anchor conflict.** `t_eco` is `00 00 8c 80` while `t_super` (turbo) is `14 05 15 0a`, yet
567+
eco and turbo are known to be **adjacent bits in status byte 35**. A position encoding that
568+
puts them far apart is refuted by hardware we already trust.
569+
570+
The duplicates most likely mean the walk crossed into a **second capability template**
571+
(`docs/11` documents multiple templates in flash), so the table bounds are themselves
572+
unconfirmed.
573+
574+
### 7.6 Next step
575+
576+
Extend the §5a method to the fault attributes: disassemble the getters and read the
577+
`(status byte, bitmask)` pairs out of the code, exactly as was done for the `ac_*` capability
578+
flags. §5a already gives the pattern and the neighbouring addresses
579+
(`0x9b6f0d0a`, `0x9b6f0ee6`), and §7.1 now gives the base needed to navigate there.
580+
581+
Do **not** infer fault bit positions from `meta0` alone until §7.5 is resolved.

0 commit comments

Comments
 (0)