Main

A Zigbee RGB Bulb as a Non-Verbal Status Indicator: Build, Test, and Degrade Gracefully

A single Zigbee RGB bulb is a workable status channel for a deaf household member. It is not a complete accessibility solution, and treating it as one is the most common way this build fails. The bulb depends on mains power, a Zigbee coordinator, a running Home Assistant instance, and a working mesh path to the bulb. Any of those can fail silently. The design below treats the bulb as one layer in a layered notification system, gives it a small and stable signal vocabulary, and defines what the household should assume when the bulb goes dark.

What the bulb can and cannot carry

Use the bulb for awareness events: someone is at the door, the washing machine finished, a package arrived, a household member wants attention. These are convenience signals where a missed event is annoying, not dangerous.

Do not use the bulb as the primary channel for life-safety events. Fire, smoke, carbon monoxide, and medical alerts need dedicated devices with their own power and their own certification. A Zigbee bulb that loses power, loses its mesh route, or sits behind a crashed Home Assistant instance will not flash. The bulb can duplicate a life-safety alert as a secondary cue, but it should never be the only path.

The same logic applies to the doorbell. A flashing bulb is useful when someone is in the room and looking at it. It does not wake a sleeping household member, and it does not reach someone in another room. Pair it with a vibration device or a phone push that the household member already trusts.

Prerequisites

You need three things working before the first automation is worth writing:

  • A Zigbee coordinator attached to Home Assistant. ZHA is a hardware-independent Zigbee gateway that creates a single Zigbee network and can replace most proprietary bridges, per the ZHA integration documentation. Zigbee2MQTT is the alternative if you already run an MQTT broker.
  • An RGB bulb paired to that network and exposed as a light entity in Home Assistant. The Light integration is the building block that provides the light.turn_on, light.turn_off, and light.toggle actions used below.
  • Home Assistant automations. The automation documentation covers the editor and the YAML structure; no coding is required for the basic version.

If you are running Zigbee2MQTT, confirm the bulb’s exposes before you design anything. The exposes documentation shows that a light expose can include state, brightness, color_temp, color_xy, and color_hs. Not every bulb exposes every feature. A bulb that only exposes color_temp cannot show a red-versus-green distinction, and no automation will change that.

Choose a small signal vocabulary

Three or four fixed meanings are easier to learn than a large palette, and they are easier to debug when something goes wrong. A workable starting set:

  • Blue, steady, low brightness — informational: package, mail, a non-urgent household message.
  • Green, steady, medium brightness — completion: laundry finished, oven timer done.
  • Amber, steady, medium brightness — attention: someone is at the door, someone in the house wants a response.
  • Red, brief flash, then off — urgent but not life-safety: a door left open, a freezer temperature excursion.

Reserve brightness and blink patterns for urgency, not for event type. If every event has its own blink rhythm, the household member has to memorize a codebook. If color carries the event and brightness or a single flash carries urgency, the vocabulary stays small.

Two practical constraints on color choice. First, some bulbs render XY colors poorly; the Zigbee2MQTT exposes documentation notes that setting colors via HS is preferred for that reason. Second, red and green are the pair most likely to be confused by anyone with color vision deficiency in the household. If that applies, substitute blue and amber and keep red for the urgent flash only.

Build the automation

The structure is the same for every event: a trigger, an optional condition, and a light.turn_on action with color and brightness. A minimal YAML example for a doorbell event:

alias: Status bulb - doorbell
trigger:
  - platform: state
    entity_id: binary_sensor.front_doorbell
    to: "on"
action:
  - service: light.turn_on
    target:
      entity_id: light.status_bulb
    data:
      hs_color: [30, 100]
      brightness_pct: 60
      transition: 0.5
mode: restart

The transition value is a fade time in seconds. A half-second fade is noticeable without being startling. If the bulb supports a flash, the ESPHome light component documents a flash_length parameter that flashes a given color for a period and then returns to the previous state; that behavior is useful for the urgent tier, but it is an ESPHome feature, not a guarantee for every Zigbee bulb. Check what your specific bulb and integration actually support before relying on it.

If you are driving the bulb through Zigbee2MQTT directly rather than through a Home Assistant light entity, the MQTT topics documentation shows the shape: publish JSON to zigbee2mqtt/FRIENDLY_NAME/set with state, brightness (0–255), and color in XY. The same page shows that device state is published back to zigbee2mqtt/FRIENDLY_NAME as JSON. Going through the Home Assistant light entity is usually simpler and keeps the automation readable.

Verify the bulb, not the UI

This is the step most builds skip. Home Assistant will happily show a light entity as on with the color you requested while the physical bulb is unreachable. The UI reflects the intended state, not the delivered state.

Test by triggering each mapped event manually and watching the physical bulb. For each event:

  1. Fire the trigger from the automation editor’s run action, or toggle the source sensor.
  2. Watch the bulb. Confirm the color, brightness, and timing match the vocabulary.
  3. Check the automation trace for errors. The automation documentation points to trace and troubleshooting guidance when an automation does not behave as expected.
  4. Repeat with the bulb powered off, then powered back on. Note how long it takes to rejoin and whether the automation recovers on the next event.

If you are on ZHA, the integration considers a mains-powered device with no activity unavailable after a configurable timeout, defaulting to 7200 seconds (two hours). That default is too slow for a status indicator. Lower it — the ZHA documentation suggests 3600 seconds as an example — so a bulb that has lost power shows as unavailable sooner. Even then, two hours or one hour is a long time to trust a silent indicator.

Graceful degradation

The household member needs to know what the absence of a signal means. There are four failure modes worth designing for.

The bulb is offline

The bulb lost power, fell off the mesh, or was switched off at the wall. Home Assistant may not notice for up to the ZHA unavailable timeout. The automation will still fire and the light entity may still accept the command. The signal is not delivered, and nothing tells the household member that.

Mitigation: add a condition that checks the bulb is available before the action, and route the event to a secondary channel when it is not. A phone push or a second indicator on a different integration is enough. The point is that the event does not disappear silently.

The coordinator or Zigbee2MQTT is down

If Zigbee2MQTT is the bridge, it publishes its own state to zigbee2mqtt/bridge/state as a retained message with online or offline payloads, per the MQTT topics documentation. Home Assistant’s MQTT integration supports Birth and Last Will messages, and the MQTT integration documentation notes that the LWT message is sent on both clean and unclean disconnects. Use that to drive an availability condition on the status automations. If the bridge is offline, the bulb cannot be reached regardless of what the light entity says.

Home Assistant restarts or crashes

During a restart, automations do not run. Events that occur in that window are lost. There is no local fallback inside Home Assistant for this; the fallback has to be a device that does not depend on Home Assistant. A doorbell with its own chime, a vibration puck paired directly to a button, or a phone notification from the source device are all reasonable secondary paths.

The network is up but the mesh path is weak

A bulb at the edge of the mesh may receive commands intermittently. The symptom is a signal that sometimes arrives late or not at all, with no error in the trace. Adding a mains-powered Zigbee router between the coordinator and the bulb is the usual fix. The ZHA documentation notes that Zigbee networks depend heavily on router devices to expand coverage.

A repeatable test procedure

Run this after any change to the bulb, the coordinator, the mesh, or the automations:

  1. List every mapped event and its expected color, brightness, and timing.
  2. Trigger each event manually and confirm the physical bulb matches.
  3. Power-cycle the bulb and confirm it rejoins and responds to the next event.
  4. Stop the Zigbee bridge (or unplug the coordinator) and confirm the availability condition routes the event to the secondary channel.
  5. Restart Home Assistant and confirm automations reload and the bulb responds.
  6. Record the results with a date. A status indicator that was verified six months ago is not verified today.

If you maintain several small systems like this, the same audit discipline applies to the rest of the house. The audit guide for small systems covers the broader inventory and review process this indicator should be part of.

When a plain switch or a mechanical timer is the better choice

If the only event you need to signal is a recurring one — the laundry cycle, a daily reminder — a mechanical timer or a plug-in lamp timer is more reliable than this build. It has no coordinator, no broker, no automation, and no firmware. It also cannot be repurposed for a second event without rewiring. The Zigbee bulb earns its complexity when you need multiple events, remote triggering, and integration with sensors that already exist.

If the household member needs a signal they can feel rather than see, a vibration device is the right primary channel and the bulb is the secondary one. The bulb is a good fit for ambient awareness in shared rooms; it is a poor fit for reaching someone who is asleep, in another room, or not facing it.

FAQ

Can I use a bulb that only supports color temperature instead of full RGB?

Only if your vocabulary fits within warm-to-cool white. You lose the color-coded event distinction and have to rely on brightness and timing alone, which is harder to learn and easier to misread. Check the bulb’s exposes before committing.

How do I know the bulb actually received the command?

You do not, from the Home Assistant UI alone. The UI shows intended state. The only reliable confirmation is watching the physical bulb, or reading back the device state from Zigbee2MQTT’s state topic if you are running that bridge. Build the test procedure around the physical bulb.

What happens if the bulb is switched off at the wall?

The automation fires, the light entity may accept the command, and nothing visible happens. ZHA will eventually mark the device unavailable after its configured timeout, but that timeout defaults to two hours. Lower it, and add a secondary channel for events that matter.

Is this safe to use for a fire alarm?

No. A Zigbee bulb depends on mains power, a coordinator, a running Home Assistant instance, and a mesh path. Any of those can fail during the exact conditions a fire alarm needs to survive. Use a certified visual fire alarm as the primary channel and treat the bulb as an optional duplicate at most.

Do I need Zigbee2MQTT or is ZHA enough?

ZHA is enough for the basic build and is simpler to set up. Zigbee2MQTT gives you more visibility into device exposes and bridge state, which helps with debugging and with the availability conditions described above. Neither is required by the other; pick the one you already run and can maintain.