private@homelab: ~/latest
local-first guides · privacy-aware · no noisy tracking
private@homelab:~$ cat guides/article.md
· ·
7–11 minutes
read

Aqara Curtain Motor ZNCLDJ11LM: Zigbee2MQTT + Home Assistant Setup

Set up the original Aqara ZNCLDJ11LM curtain motor locally with Zigbee2MQTT and Home Assistant, including the mandatory calibration workflow.

Aqara Curtain Motor ZNCLDJ11LM: Zigbee2MQTT + Home Assistant Setup

If you searched for this model by its exact number, you probably already have one — this is the original Aqara curtain motor, sold before Aqara split the lineup into the B1 (ZNCLDJ12LM) and the E1 driver/roller-shade pair. It’s not the current product Aqara sells, but it’s still a real Zigbee device with real Zigbee2MQTT support, and it still runs entirely local once paired. The question isn’t whether it works in 2026; it’s whether the calibration step and a handful of reported quirks are worth the trouble compared to just buying a newer model.

Which curtain motor do you actually have?

Aqara has shipped several visually similar rail-mounted motors under names that only differ by two digits, which is the single biggest source of confusion in the community threads about this device:

  • ZNCLDJ01LM — an older, separate model with its own Zigbee2MQTT reference page. Different hardware, different Zigbee signature. If your device shows up under this model ID in Zigbee2MQTT, the instructions below don’t fully apply — check the ZNCLDJ01LM device page specifically.
  • ZNCLDJ11LM — the model this article covers. Sold as the standalone “Aqara Smart Curtain Motor,” designed to attach to an existing curtain rail.
  • ZNCLDJ12LM (B1) — the successor model, covered in our Aqara B1 curtain motor Zigbee2MQTT guide.

There’s also a completely different mechanism worth ruling out: the E1-generation curtain driver (ZNCLBL01LM) and roller shade driver (ZNJLBL01LM), which clip onto an existing rod or rail rather than replacing the whole track assembly. Our Aqara Curtain Driver E1 setup guide covers the rail-integrated driver, and the roller shade driver is a separate rod-mounted unit again. If your device came bundled with its own curtain track, you almost certainly have the ZNCLDJ11LM or its B1 successor, not an E1 driver.

This guide covers the Zigbee2MQTT path. If you run ZHA instead, the hub-free pairing concept is the same, but the exposed controls and quirk handling differ between the two stacks — our ZHA vs Zigbee2MQTT comparison walks through how to choose.

Pairing to Zigbee2MQTT

The ZNCLDJ11LM pairs to whatever Zigbee coordinator your Zigbee2MQTT instance is running on, not to an Aqara hub — like any other Zigbee device. That’s the whole point of running it this way: no Mi Home or Aqara Home app in the loop, no cloud round-trip to open your curtains.

Put your Z2M instance into pairing mode (permit_join: true for the network, or scoped to a specific point if you’re using router-based joining), then trigger pairing on the motor itself per Aqara’s physical pairing sequence for this model. Once it joins, it should show up in Z2M’s device list under the ZNCLDJ11LM model.

Calibration isn’t optional — do this before anything else

This is the part that trips people up, and it’s also the part the Zigbee2MQTT reference page is clear about if you read past the entity list: the motor will not report accurate position, and won’t support setting the curtain to a specific percentage open, until it’s been calibrated.

The workflow:

  1. Publish a reset_limits command to the device via MQTT (see the exact payload below).
  2. Manually close the curtain fully using the physical controls (or the app command, if you still have it installed for this one step).
  3. Wait — the motor needs a moment to register that it’s reached the closed end-stop.
  4. Manually open the curtain fully.

The motor exits calibration mode automatically once it’s learned both end limits, and from that point forward it reports position as a 0-100 percentage and accepts position commands rather than just open/close.

What the ZNCLDJ11LM exposes in Home Assistant

In Zigbee2MQTT the motor surfaces as a single cover entity. From the Z2M device definition you get:

  • StateOPEN, CLOSE, or STOP, published to the device’s MQTT topic and settable via {"state": "OPEN"} / {"state": "CLOSE"} / {"state": "STOP"}.
  • Position — a 0-100 value, settable with {"position": VALUE} once calibration is complete.
  • running — a read-only boolean showing whether the motor is currently moving. You can’t /get or /set it; it’s reported in the device state.
  • motor_state — a read-only string reflecting the motor’s current state, again reported rather than settable.
  • reverse_direction and reset_limits — configuration options (the second is the calibration trigger).

Because the ZNCLDJ11LM runs on external power rather than an internal battery, there’s no battery-percentage or voltage entity to expect here — a real difference from the later battery-equipped B1. In Home Assistant it maps to a standard cover you can drive from the UI, scripts, or automations.

Home Assistant automation: scripting the calibration and daily use

Once calibrated, treating the ZNCLDJ11LM as a normal cover entity in Home Assistant works the way you’d expect — open, close, and (post-calibration) set to an intermediate position for a “50% open at sunrise, fully open at 9am” routine.

If you want to script the calibration step itself rather than doing it by hand, the sequence maps cleanly to a Home Assistant script. The calibration trigger is an MQTT publish to the device’s set topic:

Topic:   zigbee2mqtt/<your_curtain_name>/set
Payload: {"options": {"reset_limits": true}}

Follow that with a cover-close service call, a delay, then a cover-open service call. The one value you’ll have to tune for your own install is that delay: because the motor exits calibration automatically once it detects both end-stops, the delay simply needs to be longer than one full curtain traversal. A wide, slow curtain can take twenty to thirty seconds end to end; a small one, much less. Time your own curtain’s full close-to-open run once and pad it, rather than trusting a fixed number that might cut a slower motor short mid-travel.

What happens after a power outage

The ZNCLDJ11LM draws external power to operate the motor and, with no battery backup, can’t preserve its calibration state through an extended outage. If the motor loses power for a while, it can lose its learned end-stops and needs the calibration sequence run again.

A brief flicker (the kind a UPS or a quick breaker trip covers) is a different story from a multi-hour outage, and the exact threshold for when calibration actually gets wiped isn’t documented. If your curtain starts reporting nonsense positions after a power event, running reset_limits and the close/wait/open sequence again is the first thing to try — not a firmware reset, not a re-pair.

Known reporting quirks — cosmetic vs. worth checking

The most persistent complaint about this motor on Zigbee2MQTT isn’t calibration; it’s the open/closed state getting stuck. Multiple GitHub issues describe the cover reporting as permanently “closed” (from Z2M 1.25 onward) or permanently “open,” even while the numeric position attribute keeps updating correctly (Koenkk/zigbee2mqtt #12025, #15926, and #15954, the last of which covers both the ZNCLDJ11LM and the B1). In practice that means your automations keyed off position stay reliable, but anything keyed off the binary open/closed state may misfire. These reports recur across several Z2M releases without a single canonical fix, which is a fair summary of where this discontinued device’s support has sat: known issue, position works, state is the flaky part.

Worth knowing: for some curtain motors in the same Aqara/Xiaomi family that aren’t natively supported by Zigbee2MQTT, community members have had to write their own external Z2M converters to get functional support at all. That’s not the situation with the ZNCLDJ11LM today — it has a proper built-in Z2M device definition — but it’s a useful data point if support for this SKU ever regresses: the fallback path (a community converter) has precedent elsewhere in the family, it’s just more work than plug-and-play.

ZNCLDJ11LM vs B1 (ZNCLDJ12LM) vs E1 driver: which to buy today

If you already own a ZNCLDJ11LM, none of the above is a reason to replace it — it works, it’s local, and the calibration workflow, while manual, is well-documented enough to get through once. But if you’re buying new, the calculus is different.

ZNCLDJ11LM (this device) B1 / ZNCLDJ12LM E1 driver / ZNCLBL01LM
Mechanism Integrated rail-mount motor Rail-mount motor, successor generation Retrofit driver, clips onto existing rod/rail
Power External/DC only, no battery Rechargeable battery, USB-C charging Rechargeable battery
Availability Discontinued, secondhand/existing stock only Current Aqara lineup Current Aqara lineup
Zigbee2MQTT support Native, with the state-reporting quirk above Native, see B1 guide Native, see E1 driver guide
Buy new? No — not sold new Yes, if you need a full rail replacement Yes, if retrofitting an existing curtain rod

The clearest practical difference between this original and the B1 successor is power: the ZNCLDJ11LM runs only on external power, while the B1 added an onboard rechargeable battery you top up over USB-C. Aqara doesn’t publish a detailed internal-spec comparison beyond the generational succession, so treat availability and the battery as the deciding factors rather than any documented performance delta.

I think the calibration design here — a documented MQTT command plus a manual close/open cycle, rather than a calibration wizard buried in a companion app — is the right call for anyone running this device locally. It’s an extra step, but a scriptable, repeatable one that doesn’t depend on Aqara’s app still existing or still working the way it did when you bought the hardware. If you’re segmenting your smart-home gear off your main network, our Aqara and Xiaomi IoT VLAN guide covers where a locally-paired motor like this fits.

FAQ

Does the ZNCLDJ11LM need an Aqara hub, or does it pair directly to a Zigbee coordinator?
It pairs as a standard Zigbee device to whatever coordinator your Zigbee2MQTT instance runs on. No Aqara Home or Mi Home hub is required for local operation.

How do I recalibrate after a power outage?
Run the same sequence as initial setup: publish {"options": {"reset_limits": true}} to the device’s set topic, close the curtain fully, wait, then open it fully.

What’s the difference between ZNCLDJ11LM and ZNCLDJ12LM (B1)?
The B1 is the current, purchasable successor to this discontinued model, and it adds an onboard rechargeable battery with USB-C charging. The original ZNCLDJ11LM runs on external power only. Aqara doesn’t document further internal differences.

Can I set the curtain to a specific percentage, like 30% open?
Yes, but only after calibration completes. Before calibration, position reporting and percentage-based control aren’t reliable.

Does this curtain motor work fully offline / local-only in Home Assistant?
Yes. Once paired to your own Zigbee2MQTT coordinator, control doesn’t touch Aqara’s or Xiaomi’s servers at all.

If you hit the stuck open/closed state described above, key your automations off the numeric position attribute rather than the binary open/closed state, and check the current Zigbee2MQTT changelog before assuming a given release has resolved it.

local-firstHome Assistantno-cloud