Skip to content

LN882H Bluetooth Low Energy Tracker Hub

The ln882h_ble_tracker component creates a global hub so that you can track Bluetooth Low Energy devices using your LN882H node (LibreTiny lightning-ln882h family, such as the WL2H-U and LN-CB3S V1.0 modules).

The component is compatible with the same BLE sensor platforms as ESP32 BLE Tracker, so existing YAML configurations using ble_presence, ble_rssi, ble_scanner, or bthome_mithermometer work on LN882H without modification.

NOTE

The LN882H is a single-core SoC — WiFi and BLE share the same ARM Cortex-M4F core. Running continuous BLE scanning during the ESPHome Native API connection handshake can prevent WiFi from completing the TCP handshake. The recommended approach is to set continuous: false so scanning does not start on boot, then start it once Home Assistant is connected. See Use on LN882H (single-core) below.

# Example configuration — passive scanning, starts only when HA is connected
ln882h_ble_tracker:
scan_parameters:
continuous: false # do not start on boot — let api: automation control this
api:
on_client_connected:
- ln882h_ble_tracker.start_scan:
continuous: true
on_client_disconnected:
- ln882h_ble_tracker.stop_scan:
binary_sensor:
- platform: ble_presence
mac_address: XX:XX:XX:XX:XX:XX
name: "BLE Presence"
sensor:
- platform: ble_rssi
mac_address: XX:XX:XX:XX:XX:XX
name: "BLE RSSI"
- platform: bthome_mithermometer
mac_address: XX:XX:XX:XX:XX:XX
temperature:
name: "Temperature"
humidity:
name: "Humidity"
battery_level:
name: "Battery Level"
signal_strength:
name: "RSSI"
  • scan_parameters (Optional): Advanced parameters for configuring the scan behaviour. See also this guide by Texas Instruments for background reading.

    • interval (Optional, Time): The interval between each consecutive scan window. The scanner cycles through the three BLE advertising channels at this rate. On the LN882H, a larger interval leaves more CPU time for WiFi. Defaults to 500ms.

    • window (Optional, Time): The time the receiver is actively listening for packets on a channel during each scan interval. Must be ≤ interval. Defaults to 30ms.

    • duration (Optional, Time): The length of each complete scan session. When continuous is true the scanner restarts immediately after each session ends. Defaults to 5min.

    • active (Optional, boolean): When true the scanner sends scan-request packets to request additional advertisement data (scan response). Most BTHome and ATC thermometer firmware variants broadcast ADV_NONCONN_IND and never respond to scan requests; setting active: false avoids wasting radio time on unanswered requests. Defaults to false.

      NOTE

      On LN882H, scan responses (SCAN_RSP) are dropped in the BLE driver before reaching any sensor or automation — active: true transmits SCAN_REQ packets but delivers no additional data compared to active: false. Always use active: false on LN882H.

    • continuous (Optional, boolean): When true the scanner restarts automatically after each duration period. When false scanning must be started explicitly with the ln882h_ble_tracker.start_scan action or will be managed by the Bluetooth Proxy. Defaults to true.

  • bluetooth_proxy (Optional, boolean): When true, raw BLE advertisements are forwarded to Home Assistant over the ESPHome Native API, enabling the HA Bluetooth integration to see BLE devices through this node. The proxy automatically starts and stops scanning as Home Assistant subscribes and unsubscribes, overriding the continuous setting. Defaults to false.

  • id (Optional, ID): Manually specify the ID used to reference this component in lambdas and actions.

Automations:

This automation will be triggered when a BLE advertising packet is received. A variable x of type API Reference: esp32_ble_tracker::ESPBTDevice is passed to the automation for use in lambdas.

ln882h_ble_tracker:
on_ble_advertise:
- mac_address:
- XX:XX:XX:XX:XX:XX
- XX:XX:XX:XX:XX:XX
then:
- lambda: |-
ESP_LOGD("ble_adv", "New BLE device");
ESP_LOGD("ble_adv", " address: %s", x.address_str().c_str());
ESP_LOGD("ble_adv", " name: %s", x.get_name().c_str());
ESP_LOGD("ble_adv", " Advertised service UUIDs:");
for (auto uuid : x.get_service_uuids()) {
ESP_LOGD("ble_adv", " - %s", uuid.to_str().c_str());
}
ESP_LOGD("ble_adv", " Advertised service data:");
for (auto data : x.get_service_datas()) {
ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_str().c_str(), data.data.size());
}
ESP_LOGD("ble_adv", " Advertised manufacturer data:");
for (auto data : x.get_manufacturer_datas()) {
ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_str().c_str(), data.data.size());
}
  • mac_address (Optional, list of MAC Address): The MAC address to filter for this automation.
  • See Automation.

on_ble_manufacturer_data_advertise Trigger

Section titled “on_ble_manufacturer_data_advertise Trigger”

This automation will be triggered when a BLE advertising packet with manufacturer-specific data is received. A variable x of type std::vector<uint8_t> is passed to the automation for use in lambdas.

sensor:
- platform: template
name: "BLE Sensor"
id: ble_sensor
ln882h_ble_tracker:
on_ble_manufacturer_data_advertise:
- mac_address: XX:XX:XX:XX:XX:XX
manufacturer_id: 0590
then:
- lambda: |-
if (x[0] != 0x7b || x[1] != 0x61) return;
int value = x[2] + (x[3] << 8);
id(ble_sensor).publish_state(value);
  • mac_address (Optional, MAC Address): The MAC address to filter for this automation.
  • manufacturer_id (Required, string): 16-bit, 32-bit, or 128-bit BLE manufacturer ID in hex.
  • See Automation.

This automation will be triggered when a BLE advertising packet with service data is received. A variable x of type std::vector<uint8_t> is passed to the automation for use in lambdas.

sensor:
- platform: template
name: "BLE Sensor"
id: ble_sensor
ln882h_ble_tracker:
on_ble_service_data_advertise:
- mac_address: XX:XX:XX:XX:XX:XX
service_uuid: FCD2
then:
- lambda: 'id(ble_sensor).publish_state(x[0]);'
  • mac_address (Optional, MAC Address): The MAC address to filter for this automation.
  • service_uuid (Required, string): 16-bit, 32-bit, or 128-bit BLE service UUID in hex (e.g. FCD2 for BTHome v2, 181A for Environmental Sensing).
  • See Automation.

This automation will be triggered when a Bluetooth scan session has completed. When continuous is true this fires at the end of every scan cycle.

ln882h_ble_tracker:
on_scan_end:
- then:
- lambda: |-
ESP_LOGD("ble_auto", "The scan has ended!");

Start a Bluetooth scan. If a scan is already in progress the action is ignored.

ln882h_ble_tracker:
scan_parameters:
continuous: false
on_...:
- ln882h_ble_tracker.start_scan:
continuous: true
  • continuous (Optional, boolean): Whether to restart the scan automatically after each duration period. Defaults to true.

Stop the running Bluetooth scan. It can be restarted with ln882h_ble_tracker.start_scan.

on_...:
- ln882h_ble_tracker.stop_scan:

Unlike the ESP32 which runs BLE on a dedicated core, the LN882H runs both WiFi and BLE on the same ARM Cortex-M4F core at 160 MHz. Continuous BLE scanning during the initial ESPHome Native API TCP connection handshake can prevent WiFi from completing the connection. The recommended workaround is to start scanning only once Home Assistant is connected, and stop it when HA disconnects.

ln882h_ble_tracker:
scan_parameters:
continuous: false # do not start on boot
api:
on_client_connected:
- ln882h_ble_tracker.start_scan:
continuous: true
on_client_disconnected:
- ln882h_ble_tracker.stop_scan:

When bluetooth_proxy: true, the proxy starts and stops scanning automatically as Home Assistant subscribes and unsubscribes to BLE advertisements, so no api: automation is needed:

ln882h_ble_tracker:
bluetooth_proxy: true
scan_parameters:
continuous: false # proxy manages start/stop; false avoids scanning before HA connects

NOTE

The 6 % scan duty cycle (window / interval = 30 ms / 500 ms) leaves ample WiFi bandwidth to maintain the Native API connection. Devices that advertise every 10 seconds are still reliably detected — the scanner completes approximately 20 windows per advertising cycle.

The ble_scanner text sensor publishes a JSON string for every received advertisement and is the easiest way to verify that your LN882H node is picking up BLE packets and to discover MAC addresses of nearby devices.

ln882h_ble_tracker:
scan_parameters:
continuous: false # do not start on boot
api:
on_client_connected:
- ln882h_ble_tracker.start_scan:
continuous: true
on_client_disconnected:
- ln882h_ble_tracker.stop_scan:
text_sensor:
- platform: ble_scanner
name: "BLE Scanner"

Each advertisement is published as a JSON payload containing the MAC address, RSSI, and raw advertisement data. You can read it from the Home Assistant logbook or the ESPHome logs to confirm a target device is visible before configuring a dedicated sensor for it.