2 Commits

Author SHA1 Message Date
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
68cf44a585 Library v1.0 phase B: command opcodes + typed system events
src/omni_pca/commands.py — Command IntEnum (64 values, sourced from
enuUnitCommand.cs which is the canonical 'enuCommand' despite the misleading
name) + SecurityCommandResponse + CommandFailedError exception. Notable
discovery: enuUnitCommand.UserSetting (104) is actually EXECUTE_PROGRAM;
renamed for clarity, C# alias documented inline.

src/omni_pca/client.py — 18 new methods on OmniClient:
  Core: execute_command, execute_security_command, acknowledge_alerts,
        get_object_status, get_extended_status
  Wrappers: turn_unit_on/off, set_unit_level, bypass_zone, restore_zone,
        set_thermostat_{system,fan,hold}_mode,
        set_thermostat_{heat,cool}_setpoint_raw,
        execute_button, execute_program, show_message, clear_message
  All command methods raise CommandFailedError on Nak.

src/omni_pca/events.py — typed SystemEvents (opcode 55) decoder.
- EventType IntEnum (28 dispatch tags)
- 26 SystemEvent subclasses + UnknownEvent catch-all
  Includes: ZoneStateChanged, UnitStateChanged, ArmingChanged,
  AlarmActivated/Cleared, AcLost/Restored, BatteryLow/Restored,
  PhoneLine{Off,On,Dead,Restored}, UserMacroButton, ProLinkMessage,
  CentraLiteSwitch, X10CodeReceived, AllOnOff, DcmTrouble/Ok,
  EnergyCostChanged, CameraTrigger, AccessReaderEvent, UpbLinkEvent
- SystemEvents packets carry MULTIPLE events; public API is
  parse_events(message) -> list[SystemEvent], plus SystemEvent.parse()
- EventStream helper that flattens batches across messages
- Wiring of OmniClient.events() left for next pass

55 new tests across both files. 194 pass, 2 pre-existing skips. Ruff clean.
2026-05-10 14:17:12 -06:00