--- title: Zone & unit numbering description: How the Omni Pro II maps physical hardware to its 1-176 zone and 1-511 unit address space — and why your panel may report units in the 257+ range even with no 16th-house-code X-10 module installed. --- A panel that looks like it has 8 zones and a dozen lights to a homeowner is actually addressing into a much larger fixed map of 176 zone slots and 511 unit slots. The mapping is part of the controller's firmware, not configurable. If you walk the panel with [`OmniClientV1.iter_names()`](/reference/library-api/) and see units at index 257 or 393, this is why. This page is a literal transcription of *Appendix C* of HAI's *OmniPro II Installation Manual 3-2*, p74 — distilled from the live mapping our firmware-2.12 panel actually reports. ## Zones (1-176) Every group of 16 zones is one physical board / enclosure. | Index range | Source | |---|---| | 1 – 16 | Controller (onboard) | | 17 – 32 | 1st **10A06** hardwire expander board | | 33 – 48 | 2nd **10A06** hardwire expander board | | 49 – 64 | 1st **17A00** expansion enclosure | | 65 – 80 | 2nd **17A00** expansion enclosure | | 81 – 96 | 3rd **17A00** expansion enclosure | | 97 – 112 | 4th **17A00** expansion enclosure | | 113 – 128| 5th **17A00** expansion enclosure | | 129 – 144| 6th **17A00** expansion enclosure | | 145 – 160| 7th **17A00** expansion enclosure | | 161 – 176| 8th **17A00** expansion enclosure | The hardware cap is 176, regardless of how many your installer wired up. Slots without a physical sensor still respond to `RequestZoneStatus` — they just return `status=0, loop=0` (or the analog-loop "no transponder" sentinel `0x80`). ## Units (1-511) The unit address space mixes **four protocol families** — X-10, ALC, physical outputs, and "flags" — into one flat number line. Which one each block lands in is fixed by the firmware: ### X-10 (1 – 256, by house code) X-10 modules are addressed `(house_code, unit_id)` on the wire but Omni flattens that to a single integer: each consecutive house code gets the next 16 indices. The installer picks the *starting* house code "X" at setup time; the controller occupies X through X+15 (16 house codes). | Index range | Source | |---|---| | 1 – 16 | X-10 house code **X** (start), modules 1–16 | | 17 – 32 | X-10 house code **X+1**, modules 1–16 | | 33 – 48 | X-10 house code **X+2** | | 49 – 64 | X-10 house code **X+3** | | 65 – 80 | X-10 house code **X+4** | | 81 – 96 | X-10 house code **X+5** | | 97 – 112 | X-10 house code **X+6** | | 113 – 128 | X-10 house code **X+7** | | 129 – 144 | X-10 house code **X+8** | | 145 – 160 | X-10 house code **X+9** | | 161 – 176 | X-10 house code **X+10** | | 177 – 192 | X-10 house code **X+11** | | 193 – 208 | X-10 house code **X+12** | | 209 – 224 | X-10 house code **X+13** | | 225 – 240 | X-10 house code **X+14** | | 241 – 256 | X-10 house code **X+15** | ### ALC bus (parallel address space) ALC ("Advanced Lighting Control") devices share the X-10 slots above, but only every other range within a 64-block module/branch: | Index range | Source | |---|---| | 1 – 31 | ALC Module 1, Branch 1 (addresses 1-31) | | 33 – 63 | ALC Module 1, Branch 2 | | 65 – 95 | ALC Module 1, Branch 3 | | 97 – 127 | ALC Module 1, Branch 4 | | 129 – 159 | ALC Module 2, Branch 1 | | 161 – 191 | ALC Module 2, Branch 2 | | 193 – 223 | ALC Module 2, Branch 3 | | 225 – 255 | ALC Module 2, Branch 4 | ALC and X-10 numbering deliberately overlap: if you've wired an ALC device at module 1 / branch 1 / addr 5, it lives at unit index 5 — same slot the X-10 firmware would otherwise have for house-code-X module 5. You pick one or the other; the panel won't drive both into the same slot. ### Physical outputs (257 – 392) Real relay/voltage outputs on the controller and expansion enclosures: | Index range | Source | |---|---| | 257 – 272 | Outputs 1-16, 1st **17A00** expansion enclosure | | 273 – 288 | Outputs 1-16, 2nd **17A00** | | 289 – 304 | Outputs 1-16, 3rd **17A00** | | 305 – 320 | Outputs 1-16, 4th **17A00** | | 321 – 336 | Outputs 1-16, 5th **17A00** | | 337 – 352 | Outputs 1-16, 6th **17A00** | | 353 – 368 | Outputs 1-16, 7th **17A00** | | 369 – 384 | Outputs 1-16, 8th **17A00** | | 385 – 392 | Voltage outputs 1-8 on the controller itself | ### Flags (393 – 511) The top 119 unit slots aren't hardware — they're **flags**: panel variables an installer can write Programming Lines against. Flags behave like units on the wire (you can `turn_unit_on(400)` to set flag 400), but no physical load moves. | Index range | Source | |---|---| | 393 – 511 | Flags (panel variables) | ## Why this matters for omni-pca * **`OmniClientV1.iter_names()`** streams names for any defined slot in the full 1-511 range. If your `.pca` config defined sprinkler controllers as outputs 1-10 on the first 17A00, you'll see them as units 257-266 — even though only 8 "real" lights are wired up. * **`RequestUnitStatus` has two payload forms.** The short form's `start` and `end` are single bytes (max 255). The long form takes BE u16s (max 65535) — see `clsOLMsgRequestUnitStatus.cs:18-31`. Our v1 client picks the right form automatically based on the requested range. * **Per-poll record cap.** Firmware 2.12 caps a single `RequestUnitStatus` reply at ~62 records regardless of `MessageLength` headroom; querying a wider range NAKs. `OmniClientV1Adapter` chunks status polls into batches of 40 to stay well under that. If you want to see the live mapping for *your* panel, run: ```bash cd omni-pca uv run python dev/probe_v1_client.py ``` — it dumps every defined name across all object types and lets you correlate user-facing labels with their underlying unit index.