Source code for miio.integrations.lumi.curtain.curtain_youpin

import enum
import logging
from typing import Any, Dict

import click

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

_LOGGER = logging.getLogger(__name__)


# Model: ZNCLDJ21LM (also known as "Xiaomiyoupin Curtain Controller (Wi-Fi)"
MODEL_CURTAIN_HAGL05 = "lumi.curtain.hagl05"

_MAPPINGS = {
    MODEL_CURTAIN_HAGL05: {
        # # Source http://miot-spec.org/miot-spec-v2/instance?type=urn:miot-spec-v2:device:curtain:0000A00C:lumi-hagl05:1
        # Curtain
        "motor_control": {
            "siid": 2,
            "piid": 2,
        },  # 0 - Pause, 1 - Open, 2 - Close, 3 - auto
        "current_position": {"siid": 2, "piid": 3},  # Range: [0, 100, 1]
        "status": {"siid": 2, "piid": 6},  # 0 - Stopped, 1 - Opening, 2 - Closing
        "target_position": {"siid": 2, "piid": 7},  # Range: [0, 100, 1]
        # curtain_cfg
        "is_manual_enabled": {"siid": 4, "piid": 1},  #
        "polarity": {"siid": 4, "piid": 2},
        "is_position_limited": {"siid": 4, "piid": 3},
        "night_tip_light": {"siid": 4, "piid": 4},
        "run_time": {"siid": 4, "piid": 5},  # Range: [0, 255, 1]
        # motor_controller
        "adjust_value": {"siid": 5, "piid": 1},  # Range: [-100, 100, 1]
    }
}


[docs] class MotorControl(enum.Enum): Pause = 0 Open = 1 Close = 2 Auto = 3
[docs] class Status(enum.Enum): Stopped = 0 Opening = 1 Closing = 2
[docs] class Polarity(enum.Enum): Positive = 0 Reverse = 1
[docs] class CurtainStatus(DeviceStatus): def __init__(self, data: Dict[str, Any]) -> None: """Response from device. {'id': 1, 'result': [ {'did': 'current_position', 'siid': 2, 'piid': 3, 'code': 0, 'value': 0}, {'did': 'status', 'siid': 2, 'piid': 6, 'code': 0, 'value': 0}, {'did': 'target_position', 'siid': 2, 'piid': 7, 'code': 0, 'value': 0}, {'did': 'is_manual_enabled', 'siid': 4, 'piid': 1, 'code': 0, 'value': 1}, {'did': 'polarity', 'siid': 4, 'piid': 2, 'code': 0, 'value': 0}, {'did': 'is_position_limited', 'siid': 4, 'piid': 3, 'code': 0, 'value': 0}, {'did': 'night_tip_light', 'siid': 4, 'piid': 4, 'code': 0, 'value': 1}, {'did': 'run_time', 'siid': 4, 'piid': 5, 'code': 0, 'value': 0}, {'did': 'adjust_value', 'siid': 5, 'piid': 1, 'code': -4000} ]} """ self.data = data @property def status(self) -> Status: """Device status.""" return Status(self.data["status"]) @property def is_manual_enabled(self) -> bool: """True if manual controls are enabled.""" return bool(self.data["is_manual_enabled"]) @property def polarity(self) -> Polarity: """Motor rotation polarity.""" return Polarity(self.data["polarity"]) @property def is_position_limited(self) -> bool: """Position limit.""" return bool(self.data["is_position_limited"]) @property def night_tip_light(self) -> bool: """Night tip light status.""" return bool(self.data["night_tip_light"]) @property def run_time(self) -> int: """Run time of the motor.""" return self.data["run_time"] @property def current_position(self) -> int: """Current curtain position.""" return self.data["current_position"] @property def target_position(self) -> int: """Target curtain position.""" return self.data["target_position"] @property def adjust_value(self) -> int: """Adjust value.""" return self.data["adjust_value"]
[docs] class CurtainMiot(MiotDevice): """Main class representing the lumi.curtain.hagl05 curtain.""" _mappings = _MAPPINGS
[docs] @command( default_output=format_output( "", "Device status: {result.status}\n" "Manual enabled: {result.is_manual_enabled}\n" "Motor polarity: {result.polarity}\n" "Position limit: {result.is_position_limited}\n" "Enabled night tip light: {result.night_tip_light}\n" "Run time: {result.run_time}\n" "Current position: {result.current_position}\n" "Target position: {result.target_position}\n" "Adjust value: {result.adjust_value}\n", ) ) def status(self) -> CurtainStatus: """Retrieve properties.""" return CurtainStatus( { prop["did"]: prop["value"] if prop["code"] == 0 else None for prop in self.get_properties_for_mapping() } )
[docs] @command( click.argument("motor_control", type=EnumType(MotorControl)), default_output=format_output("Set motor control to {motor_control}"), ) def set_motor_control(self, motor_control: MotorControl): """Set motor control.""" return self.set_property("motor_control", motor_control.value)
[docs] @command( click.argument("target_position", type=int), default_output=format_output("Set target position to {target_position}"), ) def set_target_position(self, target_position: int): """Set target position.""" if target_position < 0 or target_position > 100: raise ValueError( "Value must be between [0, 100] value, was %s" % target_position ) return self.set_property("target_position", target_position)
[docs] @command( click.argument("manual_enabled", type=bool), default_output=format_output("Set manual control {manual_enabled}"), ) def set_manual_enabled(self, manual_enabled: bool): """Set manual control of curtain.""" return self.set_property("is_manual_enabled", manual_enabled)
[docs] @command( click.argument("polarity", type=EnumType(Polarity)), default_output=format_output("Set polarity to {polarity}"), ) def set_polarity(self, polarity: Polarity): """Set polarity of the motor.""" return self.set_property("polarity", polarity.value)
[docs] @command( click.argument("pos_limit", type=bool), default_output=format_output("Set position limit to {pos_limit}"), ) def set_position_limit(self, pos_limit: bool): """Set position limit parameter.""" return self.set_property("is_position_limited", pos_limit)
[docs] @command( click.argument("night_tip_light", type=bool), default_output=format_output("Setting night tip light {night_tip_light"), ) def set_night_tip_light(self, night_tip_light: bool): """Set night tip light.""" return self.set_property("night_tip_light", night_tip_light)
[docs] @command( click.argument("adjust_value", type=int), default_output=format_output("Set adjust value to {adjust_value}"), ) def set_adjust_value(self, adjust_value: int): """Adjust to preferred position.""" if adjust_value < -100 or adjust_value > 100: raise ValueError( "Value must be between [-100, 100] value, was %s" % adjust_value ) return self.set_property("adjust_value", adjust_value)