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.