Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Xiaomi Philips Eyecare Smart Lamp 2 #34

Merged
merged 3 commits into from
Aug 14, 2017
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mirobo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
from mirobo.vacuum import Vacuum, VacuumException
from mirobo.plug import Plug
from mirobo.strip import Strip
from mirobo.philips_eyecare import PhilipsEyecare
from mirobo.device import Device, DeviceException
134 changes: 134 additions & 0 deletions mirobo/philips_eyecare.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
from .device import Device
from typing import Any, Dict
import enum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'enum' imported but unused


class PhilipsEyecare(Device):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

"""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])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

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',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace

'ambstatus', 'ambvalue', 'eyecare', 'scene_num',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continuation line under-indented for visual indent
trailing whitespace

'bls', 'dvalue',]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continuation line under-indented for visual indent
missing whitespace after ','

values = self.send(
"get_prop",
properties
)
return PhilipsEyecareStatus(dict(zip(properties, values)))

class PhilipsEyecareStatus:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

"""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"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line contains whitespace

@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:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many blank lines (2)

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
199 changes: 199 additions & 0 deletions mirobo/philips_eyecare_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# -*- coding: UTF-8 -*-
import logging
import click
import ast

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'ast' imported but unused

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

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):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

def discover():
"""Search for plugs in the network."""
mirobo.PhilipsEyecare.discover()


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def on(dev: mirobo.PhilipsEyecare):
"""Power on."""
click.echo("Power on: %s" % dev.on())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def off(dev: mirobo.PhilipsEyecare):
"""Power off."""
click.echo("Power off: %s" % dev.off())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def bl_on(dev: mirobo.PhilipsEyecare):
"""Night Light on."""
click.echo("Night Light On: %s" % dev.bl_on())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def bl_off(dev: mirobo.PhilipsEyecare):
"""Night Light off."""
click.echo("Night Light off: %s" % dev.bl_off())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def ambient_on(dev: mirobo.PhilipsEyecare):
"""Ambient Light on."""
click.echo("Ambient Light On: %s" % dev.amb_on())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@pass_dev
def ambient_off(dev: mirobo.PhilipsEyecare):
"""Ambient Light off."""
click.echo("Ambient Light Off: %s" % dev.amb_off())


@cli.command()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines, found 1

@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__":

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines after class or function definition, found 1

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expected 2 blank lines after class or function definition, found 1

cli()
3 changes: 2 additions & 1 deletion mirobo/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
0x02f2: "Xiaomi Mi Robot Vacuum",
0x00c4: "Xiaomi Smart Mi Air Purifier",
0x031a: "Xiaomi Smart home gateway",
0x0330: "Yeelight color bulb"
0x0330: "Yeelight color bulb",
0x02f9: "Xiaomi Philips Eyecare Smart Lamp 2",
}
xiaomi_devices = {y: x for x, y in xiaomi_devices_reverse.items()}

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
'console_scripts': [
'mirobo=mirobo.vacuum_cli:cli',
'miplug=mirobo.plug_cli:cli',
'mieye=mirobo.philips_eyecare_cli:cli',
],
},
)