zigpy / zha-device-handlers

ZHA device handlers bridge the functionality gap created when manufacturers deviate from the ZCL specification, handling deviations and exceptions by parsing custom messages to and from Zigbee devices.
Apache License 2.0
777 stars 703 forks source link

TZE200_locansqn TS0601 Temp / Humi / Clock #1286

Open toy3375 opened 2 years ago

toy3375 commented 2 years ago

Hi everybody,

My Tuya devices has no entities/controls in home assistant. It´s Zigbee Tuya Temp & Humi Display with integr. Clock.

Thanks in advance for the support.

image Log.txt

MattWestb commented 2 years ago

@mrctorres caan you asking @Tropaion hi was setting up one CC-2531 and have sniffing tuya ZBGW for some hours ago perhaps hi is knowing how to getting it working.

https://github.com/zigpy/zha-device-handlers/issues/1302#issuecomment-1027216533

mrctorres commented 2 years ago

Now I capture packets with Texas Instrument firmware and Texas Instrument Smart RF Packet Sniffer vs1 software, but it doesn't work with Wireshark. Generated this file when I turned on the child device and I stopped capturing when updated the clock.

TS0601.zip

Tropaion commented 2 years ago

@mrctorres Under windows I'm just using this sniffer with WireShark, works perfectly fine: https://dsr-iot.com/downloads Here a tutorial: https://community.oh-lalabs.com/t/guide-build-a-zigbee-cc2531-sniffer-how-to-use-it/469

mrctorres commented 2 years ago

Here first packets

Device Power ON until Date and Time Update.zip

mrctorres commented 2 years ago

Add Device.zip

jacekk015 commented 2 years ago

You need to set key properly in Wireshark. https://www.youtube.com/watch?v=4vG4CVNAm_A Attached file has payload encrypted

MattWestb commented 2 years ago

@mrctorres The key is working from the paring the device. I looking little if i can find some "tuya magic" in the sniffs :))

MattWestb commented 2 years ago

@jacekk015 I think this device is needing the same treatment as the TS004F that i need sending attributes to then its joining but its looks it dont need being in INIT more do tuya ia not kicking it for rejoining.

First they is reading some attribute of cluster both known and unknown ones:

Frame 33: 60 bytes on wire (480 bits), 58 bytes captured (464 bits) on interface \\.\pipe\zboss_sniffer_COM10, id 0
IEEE 802.15.4 Data, Dst: 0x083a, Src: 0x0000
ZigBee Network Layer Data, Dst: 0x083a, Src: 0x0000
    Frame Control Field: 0x0208, Frame Type: Data, Discover Route: Suppress, Security Data
        .... .... .... ..00 = Frame Type: Data (0x0)
        .... .... ..00 10.. = Protocol Version: 2
        .... .... 00.. .... = Discover Route: Suppress (0x0)
        .... ...0 .... .... = Multicast: False
        .... ..1. .... .... = Security: True
        .... .0.. .... .... = Source Route: False
        .... 0... .... .... = Destination: False
        ...0 .... .... .... = Extended Source: False
        ..0. .... .... .... = End Device Initiator: False
    Destination: 0x083a
    Source: 0x0000
    Radius: 30
    Sequence Number: 207
    [Extended Source: SiliconL_ff:fe:eb:6d:9f (80:4b:50:ff:fe:eb:6d:9f)]
    [Origin: 1]
    ZigBee Security Header
ZigBee Application Support Layer Data, Dst Endpt: 255, Src Endpt: 1
    Frame Control Field: Data (0x40)
        .... ..00 = Frame Type: Data (0x0)
        .... 00.. = Delivery Mode: Unicast (0x0)
        ..0. .... = Security: False
        .1.. .... = Acknowledgement Request: True
        0... .... = Extended Header: False
    Destination Endpoint: 255
    Cluster: Basic (0x0000)
    Profile: Home Automation (0x0104)
    Source Endpoint: 1
    Counter: 62
ZigBee Cluster Library Frame, Command: Read Attributes, Seq: 44
    Frame Control Field: Profile-wide (0x10)
        .... ..00 = Frame Type: Profile-wide (0x0)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...1 .... = Disable Default Response: True
    Sequence Number: 44
    Command: Read Attributes (0x00)
    Attribute: Manufacturer Name (0x0004)
    Attribute: ZCL Version (0x0000)
    Attribute: Application Version (0x0001)
    Attribute: Model Identifier (0x0005)
    Attribute: Power Source (0x0007)
    Attribute: Unknown (0xfffe)

Then writing to attribute 0xffde on the basic cluster with data Uint8: 19 (0x13).

Frame 78: 52 bytes on wire (416 bits), 50 bytes captured (400 bits) on interface \\.\pipe\zboss_sniffer_COM10, id 0
IEEE 802.15.4 Data, Dst: 0x083a, Src: 0x0000
ZigBee Network Layer Data, Dst: 0x083a, Src: 0x0000
    Frame Control Field: 0x0208, Frame Type: Data, Discover Route: Suppress, Security Data
        .... .... .... ..00 = Frame Type: Data (0x0)
        .... .... ..00 10.. = Protocol Version: 2
        .... .... 00.. .... = Discover Route: Suppress (0x0)
        .... ...0 .... .... = Multicast: False
        .... ..1. .... .... = Security: True
        .... .0.. .... .... = Source Route: False
        .... 0... .... .... = Destination: False
        ...0 .... .... .... = Extended Source: False
        ..0. .... .... .... = End Device Initiator: False
    Destination: 0x083a
    Source: 0x0000
    Radius: 30
    Sequence Number: 219
    [Extended Source: SiliconL_ff:fe:eb:6d:9f (80:4b:50:ff:fe:eb:6d:9f)]
    [Origin: 1]
    ZigBee Security Header
ZigBee Application Support Layer Data, Dst Endpt: 1, Src Endpt: 1
    Frame Control Field: Data (0x00)
        .... ..00 = Frame Type: Data (0x0)
        .... 00.. = Delivery Mode: Unicast (0x0)
        ..0. .... = Security: False
        .0.. .... = Acknowledgement Request: False
        0... .... = Extended Header: False
    Destination Endpoint: 1
    Cluster: Basic (0x0000)
    Profile: Home Automation (0x0104)
    Source Endpoint: 1
    Counter: 66
ZigBee Cluster Library Frame, Command: Write Attributes, Seq: 45
    Frame Control Field: Profile-wide (0x10)
        .... ..00 = Frame Type: Profile-wide (0x0)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...1 .... = Disable Default Response: True
    Sequence Number: 45
    Command: Write Attributes (0x02)
    Attribute Field, Uint8: 19
        Attribute: Unknown (0xffde)
        Data Type: 8-Bit Unsigned Integer (0x20)
        Uint8: 19 (0x13)

Its made 2 times with the same information. Then reading the Node Descriptor and they using Silabs manufacture code in it Manufacturer Code: 0x1002`. (Frame 104:)

Then writing one unknown command to basic cluster Unknown (0xf0).

Frame 185: 48 bytes on wire (384 bits), 46 bytes captured (368 bits) on interface \\.\pipe\zboss_sniffer_COM10, id 0
IEEE 802.15.4 Data, Dst: 0x083a, Src: 0x0000
ZigBee Network Layer Data, Dst: 0x083a, Src: 0x0000
    Frame Control Field: 0x0208, Frame Type: Data, Discover Route: Suppress, Security Data
        .... .... .... ..00 = Frame Type: Data (0x0)
        .... .... ..00 10.. = Protocol Version: 2
        .... .... 00.. .... = Discover Route: Suppress (0x0)
        .... ...0 .... .... = Multicast: False
        .... ..1. .... .... = Security: True
        .... .0.. .... .... = Source Route: False
        .... 0... .... .... = Destination: False
        ...0 .... .... .... = Extended Source: False
        ..0. .... .... .... = End Device Initiator: False
    Destination: 0x083a
    Source: 0x0000
    Radius: 30
    Sequence Number: 232
    [Extended Source: SiliconL_ff:fe:eb:6d:9f (80:4b:50:ff:fe:eb:6d:9f)]
    [Origin: 1]
    ZigBee Security Header
ZigBee Application Support Layer Data, Dst Endpt: 1, Src Endpt: 1
    Frame Control Field: Data (0x40)
        .... ..00 = Frame Type: Data (0x0)
        .... 00.. = Delivery Mode: Unicast (0x0)
        ..0. .... = Security: False
        .1.. .... = Acknowledgement Request: True
        0... .... = Extended Header: False
    Destination Endpoint: 1
    Cluster: Basic (0x0000)
    Profile: Home Automation (0x0104)
    Source Endpoint: 1
    Counter: 71
ZigBee Cluster Library Frame
    Frame Control Field: Cluster-specific (0x11)
        .... ..01 = Frame Type: Cluster-specific (0x1)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...1 .... = Disable Default Response: True
    Sequence Number: 47
    Command: Unknown (0xf0)

After that the device is start sending "normal tuya DP commands":

Frame 193: 48 bytes on wire (384 bits), 46 bytes captured (368 bits) on interface \\.\pipe\zboss_sniffer_COM10, id 0
IEEE 802.15.4 Data, Dst: 0x083a, Src: 0x0000
ZigBee Network Layer Data, Dst: 0x083a, Src: 0x0000
    Frame Control Field: 0x0208, Frame Type: Data, Discover Route: Suppress, Security Data
        .... .... .... ..00 = Frame Type: Data (0x0)
        .... .... ..00 10.. = Protocol Version: 2
        .... .... 00.. .... = Discover Route: Suppress (0x0)
        .... ...0 .... .... = Multicast: False
        .... ..1. .... .... = Security: True
        .... .0.. .... .... = Source Route: False
        .... 0... .... .... = Destination: False
        ...0 .... .... .... = Extended Source: False
        ..0. .... .... .... = End Device Initiator: False
    Destination: 0x083a
    Source: 0x0000
    Radius: 30
    Sequence Number: 234
    [Extended Source: SiliconL_ff:fe:eb:6d:9f (80:4b:50:ff:fe:eb:6d:9f)]
    [Origin: 1]
    ZigBee Security Header
ZigBee Application Support Layer Data, Dst Endpt: 1, Src Endpt: 1
    Frame Control Field: Data (0x00)
        .... ..00 = Frame Type: Data (0x0)
        .... 00.. = Delivery Mode: Unicast (0x0)
        ..0. .... = Security: False
        .0.. .... = Acknowledgement Request: False
        0... .... = Extended Header: False
    Destination Endpoint: 1
    Cluster: Unknown (0xef00)
    Profile: Home Automation (0x0104)
    Source Endpoint: 1
    Counter: 72
ZigBee Cluster Library Frame
    Frame Control Field: Cluster-specific (0x11)
        .... ..01 = Frame Type: Cluster-specific (0x1)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...1 .... = Disable Default Response: True
    Sequence Number: 48
    Command: Unknown (0x03)

Frame 197: 48 bytes on wire (384 bits), 46 bytes captured (368 bits) on interface \\.\pipe\zboss_sniffer_COM10, id 0
IEEE 802.15.4 Data, Dst: 0x083a, Src: 0x0000
ZigBee Network Layer Data, Dst: 0x083a, Src: 0x0000
    Frame Control Field: 0x0208, Frame Type: Data, Discover Route: Suppress, Security Data
        .... .... .... ..00 = Frame Type: Data (0x0)
        .... .... ..00 10.. = Protocol Version: 2
        .... .... 00.. .... = Discover Route: Suppress (0x0)
        .... ...0 .... .... = Multicast: False
        .... ..1. .... .... = Security: True
        .... .0.. .... .... = Source Route: False
        .... 0... .... .... = Destination: False
        ...0 .... .... .... = Extended Source: False
        ..0. .... .... .... = End Device Initiator: False
    Destination: 0x083a
    Source: 0x0000
    Radius: 30
    Sequence Number: 236
    [Extended Source: SiliconL_ff:fe:eb:6d:9f (80:4b:50:ff:fe:eb:6d:9f)]
    [Origin: 1]
    ZigBee Security Header
ZigBee Application Support Layer Data, Dst Endpt: 1, Src Endpt: 1
    Frame Control Field: Data (0x00)
        .... ..00 = Frame Type: Data (0x0)
        .... 00.. = Delivery Mode: Unicast (0x0)
        ..0. .... = Security: False
        .0.. .... = Acknowledgement Request: False
        0... .... = Extended Header: False
    Destination Endpoint: 1
    Cluster: Unknown (0xef00)
    Profile: Home Automation (0x0104)
    Source Endpoint: 1
    Counter: 73
ZigBee Cluster Library Frame
    Frame Control Field: Cluster-specific (0x11)
        .... ..01 = Frame Type: Cluster-specific (0x1)
        .... .0.. = Manufacturer Specific: False
        .... 0... = Direction: Client to Server
        ...1 .... = Disable Default Response: True
    Sequence Number: 49
    Command: Unknown (0x03)

I have not looking on the DP command then i cant decoding them but it can being that they is sending somthing interesting in this 2 then starting initiating the device. The first frame send to DP cluster is not flagged manufacturer specific.... .0.. = Manufacturer Specific: False. If like looking on the DP command sequences please do so.

I think its worth trying getting the quirk reading and sending attribute on initiating the device and also sending command to it and see if its behaving better.

Also finding then the device is doing on time request with DP commands and how they is handshaking it with DP commands.

Pleas more feedback and if i shall looking more for "normal" zigbee things in the sniffs.

kkossev commented 2 years ago

I think this device is needing the same treatment as the TS004F that i need sending attributes to then its joining but its looks it dont need being in INIT more do tuya ia not kicking it for rejoining.

I can confirm the above. Sending the multi-attribute read command : Command: Read Attributes (0x00) Attribute: Manufacturer Name (0x0004) Attribute: ZCL Version (0x0000) Attribute: Application Version (0x0001) Attribute: Model Identifier (0x0005) Attribute: Power Source (0x0007) Attribute: Unknown (0xfffe) at any time (not neccesery during the pairing process as for TS004F!) was enough for successful date/time setup.

MattWestb commented 2 years ago

More tuya magic for implanting in Hubitat !! This is number 2 @kkossev have pinpointing and verified working (the first was TS004F). Thanks for verifying it working !!

I only hope i getting help implanting sending attributes and commands from quirks in ZHA and i can getting my TS004F working also for normal users.

MattWestb commented 2 years ago

The unknown attribute is known but not implanted in wireshark and most system then its one global attribute. 2.3.4.5 Global Attributes in ZCL R8 https://github.com/zigpy/zigpy/discussions/595#discussioncomment-1656808

jbmfg commented 2 years ago

So where does this stand now? Which quirk is the best one to use?

MattWestb commented 2 years ago

I is knowing how the command need being implanted for the devices but i cant doing the coding for getting it working. For the moment we is having 4 tuya / LIDL devices that is needs the "tuya magic" for working OK or at all in our systems.

MattWestb commented 2 years ago

@jacekk015 I think then we can getting sending the reading attributes from quirks we shall testing if more tuya TS0602 is needing it / working better. Its looks like many "normal" tuya Zigbee devices is needing this then Z2M have finding 2 and we is having 3 (2 with help of @kkossev) and i think is more is coming.

mrctorres commented 2 years ago

Is there anything else I can do to help with the sniffer or on the device itself?

jacekk015 commented 2 years ago

I think this device is needing the same treatment as the TS004F that i need sending attributes to then its joining but its looks it dont need being in INIT more do tuya ia not kicking it for rejoining.

I can confirm the above. Sending the multi-attribute read command : Command: Read Attributes (0x00) Attribute: Manufacturer Name (0x0004) Attribute: ZCL Version (0x0000) Attribute: Application Version (0x0001) Attribute: Model Identifier (0x0005) Attribute: Power Source (0x0007) Attribute: Unknown (0xfffe) at any time (not neccesery during the pairing process as for TS004F!) was enough for successful date/time setup.

Any example line code?

MattWestb commented 2 years ago

Puddly have making one example python code version of @kkossev code but i cant getting it working then i have not enough knowledge implanting it in one quirk https://github.com/zigpy/zha-device-handlers/pull/969#issuecomment-1006935550.

The TS004f is needed being kicked (leave with rejoining) or having very tight timing for populating the 3 extra EPs but it shall being possible fixing then have get read and writing attributes from the quirk.

kkossev commented 2 years ago

@MattWestb it may turn out that the Basic Cluster attributes read sequence has an effect only when is sent during the pairing process only... same as TS004F. I had a user whose device didn't work (no reporting at all!) until I added the Manufacturer ID to the list of fingerprints and the device was then excluded and re-paired again to the Zigbee concentrator.

MattWestb commented 2 years ago

Thanks for information @kkossev !! Then i can getting the read and writing i can doing the testing of your timing and also kicking if needed for the normal dimmer.

And likely devices is working OK if being pared with tuya ZBGW until battery is being removed as we have seen before :-)

MattWestb commented 2 years ago

@kkossev One more device that i have on the list for "tuya magic" is more or less confirmed https://github.com/dresden-elektronik/deconz-rest-plugin/issues/5493#issuecomment-1034174883 and we is have many Portuguese user that the device is only using one endpoint.

jbmfg commented 2 years ago

I dont really follow the last few comments. Is there anything more to be done here? Would like to be able to change to Fahrenheit plus have reliable datetime settings.

toy3375 commented 2 years ago

The only way to change Fahrenheit is first to pair to a TUYA Gateway. Change settings to Fahrenheit. Then pairing to ZHA again. Time/Date sync when paired with TUYA. After pairing to ZHA , the Time wont sync anymore and the Time slides away..

James Benjamin Goff @.***> schrieb am Sa., 19. Feb. 2022, 20:11:

I dont really follow the last few comments. Is there anything more to be done here? Would like to be able to change to Fahrenheit plus have reliable datetime settings.

— Reply to this email directly, view it on GitHub https://github.com/zigpy/zha-device-handlers/issues/1286#issuecomment-1046086022, or unsubscribe https://github.com/notifications/unsubscribe-auth/ARNNXMZWKYJV5QUQQYMVIRTU37TOXANCNFSM5MA4XE2A . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you were mentioned.Message ID: @.***>

joos81 commented 2 years ago

Since HA update 2022.4 there have been some changes in ZHA handlers. manufacturing_attributes has been replaced by attributes and some other changes. I already found a few and updated the file for this quirk, but still not able to get it to work. Does any know what has to be changed in the previous shared files to get it to work with release 2022.4?

Help is much appreciated. Attached the attempt that I've made, but it is generating errors:

2022-04-14 13:24:21 ERROR (MainThread) [homeassistant.util.logging] Exception in functools.partial(<function async_add_entities at 0x7f77488d2ca0>, <bound method EntityPlatform._async_schedule_add_entities of <EntityPlatform domain=sensor platform_name=zha config_entry=<homeassistant.config_entries.ConfigEntry object at 0x7f77520b1f40>>>, [(<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('00:12:4b:00:21:a8:e4:a2-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7749afb2b0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77364157c0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('00:12:4b:00:21:a8:e4:a2-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7749afb2b0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77364157c0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('00:12:4b:00:21:a8:e4:a2-2-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7749afb2b0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77363d86a0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('00:12:4b:00:21:a8:e4:a2-2-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7749afb2b0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77363d86a0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('b4:e3:f9:ff:fe:a5:3a:62-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363d8850>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7737566e80>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('b4:e3:f9:ff:fe:a5:3a:62-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363d8850>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7737566e80>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('50:32:5f:ff:fe:24:45:05-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363fe2e0>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f773ca7b5b0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('50:32:5f:ff:fe:24:45:05-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363fe2e0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773ca7ba90>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('50:32:5f:ff:fe:24:45:05-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363fe2e0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773ca7ba90>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('8c:f6:81:ff:fe:4b:3b:2f-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f774bb8ba60>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773cb66160>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('8c:f6:81:ff:fe:4b:3b:2f-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f774bb8ba60>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773cb66160>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('60:a4:23:ff:fe:ee:ec:82-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f774bc654c0>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f7737b72640>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('60:a4:23:ff:fe:ee:ec:82-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f774bc654c0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f774bbda610>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('60:a4:23:ff:fe:ee:ec:82-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f774bc654c0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f774bbda610>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736408b50>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f7741832e80>])), (<class 'homeassistant.components.zha.sensor.Temperature'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1026', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736408b50>, [<homeassistant.components.zha.core.channels.measurement.TemperatureMeasurement object at 0x7f7737da3fd0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('a4:c1:38:3d:47:f2:e7:c6-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736408b50>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7737da38e0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('a4:c1:38:3d:47:f2:e7:c6-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736408b50>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7737da38e0>])), (<class 'homeassistant.components.zha.sensor.Humidity'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1029', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736408b50>, [<homeassistant.components.zha.core.channels.measurement.RelativeHumidity object at 0x7f773cd3b790>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('00:12:4b:00:21:a8:e4:a2-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77417e4550>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365298e0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('00:12:4b:00:21:a8:e4:a2-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77417e4550>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365298e0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('00:12:4b:00:21:a8:e4:a2-2-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77417e4550>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365297f0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('00:12:4b:00:21:a8:e4:a2-2-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77417e4550>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365297f0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('b4:e3:f9:ff:fe:a5:3a:62-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7737cc96a0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773cba7b80>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('b4:e3:f9:ff:fe:a5:3a:62-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7737cc96a0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f773cba7b80>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('50:32:5f:ff:fe:24:45:05-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363ca3a0>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f77365296a0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('50:32:5f:ff:fe:24:45:05-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363ca3a0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365294c0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('50:32:5f:ff:fe:24:45:05-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f77363ca3a0>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f77365294c0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('8c:f6:81:ff:fe:4b:3b:2f-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736529a60>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735de73d0>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('8c:f6:81:ff:fe:4b:3b:2f-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7736529a60>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735de73d0>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('60:a4:23:ff:fe:ee:ec:82-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7610>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f7735de7c70>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('60:a4:23:ff:fe:ee:ec:82-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7610>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735de7c40>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('60:a4:23:ff:fe:ee:ec:82-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7610>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735de7c40>])), (<class 'homeassistant.components.zha.sensor.Battery'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7f40>, [<homeassistant.components.zha.core.channels.general.PowerConfigurationChannel object at 0x7f7735dec640>])), (<class 'homeassistant.components.zha.sensor.Temperature'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1026', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7f40>, [<homeassistant.components.zha.core.channels.measurement.TemperatureMeasurement object at 0x7f7735dec5e0>])), (<class 'homeassistant.components.zha.sensor.RSSISensor'>, ('a4:c1:38:3d:47:f2:e7:c6-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7f40>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735dec520>])), (<class 'homeassistant.components.zha.sensor.LQISensor'>, ('a4:c1:38:3d:47:f2:e7:c6-1-0', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7f40>, [<homeassistant.components.zha.core.channels.general.BasicChannel object at 0x7f7735dec520>])), (<class 'homeassistant.components.zha.sensor.Humidity'>, ('a4:c1:38:3d:47:f2:e7:c6-1-1029', <homeassistant.components.zha.core.device.ZHADevice object at 0x7f7735de7f40>, [<homeassistant.components.zha.core.channels.measurement.RelativeHumidity object at 0x7f7735dec610>]))], update_before_add=False) when dispatching 'zha_add_new_entities': () ts0601_temperature.zip

jacekk015 commented 2 years ago

Missing .id on the end of: self.attributes_by_name["measured_value"].id

joos81 commented 2 years ago

Yes that's it! Thanks

TheJulianJES commented 2 years ago

Do you currently have a custom working quirk for this device for Home Assistant 2022.4.5? If so, it would be nice if you could PR the changes to this repo or just send the latest quirk file here, so someone else can do it. Then, a custom quirk wouldn't be needed in the future anymore. Thanks!

joos81 commented 2 years ago

Hi, These is the extensive version with all the entities as described earlier. However updating the values (frequency, date/time etc) does not work and generate errors. But as far as I can tell there has not been a working version for that ts0601_temperature.py.zip .

joos81 commented 2 years ago

This is the version with only three entities (temperature, humidity and power). This version works without any errors. Date/time is not updated. ts0601_temperature.py.zip

MattWestb commented 2 years ago

The device is more then likely need "tuya magic spell" being casted on it then paring it for getting the reporting and clock setting working. We have implanting one working version for one device that can being tested if some like to so it. The code looks lik this and is implanted in the device class so its being run then the quirk is loaded but then restart HA its doing it but the network is not online so its only being casted then doing new joining of device. https://github.com/zigpy/zha-device-handlers/blob/16f298e9ce293d241592f86573e909f9c32809d0/zhaquirks/tuya/ts004f.py#L180-L195

github-actions[bot] commented 2 years ago

There hasn't been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.

seitz commented 2 years ago

I managed to get clock updates with this quirk: https://github.com/zigpy/zha-device-handlers/issues/1702#issuecomment-1238612059

(slightly modified by adding ("_TZE200_3towulqd", "TS0601") to the Models_info)

JeffPixelSplash commented 1 year ago

I managed to get clock updates with this quirk: #1702 (comment)

(slightly modified by adding ("_TZE200_3towulqd", "TS0601") to the Models_info)

Worked for me also. Here is my revised code...

"""Tuya temp and humidity sensor with 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 typing import Tuple, Optional, Union
##################

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput
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 TemperatureUnitConvert(t.enum8):
    """Tuya Temp unit convert enum."""

    Celsius = 0x00
    Fahrenheit = 0x01

class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
    """Tuya local TemperatureMeasurement cluster."""

    attributes = TemperatureMeasurement.attributes.copy()
    attributes.update(
        {
            0x8001: ("temp_unit_convert", t.enum8),
            0x8002: ("alarm_max_temperature", t.Single),
            0x8003: ("alarm_min_temperature", t.Single),
            0x8004: ("temperature_sensitivity", t.Single),
        }
    )

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
        ),
        9: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temp_unit_convert",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: TemperatureUnitConvert(x)
        ),
        10: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_max_temperature",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        ),
        11: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_min_temperature",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        ),
        19: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temperature_sensitivity",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        )
    }

    set_time_offset = 1970
    set_time_local_offset = 1970

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        11: "_dp_2_attr_update",
        19: "_dp_2_attr_update",
    }

    def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
        payload = TuyaTimePayload()

        utc_now = datetime.datetime.utcnow()
        now = datetime.datetime.now()

        offset_time = datetime.datetime(self.set_time_offset, 1, 1)
        offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1)

        utc_timestamp = int((utc_now - offset_time).total_seconds())
        local_timestamp = int((now - offset_time).total_seconds())

        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, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False)
        )

        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_bq5c8xfe", "TS0601"),
            ("_TZE200_locansqn", "TS0601"),
            ("_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: [
                    Basic.cluster_id,
                    TemperatureHumidityManufCluster,  # Single bus for temp, humidity, and battery
                    TuyaTemperatureMeasurement,
                    TuyaRelativeHumidity,
                    TuyaPowerConfigurationCluster2AAA,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
            }
        },
    }
toy3375 commented 1 year ago

Hey Everybody,

I can confirm. Each of my 3 devices has the right time and date . And i get current temperature , humidity and Batterie values ​​at Home Assistant. Thanks to all image

MattWestb commented 1 year ago

Hey @toy3375 Pleas reformat the log with starting on one blank line with ``` and the same after on one blank line so its can being red without loosing formatting.

Frohe . . .

toy3375 commented 1 year ago

@MattWestb : My mistake . I replyed to the E-Mail. i fixed it .

jacekk015 commented 1 year ago

Quirk corrected, now using EnchantedDevice class, which sends multi-attribute read. Worth of trying if date/time is in sync now. ts0601_temperature.py.zip

relighted commented 1 year ago

Using this seemingly off-spec sensor; and finding this quirk (thanks for all the work on this!). I get this init issue with fully latest HA, and SkyConnect, ZHA. Any ideas? I'm totally new to ZHA and quicks I'm afraid,

Logger: homeassistant.config_entries
Source: custom_zha_quirks/ts0601_temperature.py:145
First occurred: 9:25:39 AM (2 occurrences)
Last logged: 9:27:39 AM

Error setting up entry SkyConnect v1.0 for zha
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 382, in async_setup
    result = await component.async_setup_entry(hass, self)
  File "/usr/src/homeassistant/homeassistant/components/zha/__init__.py", line 100, in async_setup_entry
    setup_quirks(config)
  File "/usr/local/lib/python3.10/site-packages/zhaquirks/__init__.py", line 409, in setup
    importer.find_module(modname).load_module(modname)
  File "<frozen importlib._bootstrap_external>", line 548, in _check_name_wrapper
  File "<frozen importlib._bootstrap_external>", line 1063, in load_module
  File "<frozen importlib._bootstrap_external>", line 888, in load_module
  File "<frozen importlib._bootstrap>", line 290, in _load_module_shim
  File "<frozen importlib._bootstrap>", line 719, in _load
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/config/custom_zha_quirks/ts0601_temperature.py", line 145, in <module>
    class TuyaSensorManufCluster(TuyaManufClusterAttributes):
  File "/usr/local/lib/python3.10/site-packages/zigpy/zcl/__init__.py", line 84, in __init_subclass__
    raise TypeError(
TypeError: `manufacturer_attributes` is deprecated. Copy the parent class's `attributes` dictionary and update it with your manufacturer-specific `attributes`. Make sure to specify that it is manufacturer-specific through the  appropriate constructor or tuple!

--

jacekk015 commented 1 year ago

@relighted Use ts0601_temperature.py file from https://github.com/jacekk015/zha_quirks

adrianschneider1977 commented 1 year ago

Referring to @JeffPixelSplash 's solution including the time and date. With the latest HomeAssitant update it seems to be broken. My solution, maybe crude: (An sorry, for not the bad formatting here... New here:)

Change this:

from`` zhaquirks.tuya import TuyaLocalCluster, TuyaPowerConfigurationCluster2AAA
#` old: from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster

Change all of them to explicit type conversion:

   19: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temperature_sensitivity",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x / 10)

The whole file like it works for my _TZE200_locansqn:

"""Tuya temp and humidity sensor with 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 typing import Tuple, Optional, Union
##################

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput
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
# old: from zhaquirks.tuya.mcu import DPToAttributeMapping, TuyaDPType, TuyaMCUCluster
from zhaquirks.tuya.mcu import DPToAttributeMapping, 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 TemperatureUnitConvert(t.enum8):
    """Tuya Temp unit convert enum."""

    Celsius = 0x00
    Fahrenheit = 0x01

class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
    """Tuya local TemperatureMeasurement cluster."""

    attributes = TemperatureMeasurement.attributes.copy()
    attributes.update(
        {
            0x8001: ("temp_unit_convert", t.enum8),
            0x8002: ("alarm_max_temperature", t.Single),
            0x8003: ("alarm_min_temperature", t.Single),
            0x8004: ("temperature_sensitivity", t.Single),
        }
    )

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: float(x * 10),  # decidegree to centidegree
        ),
        2: DPToAttributeMapping(
            TuyaRelativeHumidity.ep_attribute,
            "measured_value",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x * 100),  # 0.01 to 1.0
        ),
        4: DPToAttributeMapping(
            TuyaPowerConfigurationCluster2AAA.ep_attribute,
            "battery_percentage_remaining",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x * 2),  # reported percentage is doubled
        ),
        9: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temp_unit_convert",
            #dp_type=TuyaDPType.ENUM,
            converter=lambda x: TemperatureUnitConvert(x)
        ),
        10: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_max_temperature",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x / 10)
        ),
        11: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_min_temperature",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x / 10)
        ),
        19: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temperature_sensitivity",
            #dp_type=TuyaDPType.VALUE,
            converter=lambda x: float(x / 10)
        )
    }

    set_time_offset = 1970
    set_time_local_offset = 1970

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        11: "_dp_2_attr_update",
        19: "_dp_2_attr_update",
    }

    def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
        payload = TuyaTimePayload()

        utc_now = datetime.datetime.utcnow()
        now = datetime.datetime.now()

        offset_time = datetime.datetime(self.set_time_offset, 1, 1)
        offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1)

        utc_timestamp = int((utc_now - offset_time).total_seconds())
        local_timestamp = int((now - offset_time).total_seconds())

        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, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False)
        )

        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_bq5c8xfe", "TS0601"),
            ("_TZE200_locansqn", "TS0601"),
            ("_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: [
                    Basic.cluster_id,
                    TemperatureHumidityManufCluster,  # Single bus for temp, humidity, and battery
                    TuyaTemperatureMeasurement,
                    TuyaRelativeHumidity,
                    TuyaPowerConfigurationCluster2AAA,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
            }
        },
    }

I managed to get clock updates with this quirk: #1702 (comment) (slightly modified by adding ("_TZE200_3towulqd", "TS0601") to the Models_info)

Worked for me also. Here is my revised code...

"""Tuya temp and humidity sensor with 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 typing import Tuple, Optional, Union
##################

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time, AnalogOutput
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 TemperatureUnitConvert(t.enum8):
    """Tuya Temp unit convert enum."""

    Celsius = 0x00
    Fahrenheit = 0x01

class TuyaTemperatureMeasurement(TemperatureMeasurement, TuyaLocalCluster):
    """Tuya local TemperatureMeasurement cluster."""

    attributes = TemperatureMeasurement.attributes.copy()
    attributes.update(
        {
            0x8001: ("temp_unit_convert", t.enum8),
            0x8002: ("alarm_max_temperature", t.Single),
            0x8003: ("alarm_min_temperature", t.Single),
            0x8004: ("temperature_sensitivity", t.Single),
        }
    )

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
        ),
        9: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temp_unit_convert",
            dp_type=TuyaDPType.ENUM,
            converter=lambda x: TemperatureUnitConvert(x)
        ),
        10: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_max_temperature",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        ),
        11: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "alarm_min_temperature",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        ),
        19: DPToAttributeMapping(
            TuyaTemperatureMeasurement.ep_attribute,
            "temperature_sensitivity",
            dp_type=TuyaDPType.VALUE,
            converter=lambda x: x / 10
        )
    }

    set_time_offset = 1970
    set_time_local_offset = 1970

    data_point_handlers = {
        1: "_dp_2_attr_update",
        2: "_dp_2_attr_update",
        4: "_dp_2_attr_update",
        9: "_dp_2_attr_update",
        10: "_dp_2_attr_update",
        11: "_dp_2_attr_update",
        19: "_dp_2_attr_update",
    }

    def handle_set_time_request(self, sequence_number: t.uint16_t) -> foundation.Status:
        payload = TuyaTimePayload()

        utc_now = datetime.datetime.utcnow()
        now = datetime.datetime.now()

        offset_time = datetime.datetime(self.set_time_offset, 1, 1)
        offset_time_local = datetime.datetime(self.set_time_local_offset, 1, 1)

        utc_timestamp = int((utc_now - offset_time).total_seconds())
        local_timestamp = int((now - offset_time).total_seconds())

        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, manufacturer=foundation.ZCLHeader.NO_MANUFACTURER_ID, expect_reply=False)
        )

        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_bq5c8xfe", "TS0601"),
            ("_TZE200_locansqn", "TS0601"),
            ("_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: [
                    Basic.cluster_id,
                    TemperatureHumidityManufCluster,  # Single bus for temp, humidity, and battery
                    TuyaTemperatureMeasurement,
                    TuyaRelativeHumidity,
                    TuyaPowerConfigurationCluster2AAA,
                ],
                OUTPUT_CLUSTERS: [Ota.cluster_id, Time.cluster_id],
            }
        },
    }
joos81 commented 1 year ago

Thanks! This solutions works for me as well. ~I only had to adapt the quirk file and restart home assistant. No need to remove and re-add the device.~

edit: this is not correct, turns out I had to remove and re-add the device as no new values were received since I update the quirk file

JeffPixelSplash commented 1 year ago

I'm having trouble with this. I get an error....

ImportError: cannot import name 'TuyaDPType' from 'zhaquirks.tuya.mcu'

does anyone have any suggestions?

joos81 commented 1 year ago

Did you use the updated quirk at the top of the post off @adrianschneider1977 He quoted the old version as well, that might be a bit confusing.

If you updated your file manualy, make sure that you're not only replacing the include on top, but also remove the line "dp_type=TuyaDPType.VALUE" on the other 7 locations.

Attached the updated version with all modifications. ts0601_temperature.zip

jacekk015 commented 1 year ago

... or you can just use ready to work version from: https://github.com/jacekk015/zha_quirks/blob/main/ts0601_temperature.py

relighted commented 1 year ago

Awesome community! The two devices I have finally started to behave somewhat icw the HA sky Connect. However only one of the two returns the temp en humidity in HA as sensors. I removed and re-added multiple times. Any magic option I missed?

mrctorres commented 1 year ago

Awesome community! The two devices I have finally started to behave somewhat icw the HA sky Connect. However only one of the two returns the temp en humidity in HA as sensors. I removed and re-added multiple times. Any magic option I missed?

It only worked for me when I restarted Home Assistant. Even reloading the integration and pairing again did not show the temperature and humidity.

jacekk015 commented 1 year ago

@relighted @mrctorres Which file did you both use?? From my repository?? https://github.com/jacekk015/zha_quirks/blob/main/ts0601_temperature.py

User below successfully used my quirk. https://github.com/jacekk015/zha_quirks/issues/6

MattWestb commented 1 year ago

For getting the device you working OK you need deleting it and waiting one minute and then adding it new after the quirk have being installed or the tuya magic is not working.

relighted commented 1 year ago

Yes I used the one mentioned here https://github.com/zigpy/zha-device-handlers/issues/1286#issuecomment-1463798600

I have one device working ok with temp & hum HA sensors as output in HA. The other one, which I deleted, powered off 2 hours, now re-added also is well detected but simply does not show these 2 as sensors, only 4 binary states, and the settings options.

But using the zigbee management I am able read the values manually for these temp and hum Clusters.

Otherwise, could be they have different tuya FW on them?

jacekk015 commented 1 year ago

Do you use latest version from: https://github.com/jacekk015/zha_quirks ???

Use latest version quirk file. Enable debug logging https://github.com/jacekk015/zha_quirks#in-case-of-errors-or-to-support-new-function Restart HA

Remove that non working device, and pair like a new. After pairing wait at least 10 minutes. Post full HA logs here. Don't cut out anything.

JeffPixelSplash commented 1 year ago

I have it working after a bit of a voodoo dance...

My steps were:

  1. Got rid of the old quirks I had (added .bad to the end).
  2. Added quirk from jacekk015's repository.
  3. Added device (failed)
  4. Restarted Home Assitant core
  5. Added device (succeeded but no temp/humidity sensors)
  6. Reloaded ZHA

At this point it is functioning correctly. The only anomaly is the 4 unidentified Binaryinput sensors and the "switch" control. I wonder what they all do?

What'd be awesome is some way to set the display to F rather than C.