Skip to content

Commit

Permalink
apply sublack, make linter happier
Browse files Browse the repository at this point in the history
  • Loading branch information
evan-burke committed Dec 2, 2018
1 parent 57c8a5d commit f692666
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 119 deletions.
222 changes: 121 additions & 101 deletions light-schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@
from tradfri import Tradfri

# Config
transition_supported_attrs = ['brightness','color_temp']
transition_supported_durations = ['second','seconds','minute','minutes','hour','hours']
transition_supported_attrs = ["brightness", "color_temp"]
transition_supported_durations = [
"second",
"seconds",
"minute",
"minutes",
"hour",
"hours",
]


# Debug switch for this script. separate from tradfri.py debug switch.
Expand All @@ -19,17 +26,29 @@

# Script

parser = argparse.ArgumentParser(conflict_handler='resolve')
parser = argparse.ArgumentParser(conflict_handler="resolve")

# args:
# device friendly name
# action
# action params (dict)

parser.add_argument("device", help="Friendly name of the device to update.")
parser.add_argument("action", help="Action to take on the specified device. See tradfri.py for supported actions.")
parser.add_argument("params", nargs='*', default=None, help="Parameters for the specified action.")
parser.add_argument("--verbose", "-v", default=0, type=int, choices=[1,2], help="Increase verbosity of output.")
parser.add_argument(
"action",
help="Action to take on the specified device. See tradfri.py for supported actions.",
)
parser.add_argument(
"params", nargs="*", default=None, help="Parameters for the specified action."
)
parser.add_argument(
"--verbose",
"-v",
default=0,
type=int,
choices=[1, 2],
help="Increase verbosity of output.",
)
# ^ this actually passes debug switch to the tradfri class instance.
args = parser.parse_args()

Expand All @@ -45,123 +64,124 @@
toggle()
"""

# Transition is the special case.
# Transition is the special case.
# Need to parse new_attr, duration, and start_time.
# This is... not the right way to do it, because argparse will probably do a better job at this sort of thing.
# This is... not the right way to do it, because argparse will probably do a better job at this sort of thing.
# Plus, delimiting values by '=' doesn't match the param format in argparse.

# example:
# python3 light-schedule.py geo_desk transition color_temp=3200 seconds=7 start_time=5:23


def parse_transition_params(params):
# parse new setting / attr:
attr = params[0].replace(" ", "").split("=")
if attr[0] not in transition_supported_attrs:
print("error: attribute of", attr[0], "not supported. supported attributes:", transition_supported_attrs)
quit()
else:
new_attr = { attr[0]: int(attr[1]) }
#value = attr[1]

# parse transition duration
dur = params[1].replace(" ", "").split("=")
if dur[0] not in transition_supported_durations:
print("error: duration unit of", dur[0], "not supported. supported durations:", transition_supported_durations)
quit()
else:
dur_unit = dur[0]
if 'second' in dur_unit:
dur_value = int(dur[1])
elif 'minute' in dur_unit:
dur_value = int(dur[1]) * 60
elif 'hour' in dur_unit:
dur_value = int(dur[1]) * 60 * 60
duration = datetime.timedelta(seconds=dur_value)

# if present, parse start time
try:
if 'start_time' in params[2]:
_p2 = params[2].replace(" ", "").split("=")
#print("params2:", params[2], "p2:", _p2)
start_time = dateutil.parser.parse(_p2[1])
except:
#print("except block for start_time")
start_time = None

if debug:
print("parsed values:")
print(new_attr)
print(duration)
if start_time: print(start_time)

return new_attr, duration, start_time



####
# parse new setting / attr:
attr = params[0].replace(" ", "").split("=")
if attr[0] not in transition_supported_attrs:
print(
"error: attribute of",
attr[0],
"not supported. supported attributes:",
transition_supported_attrs,
)
quit()
else:
new_attr = {attr[0]: int(attr[1])}
# value = attr[1]

# parse transition duration
dur = params[1].replace(" ", "").split("=")
if dur[0] not in transition_supported_durations:
print(
"error: duration unit of",
dur[0],
"not supported. supported durations:",
transition_supported_durations,
)
quit()
else:
dur_unit = dur[0]
if "second" in dur_unit:
dur_value = int(dur[1])
elif "minute" in dur_unit:
dur_value = int(dur[1]) * 60
elif "hour" in dur_unit:
dur_value = int(dur[1]) * 60 * 60
duration = datetime.timedelta(seconds=dur_value)

# if present, parse start time
try:
if "start_time" in params[2]:
_p2 = params[2].replace(" ", "").split("=")
# print("params2:", params[2], "p2:", _p2)
start_time = dateutil.parser.parse(_p2[1])
except:
# print("except block for start_time")
start_time = None

if debug:
print("parsed values:")
print(new_attr)
print(duration)
if start_time:
print(start_time)

return new_attr, duration, start_time


####
#### MAIN
####
####

if debug:
from pprint import pprint
print("args:")
pprint(args)
print("")
if args.params:
print("params:")
print(args.params)
print("")
from pprint import pprint

print("creating instance for device name:", args.device)
print("args:")
pprint(args)
print("")
if args.params:
print("params:")
print(args.params)
print("")

print("creating instance for device name:", args.device)

device = Tradfri(args.device, debug=args.verbose)


func = getattr(device, args.action)

if args.action == 'transition':
#special case
new_attr, duration, start_time = parse_transition_params(args.params)
resp = func(new_attr, duration, start_time)

elif args.action == 'lightswitch':
# convert to bool
test_arg = args.params[0].lower()
if test_arg == 'true' or test_arg == '1':
func_input = True
elif test_arg == 'false' or test_arg == '0':
func_input = False
else:
func_input = None
# lightswitch() function defaults to True if no input.

resp = func(func_input)

elif args.action in ['set_brightness','set_color','mireds_to_kelvin','kelvin_to_mireds']:
resp = func(int(args.params[0]))
if args.action == "transition":
# special case
new_attr, duration, start_time = parse_transition_params(args.params)
resp = func(new_attr, duration, start_time)

elif args.action == "lightswitch":
# convert to bool
test_arg = args.params[0].lower()
if test_arg == "true" or test_arg == "1":
func_input = True
elif test_arg == "false" or test_arg == "0":
func_input = False
else:
func_input = None
# lightswitch() function defaults to True if no input.

resp = func(func_input)

elif args.action in [
"set_brightness",
"set_color",
"mireds_to_kelvin",
"kelvin_to_mireds",
]:
resp = func(int(args.params[0]))

# Above are just the commonly used functions.
# There's nothing to stop user from calling a lower-level/internal function here, but args won't be used, so some may fail.
else:
resp = func()
resp = func()

if resp:
from pprint import pprint
pprint(resp)















from pprint import pprint

pprint(resp)
38 changes: 20 additions & 18 deletions tradfri.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@
import requests



# Welp. I may have needlessly rewritten this - https://home-assistant.io/components/switch.flux/
# Though - it isn't perfect anyway.
# - https://community.home-assistant.io/t/improving-the-fluxer/23729


# HomeAssistant base API URL.
#API_URL = "http://192.168.132.162:8123/api/"
# API_URL = "http://192.168.132.162:8123/api/"
CONFIG_FILENAME = "tradfri.conf"

# Min/max values for your light. These are for ikea TRADFRI white spectrum.
Expand All @@ -27,7 +26,8 @@

# Updating too fast can cause flickering. Recommended 0.1-0.2, not less than 0.1.
# Too high makes faster transitions stuttery as well, due to larger increases per step.
# If HomeAssistant is slower to respond than this, this may be significantly faster than actual min step duration.
# If HomeAssistant is slower to respond than this, this value
# may be significantly faster than actual min step duration.
MIN_STEP_DURATION = datetime.timedelta(seconds=0.1)


Expand All @@ -38,11 +38,15 @@ def __init__(self, device_name, debug=0):
# get config
self.config = configparser.ConfigParser()
_ = self.config.read(CONFIG_FILENAME)
self.api_url = self.config['tradfri']['api_url']
self.api_url = self.config["tradfri"]["api_url"]

self.entity_id = self.get_entity(device_name)
self.debug = debug
self.state = self.get_state()
if self.state["state"] == "on":
self.attrs = state["attributes"]
else:
self.attrs = {}

try:
if "Entity not found" in self.state["message"]:
Expand All @@ -54,20 +58,20 @@ def __init__(self, device_name, debug=0):
pass

def get_entity(self, device_name):
# try to get the entity ID for the given device name.
""" Try to get the entity ID for the given device name. """

# Check if it matches anything in the device map.
device_map = json.loads(self.config['tradfri']['device_map'])
device_map = json.loads(self.config["tradfri"]["device_map"])

if device_name in device_map:
return device_map['device_name']
return device_map["device_name"]

# Else, just try prepending "light" to the entity name.
else:
return "light." + device_name

return "light." + device_name

def apireq(self, endpoint, req_type="get", post_data=None):
""" Make an API request aginst HomeAssistant. """

def handle_errors(data):
if self.debug and data.status_code != 200:
print(
Expand Down Expand Up @@ -123,10 +127,7 @@ def get_attrs(self):

def check_if_on(self):
state = self.get_state()
if state["state"] == "on":
return True
else:
return False
return bool(state["state"] == "on")

def get_temp_kelvin(self):
""" Retrieves current bulb state and converts 'mireds' to kelvin.
Expand Down Expand Up @@ -208,7 +209,7 @@ def transition(self, new_attr, duration, start_time=None):
""" Highest-level function. Initiates a transition for the given
entity_id, based on the target values contained in new_attr,
and the 'duration' which is a timedelta.
If start_time is not set, start immediately.
If start_time is not set, start immediately.
Otherwise, sleeps until start_time.
"""

Expand All @@ -229,12 +230,13 @@ def plan_transition(
):
""" new_attr is a single-item dict containing type of attribute & new value,
e.g., {"brightness": 0}
duration is a timedelta, as is time_per_step. One or the other must be set. If both are set, uses 'duration'.
duration is a timedelta, as is time_per_step. One or the other must be set.
If both are set, uses 'duration'.
start_time is a datetime.
start_attrs will define the starting attributes to use;
start_attrs will define the starting attributes to use;
if not set, this will start from current attributes.
### TODO: implment time_per_step
### TODO: implment time_per_step
"""
new_attr = self.sanity_check_values(new_attr)
Expand Down

0 comments on commit f692666

Please sign in to comment.