import logging
from collections import defaultdict
from typing import Any, Dict
import click
from miio import Device, DeviceStatus
from miio.click_common import command, format_output
_LOGGER = logging.getLogger(__name__)
[docs]
class PhilipsEyecareStatus(DeviceStatus):
"""Container for status reports from Xiaomi Philips Eyecare Smart Lamp 2."""
def __init__(self, data: Dict[str, Any]) -> None:
# ['power': 'off', 'bright': 5, 'notifystatus': 'off',
# 'ambstatus': 'off', 'ambvalue': 41, 'eyecare': 'on',
# 'scene_num': 3, 'bls': 'on', 'dvalue': 0]
self.data = data
@property
def power(self) -> str:
"""Power state."""
return self.data["power"]
@property
def is_on(self) -> bool:
"""True if the device is turned on."""
return self.power == "on"
@property
def brightness(self) -> int:
"""Current brightness of the primary light."""
return self.data["bright"]
@property
def reminder(self) -> bool:
"""Indicates the eye fatigue notification is enabled or not."""
return self.data["notifystatus"] == "on"
@property
def ambient(self) -> bool:
"""True if the ambient light (second light source) is on."""
return self.data["ambstatus"] == "on"
@property
def ambient_brightness(self) -> int:
"""Brightness of the ambient light."""
return self.data["ambvalue"]
@property
def eyecare(self) -> bool:
"""True if the eyecare mode is on."""
return self.data["eyecare"] == "on"
@property
def scene(self) -> int:
"""Current fixed scene."""
return self.data["scene_num"]
@property
def smart_night_light(self) -> bool:
"""True if the smart night light mode is on."""
return self.data["bls"] == "on"
@property
def delay_off_countdown(self) -> int:
"""Countdown until turning off in minutes."""
return self.data["dvalue"]
[docs]
class PhilipsEyecare(Device):
"""Main class representing Xiaomi Philips Eyecare Smart Lamp 2."""
_supported_models = ["philips.light.sread1", "philips.light.sread2"]
[docs]
@command(
default_output=format_output(
"",
"Power: {result.power}\n"
"Brightness: {result.brightness}\n"
"Ambient light: {result.ambient}\n"
"Ambient light brightness: {result.ambient_brightness}\n"
"Eyecare mode: {result.eyecare}\n"
"Scene: {result.scene}\n"
"Eye fatigue reminder: {result.reminder}\n"
"Smart night light: {result.smart_night_light}\n"
"Delayed turn off: {result.delay_off_countdown}\n",
)
)
def status(self) -> PhilipsEyecareStatus:
"""Retrieve properties."""
properties = [
"power",
"bright",
"notifystatus",
"ambstatus",
"ambvalue",
"eyecare",
"scene_num",
"bls",
"dvalue",
]
values = self.get_properties(properties)
return PhilipsEyecareStatus(defaultdict(lambda: None, zip(properties, values)))
[docs]
@command(default_output=format_output("Powering on"))
def on(self):
"""Power on."""
return self.send("set_power", ["on"])
[docs]
@command(default_output=format_output("Powering off"))
def off(self):
"""Power off."""
return self.send("set_power", ["off"])
[docs]
@command(default_output=format_output("Turning on eyecare mode"))
def eyecare_on(self):
"""Turn the eyecare mode on."""
return self.send("set_eyecare", ["on"])
[docs]
@command(default_output=format_output("Turning off eyecare mode"))
def eyecare_off(self):
"""Turn the eyecare mode off."""
return self.send("set_eyecare", ["off"])
[docs]
@command(
click.argument("level", type=int),
default_output=format_output("Setting brightness to {level}"),
)
def set_brightness(self, level: int):
"""Set brightness level of the primary light."""
if level < 1 or level > 100:
raise ValueError("Invalid brightness: %s" % level)
return self.send("set_bright", [level])
[docs]
@command(
click.argument("number", type=int),
default_output=format_output("Setting fixed scene to {number}"),
)
def set_scene(self, number: int):
"""Set one of the fixed eyecare user scenes."""
if number < 1 or number > 4:
raise ValueError("Invalid fixed scene number: %s" % number)
return self.send("set_user_scene", [number])
[docs]
@command(
click.argument("minutes", type=int),
default_output=format_output("Setting delayed turn off to {minutes} minutes"),
)
def delay_off(self, minutes: int):
"""Set delay off minutes."""
if minutes < 0:
raise ValueError("Invalid value for a delayed turn off: %s" % minutes)
return self.send("delay_off", [minutes])
[docs]
@command(default_output=format_output("Turning on smart night light"))
def smart_night_light_on(self):
"""Turn the smart night light mode on."""
return self.send("enable_bl", ["on"])
[docs]
@command(default_output=format_output("Turning off smart night light"))
def smart_night_light_off(self):
"""Turn the smart night light mode off."""
return self.send("enable_bl", ["off"])
[docs]
@command(default_output=format_output("Turning on eye fatigue reminder"))
def reminder_on(self):
"""Enable the eye fatigue reminder / notification."""
return self.send("set_notifyuser", ["on"])
[docs]
@command(default_output=format_output("Turning off eye fatigue reminder"))
def reminder_off(self):
"""Disable the eye fatigue reminder / notification."""
return self.send("set_notifyuser", ["off"])
[docs]
@command(default_output=format_output("Turning on ambient light"))
def ambient_on(self):
"""Turn the ambient light on."""
return self.send("enable_amb", ["on"])
[docs]
@command(default_output=format_output("Turning off ambient light"))
def ambient_off(self):
"""Turn the ambient light off."""
return self.send("enable_amb", ["off"])
[docs]
@command(
click.argument("level", type=int),
default_output=format_output("Setting brightness to {level}"),
)
def set_ambient_brightness(self, level: int):
"""Set the brightness of the ambient light."""
if level < 1 or level > 100:
raise ValueError("Invalid ambient brightness: %s" % level)
return self.send("set_amb_bright", [level])