Compare commits

..

3 Commits

Author SHA1 Message Date
dd53b2a89a docs: third cross-ref pass + sync uv.lock to 2026.5.11
Final cross-reference round, covering the remaining files where wire
bytes have a user- or installer-facing counterpart:

v1/messages.py
  New Cross-references block: SETUP ZONES + SETUP TEMPERATURES for the
  fields the parsers' raw bytes ultimately come from, and APPENDIX C
  for what each synthesized index means on hardware (unit 257+ =
  expansion-enclosure outputs, 393+ = panel flags).

models.ZoneStatus
  Status-byte bit-layout doc now also points at the Owner's Manual
  CONTROL chapter's "View Zone Status" keypad screen -- same Secure /
  Not Ready / Trouble / Tamper labels.

models.UnitStatus
  State-byte semantics doc references the Owner's Manual CONTROL
  chapter for the user-side actions (All On/All Off/Scene/Bright/Dim)
  that drive units into each of these states.

mock_panel.py
  Notes that the mock's plausible-but-arbitrary RequestProperties /
  RequestStatus responses correspond on real hardware to what an
  installer typed into INSTALLER SETUP. Production fixtures should
  pre-seed MockPanel state to match a known SETUP configuration.

uv.lock
  Catches up the project's own entry to omni-pca 2026.5.11 (was
  pinned to 2026.5.10 from the previous lock generation).

No code changes; 387 tests still pass.
2026-05-11 15:54:40 -06:00
24eecceff9 docs: second cross-ref pass (HvacMode/FanMode/HoldMode, pca_file, v1/connection)
Follow-up to 0d6465d, sprinkling pca-re/docs/manuals/ citations into
three more files that map to user-visible or installer-visible panel
behavior:

models.HvacMode / FanMode / HoldMode
  Docstrings now explain which values correspond to keypad menu picks
  vs. programmatic-only states, and point at the Owner's Manual
  *Scene Commands* chapter where each menu is laid out.

pca_file.py
  Module docstring adds Cross-references to the Installation Manual's
  *INSTALLER SETUP* chapter (SETUP CONTROL/ZONES/AREAS/MISC/EXPANSION)
  -- those are the keypad screens that produce the very SetupData /
  Names / Programs blocks the parser walks. Also points at APPENDIX C
  (zone and unit mapping) for where the _CAP_OMNI_PRO_II numbers come
  from on the panel side.

v1/connection.py
  Module docstring adds cross-references to the docs-site pages that
  explain (a) the non-public handshake quirks the v1 connection relies
  on for crypto and (b) why subsequent RequestUnitStatus calls need
  the long-form BE u16 payload (Appendix C zone/unit mapping again).

No code changes, doc-only; 387 tests still pass.
2026-05-11 15:33:14 -06:00
0d6465dad0 docs: cross-reference manuals from SecurityMode, ZoneType, events, commands
Sprinkle pca-re/docs/manuals/ citations into the four files that map
hardest to user-visible panel behavior, so a reader chasing "why is
this byte 0x03 here" lands on the right manual chapter directly from
the source.

models.SecurityMode
  Per-value comments summarising what each arming mode means at the
  keypad (entry/exit delays, which zones it arms, when to use it).
  Points at the Owner's Manual SECURITY_SYSTEM_OPERATION chapter where
  these semantics are spelled out for end users.

models.ZoneType
  Class docstring now points at the Installation Manual SETUP ZONES
  table where each numeric byte value is named -- the byte values and
  short names we chose match that table one-for-one, so a reader can
  cross-walk the v1 ZoneStatus byte to "PERIMETER" / "AWAY INT" / etc.
  by row.

events.py
  Module docstring adds Cross-references to APPENDIX A (Contact ID
  reporting format) and APPENDIX B (digital communicator code sheet)
  in the Installation Manual -- the central-station codes a panel
  transmits for each AlarmKind correspond directly to those tables.

commands.py
  Module docstring points at the Owner's Manual CONTROL, Scene Commands,
  and SECURITY SYSTEM OPERATION chapters so the reader can tie each
  enuUnitCommand byte to the user-facing keypad path that triggers it.

No code changes; all 387 tests still pass.
2026-05-11 14:51:19 -06:00
8 changed files with 121 additions and 17 deletions

View File

@ -39,6 +39,19 @@ The reply (ExecuteSecurityCommandResponse, opcode 75) carries a single
status byte at ``payload[0]`` whose values are listed in
``enuSecurityCommnadResponse.cs`` :class:`SecurityCommandResponse`
mirrors that enum.
Cross-references (HAI OmniPro II Owner's Manual):
Chapter "CONTROL" (pca-re/docs/owner_manual/05_CONTROL/) documents
the user-facing keypad keys that map to these commands
e.g. UNIT_ON/OFF + UNIT_LEVEL are what a homeowner triggers via
the "Control → 1 (Unit)" menu, SHOW_MESSAGE_WITH_BEEP is
invoked from "Control → Message → Show".
Chapter "Scene Commands" (06_Scene_Commands/) covers
COMPOSE_SCENE and the per-room scene-recall path.
Chapter "SECURITY SYSTEM OPERATION" (03_SECURITY_SYSTEM_OPERATION/)
documents what each SecurityMode byte (0-6) means at the user
level the arming menu, entry/exit-delay semantics, and which
zones each mode arms.
"""
from __future__ import annotations

View File

@ -29,6 +29,16 @@ References (decompiled C# source):
bit-mask classifier we mirror below
clsText.cs:1693-1911 (GetEventText)
per-category sub-field extraction
Cross-references (HAI OmniPro II Installation Manual):
APPENDIX A CONTACT ID REPORTING FORMAT (p68): the Contact ID
event codes the panel transmits to a central monitoring station
for each :class:`AlarmKind`. The class names below mirror those
codes one-for-one. (pca-re/docs/manuals/installation_manual/
10_APPENDIX_A_CONTACT_ID_REPORTING_FORMAT/)
APPENDIX B DIGITAL COMMUNICATOR CODE SHEET (p69-73): the 4/2 and
3/1 reporting-format code tables. Useful when correlating a
SystemEvents word with what a central station would see. (12_)
"""
from __future__ import annotations

View File

@ -31,6 +31,16 @@ References:
clsOL2MsgRequestStatus.cs / clsOL2MsgStatus.cs
clsOL2MsgRequestExtendedStatus.cs / clsOL2MsgExtendedStatus.cs
clsOLMsgSystemEvents.cs
Cross-references (HAI OmniPro II Installation Manual):
*INSTALLER SETUP* (pca-re/docs/manuals/installation_manual/
04_INSTALLER_SETUP/) is the human-side counterpart to the data
this mock serves: the panel's response to a RequestProperties /
RequestStatus would on real hardware reflect whatever an installer
typed into SETUP CONTROL / SETUP ZONES / SETUP AREAS / SETUP
TEMPERATURES / SETUP MISC for that object. The mock just makes up
plausible bytes; production fixtures should pre-seed the
``MockPanel`` state to match a known SETUP configuration.
"""
from __future__ import annotations

View File

@ -490,18 +490,25 @@ class ObjectType(IntEnum):
class SecurityMode(IntEnum):
"""Area security mode (enuSecurityMode.cs).
Values 9..14 are the "arming in progress" variants the panel reports
while a delayed-arm timer is running.
The first 7 values are what the user actually picks at the keypad
when arming. Values 9..14 are the "arming in progress" variants the
panel reports while a delayed-arm timer is running.
Reference: HAI OmniPro II Owner's Manual, *Security System
Operation* chapter (pca-re/docs/owner_manual/
03_SECURITY_SYSTEM_OPERATION/) the user-facing semantics of each
mode (entry/exit delays, which zones are armed, when to use which)
come from there.
"""
OFF = 0
DAY = 1
NIGHT = 2
AWAY = 3
VACATION = 4
DAY_INSTANT = 5
NIGHT_DELAYED = 6
ANY_CHANGE = 7
OFF = 0 # disarmed; resets fire / emergency alarms, silences sirens
DAY = 1 # perimeter armed, interior motion NOT armed, entry delay
NIGHT = 2 # perimeter + non-sleeping-area motion armed, NO entry delay
AWAY = 3 # everything armed, both exit + entry delays
VACATION = 4 # same as AWAY but for multi-day absences
DAY_INSTANT = 5 # DAY with no entry delay (instant alarm on perimeter)
NIGHT_DELAYED = 6 # NIGHT with entry delay on entry-exit zones
ANY_CHANGE = 7 # programming-condition wildcard, NOT a real arming state
ARMING_DAY = 9
ARMING_NIGHT = 10
ARMING_AWAY = 11
@ -511,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
@ -521,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
@ -531,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
@ -560,6 +582,13 @@ class ZoneType(IntEnum):
the temperature/humidity sensors and a handful of utility types. Any
raw byte value still round-trips through ``ZoneStatus.zone_type``
it just won't have a named enum member.
Reference: HAI OmniPro II Installation Manual, *Installer Setup
SETUP ZONES ZONE TYPES* table (pca-re/docs/manuals/
installation_manual/04_INSTALLER_SETUP/INSTALLER_SETUP.md, p38-39).
The byte values and short names here match the installer-setup
keypad selections one-for-one (e.g. ``PERIMETER = 1`` is the same
"PERIMETER" the installer scrolls to when setting Z1..Z176 types).
"""
ENTRY_EXIT = 0
@ -657,7 +686,9 @@ class ZoneStatus:
bytes[2] status byte (current+latched+arming, see below)
bytes[3] analog loop reading (0-255)
Status byte bit layout (clsZone.cs:385, clsText.cs:3110):
Status byte bit layout (clsZone.cs:385, clsText.cs:3110, and the
"View Zone Status" keypad screen in the Owner's Manual *CONTROL*
chapter, pca-re/docs/owner_manual/05_CONTROL/):
bits 0-1 (mask 0x03): current condition
0=Secure, 1=NotReady, 2=Trouble, 3=Tamper
bits 2-3 (mask 0x0C): latched alarm status
@ -752,7 +783,11 @@ class UnitStatus:
bytes[3..4] remaining time in seconds (BE u16, 0 = indefinite)
bytes[5..6] optional ZigBee instantaneous power (W, BE u16)
State byte semantics (clsUnit.cs:405-533):
State byte semantics (clsUnit.cs:405-533; user-visible meaning in
the Owner's Manual *CONTROL → Light/Appliance Control* chapter,
pca-re/docs/owner_manual/05_CONTROL/, which documents the keypad
"All On" / "All Off" / "Scene" / "Bright/Dim" actions that put a
unit into each of these states):
0 Off
1 On
2..13 Scene A..L (state - 63 'A'..'L' as ASCII char)

View File

@ -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

View File

@ -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

View File

@ -21,6 +21,18 @@ Per-record byte counts (verified against firmware 2.12 over UDP):
AuxiliaryStatus 4 bytes per aux (relay, current, low_sp,
high_sp)
Cross-references (HAI OmniPro II Installation Manual):
*INSTALLER SETUP SETUP ZONES* (pca-re/docs/manuals/
installation_manual/04_INSTALLER_SETUP/) the zone-type and
zone-options bits that determine what each ``ZoneStatus.raw_status``
byte's high nibble means come from this chapter.
*INSTALLER SETUP SETUP TEMPERATURES* same chapter, thermostat
enable/disable + thermostat type that drives whether
``parse_v1_thermostat_status`` records are populated at all.
*APPENDIX C ZONE AND UNIT MAPPING* (12_) what each record's
synthesized index *means* on the hardware side (e.g. unit 257+
= expansion-enclosure outputs, 393+ = panel flags).
References:
clsOLMsgZoneStatus.cs / clsOLMsgRequestZoneStatus.cs
clsOLMsgUnitStatus.cs / clsOLMsgRequestUnitStatus.cs

2
uv.lock generated
View File

@ -1511,7 +1511,7 @@ wheels = [
[[package]]
name = "omni-pca"
version = "2026.5.10"
version = "2026.5.11"
source = { editable = "." }
dependencies = [
{ name = "cryptography" },