Skip to content

Commit

Permalink
fix: migrate to other valve integration since the newer one broke wit…
Browse files Browse the repository at this point in the history
…h 2024.8
  • Loading branch information
TribuneX committed Aug 23, 2024
1 parent 15a8eb0 commit b395bce
Showing 1 changed file with 94 additions and 107 deletions.
201 changes: 94 additions & 107 deletions custom_zha_quirks/ts0601_valve.py
Original file line number Diff line number Diff line change
@@ -1,165 +1,152 @@
"""Royal Gardineer Tuya Water Valve device."""
"""Collection of Tuya Valve devices e.g. water valves, gas valve etc."""
from typing import Dict

from zigpy.profiles import zha
from zigpy.quirks import CustomDevice
from zigpy.quirks.v2 import add_to_registry_v2
from zigpy.quirks.v2.homeassistant import EntityPlatform, UnitOfTime, EntityType
import zigpy.types as t
from zigpy.zcl.clusters.general import Basic, Groups, Ota, Scenes, Time
from zigpy.zcl.clusters.general import Basic, Groups, Identify, OnOff, Ota, Scenes, Time
from zigpy.zcl.clusters.smartenergy import Metering

from zhaquirks.tuya import TuyaLocalCluster
from zhaquirks import DoublingPowerConfigurationCluster
from zhaquirks import Bus
from zhaquirks.const import (
DEVICE_TYPE,
ENDPOINTS,
INPUT_CLUSTERS,
MODELS_INFO,
OUTPUT_CLUSTERS,
PROFILE_ID,
)
from zhaquirks.tuya import (
TuyaLocalCluster,
TuyaPowerConfigurationCluster,
)
from zhaquirks.tuya.mcu import (
DPToAttributeMapping,
EnchantedDevice,
# TuyaDPType,
TuyaMCUCluster,
TuyaOnOff,
TuyaPowerConfigurationCluster,
)

# Timer time left to auto-off.
TIMER_TIME_LEFT_ATTR_ID = 0xEF01
TIMER_TIME_LEFT_ATTR_NAME = "timer_time_left"

# Timer state.
TIMER_STATE_ATTR_ID = 0xEF02
TIMER_STATE_ATTR_NAME = "timer_state"

# Last valve open duration.
LAST_VALVE_OPEN_DURATION_ATTR_ID = 0xEF03
LAST_VALVE_OPEN_DURATION_ATTR_NAME = "last_valve_open_duration"

# Weather delay.
WEATHER_DELAY_ATTR_ID = 0xEF04
WEATHER_DELAY_ATTR_NAME = "weather_delay"

class RoyalGardineerWeatherDelay(t.enum8):
"""Royal Gardineer weather delay enum."""

Disabled = 0x00
Delayed_24h = 0x01
Delayed_48h = 0x02
Delayed_72h = 0x03
class TuyaValveWaterConsumed(Metering, TuyaLocalCluster):
"""Tuya Valve Water consumed cluster."""

class RoyalGardineerTimerState(t.enum8):
"""Royal Gardineer timer state enum."""

Disabled = 0x00
Active = 0x01
Enabled = 0x02

class RoyalGardineerValveWaterConsumed(Metering, TuyaLocalCluster):
"""Royal Gardineer Tuya Water Valve - water consumed cluster."""

UNIT_VOLUME_LITERS = 0x0007
TYPE_WATER_METERING = 0x02
VOLUME_LITERS = 0x0007

"""Setting unit of measurement."""
_CONSTANT_ATTRIBUTES = {
0x0300: UNIT_VOLUME_LITERS,
0x0306: TYPE_WATER_METERING,
}
_CONSTANT_ATTRIBUTES = {0x0300: VOLUME_LITERS}


class RoyalGardineerValveManufCluster(TuyaMCUCluster):
"""On/Off Royal Gardineer Tuya cluster with extra device attributes."""
class TuyaValveManufCluster(TuyaMCUCluster):
"""On/Off Tuya cluster with extra device attributes."""

attributes = TuyaMCUCluster.attributes.copy()
attributes.update(
{
TIMER_TIME_LEFT_ATTR_ID: (TIMER_TIME_LEFT_ATTR_NAME, t.uint32_t, True),
TIMER_STATE_ATTR_ID: (TIMER_STATE_ATTR_NAME, RoyalGardineerTimerState, True),
LAST_VALVE_OPEN_DURATION_ATTR_ID: (LAST_VALVE_OPEN_DURATION_ATTR_NAME, t.uint32_t, True),
WEATHER_DELAY_ATTR_ID: (WEATHER_DELAY_ATTR_NAME, RoyalGardineerWeatherDelay, True)
0xEF01: ("time_left", t.uint32_t, True),
0xEF02: ("state", t.enum8, True),
0xEF03: ("last_valve_open_duration", t.uint32_t, True),
0xEF04: ("dp_6", t.uint32_t, True),
}
)

dp_to_attribute: dict[int, DPToAttributeMapping] = {
dp_to_attribute: Dict[int, DPToAttributeMapping] = {
1: DPToAttributeMapping(
TuyaOnOff.ep_attribute,
"on_off",
# dp_type=TuyaDPType.BOOL,
),
5: DPToAttributeMapping(
RoyalGardineerValveWaterConsumed.ep_attribute,
TuyaValveWaterConsumed.ep_attribute,
"current_summ_delivered",
lambda x: x // 10,
# TuyaDPType.VALUE,
),
6: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"dp_6",
# TuyaDPType.VALUE,
),
7: DPToAttributeMapping(
TuyaPowerConfigurationCluster.ep_attribute,
# DoublingPowerConfigurationCluster.ep_attribute,
"battery_percentage_remaining",
),
10: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"weather_delay",
lambda x: RoyalGardineerWeatherDelay(x),
# TuyaDPType.VALUE,
),
11: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"timer_time_left",
lambda x: x // 60,
lambda x: x * 60,
"time_left",
# TuyaDPType.VALUE,
),
12: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"timer_state",
lambda x: RoyalGardineerTimerState(x),
"state",
# TuyaDPType.VALUE,
),
15: DPToAttributeMapping(
TuyaMCUCluster.ep_attribute,
"last_valve_open_duration",
lambda x: x // 60,
# TuyaDPType.VALUE,
),
#16 - cycle timer,
#17 - normal timer,
}

data_point_handlers = {
1: "_dp_2_attr_update",
5: "_dp_2_attr_update",
6: "_dp_2_attr_update",
7: "_dp_2_attr_update",
10: "_dp_2_attr_update",
11: "_dp_2_attr_update",
12: "_dp_2_attr_update",
15: "_dp_2_attr_update",
}

(
add_to_registry_v2("_TZE200_2wg5qrjy", "TS0601")
.replaces(RoyalGardineerValveManufCluster)
.adds(TuyaOnOff)
.adds(RoyalGardineerValveWaterConsumed)
.adds(TuyaPowerConfigurationCluster)
# Timer time left/remaining.
.number(
TIMER_TIME_LEFT_ATTR_NAME,
RoyalGardineerValveManufCluster.cluster_id,
min_value=1,
max_value=600,
step=1,
unit=UnitOfTime.MINUTES,
translation_key="timer_time_left",
)
# Weather delay.
.enum(
WEATHER_DELAY_ATTR_NAME,
RoyalGardineerWeatherDelay,
RoyalGardineerValveManufCluster.cluster_id,
translation_key="weather_delay",
)
# Timer state - read-only.
.enum(
TIMER_STATE_ATTR_NAME,
RoyalGardineerTimerState,
RoyalGardineerValveManufCluster.cluster_id,
entity_platform=EntityPlatform.SENSOR,
entity_type=EntityType.DIAGNOSTIC,
translation_key="timer_state",
)
# Last valve open duration - read-only.
.sensor(
LAST_VALVE_OPEN_DURATION_ATTR_NAME,
RoyalGardineerValveManufCluster.cluster_id,
entity_type=EntityType.DIAGNOSTIC,
unit=UnitOfTime.MINUTES,
translation_key="last_valve_open_duration",
)
)

class TuyaValve(CustomDevice):
"""Tuya valve device."""

def __init__(self, *args, **kwargs):
"""Init device."""
self.battery_bus = Bus()
super().__init__(*args, **kwargs)


signature = {
MODELS_INFO: [("_TZE200_2wg5qrjy", "TS0601")],
# SizePrefixedSimpleDescriptor(endpoint=1, profile=260, device_type=81, device_version=1,
# input_clusters=[0, 4, 5, 61184], output_clusters=[25, 10])
ENDPOINTS: {
1: {
PROFILE_ID: zha.PROFILE_ID,
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaValveManufCluster.cluster_id,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
}
},
}

replacement = {
ENDPOINTS: {
1: {
DEVICE_TYPE: zha.DeviceType.SMART_PLUG,
INPUT_CLUSTERS: [
Basic.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
TuyaOnOff,
TuyaValveWaterConsumed,
TuyaPowerConfigurationCluster,
# DoublingPowerConfigurationCluster,
TuyaValveManufCluster,
],
OUTPUT_CLUSTERS: [Time.cluster_id, Ota.cluster_id],
}
}
}

0 comments on commit b395bce

Please sign in to comment.