Last active
July 15, 2019 00:24
-
-
Save wsoyka/4b516384d0a6a88c9ba731d104dc71c7 to your computer and use it in GitHub Desktop.
yeelight python cli script
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
import argparse | |
import struct | |
import time | |
from yeelight import Bulb | |
################################################################################## | |
################################################################################## | |
## Easily run actions on your Yeelights ## | |
## (e.g. when your Home Automation solution doesn't properly support Yeelights) ## | |
## This script is based on: https://gitlab.com/stavros/python-yeelight/ ## | |
## Thanks to stavros for building the interface to the yeelights! ## | |
## To use you first have to install the plugin via pip3 install yeelight ## | |
################################################################################## | |
################################################################################## | |
""" | |
TODO | |
support multiple bulbs | |
expose duration of change | |
""" | |
##################################################################### | |
# If you want to extend this script: most arg keys are only set in # | |
# ordered_args, irgnore the mirrored ones, they are not set. # | |
##################################################################### | |
# get order of args to run in actions in order, kudos to | |
# https://stackoverflow.com/a/9028031 and | |
# https://stackoverflow.com/a/8632404 | |
def make_custom_action(customval): | |
class CustomAction(argparse.Action): | |
def __call__(self, parser, namespace, values, option_string=None): | |
if not 'ordered_args' in namespace: | |
setattr(namespace, 'ordered_args', []) | |
previous = namespace.ordered_args | |
# decide if we want passed args or set custom ones | |
if (customval is 'use_passed'): | |
previous.append((self.dest, values)) | |
else: | |
previous.append((self.dest, customval)) | |
setattr(namespace, 'ordered_args', previous) | |
if hasattr(namespace, self.dest): | |
delattr(namespace, self.dest) | |
return CustomAction | |
parser = argparse.ArgumentParser( | |
description='Control Yeelights with CLI arguments.\nBased on https://gitlab.com/stavros/python-yeelight.\n' + | |
'Commands order will be recognized and the same command can be executed multiple times in one run.', | |
formatter_class=argparse.RawTextHelpFormatter) | |
parser.add_argument('--address', '-a', dest="addr", default='10.0.0.66', metavar='XXX.XXX.XXX.XXX', | |
help="IP adress of Yeelight (HAS TO BE IN DEVELOPMENT/LAN MODE!)") | |
parser.add_argument('--delay', '-d', dest="delay", type=float, default=0.25, | |
help="delay between each command in seconds. setting to 0 can and probably will lead do commands " | |
+ "not being recognized by lamp") | |
parser.add_argument('--on', '-on', dest="on", | |
action=make_custom_action(True), nargs=0, help="turn lamp on") | |
parser.add_argument('--off', '-off', dest="on", | |
action=make_custom_action(False), nargs=0, help="turn lamp off") | |
parser.add_argument('--toggle', dest="toggle", | |
action=make_custom_action(None), nargs=0, help="toggle lamp") | |
parser.add_argument('--restart', '-re', dest="restart", action=make_custom_action(None), nargs=0, | |
help="toggle lamp twice") | |
parser.add_argument('--brightness', '-bright', dest="bright", type=float, metavar="PERCENT", | |
action=make_custom_action('use_passed'), nargs='?', help="set brightness to 0-100") | |
parser.add_argument('--color-temperature', '-ct', dest="ct", type=int, action=make_custom_action('use_passed'), | |
nargs='?', metavar="KELVIN", help="set color temperature of lamp") | |
parser.add_argument('--hue-color-temperature', '-hct', dest="hct", type=int, action=make_custom_action('use_passed'), | |
nargs='?', metavar="HUECT", | |
help="set color temperature of Yeelight based on color temperature of Phillips Hue light " | |
+"(different than normal color temperature!)") | |
parser.add_argument('--hex-color', '-hc', dest="hc", type=str, action=make_custom_action('use_passed'), nargs='?', | |
metavar="FFFFFF", help="set color of lamp based on hex") | |
# parser.add_argument('--red', '-r', dest="red", type=int, metavar="RED") | |
# parser.add_argument('--green', '-g', nargs='?',dest="green", type=int, metavar="GREEN") | |
# parser.add_argument('--blue', '-b', nargs='?', dest="blue", type=int, metavar="BLUE") | |
args = parser.parse_args() | |
def check_rgb(r, g, b): | |
return 0 <= r <= 255 and 0 <= g <= 255 and 0 <= b <= 255 | |
# check if any of the given values where set | |
def any_set(list): | |
for i in list: | |
if i is not None: | |
return True | |
return False | |
def hue_ct_to_ct(huect): | |
return 1000000 / huect | |
def on(bool): | |
if bool: | |
print("turning lamp on") | |
bulb.turn_on() | |
else: | |
print("turning lamp off") | |
bulb.turn_off() | |
def toggle(): | |
print("toggle") | |
bulb.toggle() | |
def restart(): | |
bulb.toggle() | |
time.sleep(0.25) | |
bulb.toggle() | |
def bright(b): | |
if 0 <= b <= 100: | |
print("set bright to: {0}".format(b)) | |
bulb.set_brightness(b) | |
else: | |
print("bright has to be between 0 and 100") | |
# make this hex based for simpler parsing | |
"""#if args.red is not None or args.blue is not None or args.green is not None: | |
def rgb(red,green,blue): | |
if check_rgb(red, green, blue): | |
print("set rgb to: {0},{1},{2}".format(red,green,blue)) | |
bulb.set_rgb(red, blue, green) | |
else: | |
# if any_set([args.red, args.green, args.blue]): | |
parser.error('"All 3 RGB channels have to be set.') | |
""" | |
def ct(color_temp): | |
print("set color temperature to: {0}".format(color_temp)) | |
bulb.set_color_temp(color_temp) | |
def hct(hue_color_temp): | |
new_ct = hue_ct_to_ct(hue_color_temp) | |
print("setting ct from huect: {0}".format(new_ct)) | |
bulb.set_color_temp(new_ct) | |
def hc(hex_color): | |
red, green, blue = struct.unpack('BBB', bytes.fromhex(hex_color)) | |
print("setting color to rgb: ({0},{1},{2}) (hex: {3})".format( | |
red, green, blue, hex_color)) | |
bulb.set_rgb(red, blue, green) | |
# Set HSV value. | |
# bulb.set_hsv(153, 100, 50) | |
# Set hue and saturation, but keep value (brightness) the same. | |
# bulb.set_hsv(320, 100) | |
# Save this setting as default. | |
# bulb.set_default() | |
if hasattr(args, 'ordered_args'): | |
print(args) | |
# discard original args as they are all unset | |
orig_args = args # keep a backup | |
# now use ordered args as main args | |
args = args.ordered_args | |
bulb = Bulb(orig_args.addr, effect="smooth", duration=1000) | |
# interpret variables as method names to not have huge if else tree | |
for method_name, value in args: | |
# print("key {0} value {1}".format(method_name,value)) | |
# find method by str name | |
possibles = globals().copy() | |
possibles.update(locals()) | |
method = possibles.get(method_name) | |
# print(method) | |
if not method: | |
print("couldnt find function: {0}".format(method)) | |
if value is None: | |
method() | |
else: | |
method(value) | |
time.sleep(orig_args.delay) | |
else: | |
parser.error("Specify at least one arg") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment