[Device Support Request] NOUS E6 TS0601 _TZE200_nnrfa68v
See original GitHub issueIs your feature request related to a problem? Please describe. The NOUS E6 Thermometer and Humidity sensor does not provide any values, as well as the time on it is not synced. I have modified the current sensor quirk a bit and made temperature, humidity and battery level work. Whatever I do though the time synchronization has no effect. In this issue I will provide the code I have now, maybe someone will have some ideas 😃
I have also checked the tuya zigbee communication spec but I didn’t find anything useful there.
Describe the solution you’d like I would like for the device to be officially supported 😃. And maybe additionally to suport the time sync feature.
Device signature
{
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
"endpoints": {
"1": {
"profile_id": 260,
"device_type": "0x0302",
"in_clusters": [
"0x0001",
"0x0402",
"0x0405",
"0xef00"
],
"out_clusters": [
"0x000a",
"0x0019"
]
}
},
"manufacturer": "_TZE200_nnrfa68v",
"model": "TS0601",
"class": "ts0601_sensor_cst.TuyaNousE6TempHumiditySensor"
}
Diagnostic information
{
"home_assistant": {
"installation_type": "Home Assistant OS",
"version": "2022.8.5",
"dev": false,
"hassio": true,
"virtualenv": false,
"python_version": "3.10.5",
"docker": true,
"arch": "x86_64",
"timezone": "Europe/Warsaw",
"os_name": "Linux",
"os_version": "5.15.55",
"supervisor": "2022.08.3",
"host_os": "Home Assistant OS 8.4",
"docker_version": "20.10.14",
"chassis": "vm",
"run_as_root": true
},
"custom_components": {
"hacs": {
"version": "1.26.2",
"requirements": [
"aiogithubapi>=22.2.4"
]
},
"ping_arp": {
"version": "0.1.0",
"requirements": []
}
},
"integration_manifest": {
"domain": "zha",
"name": "Zigbee Home Automation",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/zha",
"requirements": [
"bellows==0.32.0",
"pyserial==3.5",
"pyserial-asyncio==0.6",
"zha-quirks==0.0.78",
"zigpy-deconz==0.18.0",
"zigpy==0.49.1",
"zigpy-xbee==0.15.0",
"zigpy-zigate==0.9.1",
"zigpy-znp==0.8.1"
],
"usb": [
{
"vid": "10C4",
"pid": "EA60",
"description": "*2652*",
"known_devices": [
"slae.sh cc2652rb stick"
]
},
{
"vid": "10C4",
"pid": "EA60",
"description": "*sonoff*plus*",
"known_devices": [
"sonoff zigbee dongle plus"
]
},
{
"vid": "10C4",
"pid": "EA60",
"description": "*tubeszb*",
"known_devices": [
"TubesZB Coordinator"
]
},
{
"vid": "1A86",
"pid": "7523",
"description": "*tubeszb*",
"known_devices": [
"TubesZB Coordinator"
]
},
{
"vid": "1A86",
"pid": "7523",
"description": "*zigstar*",
"known_devices": [
"ZigStar Coordinators"
]
},
{
"vid": "1CF1",
"pid": "0030",
"description": "*conbee*",
"known_devices": [
"Conbee II"
]
},
{
"vid": "10C4",
"pid": "8A2A",
"description": "*zigbee*",
"known_devices": [
"Nortek HUSBZB-1"
]
},
{
"vid": "0403",
"pid": "6015",
"description": "*zigate*",
"known_devices": [
"ZiGate+"
]
},
{
"vid": "10C4",
"pid": "EA60",
"description": "*zigate*",
"known_devices": [
"ZiGate"
]
},
{
"vid": "10C4",
"pid": "8B34",
"description": "*bv 2010/10*",
"known_devices": [
"Bitron Video AV2010/10"
]
}
],
"codeowners": [
"@dmulcahey",
"@adminiuga",
"@puddly"
],
"zeroconf": [
{
"type": "_esphomelib._tcp.local.",
"name": "tube*"
},
{
"type": "_zigate-zigbee-gateway._tcp.local.",
"name": "*zigate*"
}
],
"after_dependencies": [
"onboarding",
"usb",
"zeroconf"
],
"iot_class": "local_polling",
"loggers": [
"aiosqlite",
"bellows",
"crccheck",
"pure_pcapy3",
"zhaquirks",
"zigpy",
"zigpy_deconz",
"zigpy_xbee",
"zigpy_zigate",
"zigpy_znp"
],
"is_built_in": true
},
"data": {
"ieee": "**REDACTED**",
"nwk": 50565,
"manufacturer": "_TZE200_nnrfa68v",
"model": "TS0601",
"name": "_TZE200_nnrfa68v TS0601",
"quirk_applied": true,
"quirk_class": "ts0601_sensor_cst.TuyaNousE6TempHumiditySensor",
"manufacturer_code": 4417,
"power_source": "Battery or Unknown",
"lqi": 112,
"rssi": null,
"last_seen": "2022-08-21T22:13:32",
"available": true,
"device_type": "EndDevice",
"signature": {
"node_descriptor": "NodeDescriptor(logical_type=<LogicalType.EndDevice: 2>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress: 128>, manufacturer_code=4417, maximum_buffer_size=66, maximum_incoming_transfer_size=66, server_mask=10752, maximum_outgoing_transfer_size=66, descriptor_capability_field=<DescriptorCapability.NONE: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=True, *is_full_function_device=False, *is_mains_powered=False, *is_receiver_on_when_idle=False, *is_router=False, *is_security_capable=False)",
"endpoints": {
"1": {
"profile_id": 260,
"device_type": "0x0302",
"in_clusters": [
"0x0001",
"0x0402",
"0x0405",
"0xef00"
],
"out_clusters": [
"0x000a",
"0x0019"
]
}
}
},
"active_coordinator": false,
"entities": [
{
"entity_id": "sensor.nous_e6_kuchnia_battery",
"name": "_TZE200_nnrfa68v TS0601"
},
{
"entity_id": "sensor.nous_e6_kuchnia_temperature",
"name": "_TZE200_nnrfa68v TS0601"
},
{
"entity_id": "sensor.nous_e6_kuchnia_humidity",
"name": "_TZE200_nnrfa68v TS0601"
}
],
"neighbors": [],
"endpoint_names": [
{
"name": "TEMPERATURE_SENSOR"
}
],
"user_given_name": "NOUS E6 Kuchnia",
"device_reg_id": "44dcd0624ecf150b39fd626e1efd208c",
"area_id": "kuchnia",
"cluster_details": {
"1": {
"device_type": {
"name": "TEMPERATURE_SENSOR",
"id": 770
},
"profile_id": 260,
"in_clusters": {
"0xef00": {
"endpoint_attribute": "tuya_manufacturer",
"attributes": {
"0xef00": {
"attribute_name": "mcu_version",
"value": "1.0.0"
}
},
"unsupported_attributes": {}
},
"0x0402": {
"endpoint_attribute": "temperature",
"attributes": {
"0x0000": {
"attribute_name": "measured_value",
"value": 2370
}
},
"unsupported_attributes": {}
},
"0x0405": {
"endpoint_attribute": "humidity",
"attributes": {
"0x0000": {
"attribute_name": "measured_value",
"value": 7100
}
},
"unsupported_attributes": {}
},
"0x0001": {
"endpoint_attribute": "power",
"attributes": {
"0x0021": {
"attribute_name": "battery_percentage_remaining",
"value": 200
}
},
"unsupported_attributes": {}
}
},
"out_clusters": {
"0x0019": {
"endpoint_attribute": "ota",
"attributes": {},
"unsupported_attributes": {}
},
"0x000a": {
"endpoint_attribute": "time",
"attributes": {},
"unsupported_attributes": {}
}
}
}
}
}
}
Additional logs
Here are the time_set logs that don't work
2022-08-21 23:56:06.587 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Received ZCL frame: b'\x09\x12\x24\x0D\x00'
2022-08-21 23:56:06.588 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Decoded ZCL frame header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=0, direction=<Direction.Client_to_Server: 1>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False, *is_reply=True), tsn=18, command_id=36, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-08-21 23:56:06.588 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Decoded ZCL frame: TemperatureHumidityManufCluster:set_time_request(data=[13, 0])
2022-08-21 23:56:06.588 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Received command 0x24 (TSN 18): set_time_request(data=[13, 0])
2022-08-21 23:56:06.589 WARNING (MainThread) [zigpy.zcl] [0xC585:1:0xef00] HANDLE SET TIME! NOT WORKING YET
2022-08-21 23:56:06.591 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Sending request header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.CLUSTER_COMMAND: 1>, is_manufacturer_specific=True, direction=<Direction.Server_to_Client: 0>, disable_default_response=0, reserved=0, *is_cluster=True, *is_general=False, *is_reply=False), manufacturer=4417, tsn=100, command_id=36, *direction=<Direction.Server_to_Client: 0>, *is_reply=False)
2022-08-21 23:56:06.592 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Sending request: set_time(time=[13, 0, 99, 2, 169, 246, 99, 2, 198, 22])
2022-08-21 23:56:06.592 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Sending reply header: ZCLHeader(frame_control=FrameControl(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=False, direction=<Direction.Client_to_Server: 1>, disable_default_response=1, reserved=0, *is_cluster=False, *is_general=True, *is_reply=True), tsn=18, command_id=<GeneralCommand.Default_Response: 11>, *direction=<Direction.Client_to_Server: 1>, *is_reply=True)
2022-08-21 23:56:06.593 DEBUG (MainThread) [zigpy.zcl] [0xC585:1:0xef00] Sending reply: Default_Response(command_id=36, status=<Status.SUCCESS: 0>)
2022-08-21 23:56:06.593 DEBUG (MainThread) [zigpy.device] [0xc585] Extending timeout for 0x64 request
2022-08-21 23:56:06.595 DEBUG (MainThread) [zigpy_znp.api] Sending request: AF.DataRequestExt.Req(DstAddrModeAddress=AddrModeAddress(mode=<AddrMode.NWK: 2>, address=0xC585), DstEndpoint=1, DstPanId=0x0000, SrcEndpoint=1, ClusterId=61184, TSN=100, Options=<TransmitOptions.SUPPRESS_ROUTE_DISC_NETWORK|ACK_REQUEST: 48>, Radius=30, Data=b'\x05\x41\x11\x64\x24\x00\x0A\x0D\x00\x63\x02\xA9\xF6\x63\x02\xC6\x16')
Additional context Here is the page with the device info: https://noussmart.pl/product/e6.html Here is the code I for the test quirk:
"""Tuya temp and humidity sensor with a screen."""
from typing import Dict
################## clean this up
import zigpy.types as t
from zigpy.zcl import foundation
from zhaquirks.tuya import TuyaTimePayload, TuyaCommand
import datetime
##################
from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.measurement import RelativeHumidity, TemperatureMeasurement
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
SKIP_CONFIGURATION,
)
from zhaquirks.tuya import TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster
TUYA_SET_TIME = 0x24
# NOTES:
# The data comes in as a string on cluster, if there is nothing set up you may see these lines in the logs:
# Unknown message (b'19830100a40102000400000118') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 28.0 degrees
# Unknown message (b'19840100a5020200040000022c') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 55.6% humid
# Unknown message (b'19850100a60402000400000064') on cluster 61184: unknown endpoint or cluster id: 'No cluster ID 0xef00 on (a4:c1:38:d0:18:8b:64:aa, 1)'
# 100% battery
class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
"""Tuya local TemperatureMeasurement cluster."""
class TuyaRelativeHumidity(RelativeHumidity, TuyaLocalCluster):
"""Tuya local RelativeHumidity cluster."""
class TemperatureHumidityManufCluster(TuyaMCUCluster):
"""Tuya Manufacturer Cluster with Temperature and Humidity data points."""
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaTemperatureMeasurement.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 10, # decidegree to centidegree
),
2: DPToAttributeMapping(
TuyaRelativeHumidity.ep_attribute,
"measured_value",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 100, # 0.01 to 1.0
),
4: DPToAttributeMapping(
TuyaPowerConfigurationCluster2AAA.ep_attribute,
"battery_percentage_remaining",
dp_type=TuyaDPType.VALUE,
converter=lambda x: x * 2, # reported percentage is doubled
),
}
set_time_offset = 1970
data_point_handlers = {
1: "_dp_2_attr_update",
2: "_dp_2_attr_update",
4: "_dp_2_attr_update",
}
def handle_set_data(self, command: TuyaCommand) -> foundation.Status:
return foundation.Status.SUCCESS
def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
self.warning("HANDLE SET TIME! NOT WORKING YET")
payload = TuyaTimePayload()
#utc_timestamp = int((datetime.datetime.utcnow()).timestamp())
#local_timestamp = int(datetime.datetime.now().timestamp())
utc_now = datetime.datetime.utcnow()
now = datetime.datetime.now()
offset_time = datetime.datetime(self.set_time_offset, 1, 1)
utc_timestamp = int((utc_now - offset_time).total_seconds())
local_timestamp = int((now - offset_time).total_seconds())
payload.extend(sequence_number[0].to_bytes(1, "big", signed=False))
payload.extend(sequence_number[1].to_bytes(1, "big", signed=False))
payload.extend(utc_timestamp.to_bytes(4, "big", signed=False))
payload.extend(local_timestamp.to_bytes(4, "big", signed=False))
self.create_catching_task(
self.command(TUYA_SET_TIME, payload, expect_reply=True, tsn = self.endpoint.device.application.get_sequence())
)
return foundation.Status.SUCCESS
class TuyaNousE6TempHumiditySensor(CustomDevice):
"""Custom device representing tuya temp and humidity sensor with a screen (NOUS E6)."""
signature = {
# <SimpleDescriptor endpoint=1, profile=260, device_type=81
# device_version=1
# input_clusters=[4, 5, 61184, 0]
# output_clusters=[25, 10]>
MODELS_INFO: [("_TZE200_nnrfa68v", "TS0601")],
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG, # this is how the device reports itself
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TemperatureHumidityManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
replacement = {
SKIP_CONFIGURATION: True,
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.TEMPERATURE_SENSOR,
INPUT_CLUSTERS: [
TemperatureHumidityManufCluster, # Single bus for temp, humidity, and battery
TuyaTemperatureMeasurement,
TuyaRelativeHumidity,
TuyaPowerConfigurationCluster2AAA,
],
OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
}
},
}
Issue Analytics
- State:
- Created a year ago
- Comments:20 (1 by maintainers)

Top Related StackOverflow Question
Wow, it was the manufacturer parameter! Now it works flawlessly. How did you know? 😄
Here is the current version of the quirk (which additionally is able to parse temperature_sensitivity etc, I am also trying to make setting of that param work):
Yes, I tried this for both devices. It always returns the value I have set. E.g. first I tried
READ ATTRIBUTEwhich got the initial value 0.5, then I triedWRITE ATTRIBUTEfor the values 0.1 andREAD ATTRIBUTEwhich gave again 0.1. The same I tried for 0.2. So it seems the value is correctly set.