diff --git a/custom_components/aqara_gateway/button.py b/custom_components/aqara_gateway/button.py new file mode 100644 index 0000000..f4044cb --- /dev/null +++ b/custom_components/aqara_gateway/button.py @@ -0,0 +1,41 @@ +"""Support for Aqara buttons.""" + +from homeassistant.components.button import ButtonEntity + +from . import DOMAIN, GatewayGenericDevice +from .core.gateway import Gateway + + +async def async_setup_entry(hass, config_entry, async_add_entities): + """Perform the setup for Aqara buttons.""" + + def setup(gateway: Gateway, device: dict, attr: str): + async_add_entities([GatewayButton(gateway, device, attr)]) + + aqara_gateway: Gateway = hass.data[DOMAIN][config_entry.entry_id] + aqara_gateway.add_setup('button', setup) + + +async def async_unload_entry(hass, entry): + # pylint: disable=unused-argument + """Unload entry.""" + return True + + +class GatewayButton(GatewayGenericDevice, ButtonEntity): + """Representation of an Aqara button entity.""" + + @property + def icon(self): + """Return icon.""" + if self._attr == 'find_device': + return 'mdi:radar' + return 'mdi:gesture-tap-button' + + def update(self, data: dict): + """Buttons are stateless.""" + return None + + def press(self) -> None: + """Press the button.""" + self.gateway.send(self.device, {self._attr: 1}) diff --git a/custom_components/aqara_gateway/core/const.py b/custom_components/aqara_gateway/core/const.py index 017ebba..b50352c 100755 --- a/custom_components/aqara_gateway/core/const.py +++ b/custom_components/aqara_gateway/core/const.py @@ -189,6 +189,7 @@ 'air_quality', 'alarm_control_panel', 'binary_sensor', + 'button', 'climate', 'cover', 'fan', diff --git a/custom_components/aqara_gateway/core/utils.py b/custom_components/aqara_gateway/core/utils.py index 8af8ce2..64a02e9 100755 --- a/custom_components/aqara_gateway/core/utils.py +++ b/custom_components/aqara_gateway/core/utils.py @@ -976,20 +976,24 @@ }, { 'lumi.curtain.acn010': ["Aqara", "Organ™ Smart Curtain Motor C4", "DSKDJ11LM"], 'params': [ - ['0.57.85', 'curtain_ch0_level', 'position', None], - ['0.58.85', 'curtain_ch1_level', 'position', None], + ['0.57.85', 'curtain_ch0_level', 'ch0_position', None], + ['0.58.85', 'curtain_ch1_level', 'ch1_position', None], ['13.4.85', 'run_status', 'run_state', None], - ['13.11.85', 'ch0_run_state', 'run_state', None], + ['13.11.85', 'ch0_run_state', 'ch0_run_state', None], + ['13.21.85', 'ch1_run_state', 'ch1_run_state', None], ['0.21.85', '0.21.85', '0.21.85', None], ['13.14.85', '13.14.85', '13.14.85', None], ['13.15.85', '13.15.85', '13.15.85', None], - ['13.21.85', 'ch1_run_state', 'run_state', None], ['13.13.85', None, 'mode', None], ['14.11.85', None, 'ch0_polarity', None], ['14.21.85', None, 'ch1_polarity', None], - ['14.35.85', None, 'speed', None], + ['14.35.85', None, 'speed', 'select'], + ['14.2.85', None, 'motor', 'cover'], ['1.11.85', None, 'ch0_motor', 'cover'], ['1.21.85', None, 'ch1_motor', 'cover'], + ['4.3.85', None, 'manual_enable', 'switch'], # 手动开/关窗帘 + ['8.0.2032', None, 'en_night_tip_light', 'switch'], #指示灯勿扰,1是关闭指示灯 + ['8.0.2096', None, 'find_device', 'button'], # 查找设备 ] }, { 'lumi.curtain.acn011': ["Aqara", "Smart Vertical Blinds Controller H1", "ZNMHLDJ01LM"], @@ -2094,6 +2098,9 @@ def get_select_options(zigbee_model: str, attr: str) -> Optional[dict]: return {"Weak": 0, "Middle Weak": 1, "Middle": 2, "Middle Strong": 3, "Strong": 4} if attr == 'warn dry': return {"Off": 0, "Normal": 1, "Low": 2, "Middle Low": 3, "Middle": 4, "Middle High": 5, "High": 6} + if zigbee_model in ['lumi.curtain.acn010']: + if attr == 'speed': + return {"Low": 2, "Middle": 3, "High": 4} return {"Off": 0, "On": 1} @staticmethod diff --git a/custom_components/aqara_gateway/cover.py b/custom_components/aqara_gateway/cover.py index eb1de20..a093f22 100755 --- a/custom_components/aqara_gateway/cover.py +++ b/custom_components/aqara_gateway/cover.py @@ -56,6 +56,8 @@ def setup(gateway: Gateway, device: dict, attr: str): async_add_entities([AqaraRollerShadeE1(gateway, device, attr)]) elif device['model'] == 'lumi.curtain.acn011': async_add_entities([AqaraVerticalBlindsController(gateway, device, attr)]) + elif device['model'] == 'lumi.curtain.acn010': + async_add_entities([AqaraCurtainMotorC4(gateway, device, attr)]) else: if device.get('mi_spec') or device['model'] == 'lumi.airer.acn001': async_add_entities([XiaomiCoverMIOT(gateway, device, attr)]) @@ -295,3 +297,69 @@ def set_cover_tilt_position(self, **kwargs): def stop_cover_tilt(self, **kwargs: Any) -> None: self.gateway.send(self.device, {'tilt_motor': 2}) + + +class AqaraCurtainMotorC4(XiaomiGenericCover): + """Aqara curtain motor C4 (lumi.curtain.acn010).""" + + def __init__(self, gateway, device, atrr): + if atrr == 'motor': + self._attr_supported_features = ( + CoverEntityFeature.OPEN + | CoverEntityFeature.CLOSE + | CoverEntityFeature.STOP + ) + else: + self._attr_supported_features = ( + CoverEntityFeature.OPEN + | CoverEntityFeature.CLOSE + | CoverEntityFeature.SET_POSITION + ) + super().__init__(gateway, device, atrr) + + def update(self, data: dict = None): + """Update only the matching state for this entity.""" + payload = {} + data = data or {} + + if self._attr == 'motor': + if RUN_STATE in data: + payload[RUN_STATE] = data[RUN_STATE] + elif self._attr == 'ch0_motor': + if 'ch0_position' in data: + payload[POSITION] = data['ch0_position'] + if 'ch0_run_state' in data: + payload[RUN_STATE] = data['ch0_run_state'] + elif self._attr == 'ch1_motor': + if 'ch1_position' in data: + payload[POSITION] = data['ch1_position'] + if 'ch1_run_state' in data: + payload[RUN_STATE] = data['ch1_run_state'] + + super().update(payload) + + def close_cover(self, **kwargs): + """Close the cover.""" + if self._attr == 'motor': + self.gateway.send(self.device, {'motor': 0}) + else: + self.gateway.send(self.device, {self._attr: 0}) + + def open_cover(self, **kwargs): + """Open the cover.""" + if self._attr == 'motor': + self.gateway.send(self.device, {'motor': 1}) + else: + self.gateway.send(self.device, {self._attr: 100}) + + def stop_cover(self, **kwargs): + """Stop the cover.""" + if self._attr == 'motor': + self.gateway.send(self.device, {'motor': 2}) + + def set_cover_position(self, **kwargs): + """Move the cover to a specific position.""" + if self._attr == 'motor': + return None + position = kwargs.get(ATTR_POSITION) + self.gateway.send(self.device, {self._attr: position})