diff --git a/src/omni_pca/models.py b/src/omni_pca/models.py index 4172eaf..0ba1b4d 100644 --- a/src/omni_pca/models.py +++ b/src/omni_pca/models.py @@ -518,7 +518,13 @@ class SecurityMode(IntEnum): class HvacMode(IntEnum): - """Thermostat system mode (enuThermostatMode.cs).""" + """Thermostat system mode (enuThermostatMode.cs). + + Values 0-3 match the keypad's "Thermostat → MODE" menu one-for-one + (Owner's Manual *Scene Commands → Thermostat Control* chapter, + pca-re/docs/owner_manual/06_Scene_Commands/). ``EMERGENCY_HEAT`` (4) + is heat-pump-only and not exposed in the standard keypad menu. + """ OFF = 0 HEAT = 1 @@ -528,7 +534,12 @@ class HvacMode(IntEnum): class FanMode(IntEnum): - """Thermostat fan mode (enuThermostatFanMode.cs).""" + """Thermostat fan mode (enuThermostatFanMode.cs). + + Values 0-1 match the keypad's "Thermostat → FAN" menu (Owner's + Manual *Scene Commands*, 06_Scene_Commands/). ``CYCLE`` (2) is + programmable-only and not surfaced at the keypad. + """ AUTO = 0 ON = 1 @@ -538,8 +549,12 @@ class FanMode(IntEnum): class HoldMode(IntEnum): """Thermostat hold mode (enuThermostatHoldMode.cs). - Value 255 (``OLD_ON``) is a legacy "Hold" sentinel from older firmware - that some panels still emit; treat it as equivalent to ``HOLD``. + ``OFF`` / ``HOLD`` are the two states surfaced at the keypad's + "Thermostat → HOLD" menu (Owner's Manual *Scene Commands*, + 06_Scene_Commands/). ``VACATION`` (2) is a programmable mode the + panel uses while a Vacation security mode is active. Value 255 + (``OLD_ON``) is a legacy "Hold" sentinel from older firmware that + some panels still emit; treat it as equivalent to ``HOLD``. """ OFF = 0 diff --git a/src/omni_pca/pca_file.py b/src/omni_pca/pca_file.py index c3035b8..40025ab 100644 --- a/src/omni_pca/pca_file.py +++ b/src/omni_pca/pca_file.py @@ -16,6 +16,22 @@ References: clsPcaCfg.cs — keyPC01 / keyExport constants, PCA01.CFG layout clsHAC.cs:7943-8056 — .pca header + body walker, Connection block clsCapOMNI_PRO_II.cs — per-model size constants used by the body walker + +Cross-references (HAI OmniPro II Installation Manual): + *INSTALLER SETUP* (pca-re/docs/manuals/installation_manual/ + 04_INSTALLER_SETUP/) is what populates everything we then read back + from a .pca export: + SETUP CONTROL → SetupData block (panel-wide options) + SETUP ZONES → Names section (zone-name entries) + Z*_TYPE + (encoded inside SetupData) + SETUP AREAS → Names section (area-name entries) + per-area + delays and codes in SetupData + SETUP MISC → Programs section (timed scenes, energy savers) + SETUP EXPANSION → cap counters that drive how big each names + block is on the wire + APPENDIX C — ZONE AND UNIT MAPPING (12_APPENDIX_C_-_ZONE_AND_UNIT_MAPPING/) + documents the address-space layout the cap constants in + _CAP_OMNI_PRO_II below derive from (176 zones, 511 units, etc.). """ from __future__ import annotations diff --git a/src/omni_pca/v1/connection.py b/src/omni_pca/v1/connection.py index bc78449..bfd64de 100644 --- a/src/omni_pca/v1/connection.py +++ b/src/omni_pca/v1/connection.py @@ -21,6 +21,14 @@ Reference: clsOmniLinkConnection.cs (UDP path): udpHandleRequestSecureSession lines 1461-1487 step 4 → OnlineSecure udpSend lines 1514-1560 outer PacketType = OmniLinkMessage (16) EncryptPacket lines 372-401 same crypto as TCP + +Cross-references: + *Two non-public quirks* — Owner's-Manual-style writeup of the + session-key XOR mix and per-block sequence whitening that this + handshake relies on: https://hai-omni-pro-ii.warehack.ing/explanation/quirks/ + *Zone & unit numbering* — explains why subsequent ``RequestUnitStatus`` + calls need the long-form (BE u16) payload for unit indices > 255: + https://hai-omni-pro-ii.warehack.ing/explanation/zone-unit-numbering/ """ from __future__ import annotations