Room Lighting is a Home Assistant custom integration inspired by Hubitat Room Lighting. It keeps Room Lighting's persistent state machine, timers, latches, captures, transitions, activator behavior, and per-device profile participation in one Home Assistant-native application.
Version 0.4.0 requires Home Assistant 2026.6.4 or newer and changes the integration to one application config entry with one config subentry per room.
Important
This project does not claim perfect Hubitat parity. The checked-in census and
golden-master catalog are coverage inventories, not behavioral proof. Every
paired-evidence case remains Unproven; see the
parity matrix.
One singleton room_lighting config entry owns the application lifecycle, sidebar,
admin-only WebSocket API, services, and a central RoomLightingManager. The initial
config flow has one job: create that workspace. It does not configure a room.
Each room is a Home Assistant config subentry of type room. A room subentry owns
its complete normalized configuration and stable room ID. Each room still has an
isolated RoomLightingController, runtime snapshot, timers, latches, and logical
state machine. The root manager creates, reloads, removes, and shuts down those
controllers as one application.
The manager also coordinates shared physical entities:
- Commands are serialized in request order through one application-wide coordinator.
- Command provenance is shared by every room, so another Room Lighting room's command is not treated as a physical manual change merely because it came from a different controller.
- The latest completed room command is recorded per entity.
- Overlapping, superseded, and failed decisions are surfaced in diagnostics.
- There is no hidden room priority or ownership policy. A later serialized command may produce the later device state; conflicts remain visible for review.
Every room continues to create one virtual Room Lighting device. Its entities and device are associated with both the singleton root entry and the correct room subentry using Home Assistant's supported registry APIs. Stable room IDs keep the legacy virtual entity/device identifiers intact during migration wherever Home Assistant supports that association update.
Configuration and runtime snapshots are stored in Home Assistant. A Hubitat connection is not required at runtime.
Depending on its settings, a room exposes:
- A Room Lighting enabled switch for application Pause.
- Test Activate, Test Turn Off, Update, Capture, and Stop Transition buttons.
- A Status sensor with logical state, selected profile, timers, and the latest decision.
- An optional Room Lights Activator represented as coordinated switch, light, cover, and button surfaces on the same room device, according to its selected capability type.
The integration also registers activate, turn off, toggle, test, pause/resume,
re-evaluate, capture, and stop-transition actions. New action calls use a stable
room_id. The old config_entry_id field remains a compatibility alias for
existing automations migrated from 0.3.x; its value is the legacy room ID, not the
new root entry ID.
Fan-percentage targets and compatible light-effect forwarding are clearly scoped Home Assistant-only extensions. They are excluded from the original-feature parity inventory.
- In HACS, open Custom repositories.
- Add
https://github.com/kidhasmoxy/auto-motion-lightsas an Integration. - Install Room Lighting and restart Home Assistant.
This repository is not in the default HACS catalog.
- Copy
custom_components/room_lightinginto the Home Assistant configuration directory'scustom_componentsfolder. - Restart Home Assistant.
For an occupied home, follow the presence-required deployment runbook. Do not install, restart, or pilot the integration without someone present to observe the house.
- Open Settings > Devices & services > Add integration.
- Search for Room Lighting.
- Confirm Create Room Lighting workspace once.
- Open the new Room Lighting sidebar entry and create an inert room.
Only one workspace can exist. Normal room configuration and Hubitat import happen in the sidebar, not the config-entry options flow.
The admin-only sidebar is the complete configuration interface. Its room editor is split into nine progressive sections:
- Overview
- Devices and modes
- Activation
- Turn off
- Conditions and overrides
- Profiles, periods, and capture
- Transitions
- Activator and indicator
- Diagnostics and maintenance
From that workspace an administrator can create, rename, clone, export, import, and delete rooms; associate areas; preview inert area suggestions; manage controlled entities; configure default, mode, and period profiles; edit Act/Off/Force and capability-aware targets; configure every guided means, blocker, latch, override, transition, activator, and indicator; capture values; probe devices; run explicit test actions; and inspect room/shared-device diagnostics.
The panel uses conditional sections so settings appear only when relevant. Expert JSON editors remain available for Home Assistant trigger/condition structures and complete normalized records. Python performs the authoritative validation. Saves use revision checks and a reload/rollback transaction: a validation or reload failure leaves the previously active room configuration in place.
Unsaved drafts are marked in the header and guarded on reload, room changes, and navigation. Scope removals and room deletion require explicit confirmation. Test actions and capture operations are visibly separate from saving the draft.
- New rooms have no controlled entities or activation means and start inert.
- Area suggestions are previews and never arm a room automatically.
- Newly added controlled devices begin with Act, Off, and Force disabled.
- Removing a controlled device requires confirmation and removes its active profile rows from the saved scope.
- Missing, unavailable, new, or unmapped Home Mode values resolve to an inert profile. A forced normal Activate request cannot activate through that profile.
- Hubitat imports and clones start Paused.
- Ambiguous imported behavior remains disabled and is reported as a review warning.
- Normal save and runtime test actions are separate operations.
Home Assistant has no native equivalent of Hubitat Hub Mode. A room can select an
input_select or select entity as its Home Mode source.
Mode values are never hard-coded. The workspace discovers current select options, accepts arbitrary additional values, preserves configured orphan values for review, and lets each room use a different subset. Every mode/device row independently controls Act, Off, Force, type, Activation target, preset-off target, and motion and contact stays. Off-only/vacancy profiles are supported.
Rooms can instead use one default profile or recurring lighting periods. Periods support named reusable Day Groups, fixed local times, sunrise/sunset, signed offsets, and per-period profile selection. Conflicting schedule boundaries are rejected server-side. An active room can optionally adjust when its selected profile changes.
Start Hubitat import from Diagnostics and maintenance. Paste the exported document, select the child app when needed, map source devices to Home Assistant entities, and preview every warning before creating the room.
The importer recognizes the currently modeled Room Lighting, Motion Lighting, Mode
Lighting, Group, Scene, and Scene Transition shapes. The inspected Motion Lighting
1.6.5 deviceList structure has explicit per-mode mapping support. Import metadata
stores only a bounded, redacted audit; it does not retain the source payload,
credentials, or raw unknown values. Unknown or ambiguous private fields are warnings
and remain disabled rather than being guessed. Successful parsing is not proof of
behavioral equivalence.
Version 0.4.0 automatically detects the old one-config-entry-per-room layout before any room controllers start. It selects one singleton root entry and converts every legacy room to a room subentry while preserving its normalized configuration and using the legacy config-entry ID as the stable room identity.
The migration also copies and verifies persisted snapshots under stable room keys, updates entity/device registry associations without changing unique IDs, retains unavailable entity references and import warnings, and records an interruption-safe journal. Secondary legacy entries and obsolete snapshots are removed only after the new records verify. Conflicting roots or corrupt room data stop migration safely instead of guessing. Migration itself does not activate or resume a room.
The migration is one-way. Version 0.3.x does not understand room subentries, so a code-only downgrade is not supported. Create and verify a full Home Assistant backup before upgrading; restore that backup to return to the old layout. See migration details.
The sidebar diagnostics section reports controller status, command failures, latest shared-entity owners, and overlapping decisions. Home Assistant's root-entry Download diagnostics action includes application and per-room state.
Diagnostics intentionally retain normalized entity IDs, targets, trigger/condition definitions, and room names because they are needed to understand behavior. Review them before sharing. Raw Hubitat imports and credentials are not stored.
For a behavior disagreement, retain the source event, timestamps, downstream service calls, room diagnostics, and final state. A matching final light state alone is not enough to prove parity.
- Physical-versus-digital provenance and identical-state reports vary by Home Assistant integration.
- Driver capabilities, reports, timing, and command rounding require real-device validation.
- Hubitat collision, pause, restart, transition, and private-import rules are not fully documented and remain paired-live obligations.
- A service call to a Home Assistant group entity is not proof of Zigbee Group Messaging. Radio-level multicast, retry, acknowledgement, and failed-member behavior require a validated ZHA/Zigbee2MQTT adapter and packet evidence.
- Stateless Home Assistant buttons do not establish Hubitat action/button-number semantics by themselves.
See the feature census,
parity matrix, and machine-readable
tests/golden_master/feature_inventory.json for the complete evidence boundary.
The development environment pins Home Assistant exactly to 2026.6.4. From the repository root:
uv sync --group dev
.venv\Scripts\python -m pytest -q
.venv\Scripts\python -m compileall -q custom_components tests tools
.venv\Scripts\ruff check .
.venv\Scripts\ruff format --check .
node --check custom_components\room_lighting\frontend\room-lighting-panel.jsRelease validation also runs Hassfest, HACS validation, an isolated Home Assistant
2026.6.4 container, legacy-migration smoke coverage, and desktop/tablet browser
checks. None of those local checks can change a golden-master case to Proven.
No production Home Assistant installation should be changed as part of local development or release validation.
Room Lighting is released under the MIT License. Hubitat and Hubitat Room Lighting are names of their respective owner; this is an independent Home Assistant integration.