forked from rytilahti/python-miio
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Pull request rytilahti#34 merged for testing.
- Loading branch information
Showing
5 changed files
with
337 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
from .device import Device | ||
from typing import Any, Dict | ||
|
||
|
||
class PhilipsEyecare(Device): | ||
"""Main class representing Xiaomi Philips Eyecare Smart Lamp 2.""" | ||
|
||
def on(self): | ||
"""Power on.""" | ||
return self.send("set_power", ["on"]) | ||
|
||
def off(self): | ||
"""Power off.""" | ||
return self.send("set_power", ["off"]) | ||
|
||
def eyecare_on(self): | ||
"""Eyecare on.""" | ||
return self.send("set_eyecare", ["on"]) | ||
|
||
def eyecare_off(self): | ||
"""Eyecare off.""" | ||
return self.send("set_eyecare", ["off"]) | ||
|
||
def set_bright(self, level: int): | ||
"""Set brightness level.""" | ||
return self.send("set_bright", [level]) | ||
|
||
def set_user_scene(self, num: int): | ||
"""Set eyecare user scene.""" | ||
return self.send("set_user_scene", [num]) | ||
|
||
def delay_off(self, minutes: int): | ||
"""Set delay off minutes.""" | ||
return self.send("delay_off", [minutes]) | ||
|
||
def bl_on(self): | ||
"""Night Light On.""" | ||
return self.send("enable_bl", ["on"]) | ||
|
||
def bl_off(self): | ||
"""Night Light Off.""" | ||
return self.send("enable_bl", ["off"]) | ||
|
||
def notify_user_on(self): | ||
"""Notify User On.""" | ||
return self.send("set_notifyuser", ["on"]) | ||
|
||
def notify_user_off(self): | ||
"""Notify USer Off.""" | ||
return self.send("set_notifyuser", ["off"]) | ||
|
||
def amb_on(self): | ||
"""Amblient Light On.""" | ||
return self.send("enable_amb", ["on"]) | ||
|
||
def amb_off(self): | ||
"""Ambient Light Off.""" | ||
return self.send("enable_amb", ["off"]) | ||
|
||
def set_amb_bright(self, level: int): | ||
"""Set Ambient Light brightness level.""" | ||
return self.send("set_amb_bright", [level]) | ||
|
||
def status(self): | ||
"""Retrieve properties.""" | ||
properties = ['power', 'bright', 'notifystatus', 'ambstatus', | ||
'ambvalue', 'eyecare', 'scene_num', 'bls', | ||
'dvalue', ] | ||
values = self.send( | ||
"get_prop", | ||
properties | ||
) | ||
return PhilipsEyecareStatus(dict(zip(properties, values))) | ||
|
||
|
||
class PhilipsEyecareStatus: | ||
"""Container for status reports from Xiaomi Philips Eyecare Smart Lamp 2""" | ||
|
||
def __init__(self, data: Dict[str, Any]) -> None: | ||
# ["power","bright","notifystatus","ambstatus","ambvalue","eyecare", | ||
# "scene_num","bls","dvalue"]} | ||
# ["off",5,"off","off",41,"on",3,"on",0] | ||
self.data = data | ||
|
||
@property | ||
def power(self) -> str: | ||
return self.data["power"] | ||
|
||
@property | ||
def is_on(self) -> bool: | ||
return self.power == "on" | ||
|
||
@property | ||
def bright(self) -> int: | ||
return self.data["bright"] | ||
|
||
@property | ||
def notifystatus(self) -> str: | ||
return self.data["notifystatus"] | ||
|
||
@property | ||
def ambstatus(self) -> str: | ||
return self.data["ambstatus"] | ||
|
||
@property | ||
def ambvalue(self) -> int: | ||
return self.data["ambvalue"] | ||
|
||
@property | ||
def eyecare(self) -> str: | ||
return self.data["eyecare"] | ||
|
||
@property | ||
def scene_num(self) -> str: | ||
return self.data["scene_num"] | ||
|
||
@property | ||
def bls(self) -> str: | ||
return self.data["bls"] | ||
|
||
@property | ||
def dvalue(self) -> int: | ||
return self.data["dvalue"] | ||
|
||
def __str__(self) -> str: | ||
s = "<PhilipsEyecareStatus power=%s, bright=%s, " \ | ||
"notifystatus=%s, ambstatus=%s, ambvalue=%s, " \ | ||
"eyecare=%s, scene_num=%s, bls=%s, " \ | ||
"dvalue=%s >" % \ | ||
(self.power, self.bright, | ||
self.notifystatus, self.ambstatus, self.ambvalue, | ||
self.eyecare, self.scene_num, | ||
self.bls) | ||
return s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
# -*- coding: UTF-8 -*- | ||
import logging | ||
import click | ||
import sys | ||
import ipaddress | ||
|
||
if sys.version_info < (3, 4): | ||
print("To use this script you need python 3.4 or newer, got %s" % | ||
sys.version_info) | ||
sys.exit(1) | ||
|
||
import mirobo # noqa: E402 | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
pass_dev = click.make_pass_decorator(mirobo.PhilipsEyecare) | ||
|
||
|
||
def validate_bright(ctx, param, value): | ||
value = int(value) | ||
if value < 1 or value > 100: | ||
raise click.BadParameter('Should be a positive int between 1-100.') | ||
return value | ||
|
||
|
||
def validate_minutes(ctx, param, value): | ||
value = int(value) | ||
if value < 0 or value > 60: | ||
raise click.BadParameter('Should be a positive int between 1-60.') | ||
return value | ||
|
||
|
||
def validate_scene(ctx, param, value): | ||
value = int(value) | ||
if value < 1 or value > 3: | ||
raise click.BadParameter('Should be a positive int between 1-3.') | ||
return value | ||
|
||
|
||
def validate_ip(ctx, param, value): | ||
try: | ||
ipaddress.ip_address(value) | ||
return value | ||
except ValueError as ex: | ||
raise click.BadParameter("Invalid IP: %s" % ex) | ||
|
||
|
||
def validate_token(ctx, param, value): | ||
token_len = len(value) | ||
if token_len != 32: | ||
raise click.BadParameter("Token length != 32 chars: %s" % token_len) | ||
return value | ||
|
||
|
||
@click.group(invoke_without_command=True) | ||
@click.option('--ip', envvar="DEVICE_IP", callback=validate_ip) | ||
@click.option('--token', envvar="DEVICE_TOKEN", callback=validate_token) | ||
@click.option('-d', '--debug', default=False, count=True) | ||
@click.pass_context | ||
def cli(ctx, ip: str, token: str, debug: int): | ||
"""A tool to command Xiaomi Philips Eyecare Smart Lamp 2.""" | ||
|
||
if debug: | ||
logging.basicConfig(level=logging.DEBUG) | ||
_LOGGER.info("Debug mode active") | ||
else: | ||
logging.basicConfig(level=logging.INFO) | ||
|
||
# if we are scanning, we do not try to connect. | ||
if ctx.invoked_subcommand == "discover": | ||
return | ||
|
||
if ip is None or token is None: | ||
click.echo("You have to give ip and token!") | ||
sys.exit(-1) | ||
|
||
dev = mirobo.PhilipsEyecare(ip, token, debug) | ||
_LOGGER.debug("Connecting to %s with token %s", ip, token) | ||
|
||
ctx.obj = dev | ||
|
||
if ctx.invoked_subcommand is None: | ||
ctx.invoke(status) | ||
|
||
|
||
@cli.command() | ||
def discover(): | ||
"""Search for plugs in the network.""" | ||
mirobo.PhilipsEyecare.discover() | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def status(dev: mirobo.PhilipsEyecare): | ||
"""Returns the state information.""" | ||
res = dev.status() | ||
if not res: | ||
return # bail out | ||
|
||
click.echo(click.style("Power: %s" % res.power, bold=True)) | ||
click.echo("Brightness: %s" % res.bright) | ||
click.echo("Eye Fatigue Reminder: %s" % res.notifystatus) | ||
click.echo("Ambient Light: %s" % res.ambstatus) | ||
click.echo("Ambient Light Brightness: %s" % res.ambvalue) | ||
click.echo("Eyecare Mode: %s" % res.eyecare) | ||
click.echo("Eyecare Scene: %s" % res.scene_num) | ||
click.echo("Night Light: %s " % res.bls) | ||
click.echo("Delay Off: %s minutes" % res.dvalue) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def on(dev: mirobo.PhilipsEyecare): | ||
"""Power on.""" | ||
click.echo("Power on: %s" % dev.on()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def off(dev: mirobo.PhilipsEyecare): | ||
"""Power off.""" | ||
click.echo("Power off: %s" % dev.off()) | ||
|
||
|
||
@cli.command() | ||
@click.argument('level', callback=validate_bright, required=True,) | ||
@pass_dev | ||
def set_bright(dev: mirobo.PhilipsEyecare, level): | ||
"""Set brightness level.""" | ||
click.echo("Brightness: %s" % dev.set_bright(level)) | ||
|
||
|
||
@cli.command() | ||
@click.argument('scene', callback=validate_scene, required=True,) | ||
@pass_dev | ||
def set_scene(dev: mirobo.PhilipsEyecare, scene): | ||
"""Set eyecare scene number.""" | ||
click.echo("Eyecare Scene: %s" % dev.set_user_scene(scene)) | ||
|
||
|
||
@cli.command() | ||
@click.argument('minutes', callback=validate_minutes, required=True,) | ||
@pass_dev | ||
def delay_off(dev: mirobo.PhilipsEyecare, minutes): | ||
"""Set delay off in minutes.""" | ||
click.echo("Delay off: %s" % dev.delay_off(minutes)) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def bl_on(dev: mirobo.PhilipsEyecare): | ||
"""Night Light on.""" | ||
click.echo("Night Light On: %s" % dev.bl_on()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def bl_off(dev: mirobo.PhilipsEyecare): | ||
"""Night Light off.""" | ||
click.echo("Night Light off: %s" % dev.bl_off()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def notify_on(dev: mirobo.PhilipsEyecare): | ||
"""Eye Fatigue Reminder On.""" | ||
click.echo("Eye Fatigue Reminder On: %s" % dev.notify_user_on()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def notify_off(dev: mirobo.PhilipsEyecare): | ||
"""Eye Fatigue Reminder off.""" | ||
click.echo("Eye Fatigue Reminder Off: %s" % dev.notify_user_off()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def ambient_on(dev: mirobo.PhilipsEyecare): | ||
"""Ambient Light on.""" | ||
click.echo("Ambient Light On: %s" % dev.amb_on()) | ||
|
||
|
||
@cli.command() | ||
@pass_dev | ||
def ambient_off(dev: mirobo.PhilipsEyecare): | ||
"""Ambient Light off.""" | ||
click.echo("Ambient Light Off: %s" % dev.amb_off()) | ||
|
||
|
||
@cli.command() | ||
@click.argument('level', callback=validate_bright, required=True,) | ||
@pass_dev | ||
def set_amb_bright(dev: mirobo.PhilipsEyecare, level): | ||
"""Set Ambient Light brightness level.""" | ||
click.echo("Ambient Light Brightness: %s" % dev.set_amb_bright(level)) | ||
|
||
|
||
if __name__ == "__main__": | ||
cli() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters