Fixing Tuya TS0201 Neo in Home Assistant ZHA: Making Temperature and Humidity Actually Work
Why the _TZ3000_qaaysllp sensor drops readings and how to fix it with a custom quirk
I picked up a Neo Tuya TS0201 temperature, humidity, and illumination sensor (manufacturer ID _TZ3000_qaaysllp, also known as the NAS-TH02B2) expecting a straightforward ZHA setup. It paired fine — battery and illuminance showed up immediately. But temperature and humidity were completely missing. No entities, no data, nothing.
The existing quirk in zha-device-handlers was supposed to handle this device, but it didn't help. After hours of digging through Zigbee packet captures and ZHA debug logs, I found that the problem has three separate layers — and the upstream quirk only addresses one of them. This article walks through everything I found and provides a working fix.
Symptoms: What You’ll See
After pairing, ZHA typically shows:
- Battery percentage — works fine
- Illuminance — works fine
- Temperature — entity missing, or shows
unknown/0 - Humidity — entity missing, or shows
unknown/0
In the Home Assistant logs (with ZHA debug logging enabled), you may see messages like:
Ignoring message on unknown endpoint 2
Or during device configuration:
UNSUPPORTED_ATTRIBUTE on cluster 0x0402 (TemperatureMeasurement)UNSUPPORTED_ATTRIBUTE on cluster 0x0405 (RelativeHumidity)
Why This Happens: The Root Cause
This problem has three layers, and you need to fix all three for the sensor to work. Here’s what’s going on under the hood.
Layer 1: The device lies about its capabilities
Every Zigbee device broadcasts a “simple descriptor” that tells the coordinator what clusters (features) it supports and on which endpoints. The TS0201 Neo advertises this:
Endpoint 1: Basic, PowerConfiguration, IlluminanceMeasurement, Tuya Alarm (0xE002)
Notice what’s missing: TemperatureMeasurement (0x0402) and RelativeHumidity (0x0405) are not listed at all. The device simply doesn't advertise that it can measure temperature or humidity.
Layer 2: Data arrives on an unadvertised endpoint
After a specific activation sequence (more on this below), the device does start sending temperature and humidity data — but on endpoint 2, which it never told the coordinator about. zigpy, the Zigbee library that ZHA uses, rightfully drops these messages:
Ignoring message on unknown endpoint 2
The existing upstream quirk in zha-device-handlers (zhaquirks/tuya/ts0201.py) does add a virtual endpoint 2 to the device model, which partially addresses this. But it doesn't fix the other two layers.
Layer 3: The activation sequence is missing
Even with endpoint 2 defined, the device won’t start reporting temperature and humidity until it receives what’s known as a “Tuya magic packet” — a read of specific Basic cluster attributes, crucially including the manufacturer-specific attribute 0xFFFE. This is the same mechanism that zigbee2mqtt implements as tuya.configureMagicPacket.
The upstream ZHA quirk does not send this magic packet. Without it, endpoint 2 exists in the device model but the device never sends any data to it.
Bonus layer: UNSUPPORTED_ATTRIBUTE kills entities
When ZHA initializes a device, it reads attributes to decide which Home Assistant entities to create. This device responds with UNSUPPORTED_ATTRIBUTE (error code 0x86) for direct reads on the temperature and humidity clusters. The upstream quirk uses bare cluster IDs on endpoint 2, so these reads hit the device and fail. ZHA sees the error and skips entity creation entirely.
The Fix: A Custom ZHA Quirk
I’ve published a working quirk that addresses all three layers: ts0201.py — GitHub Gist
What the quirk does differently
Compared to the upstream version, this quirk adds:
TuyaCachedReadClustermixin — Interceptsread_attributes()calls and returns cached values (from previous reports) or a zero default. It also calls_update_attribute()to notify ZHA's listener chain, ensuring entities are created even when the device returnsUNSUPPORTED_ATTRIBUTE.- Magic packet in
bind()— When ZHA configures report subscriptions on the alarm cluster, the quirk first reads Basic cluster attributes including the Tuya-specific0xFFFE. This activates the device's standard cluster reporting on endpoint 2. - Bug fix:
alarm_humidity_maxattribute ID — The upstream quirk has this as0xD00C, but the actual device reports0xD00D. Verified from live device data. NodeDescriptor— Added to the replacement dict, copied from the device's actual response.- Custom cluster classes on EP2 — Instead of bare cluster IDs (which just route messages but don’t override behavior), the quirk uses
TuyaTemperatureMeasurementandTuyaRelativeHumidityclasses that inherit the cached-read behavior.
Installation: Step by Step
Step 1: Create the custom quirks directory
If you haven’t already, create a directory for custom quirks. Using the Home Assistant file editor, SSH, or Samba:
/homeassistant/custom_zha_quirks/
Step 2: Download the quirk
Download ts0201.py from the GitHub Gist and place it in:
/homeassistant/custom_zha_quirks/ts0201.py
Step 3: Configure ZHA to use custom quirks
Add this to your configuration.yaml:
zha: custom_quirks_path: /config/custom_zha_quirks
Step 4: Restart Home Assistant
A full restart is required — not just a configuration reload.
Step 5: Remove and re-pair the device
This step is important. Many quirks only take full effect during the device interview (pairing process). After restart:
- Go to Settings > Devices & Services > ZHA
- Find the TS0201 device and remove it
- Put the sensor into pairing mode (usually by long-pressing the button)
- Re-pair through ZHA
After pairing, the device will take a minute or two to fully configure (Tuya devices have a concurrency limit of about 2 simultaneous requests, so configuration is sequential). Once complete, you should see:
- Temperature — updating with real values
- Humidity — updating with real values
- Illuminance — working as before
- Battery — working as before
How It Works: Technical Deep Dive
For those who want to understand the mechanics, here’s the data flow after the quirk is applied:
Device pairs → ZHA applies quirk (signature matches _TZ3000_qaaysllp / TS0201) → Replacement creates virtual EP2 with custom cluster classes
ZHA configures EP1 alarm cluster → bind() override triggers magic packet → Reads Basic attributes [0x0000, 0x0001, 0x0004, 0x0005, 0x0007, 0xFFFE] → 0xFFFE activates the device's reporting mechanism
Device starts sending unsolicited reports on EP2 → TemperatureMeasurement (0x0402): measured_value in hundredths of °C → RelativeHumidity (0x0405): measured_value in hundredths of %
ZHA reads attributes during init → TuyaCachedReadCluster intercepts the read → Returns cached value (or 0 if no report yet) → Calls _update_attribute() → ZHA creates the HA entity
Ongoing operation → Device sends reports every ~1 minute (or on significant change) → zigpy routes to EP2 → custom cluster → _update_attribute() → HA entity updates
Why _update_attribute() matters
In zigpy, _update_attribute() is the central notification mechanism. When called, it:
- Updates the cluster’s internal
_attr_cache - Fires a
zdo.ATTR_UPDATEDcallback - ZHA’s
ClusterHandlerreceives this and updates the Home Assistant entity
Without calling _update_attribute() in the cached-read override, ZHA would never know about the values and wouldn't create entities.
Why the magic packet works
The 0xFFFE attribute is a Tuya-specific mechanism. Reading it tells the device: "I'm a Tuya-aware coordinator, please start sending me data using standard ZCL clusters." Without this read, the device stays silent on EP2. This is well-documented in the zigbee2mqtt codebase as configureMagicPacket.
Confirmed Working Values
After applying this quirk, here are actual values received from the device (from ZHA debug logs):
- TemperatureMeasurement (EP2) — measured_value: 2640 → 26.40 °C
- RelativeHumidity (EP2) — measured_value: 4100 → 41.00 %
- IlluminanceMeasurement (EP1) — measured_value: 0 → 0 lux
- PowerConfiguration (EP1) — battery_percentage_remaining: 200 → 100%
Temperature and humidity values update approximately every minute or when a significant change is detected (>=0.5°C or >=5% humidity).
FAQ
Does this work with the NAS-TH02B2 model?
The Neo NAS-TH02B2 is the most common physical model that reports as _TZ3000_qaaysllp / TS0201 over Zigbee. Yes, this quirk is specifically for this device.
Will this conflict with the upstream quirk?
No. Custom quirks in custom_zha_quirks take precedence over built-in quirks when the device signature matches. The upstream quirk will be ignored in favor of yours.
Do I need zigbee2mqtt for this?
No. This fix is entirely for ZHA (the built-in Home Assistant Zigbee integration). If you use zigbee2mqtt, Tuya device support is handled differently through their converter system with configureMagicPacket already built in.
The device paired but temperature still shows zero
Wait 2–3 minutes after pairing. The device needs to complete its first reporting cycle. If it’s still zero after 5 minutes, check your ZHA logs for the magic packet:
[zha.zigbee.cluster_handlers] [0xABCD](tuya_alarm): bind 'Tuya Temperature and Humidity Alarm Cluster' cluster
If you see this followed by Basic cluster reads, the magic packet was sent.
Can I use this with other TS0201 variants?
This quirk is specifically for _TZ3000_qaaysllp. Other TS0201 variants (like _TZ3000_fllyghyj, _TZ3000_lfa05ajd, _TZ3210_ncw88jfq) have different behaviors and may need different quirks. The signature matching ensures this quirk only applies to the correct device.
My humidity is stuck at 5%
This is a known issue reported by some users even with working quirks. It may indicate a hardware fault with the sensor itself (the Sensirion SHTC3 chip), not a quirk problem. Try replacing the batteries and re-pairing.
Related Resources
- Working quirk (GitHub Gist) — Download
ts0201.pyfrom here - Upstream quirk (zha-device-handlers) — The built-in version this is based on
- Original device support request (#862) — The GitHub issue tracking this device
- How to install custom ZHA quirks — Community guide on custom quirk installation
- ZHA device handlers repository — The official quirks repository
- zigbee2mqtt Tuya magic packet discussion — Technical details on the 0xFFFE mechanism
- Neo NAS-TH02B2 review (SmartHomeScene) — Hardware review and specifications
If you’re dealing with a similar Tuya sensor that pairs but doesn’t report data in ZHA, the pattern described here — missing endpoint, magic packet activation, cached reads to prevent UNSUPPORTED_ATTRIBUTE — applies to many Tuya devices beyond just the TS0201. I hope this saves you the hours I spent figuring it out.