From a9e799cb06b0c57198a94948d58749bdf7fe473b Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:08:16 +0100 Subject: [PATCH] Clean up time API (#221) --- esphomeyaml/components/time/__init__.py | 80 ++++++++++++++++--------- esphomeyaml/components/time/sntp.py | 6 +- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/esphomeyaml/components/time/__init__.py b/esphomeyaml/components/time/__init__.py index 375c4f6eff..3d4d7c44c7 100644 --- a/esphomeyaml/components/time/__init__.py +++ b/esphomeyaml/components/time/__init__.py @@ -8,7 +8,7 @@ import esphomeyaml.config_validation as cv from esphomeyaml import automation from esphomeyaml.const import CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, CONF_HOURS, \ CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_SECONDS, CONF_TIMEZONE, CONF_TRIGGER_ID -from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns +from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, ArrayInitializer _LOGGER = logging.getLogger(__name__) @@ -47,18 +47,8 @@ def _tz_dst_str(dt): _tz_timedelta(td)) -def detect_tz(): - try: - import tzlocal - import pytz - except ImportError: - raise vol.Invalid("No timezone specified and 'tzlocal' not installed. To automatically " - "detect the timezone please install tzlocal (pip2 install tzlocal)") - try: - tz = tzlocal.get_localzone() - except pytz.exceptions.UnknownTimeZoneError: - _LOGGER.warning("Could not auto-detect timezone. Using UTC...") - return 'UTC' +def convert_tz(pytz_obj): + tz = pytz_obj def _dst(dt, is_dst): try: @@ -107,18 +97,34 @@ def detect_tz(): tzbase = '{}{}'.format(norm_tzname, _tz_timedelta(-1 * norm_utcoffset)) if dst_begins is None: # No DST in this timezone - _LOGGER.info("Auto-detected timezone '%s' with UTC offset %s", + _LOGGER.info("Detected timezone '%s' with UTC offset %s", norm_tzname, _tz_timedelta(norm_utcoffset)) return tzbase tzext = '{}{},{},{}'.format(dst_tzname, _tz_timedelta(-1 * dst_utcoffset), _tz_dst_str(dst_begins), _tz_dst_str(dst_ends)) - _LOGGER.info("Auto-detected timezone '%s' with UTC offset %s and daylight savings time from " + _LOGGER.info("Detected timezone '%s' with UTC offset %s and daylight savings time from " "%s to %s", norm_tzname, _tz_timedelta(norm_utcoffset), dst_begins.strftime("%x %X"), dst_ends.strftime("%x %X")) return tzbase + tzext +def detect_tz(): + try: + import tzlocal + import pytz + except ImportError: + raise vol.Invalid("No timezone specified and 'tzlocal' not installed. To automatically " + "detect the timezone please install tzlocal (pip2 install tzlocal)") + try: + tz = tzlocal.get_localzone() + except pytz.exceptions.UnknownTimeZoneError: + _LOGGER.warning("Could not auto-detect timezone. Using UTC...") + return 'UTC' + + return convert_tz(tz) + + def _parse_cron_int(value, special_mapping, message): special_mapping = special_mapping or {} if isinstance(value, (str, unicode)) and value in special_mapping: @@ -233,8 +239,19 @@ def validate_cron_keys(value): return cv.has_at_least_one_key(*CRON_KEYS)(value) +def validate_tz(value): + value = cv.string_strict(value) + + try: + import pytz + + return convert_tz(pytz.timezone(value)) + except Exception: # pylint: disable=broad-except + return value + + TIME_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Optional(CONF_TIMEZONE, default=detect_tz): cv.string, + vol.Optional(CONF_TIMEZONE, default=detect_tz): validate_tz, vol.Optional(CONF_ON_TIME): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(CronTrigger), vol.Optional(CONF_SECONDS): validate_cron_seconds, @@ -254,18 +271,25 @@ def setup_time_core_(time_var, config): for conf in config.get(CONF_ON_TIME, []): rhs = App.register_component(time_var.Pmake_cron_trigger()) trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) - for second in conf.get(CONF_SECONDS, [x for x in range(0, 61)]): - add(trigger.add_second(second)) - for minute in conf.get(CONF_MINUTES, [x for x in range(0, 60)]): - add(trigger.add_minute(minute)) - for hour in conf.get(CONF_HOURS, [x for x in range(0, 24)]): - add(trigger.add_hour(hour)) - for day_of_month in conf.get(CONF_DAYS_OF_MONTH, [x for x in range(1, 32)]): - add(trigger.add_day_of_month(day_of_month)) - for month in conf.get(CONF_MONTHS, [x for x in range(1, 13)]): - add(trigger.add_month(month)) - for day_of_week in conf.get(CONF_DAYS_OF_WEEK, [x for x in range(1, 8)]): - add(trigger.add_day_of_week(day_of_week)) + + seconds = conf.get(CONF_SECONDS, [x for x in range(0, 61)]) + add(trigger.add_seconds(ArrayInitializer(*seconds, multiline=False))) + + minutes = conf.get(CONF_MINUTES, [x for x in range(0, 60)]) + add(trigger.add_minutes(ArrayInitializer(*minutes, multiline=False))) + + hours = conf.get(CONF_HOURS, [x for x in range(0, 24)]) + add(trigger.add_hours(ArrayInitializer(*hours, multiline=False))) + + days_of_month = conf.get(CONF_DAYS_OF_MONTH, [x for x in range(1, 32)]) + add(trigger.add_days_of_month(ArrayInitializer(*days_of_month, multiline=False))) + + months = conf.get(CONF_MONTHS, [x for x in range(1, 13)]) + add(trigger.add_months(ArrayInitializer(*months, multiline=False))) + + days_of_week = conf.get(CONF_DAYS_OF_WEEK, [x for x in range(1, 8)]) + add(trigger.add_days_of_week(ArrayInitializer(*days_of_week, multiline=False))) + automation.build_automation(trigger, NoArg, conf) diff --git a/esphomeyaml/components/time/sntp.py b/esphomeyaml/components/time/sntp.py index 19ba250b10..9b09b6e220 100644 --- a/esphomeyaml/components/time/sntp.py +++ b/esphomeyaml/components/time/sntp.py @@ -3,7 +3,7 @@ import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml.components import time as time_ from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_SERVERS -from esphomeyaml.helpers import App, Pvariable +from esphomeyaml.helpers import App, Pvariable, add SNTPComponent = time_.time_ns.SNTPComponent @@ -15,8 +15,10 @@ PLATFORM_SCHEMA = time_.TIME_PLATFORM_SCHEMA.extend({ def to_code(config): - rhs = App.make_sntp_component(*config.get(CONF_SERVERS, [])) + rhs = App.make_sntp_component() sntp = Pvariable(config[CONF_ID], rhs) + if CONF_SERVERS in config: + add(sntp.set_servers(*config[CONF_SERVERS])) time_.setup_time(sntp, config)