4 Commits

Author SHA1 Message Date
9ea05c3b94 docs: add Hardware specs reference + Zone & unit numbering explanation
Two new pages distilled from HAI's official OmniPro II Installation
Manual 3-2 + Product Specifications datasheet (Quadomated mirror).

reference/hardware-specs.md
  Capacity ceilings (176 zones, 511 units, 8 areas, 64 thermostats,
  128 buttons, 1500 programs, 99 codes, 128 messages, etc.), digital
  communicator + network features, electrical specs with the per-output
  current caps and the 24-hour battery-standby derating numbers,
  physical dimensions, environmental ranges, listings, languages, and
  part-number lookup. The numbers here are the source of every cap in
  clsCapOMNI_PRO_II.cs and the upper bounds for the protocol's range
  fields, so anyone debugging "why does my panel NAK at index N" should
  start here.

explanation/zone-unit-numbering.md
  Appendix C of the install manual, transcribed and explained: how the
  panel maps physical hardware to its 1-176 zone and 1-511 unit
  address spaces. Documents the four overlapping families that share
  the unit number line -- X-10 (1-256, by house code), ALC bus
  (parallel address space within those slots), physical outputs
  (257-392), and panel flags (393-511) -- which is why the working
  panel reports units at index 257+ (sprinkler outputs on the first
  17A00 expansion enclosure) and 393+ (named flags) even though only
  a dozen lights are wired up.

  Closes a real debugging mystery from Phase 2/3 of the v1+UDP work:
  OmniClientV1's long-form RequestUnitStatus path (BE u16 start/end)
  exists specifically to address units > 255, which only happens
  because of this firmware-fixed address layout.

astro.config.mjs
  Slot both new pages into the existing Reference and Explanation
  sidebar groups.
2026-05-11 13:23:58 -06:00
d5d2ea3d32 Diagrams: five hand-crafted SVGs explaining the protocol + architecture
The auto-extracted manual SVGs were unusable PDF text-glyph soup. These
are fresh, theme-aware (currentColor everywhere, accent via the
--sl-color-accent CSS var), and built to teach.

src/assets/diagrams/handshake-sequence.svg
  Sequence diagram with CLIENT and CONTROLLER swim lanes, five steps:
  ClientRequestNewSession -> ControllerAckNewSession (carries SessionID)
  -> derive SessionKey (inline note) -> ClientRequestSecureSession
  (encrypted, accent-coloured) -> ControllerAckSecureSession (encrypted)
  -> first OmniLink2Message. Plaintext arrows in currentColor, encrypted
  arrows in accent.

src/assets/diagrams/packet-structure.svg
  Bytes-on-the-wire box diagram: outer Packet header (seq u16 + type +
  reserved + encrypted payload) decomposed below into the inner Message
  (start byte 0x21, length, opcode, data, CRC u16 LE). Plain vs encrypted
  fields colour-coded with a legend.

src/assets/diagrams/session-key-derivation.svg
  Quirk #1 visual. Three rows of byte cells: ControllerKey (16 bytes,
  with bytes 0..10 in plain colour and 11..15 highlighted), SessionID
  (5 bytes), and the resulting SessionKey with the XOR boundary
  visible. XOR operator in the accent colour to draw the eye.

src/assets/diagrams/per-block-whitening.svg
  Quirk #2 visual. seq pill at the top, three blocks below (block 1,
  block 2, block N) each showing 16 byte cells with the first two
  highlighted in accent and labelled with the seq XOR mask. Drives home
  that it's the SAME mask on EVERY block.

src/assets/diagrams/architecture.svg
  Three groups (LIBRARY, HA INTEGRATION, TEST SURFACE) with boxes
  inside. Library shows the four protocol-layer modules + connection +
  client + models + events. HA shows coordinator + 8 platforms. Test
  surface shows MockPanel (accent-coloured), HA test harness, e2e tests,
  unit tests. One accent-coloured arrow runs from OmniConnection across
  to MockPanel labelled 'TCP/4369 (encrypted)'.

src/assets/diagrams/pca-file-format.svg
  Key chain: hardcoded keyPC01 -> decrypts PCA01.CFG (boxes for the
  CFG fields including the highlighted pca_key) -> arrow showing the
  extracted pca_key -> decrypts the .pca file (boxes for PCA03 magic,
  account info, model byte, body, and the highlighted ControllerKey)
  -> caption 'feeds session-key derivation (quirk #1)'.

Wired in via inline-SVG-via-?raw-import + set:html (so currentColor
adapts to the theme). Required converting four pages to .mdx:
  reference/protocol.mdx        + handshake + packet diagrams
  reference/file-format.mdx     + pca-file-format diagram
  explanation/quirks.mdx        + session-key + whitening diagrams
  explanation/architecture.mdx  + architecture diagram

Two MDX paper cuts during conversion: bare '<100ms' and '<50ms' in
architecture.mdx confused the JSX parser; backticked them as .

Build: 23 pages clean. Verified inline SVG ships in the rendered HTML
(grep for SVG title IDs returns 2/2 hits per relevant page). Container
rebuilt + redeployed. Protocol page is now 92750 bytes (was ~63000),
quirks page 84156 (was ~63000).
2026-05-10 17:32:49 -06:00
9dbe563aed Content + docker pin: 13-page Starlight site live behind Caddy
src/content/docs/ — twelve pages totalling ~18,800 words, ported from
the omni-pca repo's docs and reference material:

  index.mdx (377 w)               landing page with three CardGrid links
  start/quickstart.md (572 w)     three flows: decode .pca / talk to
                                  panel / install in HA

  reference/protocol.md (2525 w)  byte-level Omni-Link II spec, full
                                  packet+message layouts, the two
                                  non-public quirks, opcode tables
  reference/file-format.md (1593 w)  XOR-LCG cipher, key derivation,
                                  PCA01.CFG schema, .pca PCA03 header
  reference/library-api.md (1170 w)  module-by-module Python API summary
  reference/ha-entities.md (1070 w)  per-platform entity catalogue
  reference/ha-services.md (567 w)   seven services + automation YAML

  explanation/quirks.md (1448 w)  the headline RE essay — session-key
                                  XOR mix + per-block whitening, why
                                  no public client documents them
  explanation/architecture.md (1123 w)  library + HA + mock + tests
  explanation/pc-access-bug.md (1131 w)  LargeVocabulary off-by-N

  journey.md (6194 w)             chronological retrospective ported
                                  from omni-pca/docs/JOURNEY.md
  changelog.md (1213 w)           full 2026.5.10 release notes

Dockerfile — pinned node:lts-alpine and caddy:latest (registry-1
.docker.io was returning 'tls: internal error' on node:25-alpine and
caddy:2-alpine pulls; the pinned tags are cached locally and work).
TODO comment notes to bump back to node:25 once registry stabilises.

.gitignore — added .env / .env.local just in case.

Build: 13 pages built clean in 1.83s, sitemap + Pagefind search index
emitted. Container runs at hai-omni-docs-docs (caddy network), accepts
requests with Host: hai-omni-pro-ii.warehack.ing, returns rendered
Starlight HTML with title/description meta intact. Once DNS for
hai-omni-pro-ii.warehack.ing points at the host, the site is live.
2026-05-10 17:05:25 -06:00
c5e72c679b Initial scaffold
Astro 6 + Starlight 0.39 documentation site for omni-pca, organised
around the Diatáxis framework (Tutorials / How-to / Reference /
Explanation), plus a chronological Journey page and Changelog.

Theme: muted slate-blue with amber accents. astro-icon + lucide
preinstalled. Astro telemetry and Starlight devToolbar both off.

Deployment: multi-stage Dockerfile (node:25-alpine builder ->
caddy:2-alpine runtime), inner Caddy serves static dist on :80,
outer caddy-docker-proxy on the host terminates TLS for
hai-omni-pro-ii.warehack.ing.
2026-05-10 16:42:12 -06:00