Repository: zigpy/zha-device-handlers

Issue:
[BUG]Ikea FYRTUR blind and remote reporting wrong battery or no battery
First 

Blind:

Never updates the battery automatically.

However if you do a zigbee get cluster attribute for battery percentage remaining it does return a correct value.

Remote:

does update battery on its own.

Both:

both values are displayed correctly in the get attribute box but the sensor for the batteries figures are always half what it shows.
![zha cluster 2](https://user-images.githubusercontent.com/44187409/77225998-78782080-6b6c-11ea-908b-7518207189ad.JPG)
![zha cluster 1](https://user-images.githubusercontent.com/44187409/77226005-8332b580-6b6c-11ea-8a51-03e128548433.JPG)




Discussion:
please remove the device via the remove device button in the screenshot above. activate the device after clicking the button to ensure the device is awake. Then after about a minute please re-pair the device via the add devices screen and post the entire contents of that log area on that screen in a code block here. 
Hi! I'm having the exact same issue described by @blair287 

Also same thing happens with the **current_position_lift_percentage**, I have to update the attribute manually so home assistant frontend updates the cover status.

This is the output of the log area:

```
[0xfc13] Delivery error for seq # 0x64, on endpoint id 0 cluster 0x0036: message send failure
Couldn't open '08:6b:d7:ff:fe:58:64:f9' for joining: [0xfc13:0:0x0036]: Message send failure
Device 0x8499 (d0:cf:5e:ff:fe:ea:35:27) joined the network
[0x8499:zdo] ZDO request 0x0013: [0x8499, d0:cf:5e:ff:fe:ea:35:27, 128]
[0x8499] Requesting 'Node Descriptor'
[0x8499] Extending timeout for 0x66 request
[0x8499] Node Descriptor: <Optional byte1=2 byte2=64 mac_capability_flags=128 manufacturer_code=4476 maximum_buffer_size=82 maximum_incoming_transfer_size=82 server_mask=11264 maximum_outgoing_transfer_size=82 descriptor_capability_field=0>
[0x8499] Discovering endpoints
[0x8499] Extending timeout for 0x68 request
[0x8499] Discovered endpoints: [1]
[0x8499:1] Discovering endpoint information
[0x8499] Extending timeout for 0x6a request
[0x8499:1] Discovered endpoint information: <SimpleDescriptor endpoint=1 profile=260 device_type=514 device_version=1 input_clusters=[0, 1, 3, 4, 5, 32, 258, 4096, 64636] output_clusters=[25, 4096]>
[0x8499] Extending timeout for 0x6c request
[0x8a95:1:0x0402] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=96 command_id=Command.Report_Attributes>
[0x8a95:1:0x0402] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=int16s, value=2174>>]]
[0x8a95:1:0x0402] Attribute report received: measured_value=2174
[0x8a95:1:0x0405] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=97 command_id=Command.Report_Attributes>
[0x8a95:1:0x0405] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=uint16_t, value=5067>>]]
[0x8a95:1:0x0405] Attribute report received: measured_value=5067
[0x8a95:1:0x0403] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=98 command_id=Command.Report_Attributes>
[0x8a95:1:0x0403] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=int16s, value=1013>>, <Attribute attrid=20 value=<TypeValue type=int8s, value=-1>>, <Attribute attrid=16 value=<TypeValue type=int16s, value=10132>>]]
[0x8a95:1:0x0403] Attribute report received: measured_value=1013, 20=-1, 16=10132
[0x8499:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=108 command_id=Command.Read_Attributes_rsp>
[0x8499:1] Manufacturer: IKEA of Sweden
[0x8499:1] Model: FYRTUR block-out roller blind
Checking quirks for IKEA of Sweden FYRTUR block-out roller blind (d0:cf:5e:ff:fe:ea:35:27)
Considering <class 'zhaquirks.ikea.tradfriplug.TradfriPlug'>
Fail because endpoint list mismatch: {1, 2, 242} {1}
Considering <class 'bellows.zigbee.application.EZSPCoordinator'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.gledopto.soposhgu10.SoposhGU10'>
Fail because endpoint list mismatch: {11, 13} {1}
Considering <class 'zhaquirks.lutron.lzl4bwhl01remote.LutronLZL4BWHL01Remote2'>
Fail because profile_id mismatch on at least one endpoint
Considering <class 'zhaquirks.netvox.z308e3ed.Z308E3ED'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.osram.a19twhite.A19TunableWhite'>
Fail because endpoint list mismatch: {3} {1}
Considering <class 'zhaquirks.philips.rom001.PhilipsROM001'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.philips.rwl021.PhilipsRWL021'>
Fail because endpoint list mismatch: {1, 2} {1}
Considering <class 'zhaquirks.smartthings.multi.SmartthingsMultiPurposeSensor'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.smartthings.tag_v4.SmartThingsTagV4'>
Fail because device_type mismatch on at least one endpoint
Considering <class 'zhaquirks.xbee.xbee3_io.XBee3Sensor'>
Fail because endpoint list mismatch: {232, 230} {1}
Considering <class 'zhaquirks.xbee.xbee_io.XBeeSensor'>
Fail because endpoint list mismatch: {232, 230} {1}
Considering <class 'zhaquirks.xiaomi.mija.smoke.MijiaHoneywellSmokeDetectorSensor'>
Fail because device_type mismatch on at least one endpoint
device - 0x8499:d0:cf:5e:ff:fe:ea:35:27 entering async_device_initialized - is_new_join: True
device - 0x8499:d0:cf:5e:ff:fe:ea:35:27 has joined the ZHA zigbee network
[0x8499](FYRTUR block-out roller blind): started configuration
[0x8499:ZDO](FYRTUR block-out roller blind): 'async_configure' stage succeeded
[0x8499] Extending timeout for 0x6e request
[0x8499] Extending timeout for 0x70 request
[0x8499] Extending timeout for 0x72 request
[0x8499:1:0x0102]: bound 'window_covering' cluster: Status.SUCCESS
[0x8499] Extending timeout for 0x74 request
[0x8499:1:0x0000]: bound 'basic' cluster: Status.SUCCESS
[0x8499:1:0x0000]: finished channel configuration
[0x8499] Extending timeout for 0x76 request
[0x8499:1:0x0020] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=114 command_id=Command.Write_Attributes_rsp>
[0x8499:1:0x0020]: 3300.0s check-in interval set: [[<WriteAttributesStatusRecord status=Status.SUCCESS>]]
[0x8499] Extending timeout for 0x78 request
[0x8499:1:0x0102] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=116 command_id=Command.Configure_Reporting_rsp>
[0x8499:1:0x0102]: reporting 'current_position_lift_percentage' attr on 'window_covering' cluster: 0/900/1: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]]'
[0x8499:1:0x0102]: finished channel configuration
[0x8499] Extending timeout for 0x7a request
[0x8499:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=118 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0000]: initializing channel: from_cache: False
[0x8499] Extending timeout for 0x7c request
[0x8499:1:0x0020]: bound 'poll_control' cluster: Status.SUCCESS
[0x8499:1:0x0020]: finished channel configuration
[0x8499:1:0x1000]: bound 'lightlink' cluster: Status.SUCCESS
[0x8499:1:0x1000]: finished channel configuration
[0x8499:zdo] ZDO request 0x0036: [180, <Bool.true: 1>]
[0x8499:1:0x0001]: bound 'power' cluster: Status.SUCCESS
[0x8499] Extending timeout for 0x7e request
[0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=126 command_id=Command.Configure_Reporting_rsp>
[0x8499:1:0x0001]: reporting 'battery_voltage' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]]'
[0x8499] Extending timeout for 0x80 request
[0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=128 command_id=Command.Configure_Reporting_rsp>
[0x8499:1:0x0001]: reporting 'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]]'
[0x8499:1:0x0001]: finished channel configuration
[0x8499:1:0x0102]: 'async_configure' stage succeeded
[0x8499:1:0x0000]: 'async_configure' stage succeeded
[0x8499:1:0x0020]: 'async_configure' stage succeeded
[0x8499:1:0x1000]: 'async_configure' stage succeeded
[0x8499:1:0x0001]: 'async_configure' stage succeeded
[0x8499](FYRTUR block-out roller blind): completed configuration
[0x8499](FYRTUR block-out roller blind): stored in registry: ZhaDeviceEntry(name='IKEA of Sweden FYRTUR block-out roller blind', ieee='d0:cf:5e:ff:fe:ea:35:27', last_seen=1586643327.456316)
[0x8499] Extending timeout for 0x82 request
[0x8499:1:0x0003] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=130 command_id=Command.Default_Response>
[0x8499:1:0x0003]: executed 'trigger_effect' command with args: '(2, 0)' kwargs: '{}' result: [64, <Status.SUCCESS: 0>]
[0x8499](FYRTUR block-out roller blind): started initialization
[0x8499:ZDO](FYRTUR block-out roller blind): 'async_initialize' stage succeeded
[0x8499] Extending timeout for 0x84 request
[0x8499] Extending timeout for 0x86 request
[0x8499:1:0x0020]: initializing channel: from_cache: False
[0x8499:1:0x1000]: initializing channel: from_cache: False
[0x8499] Extending timeout for 0x88 request
[0x8499] Extending timeout for 0x8a request
[0x8499:1:0x0102] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=132 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0102]: Attribute report 'Window Covering'[current_position_lift_percentage] = 0
[0x8499:1:0x0102]: initializing channel: from_cache: False
[0x8499] Extending timeout for 0x8c request
[0x8499:1:0x0000] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=134 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=136 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0102] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=138 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0000]: initializing channel: from_cache: False
[0x8499:1:0x0001]: initializing channel: from_cache: False
[0x8499] Extending timeout for 0x8e request
[0x8499:1:0x0102]: Attribute report 'Window Covering'[current_position_lift_percentage] = 0
[0x8499:1:0x0102]: read current position: 0
polling current state
read pos=0
[0x8499:1:0x0102] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=140 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=142 command_id=Command.Read_Attributes_rsp>
[0x8499:1:0x0102]: Attribute report 'Window Covering'[current_position_lift_percentage] = 0
setting position: 0
[0x8499:1:0x0102]: 'async_initialize' stage succeeded
[0x8499:1:0x0000]: 'async_initialize' stage succeeded
[0x8499:1:0x0020]: 'async_initialize' stage succeeded
[0x8499:1:0x1000]: 'async_initialize' stage succeeded
[0x8499:1:0x0001]: 'async_initialize' stage succeeded
[0x8499](FYRTUR block-out roller blind): power source: Battery or Unknown
[0x8499](FYRTUR block-out roller blind): completed initialization
[0x9314:1:0x0400] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=122 command_id=Command.Report_Attributes>
[0x9314:1:0x0400] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=uint16_t, value=45>>]]
[0x9314:1:0x0400] Attribute report received: measured_value=45
[0x9314:1:0x0406] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=True> manufacturer=None tsn=123 command_id=Command.Report_Attributes>
[0x9314:1:0x0406] ZCL request 0x000a: [[<Attribute attrid=0 value=<TypeValue type=bitmap8, value=1>>]]
[0x9314:1:0x0406] Attribute report received: occupancy=1
[0x9314:1:0x0500]: Updated alarm state: 1
[0x9f51:1:0x0500]: Updated alarm state: 0

```
Read `battery_voltage` attribute of the `power configuration` cluster from ZHA device card in ZHA configuration panel.
And at what battery level blinds stop responding?
Sorry I'm not sure exactly what info you need and English is not my main language, so I'll give you all the possible info. Sorry if some of it was not needed.

In my case the blinds haven't stopped responding, but this is what I have to do in order to get the status of the blind displayed correctly on home-assistant:
1. Call service _cover.set_cover_position_ with position attribute, in this example I set to the value to 80. The blind will correctly move to the desired position.

2. Now if I go to the status of the cover, the value doesn't get updated, it will show the last value that I updated manually.
![imagen](https://user-images.githubusercontent.com/16177130/79076966-155a5380-7cfe-11ea-9c37-8769c1d53dd4.png)

3. For the status to update on the frontend, I go to WindowCovering cluster and click on "Get ZIGBEE ATTRIBUTE" for attribute _current_position_lift_percentage_. Now I have the correct value for the blind displayed on the frontend (Although the status shows opening when it should say open):
![imagen](https://user-images.githubusercontent.com/16177130/79077030-800b8f00-7cfe-11ea-871f-e726ec2e5be2.png)
![imagen](https://user-images.githubusercontent.com/16177130/79077192-e04f0080-7cff-11ea-99a7-9cd8630c2038.png)



The same thing happens with the battery sensor, I have to get the battery_percentage_remaining from the zha page in order for the sensor to be updated. And the sensor always shows half of the given value.
![imagen](https://user-images.githubusercontent.com/16177130/79077110-30799300-7cff-11ea-8528-8e16eaaa061c.png)
![imagen](https://user-images.githubusercontent.com/16177130/79077114-3a9b9180-7cff-11ea-9a2a-56a8f7f28c15.png)


If I get the _battery_voltage_ attribute, this is what I get:
![imagen](https://user-images.githubusercontent.com/16177130/79077163-9f56ec00-7cff-11ea-9996-f6e46e619673.png)


Thanks for the help, let me know if I can give you more information to help fix this.
ah, it does support `battery_percent_remaining` attribute, so it shouldn't need a quirk. Per log it configured the attribute reporting successfuly
```
[0x8499:1:0x0001]: reporting 'battery_percentage_remaining' attr on 'power' cluster: 3600/10800/1: Result: '[[<ConfigureReportingResponseRecord status=Status.SUCCESS>]
```

How long have you waited for the battery sensor to update? 

Enable debug logging for zigpy and zha, in `configuration.yaml`

logger:
  default: info
  logs:
    homeassistant.components.zha: debug
    zigpy: debug
    bellows.zigbee.application: debug
    bellows.ezsp: debug
    zigpy_xbee.zigbee.application: debug
    zigpy_xbee.api: debug
    zigpy_deconz.zigbee.application: debug
    zigpy_deconz.api: debug
    zigpy_zigate: debug
```

run it for 24 hours, then do `grep 0x8499:1:0x0001 home-assistant.log` to see if you get attribute updates reported. If battery level doesn't change, then blind should report it once every 24 hours IIRC
This is the output of the command _grep 0x8499:1:0x0001 home-assistant.log_ after two full days of running home-assistant with debug logging enabled:
```
2020-04-13 00:26:27 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x8499:1:0x0001]: initializing channel: from_cache: True
2020-04-13 00:26:28 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x8499:1:0x0001]: 'async_initialize' stage succeeded
2020-04-13 00:27:03 DEBUG (MainThread) [zigpy.zcl] [0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=41 command_id=Command.Read_Attributes_rsp>
2020-04-13 00:27:03 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x8499:1:0x0001]: initializing channel: from_cache: False
2020-04-13 00:27:04 DEBUG (MainThread) [zigpy.zcl] [0x8499:1:0x0001] ZCL deserialize: <ZCLHeader frame_control=<FrameControl frame_type=GLOBAL_COMMAND manufacturer_specific=False is_reply=True disable_default_response=False> manufacturer=None tsn=47 command_id=Command.Read_Attributes_rsp>
2020-04-13 00:27:04 DEBUG (MainThread) [homeassistant.components.zha.core.channels.base] [0x8499:1:0x0001]: 'async_initialize' stage succeeded
```

It's never once updated battery on its own without the attribute being read manually. 

Now after 109.4 update I'm not getting bettery from the remote either.
The half battery life still isnt fixed any eta surely this is simple to fix just x2 the output.
There is already a custom cluster that does this. Just needs to be used
> There is already a custom cluster that does this. Just needs to be used

How can that be done please? How come its not used by default?
?
Because IKEA doesn’t follow the ZCL spec. We’ll have to add a quirk for it. Be patient this is done as time permits as a hobby.
In other words: PRs are welcome.
Im sorry i thought you meant there was a setting i could change.


Resolving patch:
diff --git a/zhaquirks/ikea/blinds.py b/zhaquirks/ikea/blinds.py
--- a/zhaquirks/ikea/blinds.py
+++ b/zhaquirks/ikea/blinds.py
@@ -31,9 +31,9 @@ class IkeaTradfriRollerBlinds(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI Fyrtur blinds."""
 
     signature = {
-        # <SimpleDescriptor endpoint=1 profile=260 device_type=2080
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=514
         # device_version=1
-        # input_clusters=[0, 1, 3, 4, 5, 32, 258, 4096]
+        # input_clusters=[0, 1, 3, 4, 5, 32, 258, 4096, 64636]
         # output_clusters=[25, 4096]>
         MODELS_INFO: [
             (IKEA, "FYRTUR block-out roller blind"),
@@ -52,6 +52,7 @@ class IkeaTradfriRollerBlinds(CustomDevice):
                     PollControl.cluster_id,
                     WindowCovering.cluster_id,
                     LightLink.cluster_id,
+                    IKEA_CLUSTER_ID,
                 ],
                 OUTPUT_CLUSTERS: [Ota.cluster_id, LightLink.cluster_id],
             }
@@ -59,11 +60,11 @@ class IkeaTradfriRollerBlinds(CustomDevice):
     }
 
     replacement = {
-        "endpoints": {
+        ENDPOINTS: {
             1: {
-                "profile_id": zha.PROFILE_ID,
-                "device_type": zha.DeviceType.WINDOW_COVERING_DEVICE,
-                "input_clusters": [
+                PROFILE_ID: zha.PROFILE_ID,
+                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
+                INPUT_CLUSTERS: [
                     Basic.cluster_id,
                     DoublingPowerConfigurationCluster,
                     Identify.cluster_id,
@@ -72,8 +73,9 @@ class IkeaTradfriRollerBlinds(CustomDevice):
                     PollControl.cluster_id,
                     WindowCovering.cluster_id,
                     LightLink.cluster_id,
+                    IKEA_CLUSTER_ID,
                 ],
-                "output_clusters": [Ota.cluster_id, LightLink.cluster_id],
+                OUTPUT_CLUSTERS: [Ota.cluster_id, LightLink.cluster_id],
             }
         }
     }
diff --git a/zhaquirks/ikea/opencloseremote.py b/zhaquirks/ikea/opencloseremote.py
--- a/zhaquirks/ikea/opencloseremote.py
+++ b/zhaquirks/ikea/opencloseremote.py
@@ -33,7 +33,14 @@ class IkeaTradfriOpenCloseRemote(CustomDevice):
     """Custom device representing IKEA of Sweden TRADFRI remote control."""
 
     signature = {
-        MODELS_INFO: [("\x02KE", "TRADFRI open/close remote")],
+        # <SimpleDescriptor endpoint=1 profile=260 device_type=515
+        # device_version=1
+        # input_clusters=[0, 1, 3, 9, 32, 4096, 64636]
+        # output_clusters=[3, 4, 6, 8, 25, 258, 4096]>
+        MODELS_INFO: [
+            ("\x02KE", "TRADFRI open/close remote"),
+            (IKEA, "TRADFRI open/close remote"),
+        ],
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,


Test patch: