2 Commits

Author SHA1 Message Date
2e439364bd HA custom_component scaffold (binary_sensor for zones)
custom_components/omni_pca/ — drop-in HA integration:
- manifest.json (HA 2026.x, iot_class=local_push, requires omni-pca lib)
- config_flow.py — host/port/controller_key with auth + reauth steps,
  parse_controller_key() extracted as pure testable function
- coordinator.py — OmniDataUpdateCoordinator with long-lived OmniClient,
  unsolicited push wiring, ConfigEntryAuthFailed on bad key, reconnect on err
- binary_sensor.py — one entity per named zone, zone_type -> device_class map
  (OPENING/MOTION/SMOKE/etc), is_on derived from ZoneProperties.status
- const.py, strings.json, translations/en.json, README.md
- hacs.json at root for HACS distribution

tests: 97 pass + 2 skip (HA harness not installed; importorskip in
test_ha_imports.py). 12 cases for parse_controller_key validation.
Ruff clean across src/ tests/ custom_components/. Status of HA component
itself NOT validated against a running HA — needs that next.
2026-05-10 13:09:27 -06:00
9a024181ae Initial scaffold + protocol primitives
Project scaffold (uv, pyproject.toml CalVer 2026.5.10, ruff, pytest, mypy
strict config, MIT, README, .gitignore protecting any .pca / panel keys).

Library primitives (src/omni_pca/):
- crypto.py     AES-128-ECB + per-block XOR seq pre-whitening, session-key
                derivation (CK[0:11] || (CK[11:16] XOR SessionID))
- opcodes.py    Byte-exact PacketType (12), v1 MessageType (104),
                v2 MessageType (83), ConnectionType, ProtocolVersion
- packet.py     Outer Packet dataclass with encode/decode
- message.py    Inner Message + CRC-16/MODBUS, helpers for v1/v2
- pca_file.py   Borland LCG XOR cipher, PcaReader, .pca + .CFG parsers
                (KEY_PC01 = 0x14326573, KEY_EXPORT = 0x17569237 — fixed
                from initial typo; verified via test_keys_match_decompiled)
- __main__.py   CLI: 'omni-pca decode-pca <file> --field {host,port,...}'
                PII opt-in via --include-pii

49 tests pass, 1 skipped (live fixture). Ruff clean.
2026-05-10 12:46:26 -06:00