We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Device Support Request] Tuya Smart Zigbee Curtain Switch Module (_TZ3000_mowcrwsa)
**Is your feature request related to a problem? Please describe.**
Device can be paired in ZHA but not working properly in HA.
Manufacturer ID _TZ3000_mowcrwsa is not added as MODELS_INFO in ts130f.py

**Describe the solution you'd like**
Add manufacturer ID of the below device signature to class TuyaZemismartTS130F(CustomDevice): of zha-device-handlers/zhaquirks/tuya/ts130f.py

**Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.**
{
  "node_descriptor": "NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.0: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)",
  "endpoints": {
    "1": {
      "profile_id": 260,
      "device_type": "0x0202",
      "in_clusters": [
        "0x0000",
        "0x0004",
        "0x0005",
        "0x0006",
        "0x0102"
      ],
      "out_clusters": [
        "0x000a",
        "0x0019"
      ]
    }
  },
  "manufacturer": "_TZ3000_mowcrwsa",
  "model": "TS130F",
  "class": "zigpy.device.Device"
}

**Additional context**
Add any other context or screenshots about the feature request here.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `zhaquirks/tuya/ts130f.py`
Content:
```
1 """Device handler for loratap TS130F smart curtain switch."""
2 from zigpy.profiles import zha
3 from zigpy.quirks import CustomCluster, CustomDevice
4 import zigpy.types as t
5 from zigpy.zcl.clusters.closures import WindowCovering
6 from zigpy.zcl.clusters.general import Basic, Groups, OnOff, Ota, Scenes, Time
7 
8 from zhaquirks.const import (
9     DEVICE_TYPE,
10     ENDPOINTS,
11     INPUT_CLUSTERS,
12     MODELS_INFO,
13     OUTPUT_CLUSTERS,
14     PROFILE_ID,
15 )
16 
17 ATTR_CURRENT_POSITION_LIFT_PERCENTAGE = 0x0008
18 CMD_GO_TO_LIFT_PERCENTAGE = 0x0005
19 
20 
21 class TuyaWithBacklightOnOffCluster(CustomCluster):
22     """TuyaSmartCurtainOnOffCluster: fire events corresponding to press type."""
23 
24     cluster_id = OnOff.cluster_id
25 
26     LIGHT_MODE_1 = {0x8001: 0}
27     LIGHT_MODE_2 = {0x8001: 1}
28     LIGHT_MODE_3 = {0x8001: 2}
29 
30     attributes = {0x8001: ("backlight_mode", t.enum8)}
31 
32 
33 class TuyaCoveringCluster(CustomCluster, WindowCovering):
34     """TuyaSmartCurtainWindowCoveringCluster: Allow to setup Window covering tuya devices."""
35 
36     attributes = WindowCovering.attributes.copy()
37     attributes.update({0xF000: ("tuya_moving_state", t.enum8)})
38     attributes.update({0xF001: ("calibration", t.enum8)})
39     attributes.update({0xF002: ("motor_reversal", t.enum8)})
40 
41     def _update_attribute(self, attrid, value):
42         if attrid == ATTR_CURRENT_POSITION_LIFT_PERCENTAGE:
43             # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)
44             value = 100 - value
45         super()._update_attribute(attrid, value)
46 
47     async def command(
48         self, command_id, *args, manufacturer=None, expect_reply=True, tsn=None
49     ):
50         """Override default command to invert percent lift value."""
51         if command_id == CMD_GO_TO_LIFT_PERCENTAGE:
52             percent = args[0]
53             # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)
54             percent = 100 - percent
55             v = (percent,)
56             return await super().command(command_id, *v)
57         return await super().command(
58             command_id,
59             *args,
60             manufacturer=manufacturer,
61             expect_reply=expect_reply,
62             tsn=tsn
63         )
64 
65 
66 class TuyaTS130F(CustomDevice):
67     """Tuya smart curtain roller shutter."""
68 
69     signature = {
70         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))
71         MODELS_INFO: [
72             ("_TZ3000_8kzqqzu4", "TS130F"),
73             ("_TZ3000_vd43bbfq", "TS130F"),
74             ("_TZ3000_egq7y6pr", "TS130F"),
75         ],
76         ENDPOINTS: {
77             1: {
78                 PROFILE_ID: zha.PROFILE_ID,
79                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
80                 INPUT_CLUSTERS: [
81                     Basic.cluster_id,
82                     Groups.cluster_id,
83                     Scenes.cluster_id,
84                     Time.cluster_id,
85                     OnOff.cluster_id,
86                     WindowCovering.cluster_id,
87                 ],
88                 OUTPUT_CLUSTERS: [Ota.cluster_id],
89             },
90         },
91     }
92     replacement = {
93         ENDPOINTS: {
94             1: {
95                 PROFILE_ID: zha.PROFILE_ID,
96                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
97                 INPUT_CLUSTERS: [
98                     Basic.cluster_id,
99                     Groups.cluster_id,
100                     Scenes.cluster_id,
101                     Time.cluster_id,
102                     TuyaWithBacklightOnOffCluster,
103                     TuyaCoveringCluster,
104                 ],
105                 OUTPUT_CLUSTERS: [Ota.cluster_id],
106             },
107         },
108     }
109 
110 
111 class TuyaZemismartTS130F(CustomDevice):
112     """Tuya ZemiSmart smart curtain roller shutter."""
113 
114     signature = {
115         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0x0000, 0x0004, 0x0005, 0x0006, 0x0102], output_clusters=[0x000a, 0x0019]))
116         MODELS_INFO: [("_TZ3000_ltiqubue", "TS130F")],
117         ENDPOINTS: {
118             1: {
119                 PROFILE_ID: zha.PROFILE_ID,
120                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
121                 INPUT_CLUSTERS: [
122                     Basic.cluster_id,
123                     Groups.cluster_id,
124                     Scenes.cluster_id,
125                     OnOff.cluster_id,
126                     WindowCovering.cluster_id,
127                 ],
128                 OUTPUT_CLUSTERS: [
129                     Time.cluster_id,
130                     Ota.cluster_id,
131                 ],
132             },
133         },
134     }
135     replacement = {
136         ENDPOINTS: {
137             1: {
138                 PROFILE_ID: zha.PROFILE_ID,
139                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
140                 INPUT_CLUSTERS: [
141                     Basic.cluster_id,
142                     Groups.cluster_id,
143                     Scenes.cluster_id,
144                     TuyaWithBacklightOnOffCluster,
145                     TuyaCoveringCluster,
146                 ],
147                 OUTPUT_CLUSTERS: [
148                     Time.cluster_id,
149                     Ota.cluster_id,
150                 ],
151             },
152         },
153     }
154 
155 
156 class TuyaTS130F_Module(CustomDevice):
157     """Tuya smart curtain roller shutter."""
158 
159     signature = {
160         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))
161         MODELS_INFO: [("_TZ3000_vd43bbfq", "TS130F")],
162         ENDPOINTS: {
163             1: {
164                 PROFILE_ID: zha.PROFILE_ID,
165                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
166                 INPUT_CLUSTERS: [
167                     Basic.cluster_id,
168                     Groups.cluster_id,
169                     Scenes.cluster_id,
170                     WindowCovering.cluster_id,
171                 ],
172                 OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
173             },
174         },
175     }
176     replacement = {
177         ENDPOINTS: {
178             1: {
179                 PROFILE_ID: zha.PROFILE_ID,
180                 DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,
181                 INPUT_CLUSTERS: [
182                     Basic.cluster_id,
183                     Groups.cluster_id,
184                     Scenes.cluster_id,
185                     TuyaCoveringCluster,
186                 ],
187                 OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
188             },
189         },
190     }
191
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/zhaquirks/tuya/ts130f.py b/zhaquirks/tuya/ts130f.py
--- a/zhaquirks/tuya/ts130f.py
+++ b/zhaquirks/tuya/ts130f.py
@@ -9,7 +9,7 @@
     DEVICE_TYPE,
     ENDPOINTS,
     INPUT_CLUSTERS,
-    MODELS_INFO,
+    MODEL,
     OUTPUT_CLUSTERS,
     PROFILE_ID,
 )
@@ -63,16 +63,12 @@
         )
 
 
-class TuyaTS130F(CustomDevice):
-    """Tuya smart curtain roller shutter."""
+class TuyaTS130FTI(CustomDevice):
+    """Tuya smart curtain roller shutter Time In."""
 
     signature = {
         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))
-        MODELS_INFO: [
-            ("_TZ3000_8kzqqzu4", "TS130F"),
-            ("_TZ3000_vd43bbfq", "TS130F"),
-            ("_TZ3000_egq7y6pr", "TS130F"),
-        ],
+        MODEL: "TS130F",
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
@@ -113,7 +109,7 @@
 
     signature = {
         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0x0000, 0x0004, 0x0005, 0x0006, 0x0102], output_clusters=[0x000a, 0x0019]))
-        MODELS_INFO: [("_TZ3000_ltiqubue", "TS130F")],
+        MODEL: "TS130F",
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,
@@ -153,12 +149,13 @@
     }
 
 
-class TuyaTS130F_Module(CustomDevice):
-    """Tuya smart curtain roller shutter."""
+class TuyaTS130FTO(CustomDevice):
+    """Tuya smart curtain roller shutter Time Out."""
 
     signature = {
         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))
-        MODELS_INFO: [("_TZ3000_vd43bbfq", "TS130F")],
+        # This singnature is not correct is one copy of the first one and the cluster is not inline with the device.
+        MODEL: "TS130F",
         ENDPOINTS: {
             1: {
                 PROFILE_ID: zha.PROFILE_ID,

{"golden_diff": "diff --git a/zhaquirks/tuya/ts130f.py b/zhaquirks/tuya/ts130f.py\n--- a/zhaquirks/tuya/ts130f.py\n+++ b/zhaquirks/tuya/ts130f.py\n@@ -9,7 +9,7 @@\n     DEVICE_TYPE,\n     ENDPOINTS,\n     INPUT_CLUSTERS,\n-    MODELS_INFO,\n+    MODEL,\n     OUTPUT_CLUSTERS,\n     PROFILE_ID,\n )\n@@ -63,16 +63,12 @@\n         )\n \n \n-class TuyaTS130F(CustomDevice):\n-    \"\"\"Tuya smart curtain roller shutter.\"\"\"\n+class TuyaTS130FTI(CustomDevice):\n+    \"\"\"Tuya smart curtain roller shutter Time In.\"\"\"\n \n     signature = {\n         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n-        MODELS_INFO: [\n-            (\"_TZ3000_8kzqqzu4\", \"TS130F\"),\n-            (\"_TZ3000_vd43bbfq\", \"TS130F\"),\n-            (\"_TZ3000_egq7y6pr\", \"TS130F\"),\n-        ],\n+        MODEL: \"TS130F\",\n         ENDPOINTS: {\n             1: {\n                 PROFILE_ID: zha.PROFILE_ID,\n@@ -113,7 +109,7 @@\n \n     signature = {\n         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0x0000, 0x0004, 0x0005, 0x0006, 0x0102], output_clusters=[0x000a, 0x0019]))\n-        MODELS_INFO: [(\"_TZ3000_ltiqubue\", \"TS130F\")],\n+        MODEL: \"TS130F\",\n         ENDPOINTS: {\n             1: {\n                 PROFILE_ID: zha.PROFILE_ID,\n@@ -153,12 +149,13 @@\n     }\n \n \n-class TuyaTS130F_Module(CustomDevice):\n-    \"\"\"Tuya smart curtain roller shutter.\"\"\"\n+class TuyaTS130FTO(CustomDevice):\n+    \"\"\"Tuya smart curtain roller shutter Time Out.\"\"\"\n \n     signature = {\n         # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n-        MODELS_INFO: [(\"_TZ3000_vd43bbfq\", \"TS130F\")],\n+        # This singnature is not correct is one copy of the first one and the cluster is not inline with the device.\n+        MODEL: \"TS130F\",\n         ENDPOINTS: {\n             1: {\n                 PROFILE_ID: zha.PROFILE_ID,\n", "issue": "[Device Support Request] Tuya Smart Zigbee Curtain Switch Module (_TZ3000_mowcrwsa)\n**Is your feature request related to a problem? Please describe.**\r\nDevice can be paired in ZHA but not working properly in HA.\r\nManufacturer ID _TZ3000_mowcrwsa is not added as MODELS_INFO in ts130f.py\r\n\r\n**Describe the solution you'd like**\r\nAdd manufacturer ID of the below device signature to class TuyaZemismartTS130F(CustomDevice): of zha-device-handlers/zhaquirks/tuya/ts130f.py\r\n\r\n**Device signature - this can be acquired by removing the device from ZHA and pairing it again from the add devices screen. Be sure to add the entire content of the log panel after pairing the device to a code block below this line.**\r\n{\r\n  \"node_descriptor\": \"NodeDescriptor(logical_type=<LogicalType.Router: 1>, complex_descriptor_available=0, user_descriptor_available=0, reserved=0, aps_flags=0, frequency_band=<FrequencyBand.Freq2400MHz: 8>, mac_capability_flags=<MACCapabilityFlags.AllocateAddress|RxOnWhenIdle|MainsPowered|FullFunctionDevice: 142>, manufacturer_code=4098, maximum_buffer_size=82, maximum_incoming_transfer_size=82, server_mask=11264, maximum_outgoing_transfer_size=82, descriptor_capability_field=<DescriptorCapability.0: 0>, *allocate_address=True, *is_alternate_pan_coordinator=False, *is_coordinator=False, *is_end_device=False, *is_full_function_device=True, *is_mains_powered=True, *is_receiver_on_when_idle=True, *is_router=True, *is_security_capable=False)\",\r\n  \"endpoints\": {\r\n    \"1\": {\r\n      \"profile_id\": 260,\r\n      \"device_type\": \"0x0202\",\r\n      \"in_clusters\": [\r\n        \"0x0000\",\r\n        \"0x0004\",\r\n        \"0x0005\",\r\n        \"0x0006\",\r\n        \"0x0102\"\r\n      ],\r\n      \"out_clusters\": [\r\n        \"0x000a\",\r\n        \"0x0019\"\r\n      ]\r\n    }\r\n  },\r\n  \"manufacturer\": \"_TZ3000_mowcrwsa\",\r\n  \"model\": \"TS130F\",\r\n  \"class\": \"zigpy.device.Device\"\r\n}\r\n\r\n**Additional context**\r\nAdd any other context or screenshots about the feature request here.\r\n\n", "before_files": [{"content": "\"\"\"Device handler for loratap TS130F smart curtain switch.\"\"\"\nfrom zigpy.profiles import zha\nfrom zigpy.quirks import CustomCluster, CustomDevice\nimport zigpy.types as t\nfrom zigpy.zcl.clusters.closures import WindowCovering\nfrom zigpy.zcl.clusters.general import Basic, Groups, OnOff, Ota, Scenes, Time\n\nfrom zhaquirks.const import (\n    DEVICE_TYPE,\n    ENDPOINTS,\n    INPUT_CLUSTERS,\n    MODELS_INFO,\n    OUTPUT_CLUSTERS,\n    PROFILE_ID,\n)\n\nATTR_CURRENT_POSITION_LIFT_PERCENTAGE = 0x0008\nCMD_GO_TO_LIFT_PERCENTAGE = 0x0005\n\n\nclass TuyaWithBacklightOnOffCluster(CustomCluster):\n    \"\"\"TuyaSmartCurtainOnOffCluster: fire events corresponding to press type.\"\"\"\n\n    cluster_id = OnOff.cluster_id\n\n    LIGHT_MODE_1 = {0x8001: 0}\n    LIGHT_MODE_2 = {0x8001: 1}\n    LIGHT_MODE_3 = {0x8001: 2}\n\n    attributes = {0x8001: (\"backlight_mode\", t.enum8)}\n\n\nclass TuyaCoveringCluster(CustomCluster, WindowCovering):\n    \"\"\"TuyaSmartCurtainWindowCoveringCluster: Allow to setup Window covering tuya devices.\"\"\"\n\n    attributes = WindowCovering.attributes.copy()\n    attributes.update({0xF000: (\"tuya_moving_state\", t.enum8)})\n    attributes.update({0xF001: (\"calibration\", t.enum8)})\n    attributes.update({0xF002: (\"motor_reversal\", t.enum8)})\n\n    def _update_attribute(self, attrid, value):\n        if attrid == ATTR_CURRENT_POSITION_LIFT_PERCENTAGE:\n            # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)\n            value = 100 - value\n        super()._update_attribute(attrid, value)\n\n    async def command(\n        self, command_id, *args, manufacturer=None, expect_reply=True, tsn=None\n    ):\n        \"\"\"Override default command to invert percent lift value.\"\"\"\n        if command_id == CMD_GO_TO_LIFT_PERCENTAGE:\n            percent = args[0]\n            # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)\n            percent = 100 - percent\n            v = (percent,)\n            return await super().command(command_id, *v)\n        return await super().command(\n            command_id,\n            *args,\n            manufacturer=manufacturer,\n            expect_reply=expect_reply,\n            tsn=tsn\n        )\n\n\nclass TuyaTS130F(CustomDevice):\n    \"\"\"Tuya smart curtain roller shutter.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n        MODELS_INFO: [\n            (\"_TZ3000_8kzqqzu4\", \"TS130F\"),\n            (\"_TZ3000_vd43bbfq\", \"TS130F\"),\n            (\"_TZ3000_egq7y6pr\", \"TS130F\"),\n        ],\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    Time.cluster_id,\n                    OnOff.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [Ota.cluster_id],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    Time.cluster_id,\n                    TuyaWithBacklightOnOffCluster,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [Ota.cluster_id],\n            },\n        },\n    }\n\n\nclass TuyaZemismartTS130F(CustomDevice):\n    \"\"\"Tuya ZemiSmart smart curtain roller shutter.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0x0000, 0x0004, 0x0005, 0x0006, 0x0102], output_clusters=[0x000a, 0x0019]))\n        MODELS_INFO: [(\"_TZ3000_ltiqubue\", \"TS130F\")],\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    OnOff.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [\n                    Time.cluster_id,\n                    Ota.cluster_id,\n                ],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    TuyaWithBacklightOnOffCluster,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [\n                    Time.cluster_id,\n                    Ota.cluster_id,\n                ],\n            },\n        },\n    }\n\n\nclass TuyaTS130F_Module(CustomDevice):\n    \"\"\"Tuya smart curtain roller shutter.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n        MODELS_INFO: [(\"_TZ3000_vd43bbfq\", \"TS130F\")],\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],\n            },\n        },\n    }\n", "path": "zhaquirks/tuya/ts130f.py"}], "after_files": [{"content": "\"\"\"Device handler for loratap TS130F smart curtain switch.\"\"\"\nfrom zigpy.profiles import zha\nfrom zigpy.quirks import CustomCluster, CustomDevice\nimport zigpy.types as t\nfrom zigpy.zcl.clusters.closures import WindowCovering\nfrom zigpy.zcl.clusters.general import Basic, Groups, OnOff, Ota, Scenes, Time\n\nfrom zhaquirks.const import (\n    DEVICE_TYPE,\n    ENDPOINTS,\n    INPUT_CLUSTERS,\n    MODEL,\n    OUTPUT_CLUSTERS,\n    PROFILE_ID,\n)\n\nATTR_CURRENT_POSITION_LIFT_PERCENTAGE = 0x0008\nCMD_GO_TO_LIFT_PERCENTAGE = 0x0005\n\n\nclass TuyaWithBacklightOnOffCluster(CustomCluster):\n    \"\"\"TuyaSmartCurtainOnOffCluster: fire events corresponding to press type.\"\"\"\n\n    cluster_id = OnOff.cluster_id\n\n    LIGHT_MODE_1 = {0x8001: 0}\n    LIGHT_MODE_2 = {0x8001: 1}\n    LIGHT_MODE_3 = {0x8001: 2}\n\n    attributes = {0x8001: (\"backlight_mode\", t.enum8)}\n\n\nclass TuyaCoveringCluster(CustomCluster, WindowCovering):\n    \"\"\"TuyaSmartCurtainWindowCoveringCluster: Allow to setup Window covering tuya devices.\"\"\"\n\n    attributes = WindowCovering.attributes.copy()\n    attributes.update({0xF000: (\"tuya_moving_state\", t.enum8)})\n    attributes.update({0xF001: (\"calibration\", t.enum8)})\n    attributes.update({0xF002: (\"motor_reversal\", t.enum8)})\n\n    def _update_attribute(self, attrid, value):\n        if attrid == ATTR_CURRENT_POSITION_LIFT_PERCENTAGE:\n            # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)\n            value = 100 - value\n        super()._update_attribute(attrid, value)\n\n    async def command(\n        self, command_id, *args, manufacturer=None, expect_reply=True, tsn=None\n    ):\n        \"\"\"Override default command to invert percent lift value.\"\"\"\n        if command_id == CMD_GO_TO_LIFT_PERCENTAGE:\n            percent = args[0]\n            # Invert the percentage value (cf https://github.com/dresden-elektronik/deconz-rest-plugin/issues/3757)\n            percent = 100 - percent\n            v = (percent,)\n            return await super().command(command_id, *v)\n        return await super().command(\n            command_id,\n            *args,\n            manufacturer=manufacturer,\n            expect_reply=expect_reply,\n            tsn=tsn\n        )\n\n\nclass TuyaTS130FTI(CustomDevice):\n    \"\"\"Tuya smart curtain roller shutter Time In.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n        MODEL: \"TS130F\",\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    Time.cluster_id,\n                    OnOff.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [Ota.cluster_id],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    Time.cluster_id,\n                    TuyaWithBacklightOnOffCluster,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [Ota.cluster_id],\n            },\n        },\n    }\n\n\nclass TuyaZemismartTS130F(CustomDevice):\n    \"\"\"Tuya ZemiSmart smart curtain roller shutter.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0x0000, 0x0004, 0x0005, 0x0006, 0x0102], output_clusters=[0x000a, 0x0019]))\n        MODEL: \"TS130F\",\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    OnOff.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [\n                    Time.cluster_id,\n                    Ota.cluster_id,\n                ],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    TuyaWithBacklightOnOffCluster,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [\n                    Time.cluster_id,\n                    Ota.cluster_id,\n                ],\n            },\n        },\n    }\n\n\nclass TuyaTS130FTO(CustomDevice):\n    \"\"\"Tuya smart curtain roller shutter Time Out.\"\"\"\n\n    signature = {\n        # SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=0x0202, device_version=1, input_clusters=[0, 4, 5, 6, 10, 0x0102], output_clusters=[25]))\n        # This singnature is not correct is one copy of the first one and the cluster is not inline with the device.\n        MODEL: \"TS130F\",\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    WindowCovering.cluster_id,\n                ],\n                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],\n            },\n        },\n    }\n    replacement = {\n        ENDPOINTS: {\n            1: {\n                PROFILE_ID: zha.PROFILE_ID,\n                DEVICE_TYPE: zha.DeviceType.WINDOW_COVERING_DEVICE,\n                INPUT_CLUSTERS: [\n                    Basic.cluster_id,\n                    Groups.cluster_id,\n                    Scenes.cluster_id,\n                    TuyaCoveringCluster,\n                ],\n                OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],\n            },\n        },\n    }\n", "path": "zhaquirks/tuya/ts130f.py"}]}