Source code for miio.integrations.yeelight.dual_switch.yeelight_dual_switch

import enum
from typing import Any, Dict

import click

from miio.click_common import EnumType, command, format_output
from miio.miot_device import DeviceStatus, MiotDevice, MiotMapping


[docs] class Switch(enum.Enum): First = 0 Second = 1
_MAPPINGS: MiotMapping = { "yeelink.switch.sw1": { # http://miot-spec.org/miot-spec-v2/instance?type=urn:miot-spec-v2:device:switch:0000A003:yeelink-sw1:1:0000C809 # First Switch (siid=2) "switch_1_state": {"siid": 2, "piid": 1}, # bool "switch_1_default_state": {"siid": 2, "piid": 2}, # 0 - Off, 1 - On "switch_1_off_delay": { "siid": 2, "piid": 3, }, # -1 - Off, [1, 43200] - delay in sec # Second Switch (siid=3) "switch_2_state": {"siid": 3, "piid": 1}, # bool "switch_2_default_state": {"siid": 3, "piid": 2}, # 0 - Off, 1 - On "switch_2_off_delay": { "siid": 3, "piid": 3, }, # -1 - Off, [1, 43200] - delay in sec # Extensions (siid=4) "interlock": {"siid": 4, "piid": 1}, # bool "flex_mode": {"siid": 4, "piid": 2}, # 0 - Off, 1 - On "rc_list": {"siid": 4, "piid": 3}, # string "rc_list_for_del": {"siid": 4, "piid": 4}, # string "toggle": {"siid": 4, "piid": 5}, # 0 - First switch, 1 - Second switch } }
[docs] class DualControlModuleStatus(DeviceStatus): def __init__(self, data: Dict[str, Any]) -> None: """ Response of Yeelight Dual Control Module { 'id': 1, 'result': [ {'did': 'switch_1_state', 'siid': 2, 'piid': 1, 'code': 0, 'value': False}, {'did': 'switch_1_default_state', 'siid': 2, 'piid': 2, 'code': 0, 'value': True}, {'did': 'switch_1_off_delay', 'siid': 2, 'piid': 3, 'code': 0, 'value': 300}, {'did': 'switch_2_state', 'siid': 3, 'piid': 1, 'code': 0, 'value': False}, {'did': 'switch_2_default_state', 'siid': 3, 'piid': 2, 'code': 0, 'value': False}, {'did': 'switch_2_off_delay', 'siid': 3, 'piid': 3, 'code': 0, 'value': 0}, {'did': 'interlock', 'siid': 4, 'piid': 1, 'code': 0, 'value': False}, {'did': 'flex_mode', 'siid': 4, 'piid': 2, 'code': 0, 'value': True}, {'did': 'rc_list', 'siid': 4, 'piid': 2, 'code': 0, 'value': '[{"mac":"9db0eb4124f8","evtid":4097,"pid":339,"beaconkey":"3691bc0679eef9596bb63abf"}]'}, ] } """ self.data = data @property def switch_1_state(self) -> bool: """First switch state.""" return bool(self.data["switch_1_state"]) @property def switch_1_default_state(self) -> bool: """First switch default state.""" return bool(self.data["switch_1_default_state"]) @property def switch_1_off_delay(self) -> int: """First switch off delay.""" return self.data["switch_1_off_delay"] @property def switch_2_state(self) -> bool: """Second switch state.""" return bool(self.data["switch_2_state"]) @property def switch_2_default_state(self) -> bool: """Second switch default state.""" return bool(self.data["switch_2_default_state"]) @property def switch_2_off_delay(self) -> int: """Second switch off delay.""" return self.data["switch_2_off_delay"] @property def interlock(self) -> bool: """Interlock.""" return bool(self.data["interlock"]) @property def flex_mode(self) -> int: """Flex mode.""" return self.data["flex_mode"] @property def rc_list(self) -> str: """List of paired remote controls.""" return self.data["rc_list"]
[docs] class YeelightDualControlModule(MiotDevice): """Main class representing the Yeelight Dual Control Module (yeelink.switch.sw1) which uses MIoT protocol.""" _mappings = _MAPPINGS
[docs] @command( default_output=format_output( "", "First Switch Status: {result.switch_1_state}\n" "First Switch Default State: {result.switch_1_default_state}\n" "First Switch Delay: {result.switch_1_off_delay}\n" "Second Switch Status: {result.switch_2_state}\n" "Second Switch Default State: {result.switch_2_default_state}\n" "Second Switch Delay: {result.switch_2_off_delay}\n" "Interlock: {result.interlock}\n" "Flex Mode: {result.flex_mode}\n" "RC list: {result.rc_list}\n", ) ) def status(self) -> DualControlModuleStatus: """Retrieve properties.""" p = [ "switch_1_state", "switch_1_default_state", "switch_1_off_delay", "switch_2_state", "switch_2_default_state", "switch_2_off_delay", "interlock", "flex_mode", "rc_list", ] # Filter only readable properties for status properties = [ {"did": k, **v} for k, v in filter(lambda item: item[0] in p, self._get_mapping().items()) ] values = self.get_properties(properties) return DualControlModuleStatus( dict(map(lambda v: (v["did"], v["value"]), values)) )
[docs] @command( click.argument("switch", type=EnumType(Switch)), default_output=format_output("Turn {switch} switch on"), ) def on(self, switch: Switch): """Turn switch on.""" if switch == Switch.First: return self.set_property("switch_1_state", True) elif switch == Switch.Second: return self.set_property("switch_2_state", True)
[docs] @command( click.argument("switch", type=EnumType(Switch)), default_output=format_output("Turn {switch} switch off"), ) def off(self, switch: Switch): """Turn switch off.""" if switch == Switch.First: return self.set_property("switch_1_state", False) elif switch == Switch.Second: return self.set_property("switch_2_state", False)
[docs] @command( click.argument("switch", type=EnumType(Switch)), default_output=format_output("Toggle {switch} switch"), ) def toggle(self, switch: Switch): """Toggle switch.""" return self.set_property("toggle", switch.value)
[docs] @command( click.argument("state", type=bool), click.argument("switch", type=EnumType(Switch)), default_output=format_output("Set {switch} switch default state to: {state}"), ) def set_default_state(self, state: bool, switch: Switch): """Set switch default state.""" if switch == Switch.First: return self.set_property("switch_1_default_state", int(state)) elif switch == Switch.Second: return self.set_property("switch_2_default_state", int(state))
[docs] @command( click.argument("delay", type=int), click.argument("switch", type=EnumType(Switch)), default_output=format_output("Set {switch} switch off delay to {delay} sec."), ) def set_switch_off_delay(self, delay: int, switch: Switch): """Set switch off delay, should be between -1 to 43200 (in seconds)""" if delay < -1 or delay > 43200: raise ValueError( "Invalid switch delay: %s (should be between -1 to 43200)" % delay ) if switch == Switch.First: return self.set_property("switch_1_off_delay", delay) elif switch == Switch.Second: return self.set_property("switch_2_off_delay", delay)
[docs] @command( click.argument("flex_mode", type=bool), default_output=format_output("Set flex mode to: {flex_mode}"), ) def set_flex_mode(self, flex_mode: bool): """Set flex mode.""" return self.set_property("flex_mode", int(flex_mode))
[docs] @command( click.argument("rc_mac", type=str), default_output=format_output("Delete remote control with MAC: {rc_mac}"), ) def delete_rc(self, rc_mac: str): """Delete remote control by MAC.""" return self.set_property("rc_list_for_del", rc_mac)
[docs] @command( click.argument("interlock", type=bool), default_output=format_output("Set interlock to: {interlock}"), ) def set_interlock(self, interlock: bool): """Set interlock.""" return self.set_property("interlock", interlock)