Skip to content

About

Home Assistant custom integration for STEINEL Connect Bluetooth Mesh lamps (on/off, brightness, firmware update) - works over local adapters and Bluetooth proxies

Topics

Resources

Stars

6 stars

Watchers

2 watching

Forks

Repository files navigation

STEINEL

STEINEL Connect BLE for Home Assistant

HACS Custom Validate MIT License

A Home Assistant custom integration for local control of STEINEL Connect Bluetooth Mesh devices, including the L 845 C. It supports discovery, provisioning, on/off and brightness control, and automatically exposes colour temperature, colour and sensor features when the device implements the required models.

Communication works through Home Assistant Bluetooth adapters and ESPHome Bluetooth proxies. No cloud account or STEINEL gateway is required.

The protocol was independently reverse-engineered from the official STEINEL Connect Android app and validated against real hardware. This project is not affiliated with or endorsed by STEINEL and does not use an official STEINEL SDK. See Legal.

Features

  • Existing Mesh import - import a STEINEL Connect App JSON export to use already provisioned lamps without resetting them. Groups, scenes, motion automation, twilight and basic-light settings remain in the native Mesh.

  • Bluetooth discovery - devices advertising the Bluetooth Mesh Provisioning or Proxy service are discovered automatically by Home Assistant.

  • PB-GATT provisioning - an unprovisioned lamp receives a randomly generated NetKey, AppKey and Device Key owned by its Home Assistant config entry.

  • Automatic recovery from another mesh - if a lamp is already provisioned into an unknown Bluetooth Mesh network, the integration attempts STEINEL's proprietary Global Reset and then provisions the device without requiring the old mesh keys.

  • Adaptive model support - Composition Data is read after provisioning and the AppKey is bound only to models actually present on the device. Supported models include Generic OnOff, Light Lightness, Light LC, Light CTL and Light HSL.

  • Standard Home Assistant light entities - on/off and brightness are available where supported. Colour temperature and HS colour are exposed automatically for compatible lamps.

  • Remembered brightness - turning a lamp off and back on restores the last brightness acknowledged by Home Assistant, including devices that otherwise return to their configured 100% OnPowerUp level. Acknowledged light state is retained across Home Assistant and integration restarts.

  • Optional sensor entities - devices with the STEINEL Sensor Extension model can expose presence, motion, people count, temperature, humidity, CO₂, VOC, noise, ambient illuminance, air pressure, dew point, and time-since-motion/presence values. Unsupported properties remain unavailable. All properties of a device are refreshed by one shared polling cycle so they do not establish competing BLE sessions; light commands take priority over background polling. Sensor data uses the packed Format A/B property headers used by STEINEL's app. Both polling replies and live reports update motion, including the transition back to clear. Unknown or invalid motion/presence values are unavailable rather than being reported as detected.

  • Light LC configuration - compatible sensor lights expose controls for automatic light control, motion automation, main-light brightness and time, basic-light brightness and time, and the ambient-light threshold. This includes the corresponding functions used by products such as the L 810 SC. Controller and sensor models may occupy different Mesh elements, as on the L40 SC; a separate ambient-lux sensor entity is not required.

  • Bluetooth proxy support - connections use Home Assistant's Bluetooth stack and bleak-retry-connector, so an ESPHome proxy such as the XIAO ESP32S3 can provide the BLE connection.

  • Acknowledged state updates - acknowledged Bluetooth Mesh status messages update the entity state in Home Assistant.

  • Initial state retrieval - after connecting, the integration queries the on/off, lightness, CTL and HSL states supported by the element, avoiding an unknown light state when the device responds.

  • Reachability tracking - every configured device has a Bluetooth device_tracker that reports home while its Mesh Proxy connection is usable or the device has advertised recently. This remains meaningful when idle disconnect is enabled and no permanent GATT connection is held.

  • Advertised device information - product ID, firmware, hardware revision, bootloader and device hash are read passively from manufacturer data where the firmware advertises them.

  • Proxy connection queue - connection establishment is serialized across STEINEL entries, avoiding simultaneous connection attempts that can exhaust a small ESPHome proxy's BLE slots.

  • Guided reset repair - a failed foreign-mesh reset creates an actionable Home Assistant repair that explains the power-cycle timing and retries setup immediately after confirmation.

  • Diagnostics and configurable behaviour - credential-free diagnostics, background reconnection, command timeouts, retry counts, sensor polling and brightness restoration can be managed from the integration options.

Installation

This repository is not currently part of the default HACS store. Add it as a HACS custom repository or install it manually.

HACS (recommended)

Add to HACS

The badge requires HACS and the My Home Assistant integration. Alternatively:

  1. Open HACS and select the ⋮ menu in the top-right corner.
  2. Select Custom repositories.
  3. Add https://github.com/matze19999/steinel-ble as type Integration.
  4. Find and install STEINEL Connect Bluetooth Mesh.
  5. Restart Home Assistant.

The integration is then available under Settings → Devices & services → Add integration → STEINEL Connect Bluetooth Mesh. Home Assistant may also offer it automatically after discovering a compatible device.

Manual

Copy custom_components/steinel_ble into the custom_components directory of your Home Assistant configuration and restart Home Assistant.

Requirements

  • Home Assistant 2026.8 or newer
  • A connectable local Bluetooth adapter or ESPHome Bluetooth proxy in range
  • A compatible STEINEL Connect Bluetooth Mesh device

If the device requires a 16-byte Static OOB key, enter its 32 hexadecimal characters during setup. Otherwise leave the field empty to use No OOB provisioning.

Setting up a device

  1. Power the STEINEL device and keep it within reliable Bluetooth range of the adapter or proxy.
  2. Open Settings → Devices & services. Select the discovered device, or use Add integration → STEINEL Connect Bluetooth Mesh and enter its Bluetooth address.
  3. Confirm the device and optionally enter its Static OOB key.
  4. The integration provisions the device, reads its Composition Data, adds the AppKey, binds its supported models and creates the applicable entities.

Each configured lamp stores its own Bluetooth Mesh credentials in its Home Assistant config entry. Include Home Assistant's .storage configuration in backups: losing the NetKey, AppKey or Device Key also loses authenticated access to the provisioned device.

Device already belongs to another mesh

To keep the existing Mesh, enable Keep existing Mesh: import STEINEL App JSON during manual setup or in the discovered device's setup dialog:

  1. Export the network from STEINEL Connect and paste the JSON file's contents into the import form.
  2. Select the exported node matching the lamp's Bluetooth address and choose an AppKey already bound to its models. The app's provisioner is omitted.
  3. Reserve a separate, unused unicast source address for this Home Assistant entry in the network's address allocation. Enter it as hexadecimal. Do not reuse the phone's or a lamp element's address. Each imported HA entry needs its own source address, and future provisioners must not allocate it.
  4. Enter the network's current IV Index if known, or use 0 as an initial value when the export omits it. The integration authenticates Secure Network or Mesh Private beacons with the imported NetKey and synchronizes the full IV Index before sending commands. Enter the source's next unused sequence number as a decimal number. Sequence 0 is suitable only for a source that has never transmitted; restoring an old source requires a value above every sequence it previously used.
  5. Close STEINEL Connect to release its BLE connection, then finish setup.

The integration connects directly to the existing Mesh Proxy. It does not reset the lamp, add AppKeys, rebind models, change subscriptions, or overwrite scenes. Only models already bound to the chosen AppKey are exposed. Model rescans restore these imported bindings and repeat read-only sensor detection. Control commands and explicit edits of configuration entities still change the corresponding live device states and settings.

Only the chosen node's credentials and model composition are stored; the full export is not retained. Keys are redacted from diagnostics. Keep exports private and do not add them to this repository. Finish any ongoing Mesh Key Refresh before importing. On connection, the integration waits up to ten seconds for an authenticated beacon. Verified IV state is saved without resetting the sequence number or source address. During IV Update, the previous index is used for transmission and both current and previous-index replies are supported. If no beacon arrives, the configured IV state is used unless incoming traffic already indicates an IVI mismatch; that case fails with an explanatory connection error. No index is guessed from IVI alone and a persisted IV Index is never automatically rolled back. The integration does not reset the lamp. Re-export and recreate the entry if model bindings change in the app.

If you prefer to replace the existing Mesh, leave the import option disabled and follow the reset procedure below.

The integration can reset a provisioned STEINEL device without knowing its existing mesh keys. The lamp only accepts this command during a short window after mains power is applied, and it must not already be connected to another Bluetooth client.

When Home Assistant discovers a provisioned device, the setup dialog displays the required preparation steps:

  1. Completely close the STEINEL app and any other app that may connect to the lamp. Merely leaving the app in the background may not be sufficient.
  2. Briefly disconnect the lamp from mains power.
  3. Restore power and submit the Home Assistant setup form immediately.
  4. Home Assistant attempts the Global Reset, waits for the Mesh Provisioning service and then continues setup automatically.

If the reset window was missed, remove or reload the failed integration entry and repeat the power-cycle procedure. Do not open the STEINEL app during this process.

Options and diagnostics

Lamp settings

After updating and restarting Home Assistant, open the lamp under Settings → Devices & services → STEINEL Connect Bluetooth Mesh and expand its Configuration section. Compatible occupancy-sensing lamps expose:

  • main-light brightness and duration;
  • basic-light brightness and duration;
  • the Light LC light threshold;
  • automatic light control; and
  • motion automation.

Sensor and controller addresses are matched across the same node. Values are read from the LC controller's own address, not from the sensor element. Property edits require both the LC Server and LC Setup Server to be bound to the selected AppKey. The two mode switches only require the LC Server. Models and bindings imported from the App remain unchanged, and setup does not turn automation on or overwrite existing settings. Edits are displayed only after receiving a valid status reply. An unsupported or unreadable property can remain unavailable without disabling the rest of the device.

Existing entries do not need to be removed or reimported. If occupancy sensing was not previously detected, use the integration's Configure → Rescan models and sensor properties option once. Standard LC settings are exposed here; vendor-specific Eco/Nightmatic modes, detection range, scenes and schedules are not added by this version.

Connection options

Open Settings → Devices & services → STEINEL Connect Bluetooth Mesh, select the device and choose Configure to adjust:

  • BLE connection and Provisioning Invite attempts;
  • the acknowledged Mesh command timeout;
  • the sensor polling interval;
  • remembered-brightness restoration and its delay; and
  • optional release of an idle BLE connection and the idle delay; and
  • the time after which a missing Bluetooth advertisement marks the device as unreachable; and
  • a one-time rescan of Composition Data and sensor properties.

Changing an option reloads only that device. Persistent BLE connections remain the default and provide the fastest response. Enabling idle disconnect frees a proxy connection slot after the configured period, but the next command must first reconnect and therefore responds more slowly. In testing with a XIAO ESP32S3 Bluetooth proxy and an L 845 C, a command after an idle disconnect took approximately 12 seconds. The actual delay depends on signal quality, proxy load and the STEINEL device. Unexpected connection losses are handled in the background with exponential backoff.

The rescan option is a one-time action when saving: it clears the model and sensor discovery cache and reloads the device, even if no other option changed. It returns to off afterward. Updating from versions before 0.7.1 automatically repeats sensor discovery once with the corrected sensor parser; no reset or reimport is needed.

Home Assistant's device diagnostics download includes model composition, detected sensor properties, active and passive reachability, last advertisement, connection state, reconnect count, Bluetooth source and RSSI. sensor_raw_values includes the decoded properties' raw value bytes (without their packed headers), alongside sensor_values. NetKey, AppKey, Device Key and Static OOB values are always redacted.

A lamp can expose both a physical light element and a separate Light LC control element. The latter is named Light control (0x...), with its Mesh element address, rather than appearing as a second identically named light. These entities control different Mesh models and do not necessarily represent two separate bulbs.

A missing status reply causes the individual light command to fail; it does not mark every sensor unavailable while BLE remains connected. Actual transport errors start background reconnection automatically.

If commands still time out, download device diagnostics before reloading the entry. mesh_receive_counts separates unrelated network traffic (network_other_key), an IVI mismatch (network_iv_mismatch), failed network authentication (network_invalid), and authenticated Network/Access messages. A matching NID or IVI alone does not prove the NetKey or full IV Index is correct. An access_other_key count indicates an application-key identifier mismatch; access_invalid includes failed Access authentication or malformed messages. These counters reset when the Mesh connection is recreated. Share the integration's diagnostics and debug log, not the original App JSON export. mesh_iv_state also shows the local and transmit IV Index, IV Update state, and the most recently authenticated beacon's public IV and flag fields. Beacon authentication follows the Bluetooth Mesh Protocol specification, including its Secure Network and Mesh Private beacon test vectors.

How it works

After provisioning, the integration:

  1. reconnects through the best connectable Bluetooth path;
  2. configures the Mesh Proxy filter for the node;
  3. reads the node's Composition Data;
  4. adds the application key;
  5. binds supported Generic, Light and known STEINEL vendor models; and
  6. creates entities only for applicable elements and model families.

Both outgoing and incoming segmented lower-transport messages are supported. GATT Proxy fragments belonging to one PDU are sent together, including when access messages and transport acknowledgements are produced concurrently. Normal control uses acknowledged access messages so returned device states can be reflected in Home Assistant.

Troubleshooting

Enable debug logging when investigating a connection, reset or provisioning problem:

logger:
  logs:
    custom_components.steinel_ble: debug

Bluetooth Mesh Provisioning and Proxy advertisements can take time to change after provisioning or reset. The integration clears a stale GATT service cache where supported and retries setup automatically.

For a failed automatic reset, first verify that:

  • the STEINEL mobile app is fully closed;
  • no phone or other Bluetooth client is connected to the lamp;
  • the lamp was power-cycled immediately before setup was confirmed;
  • the Bluetooth proxy has a free connection slot and a reliable signal; and
  • the device is still visible to Home Assistant as connectable.

Limitations

  • Automatic Global Reset depends on a short device-specific startup window and may require repeating the power-cycle procedure.
  • The L 845 C is the primary hardware used for real-device validation. Other devices are detected by their advertised services and model composition, but not every STEINEL product and firmware version has been tested.
  • Sensor support depends on STEINEL's vendor Sensor Extension model. Entities for properties not implemented by a device remain unavailable.
  • Scene management, additional vendor-specific settings, firmware updates and Bluetooth Mesh BLOB/DFU are not currently exposed.
  • A device without imported credentials is either provisioned as new or reset from its previous network during setup.

Development

Run the local checks with:

python -m pip install -r requirements-test.txt
ruff check custom_components tests
ruff format --check custom_components tests
pytest

Contributing

Issues and pull requests are welcome. Reports from STEINEL Connect products other than the L 845 C are particularly useful. Please include the model, firmware version, discovered Composition Data and relevant debug logs where possible, but never publish mesh keys or other credentials.

Legal

This is an independent, community-built integration. It is not affiliated with, endorsed by, or sponsored by STEINEL Vertrieb GmbH or any of its affiliates. "STEINEL" and the STEINEL logo are trademarks of their respective owner and are used solely to identify the products with which this integration interoperates.

No STEINEL software, firmware or copyrighted application assets are included in this repository. The protocol implementation is independent work based on reverse-engineering for interoperability purposes.

Licensed under the MIT License.

About

Home Assistant custom integration for STEINEL Connect Bluetooth Mesh lamps (on/off, brightness, firmware update) - works over local adapters and Bluetooth proxies

Topics

Resources

Stars

6 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages