program-format: document AND-record field layout (firmware >=3.0)
Add a per-byte breakdown of the multi-record AND record format from clsProgram.cs:326-436, with the enuCondOP and enuCondArgType companion enum tables. Note the Arg1_Traditional special case where the Cond u16 carries the condition instead of the structured Arg1_* fields, and flag the open question about disk byte order for Arg1_IX / Arg2_IX / CompConst (Read says LE, accessors say BE; needs a non-symmetric controlled capture to disambiguate).
This commit is contained in:
parent
2300be0f6c
commit
7a766d69ba
@ -363,10 +363,81 @@ table:
|
||||
| `WHEN` (5) | Event trigger | event-id at bytes 9-10 (no swap); cmd/par/pr2 zero |
|
||||
| `AT` (6) | Single-occurrence time trigger | time fields (layout TBD) |
|
||||
| `EVERY` (7) | Recurring time trigger | interval (layout TBD) |
|
||||
| `AND` (8) | One AND-IF condition | structured: `OP` / `Arg1_ArgType` / `Arg1_IX` / `Arg1_Field` / `Arg2_*` / `CompConst` (layout TBD) |
|
||||
| `AND` (8) | One AND-IF condition | structured `OP` / `Arg1` / `Arg2` / `CompConst` — see [AND-record layout](#and-record-layout-firmware-30) |
|
||||
| `OR` (9) | Separator between AND-groups | **no payload** — only the `prog_type` byte is set |
|
||||
| `THEN` (10) | Action | same `cmd` / `par` / `pr2` layout as compact form |
|
||||
|
||||
#### `AND`-record layout (firmware ≥3.0)
|
||||
|
||||
Per the `clsProgram.cs:326-436` accessors, an `AND` record's 14 bytes
|
||||
decompose as:
|
||||
|
||||
| Byte(s) | Field | Type | Notes |
|
||||
|--------:|---|---|---|
|
||||
| 0 | `prog_type` | byte | `= 8` (AND) |
|
||||
| 1 | `OP` | byte | `enuCondOP` — operator (see below) |
|
||||
| 2 | `Arg1_ArgType` | byte | `enuCondArgType` — what Arg1 is (Zone, Unit, …) |
|
||||
| 3-4 | `Arg1_IX` | u16 | Index/number of the Arg1 object |
|
||||
| 5 | `Arg1_Field` | byte | Which sub-field of Arg1 (per-type enum) |
|
||||
| 6 | `Arg2_ArgType` | byte | |
|
||||
| 7-8 | `Arg2_IX` | u16 | |
|
||||
| 9 | `Arg2_Field` | byte | |
|
||||
| 10-11 | `CompConst` | u16 | Constant operand for comparison ops |
|
||||
| 12-13 | (unused, zero) | | |
|
||||
|
||||
`enuCondOP` (byte 1):
|
||||
|
||||
| Value | Name |
|
||||
|------:|---|
|
||||
| 0 | `Arg1_Traditional` |
|
||||
| 1 | `Arg1_EQ_Arg2` |
|
||||
| 2 | `Arg1_NE_Arg2` |
|
||||
| 3 | `Arg1_LT_Arg2` |
|
||||
| 4 | `Arg1_GT_Arg2` |
|
||||
| 5 | `Arg1_Odd` |
|
||||
| 6 | `Arg1_Even` |
|
||||
| 7 | `Arg1_Multiple_Arg2` |
|
||||
| 8 | `Arg1_IN_Arg2` |
|
||||
| 9 | `Arg1_NOT_IN_Arg2` |
|
||||
|
||||
`enuCondArgType` (bytes 2, 6):
|
||||
|
||||
| Value | Name |
|
||||
|------:|---|
|
||||
| 0 | `Constant` |
|
||||
| 1 | `UserSetting` |
|
||||
| 2 | `Zone` |
|
||||
| 3 | `Unit` |
|
||||
| 4 | `Thermostat` |
|
||||
| 5 | `Auxillary` |
|
||||
| 6 | `Area` |
|
||||
| 7 | `TimeDate` |
|
||||
| 8 | `Audio` |
|
||||
| 9 | `AccessControl` |
|
||||
| 10 | `Message` |
|
||||
| 11 | `System` |
|
||||
|
||||
**Important special case:** when `OP == Arg1_Traditional` (= 0), the
|
||||
AND record's condition is rendered from the **`Cond` u16 at bytes
|
||||
1-2** using the same per-family scheme as compact-form `cond` (see
|
||||
[cond/cond2 bit split](#condcond2-bit-split) above) — see
|
||||
`clsText.cs:2281-2284 GetComplexConditionText`. The richer
|
||||
`Arg1_*` / `Arg2_*` / `CompConst` fields above are only used when
|
||||
`OP > 0`. So the same byte positions serve double duty: as `Cond`
|
||||
(traditional) or as `OP` + `Arg1_ArgType` (structured).
|
||||
|
||||
:::caution[Open: disk byte order for `Arg1_IX` / `Arg2_IX` / `CompConst`]
|
||||
The C# `clsProgram.Read` reads u16 fields **little-endian** via
|
||||
`clsPcaCryptFileStream.ReadUInt16`, but the `Arg1_IX` /
|
||||
`Arg2_IX` / `CompConst` accessors index `Data[]` as **big-endian**.
|
||||
This implies an implicit byte swap somewhere we haven't fully traced.
|
||||
Our one captured `AND IF NEVER` record (`08 00 00 00 01 00 00 00 00
|
||||
00 00 00 00 00`) is byte-symmetric (all zero except byte 4 = `0x01`)
|
||||
so it doesn't disambiguate. Resolving the disk byte order needs a
|
||||
controlled capture of `AND IF ZONE 5 SECURE` or `AND IF UNIT 7 ON` —
|
||||
the first non-symmetric example will pin it down.
|
||||
:::
|
||||
|
||||
A 5-record block from our test fixture (one WHEN, three ANDs, one
|
||||
THEN, all in adjacent slots):
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user