Skip to content

Repository files navigation

Room Lighting for Home Assistant

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.

Architecture

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.

What each room creates

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.

Installation

HACS custom repository

  1. In HACS, open Custom repositories.
  2. Add https://github.com/kidhasmoxy/auto-motion-lights as an Integration.
  3. Install Room Lighting and restart Home Assistant.

This repository is not in the default HACS catalog.

Manual installation

  1. Copy custom_components/room_lighting into the Home Assistant configuration directory's custom_components folder.
  2. 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.

First-time setup

  1. Open Settings > Devices & services > Add integration.
  2. Search for Room Lighting.
  3. Confirm Create Room Lighting workspace once.
  4. 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.

Sidebar workspace

The admin-only sidebar is the complete configuration interface. Its room editor is split into nine progressive sections:

  1. Overview
  2. Devices and modes
  3. Activation
  4. Turn off
  5. Conditions and overrides
  6. Profiles, periods, and capture
  7. Transitions
  8. Activator and indicator
  9. 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.

Safety defaults

  • 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 Mode and profiles

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.

Hubitat import

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.

Upgrade from 0.3.x

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.

Diagnostics and troubleshooting

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.

Known parity boundaries

  • 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.

Development and validation

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.js

Release 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.

License

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.

About

A Home Assistant custom integration recreating Hubitat Room Lighting with flexible per-room modes.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages