TapHome

Aqara Motion Sensor (RTCGQ11LM)

Packet Parser → MQTT
Submitted by
Last updated: 06. 2026

Requires external gateway

Zigbee2MQTT Zigbee2MQTT bridge (any supported Zigbee coordinator — e.g. Sonoff ZBDongle-E/P, CC2652, ConBee II) — product page

Aqara Motion Sensor (RTCGQ11LM)

The Aqara RTCGQ11LM (sold in some markets as the Xiaomi Mi Motion Sensor) is a compact battery-powered Zigbee 3.0 PIR occupancy sensor using a CR2450 coin cell. It communicates with TapHome indirectly — the sensor pairs with a Zigbee2MQTT coordinator (e.g., Sonoff ZBDongle-P/E or a CC2652-based stick), which bridges the Zigbee messages to MQTT topics. TapHome subscribes to those MQTT topics via a PacketParser MQTT module.

The template maps the sensor as a binary occupancy input (motion / no motion) and exposes battery percentage, raw battery voltage and Zigbee link quality as service attributes.

Configuration

Zigbee2MQTT setup

Before importing the TapHome template, the RTCGQ11LM must be paired with a Zigbee2MQTT coordinator:

  1. Open the Zigbee2MQTT web UI and enable pairing mode (Permit join)
  2. On the RTCGQ11LM, press and hold the reset button for approximately 5 seconds, until the blue LED begins blinking
  3. The device appears in the Zigbee2MQTT device list with an IEEE address (e.g., 0x00158d00036cd3e2). Optionally set a friendly name in the Zigbee2MQTT web UI under the device settings.

If pairing is unsuccessful, try a single short button press instead of a long hold. On CC2531-based coordinators, removing and reinserting the USB stick before restarting Zigbee2MQTT often fixes stuck pairing.

Module variable

After importing the template in TapHome, set the XiaomiRTCGQ11LM custom variable to identify the device on the MQTT broker:

VariableDescriptionHow to obtainExample
XiaomiRTCGQ11LMZigbee2MQTT friendly name or IEEE address of this RTCGQ11LMZigbee2MQTT web UI → Devices → find RTCGQ11LM → copy IEEE or friendly name0x00158d00036cd3e2

The default placeholder in the template (0x00158d00036cd3e2) is an example and must be replaced with the actual address of your sensor. The listener script subscribes to zigbee2mqtt/{XiaomiRTCGQ11LM} and parses the JSON state payload.

Using a friendly name (e.g. hallway_motion) instead of the raw IEEE address makes the configuration more readable and keeps it stable if the sensor is ever re-paired.

Device capabilities

Motion detection

The template maps the sensor as a Reed Contact device in TapHome. The reed-contact naming is a template-side convention; the behaviour is a standard PIR occupancy input. Motion events arrive on the zigbee2mqtt/{id} topic as JSON and are mapped to a numeric state:

Zigbee2MQTT payloadTapHome value
"occupancy": true1 (motion)
"occupancy": false0 (idle)
other / missingNaN

The first occupancy: true message is published on the first motion event after the device joins the network — not on pairing completion.

The RTCGQ11LM hardware enforces a 60-second dead zone after every detection: once motion is reported, the sensor ignores further movement for 60 seconds. The Zigbee2MQTT occupancy_timeout option should therefore be left at the default 90 s (or higher) — values below 60 s would generate an occupancy: false message while a person is still present. This limit cannot be bypassed without a hardware modification.

The sensor instance exposes three read-only service attributes parsed from the same JSON state message:

  • Battery — remaining battery percentage (0–100 %), formatted as "N%". May take up to 24 hours to report the first value after pairing. Shown as "-" until the first message arrives.
  • Voltage — raw battery voltage in millivolts (typically ~3000 mV on a fresh CR2450), formatted as "N mV". Useful as an independent low-battery signal — battery percentage can still look healthy while the cell is already too weak for reliable Zigbee transmissions.
  • LinkQuality — Zigbee link quality indicator (0–255 LQI), formatted as "N lqi". Values below 20 generally indicate an unreliable link.
Capabilities not currently mapped

The RTCGQ11LM also publishes the following entities via Zigbee2MQTT that are not parsed by this template — they can be added by extending the listener script in a future template revision:

  • illuminance / illuminance_lux — ambient light level in lux (useful for lux-gated motion automations)
  • device_temperature — internal chip temperature in °C (diagnostic only, not ambient room temperature)
  • power_outage_count — counter of battery-removal events

The Zigbee2MQTT availability topic (zigbee2mqtt/{id}/availability) and the occupancy_timeout configuration option (zigbee2mqtt/bridge/request/device/options) are also not handled by the template; LinkQuality and Battery are the recommended liveness signal for this sleep-capable device.

Troubleshooting

Sensor not reporting any state
  1. Verify the RTCGQ11LM appears in the Zigbee2MQTT device list with a green status.
  2. Check that the XiaomiRTCGQ11LM variable matches the friendly name or IEEE address exactly — it is case-sensitive for friendly names.
  3. Trigger motion in front of the sensor. The first state message is only published on the first detection after join.
  4. Use an MQTT client (e.g. MQTT Explorer) to subscribe to zigbee2mqtt/# and confirm that messages appear on zigbee2mqtt/{your_name} when motion is triggered.
Motion still active long after the person left

This is the expected 60-second hardware dead zone combined with the Zigbee2MQTT occupancy_timeout (default 90 s). The sensor does not report occupancy: false until the timeout expires with no further motion. Shorter timeouts are not reliable — the sensor simply ignores motion for the first 60 s after detection.

Random disconnections

Common causes for Aqara/Xiaomi end-devices dropping from the Zigbee mesh:

  1. Weak signal — check LinkQuality; values below 20 usually mean the sensor needs a closer mains-powered Zigbee router.
  2. Low battery voltage — the Voltage attribute is a better indicator than the percentage. Zigbee2MQTT explicitly notes that the sensor can drop from the network even while the reported battery percentage still looks healthy, so watch for a noticeable drop from the ~3000 mV fresh-cell value and replace the CR2450 when the link becomes unreliable.
  3. Incompatible routers — Centralite, General Electric, Iris, Ledvance, Legrand, OSRAM, Sylvania, SmartThings and Securifi routers are known to cause retention issues for older Xiaomi/Aqara devices. Bonding the sensor directly to the coordinator (reset the sensor while next to the coordinator) often resolves this.

Aqara Zigbee end-devices do not support pinging in standard Zigbee2MQTT availability mode and may appear offline even when working normally. Do not rely on the Zigbee2MQTT availability topic for liveness — use LinkQuality and Battery as health indicators instead.

How to install in TapHome

Prerequisites

  • Zigbee gateway with Tasmota firmware (e.g., Sonoff ZBBridge, eWeLink ZB-GW03)
  • MQTT broker running on your local network (TapHome built-in broker or external)
  • TapHome CCU on the same network

TapHome has a built-in MQTT broker — enable it in SettingsHardwareMQTT Broker. No additional software is needed.

Step 1 — Set Up the Tasmota Zigbee Gateway

  1. Flash Tasmota firmware on a supported Zigbee coordinator (e.g., Sonoff ZBBridge, eWeLink ZB-GW03)
  2. Connect the gateway to your Wi-Fi network via the Tasmota web UI
  3. Navigate to ConfigurationConfigure MQTT and set:
    • Host: your MQTT broker IP (e.g., 192.168.1.10)
    • Port: 1883
    • Topic: note down the topic name (e.g., tasmota_XXXXX) — you will need it during template import

For detailed instructions, see the Tasmota Zigbee documentation.

Step 2 — Import the Gateway Template in TapHome

  1. Download the gateway template from the Zigbee2Tasmota Gateway compatibility page
  2. In TapHome, go to SettingsHardwarePacket ParserImport
  3. Import the template with these parameters:
    • MQTT Broker IP Address: your broker IP (e.g., 192.168.1.10)
    • MQTT Broker Port: 1883
    • Gateway name: the Tasmota MQTT topic from Step 1 (e.g., tasmota_XXXXX)

After import, you will see two devices: Permit Join (switch) and Devices Found (counter).

Step 3 — Pair a Zigbee Device

  1. In TapHome, turn on the Permit Join switch — this opens a 60-second pairing window
  2. On the Zigbee device, start the pairing procedure (typically hold the reset button for 5 seconds until the LED blinks)
  3. Watch the Devices Found counter — it increments when a new device joins
  4. Check the Service Attributes of the gateway to see the new device’s ID (e.g., 0x1234), manufacturer, and model
  5. The pairing mode deactivates automatically after the timeout

Step 4 — Import the Device Template

  1. Download the device-specific template from the corresponding compatibility page
  2. Import the template with these parameters:
    • MQTT Broker IP Address: same as the gateway
    • MQTT Broker Port: 1883
    • Gateway name: same Tasmota MQTT topic as above
    • Device ID: the short address from pairing (e.g., 0x1234)

Available devices

Aqara Motion Sensor (RTCGQ11LM) Module
Custom Variables
XiaomiRTCGQ11LM (string) = 0x00158d00036cd3e2Zigbee2MQTT friendly name or IEEE address (0x… 16-hex) of this RTCGQ11LM — used as the MQTT topic suffix zigbee2mqtt/{this}. Default placeholder must be replaced with the real sensor address after pairing.
Motion Sensor Reed Contact Read-only

PIR occupancy detection — reports motion (1) when detected, idle (0) after the 60 s hardware dead zone and the Zigbee2MQTT occupancy_timeout expire.

boolean JSON (PARSEJSON on occupancy key)
Service Attributes
BatteryRemaining battery percentage (CR2450 coin cell, 0–100 %). Formatted as 'N%'; may take up to 24 h to report the first value after pairing.
VoltageRaw battery voltage in millivolts (~3000 mV on a fresh CR2450). More precise low-battery indicator than the percentage.
LinkQualityZigbee link quality indicator (0–255 LQI). Values below 20 typically indicate an unreliable link and frequent disconnections.

Motion Sensor

Read (module)
# Simple HTTP Request:
# VAR response := SENDHTTPREQUEST("/example/getValue");
# IF response.IsSuccess
#  VAR content := response.Content;
#  VAR responseHeaders := response.Headers;
#  RETURN(PARSEXML(content, "//element1/value1"));
# ELSE
#  ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
#  RETURN(NaN);
# END
#
# Set Http request method, body and headers
# VAR response := SENDHTTPREQUEST("/example/getValue", "GET", "some data", "header1:value1", "header2:value2", ...);
# OR
# VAR request := HTTPREQUEST("/example/getValue", "POST", "some data");
# request.headers := { "header1:value1", "header2:value2", ...};
# request.method := "GET";
# request.data := null;
# VAR response := SENDHTTPREQUEST(request);
#
#
# Send TCP, UDP data:
# VAR data1 := BYTECOLLECTION("0a bb ea df 01");
# SENDDATA(data1);
# VAR data2 := "{\"name\":\"John\", \"age\":32}";
# SENDDATA(data2);
# VAR data3 := TOBYTES("{\"name\":\"John\", \"age\":32}", "iso-8859-1");
# SENDDATA(data3);
# Process received TCP or UDP data and set device values in the Listener script
#
#
# Download data from FTP:
# FTPDOWNLOAD("filePath");
Listener
IF (COMPARE(RECEIVEDMSG.TOPIC, "zigbee2mqtt/"+ XiaomiRTCGQ11LM, CompareOptions.IgnoreCase) = 0)
    VAR value := TOSTRING(PARSEJSON(RECEIVEDMSG.PAYLOAD, "occupancy")); 
    IF (COMPARE(value, "true", CompareOptions.IgnoreCase) = 0)
        Rc := 1; 
    ELSEIF (COMPARE(value, "false", CompareOptions.IgnoreCase) = 0)
        Rc := 0;
    ELSE
        Rc := NaN;
    END   
    battery := PARSEJSON(RECEIVEDMSG.PAYLOAD,"battery", true);
    voltage := PARSEJSON(RECEIVEDMSG.PAYLOAD,"voltage", true);
    link := PARSEJSON(RECEIVEDMSG.PAYLOAD,"linkquality", true);
END;
Service Attributes
Battery
IF(ISNAN(battery),"-",battery+"%");
Voltage
IF(ISNAN(voltage),"-",voltage+"mV");
LinkQuality
IF(ISNAN(link),"-",link+"lqi");
Connection: Packet Parser → MQTT
Possible improvements (5)
  • Illuminance — illuminance / illuminance_lux JSON key (unit lx, 0+). Ambient light level reported alongside occupancy. Could drive lux-gated motion automations (e.g. only switch lights below 50 lx). Not parsed by the current listener script — would require an additional PARSEJSON call plus a service_attribute entry.
  • Device Temperature — device_temperature JSON key (unit °C). Internal chip temperature — not ambient room temperature. Useful for diagnostic alerts (overheating, direct sunlight on the sensor) but not for climate control. Not parsed by the current listener script.
  • Power Outage Count — power_outage_count JSON key (integer). Increments when the battery is removed/reinserted or the device loses power. Could detect tampering or battery swaps. Not parsed by the current listener script.
  • Availability (LWT) — online / offline string payload published by Z2M if availability is enabled globally or per device (availability: true in configuration.yaml). Could detect dropped sensors. Not subscribed by the current template.
  • Occupancy Timeout Configuration — occupancy_timeout (seconds, minimum 60, default 90) controls how long after motion the sensor waits before reporting occupancy: false. Currently set via Z2M frontend / configuration.yaml — TapHome template does not expose this as a setting and does not publish to bridge/request topics.

Sources

Found a problem with this device template?

Tell us what's wrong, what's missing, or how the template should behave. We rely on your feedback to keep the catalog accurate.

Verified by TapHome

Want to use this in your TapHome Core?

Open this template in the Customer Portal to apply it to one of your homes, or to draft a refinement and submit it back to the catalog.

Open in portal