From 415e12309b72dfa5bf24db8e3463473491977f67 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 7 Nov 2018 22:41:54 +0100 Subject: [PATCH 01/11] Improve OTA v2 error and log messages --- esphomeyaml/espota2.py | 54 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/esphomeyaml/espota2.py b/esphomeyaml/espota2.py index a2733c85c7..5eaaccd669 100755 --- a/esphomeyaml/espota2.py +++ b/esphomeyaml/espota2.py @@ -4,6 +4,8 @@ import random import socket import sys +from esphomeyaml.core import ESPHomeYAMLError + RESPONSE_OK = 0 RESPONSE_REQUEST_AUTH = 1 @@ -49,7 +51,7 @@ def update_progress(progress): sys.stderr.flush() -class OTAError(Exception): +class OTAError(ESPHomeYAMLError): pass @@ -202,12 +204,52 @@ def perform_ota(sock, password, file_handle, filename): _LOGGER.info("OTA successful") -def run_ota(remote_host, remote_port, password, filename): - _LOGGER.info("Connecting to %s:%s...", remote_host, remote_port) - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(5.0) +def is_ip_address(host): + parts = host.split('.') + if len(parts) != 4: + return False try: - sock.connect((remote_host, remote_port)) + for p in parts: + int(p) + return True + except ValueError: + return False + + +def resolve_ip_address(host): + if is_ip_address(host): + return host + + _LOGGER.info("Resolving IP Address of %s", host) + hosts = [host] + if host.endswith('.local'): + hosts.append(host[:-6]) + + errors = [] + for x in hosts: + try: + ip = socket.gethostbyname(x) + break + except socket.error as err: + errors.append(err) + else: + _LOGGER.error("Error resolving IP address of %s. Is it connected to WiFi?", + host) + + _LOGGER.error("(If this error persists, please set a static IP address: " + "https://esphomelib.com/esphomeyaml/components/wifi.html#manual-ips") + raise OTAError("Errors: {}".format(', '.join(str(x) for x in errors))) + + _LOGGER.info(" -> %s", ip) + return ip + + +def run_ota(remote_host, remote_port, password, filename): + ip = resolve_ip_address(remote_host) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(10.0) + try: + sock.connect((ip, remote_port)) except socket.error as err: sock.close() _LOGGER.error("Connecting to %s:%s failed: %s", remote_host, remote_port, err) From 94978d0063f99fedc049908347e8fa7948fa833f Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Wed, 7 Nov 2018 23:27:06 +0100 Subject: [PATCH 02/11] Fix HLW8012 Voltage Divider option not being added to source (#224) --- esphomeyaml/components/sensor/hlw8012.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/esphomeyaml/components/sensor/hlw8012.py b/esphomeyaml/components/sensor/hlw8012.py index 65bafbb69f..818e2802c6 100644 --- a/esphomeyaml/components/sensor/hlw8012.py +++ b/esphomeyaml/components/sensor/hlw8012.py @@ -50,6 +50,8 @@ def to_code(config): sensor.register_sensor(hlw.make_power_sensor(conf[CONF_NAME]), conf) if CONF_CURRENT_RESISTOR in config: add(hlw.set_current_resistor(config[CONF_CURRENT_RESISTOR])) + if CONF_VOLTAGE_DIVIDER in config: + add(hlw.set_voltage_divider(config[CONF_VOLTAGE_DIVIDER])) if CONF_CHANGE_MODE_EVERY in config: add(hlw.set_change_mode_every(config[CONF_CHANGE_MODE_EVERY])) From 359477940156d9a10d6ae9bb917eff7cba891458 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Thu, 8 Nov 2018 16:01:07 +0100 Subject: [PATCH 03/11] Better typing to components (#225) * Add better typing * Fix --- esphomeyaml/components/binary_sensor/esp32_ble_tracker.py | 6 ++++-- esphomeyaml/components/binary_sensor/esp32_touch.py | 3 +++ esphomeyaml/components/binary_sensor/gpio.py | 2 ++ esphomeyaml/components/binary_sensor/nextion.py | 7 +++++-- esphomeyaml/components/binary_sensor/pn532.py | 3 +++ esphomeyaml/components/binary_sensor/rdm6300.py | 3 +++ esphomeyaml/components/binary_sensor/remote_receiver.py | 1 + esphomeyaml/components/binary_sensor/status.py | 2 ++ esphomeyaml/components/binary_sensor/template.py | 6 ++++-- esphomeyaml/components/sensor/adc.py | 2 ++ esphomeyaml/components/sensor/ads1115.py | 3 +++ esphomeyaml/components/sensor/bh1750.py | 2 ++ esphomeyaml/components/sensor/ble_rssi.py | 5 ++++- esphomeyaml/components/sensor/dallas.py | 3 +++ esphomeyaml/components/sensor/duty_cycle.py | 2 ++ esphomeyaml/components/sensor/esp32_hall.py | 2 ++ esphomeyaml/components/sensor/max6675.py | 2 ++ esphomeyaml/components/sensor/mqtt_subscribe.py | 2 ++ esphomeyaml/components/sensor/pulse_counter.py | 2 ++ esphomeyaml/components/sensor/rotary_encoder.py | 2 ++ esphomeyaml/components/sensor/template.py | 2 ++ esphomeyaml/components/sensor/tsl2561.py | 2 ++ esphomeyaml/components/sensor/ultrasonic.py | 2 ++ esphomeyaml/components/sensor/uptime.py | 2 ++ esphomeyaml/components/sensor/wifi_signal.py | 2 ++ esphomeyaml/components/switch/output.py | 2 ++ esphomeyaml/components/switch/remote_transmitter.py | 1 + esphomeyaml/components/switch/restart.py | 2 ++ esphomeyaml/components/switch/shutdown.py | 2 ++ esphomeyaml/components/switch/uart.py | 2 ++ esphomeyaml/components/text_sensor/mqtt_subscribe.py | 2 ++ esphomeyaml/components/text_sensor/template.py | 2 ++ esphomeyaml/components/text_sensor/version.py | 2 ++ esphomeyaml/writer.py | 1 + 34 files changed, 79 insertions(+), 7 deletions(-) diff --git a/esphomeyaml/components/binary_sensor/esp32_ble_tracker.py b/esphomeyaml/components/binary_sensor/esp32_ble_tracker.py index 7057f890a3..7208afabc6 100644 --- a/esphomeyaml/components/binary_sensor/esp32_ble_tracker.py +++ b/esphomeyaml/components/binary_sensor/esp32_ble_tracker.py @@ -1,15 +1,17 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv from esphomeyaml.components import binary_sensor from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \ make_address_array +import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME -from esphomeyaml.helpers import get_variable +from esphomeyaml.helpers import esphomelib_ns, get_variable DEPENDENCIES = ['esp32_ble_tracker'] +ESP32BLEPresenceDevice = esphomelib_ns.ESP32BLEPresenceDevice PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ESP32BLEPresenceDevice), vol.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker) })) diff --git a/esphomeyaml/components/binary_sensor/esp32_touch.py b/esphomeyaml/components/binary_sensor/esp32_touch.py index f122f1b737..7ebde4e93b 100644 --- a/esphomeyaml/components/binary_sensor/esp32_touch.py +++ b/esphomeyaml/components/binary_sensor/esp32_touch.py @@ -34,7 +34,10 @@ def validate_touch_pad(value): return value +ESP32TouchBinarySensor = binary_sensor.binary_sensor_ns.ESP32TouchBinarySensor + PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ESP32TouchBinarySensor), vol.Required(CONF_PIN): validate_touch_pad, vol.Required(CONF_THRESHOLD): cv.uint16_t, cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_variable_id(ESP32TouchComponent), diff --git a/esphomeyaml/components/binary_sensor/gpio.py b/esphomeyaml/components/binary_sensor/gpio.py index 85994ca97f..4d4e880218 100644 --- a/esphomeyaml/components/binary_sensor/gpio.py +++ b/esphomeyaml/components/binary_sensor/gpio.py @@ -7,8 +7,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Application MakeGPIOBinarySensor = Application.MakeGPIOBinarySensor +GPIOBinarySensorComponent = binary_sensor.binary_sensor_ns.GPIOBinarySensorComponent PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(GPIOBinarySensorComponent), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOBinarySensor), vol.Required(CONF_PIN): pins.gpio_input_pin_schema })) diff --git a/esphomeyaml/components/binary_sensor/nextion.py b/esphomeyaml/components/binary_sensor/nextion.py index 3a96b4684c..981e85dbb0 100644 --- a/esphomeyaml/components/binary_sensor/nextion.py +++ b/esphomeyaml/components/binary_sensor/nextion.py @@ -1,8 +1,8 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv -from esphomeyaml.components import binary_sensor +from esphomeyaml.components import binary_sensor, display from esphomeyaml.components.display.nextion import Nextion +import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_COMPONENT_ID, CONF_NAME, CONF_PAGE_ID from esphomeyaml.helpers import get_variable @@ -10,7 +10,10 @@ DEPENDENCIES = ['display'] CONF_NEXTION_ID = 'nextion_id' +NextionTouchComponent = display.display_ns.NextionTouchComponent + PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(NextionTouchComponent), vol.Required(CONF_PAGE_ID): cv.uint8_t, vol.Required(CONF_COMPONENT_ID): cv.uint8_t, cv.GenerateID(CONF_NEXTION_ID): cv.use_variable_id(Nextion) diff --git a/esphomeyaml/components/binary_sensor/pn532.py b/esphomeyaml/components/binary_sensor/pn532.py index 1c2b5be073..fab8482391 100644 --- a/esphomeyaml/components/binary_sensor/pn532.py +++ b/esphomeyaml/components/binary_sensor/pn532.py @@ -27,7 +27,10 @@ def validate_uid(value): return value +PN532BinarySensor = binary_sensor.binary_sensor_ns.PN532BinarySensor + PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(PN532BinarySensor), vol.Required(CONF_UID): validate_uid, cv.GenerateID(CONF_PN532_ID): cv.use_variable_id(PN532Component) })) diff --git a/esphomeyaml/components/binary_sensor/rdm6300.py b/esphomeyaml/components/binary_sensor/rdm6300.py index 394af241ac..ff51f973db 100644 --- a/esphomeyaml/components/binary_sensor/rdm6300.py +++ b/esphomeyaml/components/binary_sensor/rdm6300.py @@ -9,7 +9,10 @@ DEPENDENCIES = ['rdm6300'] CONF_RDM6300_ID = 'rdm6300_id' +RDM6300BinarySensor = binary_sensor.binary_sensor_ns.RDM6300BinarySensor + PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(RDM6300BinarySensor), vol.Required(CONF_UID): cv.uint32_t, cv.GenerateID(CONF_RDM6300_ID): cv.use_variable_id(rdm6300.RDM6300Component) })) diff --git a/esphomeyaml/components/binary_sensor/remote_receiver.py b/esphomeyaml/components/binary_sensor/remote_receiver.py index 51c7efb42c..e2ef0f43c5 100644 --- a/esphomeyaml/components/binary_sensor/remote_receiver.py +++ b/esphomeyaml/components/binary_sensor/remote_receiver.py @@ -36,6 +36,7 @@ RCSwitchTypeCReceiver = remote_ns.RCSwitchTypeCReceiver RCSwitchTypeDReceiver = remote_ns.RCSwitchTypeDReceiver PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(RemoteReceiver), vol.Optional(CONF_LG): vol.Schema({ vol.Required(CONF_DATA): cv.hex_uint32_t, vol.Optional(CONF_NBITS, default=28): vol.All(vol.Coerce(int), cv.one_of(28, 32)), diff --git a/esphomeyaml/components/binary_sensor/status.py b/esphomeyaml/components/binary_sensor/status.py index 11324b887f..af2f0ff66b 100644 --- a/esphomeyaml/components/binary_sensor/status.py +++ b/esphomeyaml/components/binary_sensor/status.py @@ -6,9 +6,11 @@ from esphomeyaml.helpers import App, Application, variable DEPENDENCIES = ['mqtt'] MakeStatusBinarySensor = Application.MakeStatusBinarySensor +StatusBinarySensor = binary_sensor.binary_sensor_ns.StatusBinarySensor PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeStatusBinarySensor), + cv.GenerateID(): cv.declare_variable_id(StatusBinarySensor), })) diff --git a/esphomeyaml/components/binary_sensor/template.py b/esphomeyaml/components/binary_sensor/template.py index 1d5e0f2d36..fb62e24024 100644 --- a/esphomeyaml/components/binary_sensor/template.py +++ b/esphomeyaml/components/binary_sensor/template.py @@ -1,13 +1,15 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv from esphomeyaml.components import binary_sensor +import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME -from esphomeyaml.helpers import App, Application, process_lambda, variable, optional, bool_, add +from esphomeyaml.helpers import App, Application, add, bool_, optional, process_lambda, variable MakeTemplateBinarySensor = Application.MakeTemplateBinarySensor +TemplateBinarySensor = binary_sensor.binary_sensor_ns.TemplateBinarySensor PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TemplateBinarySensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateBinarySensor), vol.Required(CONF_LAMBDA): cv.lambda_, })) diff --git a/esphomeyaml/components/sensor/adc.py b/esphomeyaml/components/sensor/adc.py index ca02b815b5..dc0c7bc561 100644 --- a/esphomeyaml/components/sensor/adc.py +++ b/esphomeyaml/components/sensor/adc.py @@ -23,8 +23,10 @@ def validate_adc_pin(value): MakeADCSensor = Application.MakeADCSensor +ADCSensorComponent = sensor.sensor_ns.ADCSensorComponent PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ADCSensorComponent), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeADCSensor), vol.Required(CONF_PIN): validate_adc_pin, vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES)), diff --git a/esphomeyaml/components/sensor/ads1115.py b/esphomeyaml/components/sensor/ads1115.py index 008ea4c291..153d55d640 100644 --- a/esphomeyaml/components/sensor/ads1115.py +++ b/esphomeyaml/components/sensor/ads1115.py @@ -45,7 +45,10 @@ def validate_mux(value): return cv.one_of(*MUX)(value) +ADS1115Sensor = sensor.sensor_ns.ADS1115Sensor + PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ADS1115Sensor), vol.Required(CONF_MULTIPLEXER): validate_mux, vol.Required(CONF_GAIN): validate_gain, cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component), diff --git a/esphomeyaml/components/sensor/bh1750.py b/esphomeyaml/components/sensor/bh1750.py index dd43d5e0de..d04041c2f8 100644 --- a/esphomeyaml/components/sensor/bh1750.py +++ b/esphomeyaml/components/sensor/bh1750.py @@ -15,8 +15,10 @@ BH1750_RESOLUTIONS = { } MakeBH1750Sensor = Application.MakeBH1750Sensor +BH1750Sensor = sensor.sensor_ns.BH1750Sensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(BH1750Sensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBH1750Sensor), vol.Optional(CONF_ADDRESS, default=0x23): cv.i2c_address, vol.Optional(CONF_RESOLUTION): vol.All(cv.positive_float, cv.one_of(*BH1750_RESOLUTIONS)), diff --git a/esphomeyaml/components/sensor/ble_rssi.py b/esphomeyaml/components/sensor/ble_rssi.py index 01bc1704bb..4240b41bd4 100644 --- a/esphomeyaml/components/sensor/ble_rssi.py +++ b/esphomeyaml/components/sensor/ble_rssi.py @@ -5,11 +5,14 @@ from esphomeyaml.components import sensor from esphomeyaml.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESP32BLETracker, \ make_address_array from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME -from esphomeyaml.helpers import get_variable +from esphomeyaml.helpers import get_variable, esphomelib_ns DEPENDENCIES = ['esp32_ble_tracker'] +ESP32BLERSSISensor = esphomelib_ns.ESP32BLERSSISensor + PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ESP32BLERSSISensor), vol.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker) })) diff --git a/esphomeyaml/components/sensor/dallas.py b/esphomeyaml/components/sensor/dallas.py index 42fc2035b8..a5706cbf5e 100644 --- a/esphomeyaml/components/sensor/dallas.py +++ b/esphomeyaml/components/sensor/dallas.py @@ -7,7 +7,10 @@ from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAM CONF_RESOLUTION from esphomeyaml.helpers import HexIntLiteral, get_variable +DallasTemperatureSensor = sensor.sensor_ns.DallasTemperatureSensor + PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(DallasTemperatureSensor), vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int, vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int, cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent), diff --git a/esphomeyaml/components/sensor/duty_cycle.py b/esphomeyaml/components/sensor/duty_cycle.py index 0bd41b9976..58cf433070 100644 --- a/esphomeyaml/components/sensor/duty_cycle.py +++ b/esphomeyaml/components/sensor/duty_cycle.py @@ -7,8 +7,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INT from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, variable MakeDutyCycleSensor = Application.MakeDutyCycleSensor +DutyCycleSensor = sensor.sensor_ns.DutyCycleSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(DutyCycleSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDutyCycleSensor), vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema, vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, diff --git a/esphomeyaml/components/sensor/esp32_hall.py b/esphomeyaml/components/sensor/esp32_hall.py index 2bdb062e8e..e86377dd39 100644 --- a/esphomeyaml/components/sensor/esp32_hall.py +++ b/esphomeyaml/components/sensor/esp32_hall.py @@ -8,8 +8,10 @@ from esphomeyaml.helpers import App, Application, variable ESP_PLATFORMS = [ESP_PLATFORM_ESP32] MakeESP32HallSensor = Application.MakeESP32HallSensor +ESP32HallSensor = sensor.sensor_ns.ESP32HallSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ESP32HallSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeESP32HallSensor), vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, })) diff --git a/esphomeyaml/components/sensor/max6675.py b/esphomeyaml/components/sensor/max6675.py index 007acbd6b4..5d2432de62 100644 --- a/esphomeyaml/components/sensor/max6675.py +++ b/esphomeyaml/components/sensor/max6675.py @@ -9,8 +9,10 @@ from esphomeyaml.const import CONF_CS_PIN, CONF_MAKE_ID, CONF_NAME, CONF_SPI_ID, from esphomeyaml.helpers import App, Application, get_variable, gpio_output_pin_expression, variable MakeMAX6675Sensor = Application.MakeMAX6675Sensor +MAX6675Sensor = sensor.sensor_ns.MAX6675Sensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(MAX6675Sensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMAX6675Sensor), cv.GenerateID(CONF_SPI_ID): cv.use_variable_id(SPIComponent), vol.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, diff --git a/esphomeyaml/components/sensor/mqtt_subscribe.py b/esphomeyaml/components/sensor/mqtt_subscribe.py index 8b8ce50317..203c2595d6 100644 --- a/esphomeyaml/components/sensor/mqtt_subscribe.py +++ b/esphomeyaml/components/sensor/mqtt_subscribe.py @@ -8,8 +8,10 @@ from esphomeyaml.helpers import App, Application, add, variable DEPENDENCIES = ['mqtt'] MakeMQTTSubscribeSensor = Application.MakeMQTTSubscribeSensor +MQTTSubscribeSensor = sensor.sensor_ns.MQTTSubscribeSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(MQTTSubscribeSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMQTTSubscribeSensor), vol.Required(CONF_TOPIC): cv.subscribe_topic, vol.Optional(CONF_QOS): cv.mqtt_qos, diff --git a/esphomeyaml/components/sensor/pulse_counter.py b/esphomeyaml/components/sensor/pulse_counter.py index 3b3200ea56..49bdfb68cb 100644 --- a/esphomeyaml/components/sensor/pulse_counter.py +++ b/esphomeyaml/components/sensor/pulse_counter.py @@ -17,6 +17,7 @@ COUNT_MODES = { COUNT_MODE_SCHEMA = vol.All(vol.Upper, cv.one_of(*COUNT_MODES)) MakePulseCounterSensor = Application.MakePulseCounterSensor +PulseCounterSensorComponent = sensor.sensor_ns.PulseCounterSensorComponent def validate_internal_filter(value): @@ -33,6 +34,7 @@ def validate_internal_filter(value): PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(PulseCounterSensorComponent), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakePulseCounterSensor), vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema, vol.Optional(CONF_COUNT_MODE): vol.Schema({ diff --git a/esphomeyaml/components/sensor/rotary_encoder.py b/esphomeyaml/components/sensor/rotary_encoder.py index 22c5552bfc..595d398bb8 100644 --- a/esphomeyaml/components/sensor/rotary_encoder.py +++ b/esphomeyaml/components/sensor/rotary_encoder.py @@ -17,8 +17,10 @@ CONF_PIN_B = 'pin_b' CONF_PIN_RESET = 'pin_reset' MakeRotaryEncoderSensor = Application.MakeRotaryEncoderSensor +RotaryEncoderSensor = sensor.sensor_ns.RotaryEncoderSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(RotaryEncoderSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRotaryEncoderSensor), vol.Required(CONF_PIN_A): pins.internal_gpio_input_pin_schema, vol.Required(CONF_PIN_B): pins.internal_gpio_input_pin_schema, diff --git a/esphomeyaml/components/sensor/template.py b/esphomeyaml/components/sensor/template.py index 8c115a9239..5f090fb5b0 100644 --- a/esphomeyaml/components/sensor/template.py +++ b/esphomeyaml/components/sensor/template.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_ from esphomeyaml.helpers import App, process_lambda, variable, Application, float_, optional, add MakeTemplateSensor = Application.MakeTemplateSensor +TemplateSensor = sensor.sensor_ns.TemplateSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TemplateSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSensor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, diff --git a/esphomeyaml/components/sensor/tsl2561.py b/esphomeyaml/components/sensor/tsl2561.py index 0f973de264..3bf94eb0ce 100644 --- a/esphomeyaml/components/sensor/tsl2561.py +++ b/esphomeyaml/components/sensor/tsl2561.py @@ -29,8 +29,10 @@ def validate_integration_time(value): MakeTSL2561Sensor = Application.MakeTSL2561Sensor +TSL2561Sensor = Application.TSL2561Sensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TSL2561Sensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTSL2561Sensor), vol.Optional(CONF_ADDRESS, default=0x39): cv.i2c_address, vol.Optional(CONF_INTEGRATION_TIME): validate_integration_time, diff --git a/esphomeyaml/components/sensor/ultrasonic.py b/esphomeyaml/components/sensor/ultrasonic.py index 75c56090ca..61794f431d 100644 --- a/esphomeyaml/components/sensor/ultrasonic.py +++ b/esphomeyaml/components/sensor/ultrasonic.py @@ -9,8 +9,10 @@ from esphomeyaml.helpers import App, Application, add, gpio_input_pin_expression gpio_output_pin_expression, variable MakeUltrasonicSensor = Application.MakeUltrasonicSensor +UltrasonicSensorComponent = sensor.sensor_ns.UltrasonicSensorComponent PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(UltrasonicSensorComponent), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeUltrasonicSensor), vol.Required(CONF_TRIGGER_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema, diff --git a/esphomeyaml/components/sensor/uptime.py b/esphomeyaml/components/sensor/uptime.py index b58e595e27..38548c1db3 100644 --- a/esphomeyaml/components/sensor/uptime.py +++ b/esphomeyaml/components/sensor/uptime.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL from esphomeyaml.helpers import App, Application, variable MakeUptimeSensor = Application.MakeUptimeSensor +UptimeSensor = sensor.sensor_ns.UptimeSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(UptimeSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeUptimeSensor), vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, })) diff --git a/esphomeyaml/components/sensor/wifi_signal.py b/esphomeyaml/components/sensor/wifi_signal.py index f9b10a0a2f..060377839e 100644 --- a/esphomeyaml/components/sensor/wifi_signal.py +++ b/esphomeyaml/components/sensor/wifi_signal.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_UPDATE_INTERVAL from esphomeyaml.helpers import App, Application, variable MakeWiFiSignalSensor = Application.MakeWiFiSignalSensor +WiFiSignalSensor = sensor.sensor_ns.WiFiSignalSensor PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(WiFiSignalSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeWiFiSignalSensor), vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, })) diff --git a/esphomeyaml/components/switch/output.py b/esphomeyaml/components/switch/output.py index 05076930b4..bc5d9b6d7e 100644 --- a/esphomeyaml/components/switch/output.py +++ b/esphomeyaml/components/switch/output.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT from esphomeyaml.helpers import App, Application, get_variable, variable MakeOutputSwitch = Application.MakeOutputSwitch +OutputSwitch = switch.switch_ns.OutputSwitch PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(OutputSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeOutputSwitch), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), })) diff --git a/esphomeyaml/components/switch/remote_transmitter.py b/esphomeyaml/components/switch/remote_transmitter.py index 9daf53c42e..2ac9ee8e75 100644 --- a/esphomeyaml/components/switch/remote_transmitter.py +++ b/esphomeyaml/components/switch/remote_transmitter.py @@ -39,6 +39,7 @@ RCSwitchTypeDTransmitter = remote_ns.RCSwitchTypeDTransmitter validate_raw_data = [vol.Any(vol.Coerce(int), cv.time_period_microseconds)] PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(RemoteTransmitter), vol.Optional(CONF_LG): vol.Schema({ vol.Required(CONF_DATA): cv.hex_uint32_t, vol.Optional(CONF_NBITS, default=28): vol.All(vol.Coerce(int), cv.one_of(28, 32)), diff --git a/esphomeyaml/components/switch/restart.py b/esphomeyaml/components/switch/restart.py index 73f9182429..90a8f1de3f 100644 --- a/esphomeyaml/components/switch/restart.py +++ b/esphomeyaml/components/switch/restart.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME from esphomeyaml.helpers import App, Application, variable MakeRestartSwitch = Application.MakeRestartSwitch +RestartSwitch = switch.switch_ns.RestartSwitch PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(RestartSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRestartSwitch), vol.Optional(CONF_INVERTED): cv.invalid("Restart switches do not support inverted mode!"), })) diff --git a/esphomeyaml/components/switch/shutdown.py b/esphomeyaml/components/switch/shutdown.py index 6116136ca4..330750eb0c 100644 --- a/esphomeyaml/components/switch/shutdown.py +++ b/esphomeyaml/components/switch/shutdown.py @@ -6,8 +6,10 @@ from esphomeyaml.const import CONF_INVERTED, CONF_MAKE_ID, CONF_NAME from esphomeyaml.helpers import App, Application, variable MakeShutdownSwitch = Application.MakeShutdownSwitch +ShutdownSwitch = switch.switch_ns.ShutdownSwitch PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(ShutdownSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeShutdownSwitch), vol.Optional(CONF_INVERTED): cv.invalid("Shutdown switches do not support inverted mode!"), })) diff --git a/esphomeyaml/components/switch/uart.py b/esphomeyaml/components/switch/uart.py index e64f05f1ab..dccfc75deb 100644 --- a/esphomeyaml/components/switch/uart.py +++ b/esphomeyaml/components/switch/uart.py @@ -10,6 +10,7 @@ from esphomeyaml.helpers import App, Application, ArrayInitializer, get_variable DEPENDENCIES = ['uart'] MakeUARTSwitch = Application.MakeUARTSwitch +UARTSwitch = switch.switch_ns.UARTSwitch def validate_data(value): @@ -23,6 +24,7 @@ def validate_data(value): PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(UARTSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeUARTSwitch), cv.GenerateID(CONF_UART_ID): cv.use_variable_id(UARTComponent), vol.Required(CONF_DATA): validate_data, diff --git a/esphomeyaml/components/text_sensor/mqtt_subscribe.py b/esphomeyaml/components/text_sensor/mqtt_subscribe.py index a4ba9705c1..7b2ea32449 100644 --- a/esphomeyaml/components/text_sensor/mqtt_subscribe.py +++ b/esphomeyaml/components/text_sensor/mqtt_subscribe.py @@ -8,8 +8,10 @@ from esphomeyaml.helpers import App, Application, add, variable DEPENDENCIES = ['mqtt'] MakeMQTTSubscribeTextSensor = Application.MakeMQTTSubscribeTextSensor +MQTTSubscribeTextSensor = text_sensor.text_sensor_ns.MQTTSubscribeTextSensor PLATFORM_SCHEMA = cv.nameable(text_sensor.TEXT_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(MQTTSubscribeTextSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMQTTSubscribeTextSensor), vol.Required(CONF_TOPIC): cv.subscribe_topic, vol.Optional(CONF_QOS): cv.mqtt_qos, diff --git a/esphomeyaml/components/text_sensor/template.py b/esphomeyaml/components/text_sensor/template.py index 3441ee5e6f..4a15ce967d 100644 --- a/esphomeyaml/components/text_sensor/template.py +++ b/esphomeyaml/components/text_sensor/template.py @@ -7,8 +7,10 @@ from esphomeyaml.helpers import App, Application, add, optional, process_lambda, variable MakeTemplateTextSensor = Application.MakeTemplateTextSensor +TemplateTextSensor = text_sensor.text_sensor_ns.TemplateTextSensor PLATFORM_SCHEMA = cv.nameable(text_sensor.TEXT_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TemplateTextSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateTextSensor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, diff --git a/esphomeyaml/components/text_sensor/version.py b/esphomeyaml/components/text_sensor/version.py index 7e01302924..6eb8396000 100644 --- a/esphomeyaml/components/text_sensor/version.py +++ b/esphomeyaml/components/text_sensor/version.py @@ -4,8 +4,10 @@ from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME from esphomeyaml.helpers import App, Application, variable MakeVersionTextSensor = Application.MakeVersionTextSensor +VersionTextSensor = text_sensor.text_sensor_ns.VersionTextSensor PLATFORM_SCHEMA = cv.nameable(text_sensor.TEXT_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(VersionTextSensor), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeVersionTextSensor), })) diff --git a/esphomeyaml/writer.py b/esphomeyaml/writer.py index c045fade11..4f1900c662 100644 --- a/esphomeyaml/writer.py +++ b/esphomeyaml/writer.py @@ -103,6 +103,7 @@ def get_ini_content(config, path): build_flags |= get_build_flags(config, 'BUILD_FLAGS') build_flags.add(u"-DESPHOMEYAML_USE") build_flags.add("-Wno-unused-variable") + build_flags.add("-Wno-unused-but-set-variable") build_flags |= get_build_flags(config, 'required_build_flags') build_flags |= get_build_flags(config, 'REQUIRED_BUILD_FLAGS') From e3094d9689bc86db2b93c1da8071e2bfef5ad516 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 14:27:12 +0100 Subject: [PATCH 04/11] OTA Send back acknowledgement --- esphomeyaml/espota2.py | 1 + 1 file changed, 1 insertion(+) diff --git a/esphomeyaml/espota2.py b/esphomeyaml/espota2.py index 5eaaccd669..bb9963d8ff 100755 --- a/esphomeyaml/espota2.py +++ b/esphomeyaml/espota2.py @@ -200,6 +200,7 @@ def perform_ota(sock, password, file_handle, filename): receive_exactly(sock, 1, 'receive OK', RESPONSE_RECEIVE_OK) receive_exactly(sock, 1, 'Update end', RESPONSE_UPDATE_END_OK) + send_check(sock, RESPONSE_OK, 'end acknowledgement') _LOGGER.info("OTA successful") From 3ec931ffa49a2e93681af6fb416535030efc4b3c Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:05:50 +0100 Subject: [PATCH 05/11] Add restore state option to template switch (#222) * Add restore state option to template switch * Add test --- esphomeyaml/components/switch/template.py | 8 +++++++- esphomeyaml/const.py | 1 + tests/test1.yaml | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/esphomeyaml/components/switch/template.py b/esphomeyaml/components/switch/template.py index 0d7f967322..121bbeff1c 100644 --- a/esphomeyaml/components/switch/template.py +++ b/esphomeyaml/components/switch/template.py @@ -4,18 +4,21 @@ import esphomeyaml.config_validation as cv from esphomeyaml import automation from esphomeyaml.components import switch from esphomeyaml.const import CONF_LAMBDA, CONF_MAKE_ID, CONF_NAME, CONF_TURN_OFF_ACTION, \ - CONF_TURN_ON_ACTION, CONF_OPTIMISTIC + CONF_TURN_ON_ACTION, CONF_OPTIMISTIC, CONF_RESTORE_STATE from esphomeyaml.helpers import App, Application, process_lambda, variable, NoArg, add, bool_, \ optional MakeTemplateSwitch = Application.MakeTemplateSwitch +TemplateSwitch = switch.switch_ns.TemplateSwitch PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TemplateSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSwitch), vol.Optional(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_OPTIMISTIC): cv.boolean, vol.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(single=True), vol.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(single=True), + vol.Optional(CONF_RESTORE_STATE): cv.boolean, }), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) @@ -40,6 +43,9 @@ def to_code(config): if CONF_OPTIMISTIC in config: add(make.Ptemplate_.set_optimistic(config[CONF_OPTIMISTIC])) + if CONF_RESTORE_STATE in config: + add(make.Ptemplate_.set_restore_state(config[CONF_RESTORE_STATE])) + BUILD_FLAGS = '-DUSE_TEMPLATE_SWITCH' diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index e289bd10a2..0eacce7392 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -359,6 +359,7 @@ CONF_STEP_PIN = 'step_pin' CONF_DIR_PIN = 'dir_pin' CONF_SLEEP_PIN = 'sleep_pin' CONF_SEND_FIRST_AT = 'send_first_at' +CONF_RESTORE_STATE = 'restore_state' ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' diff --git a/tests/test1.yaml b/tests/test1.yaml index 9d7ca7cb8a..ee8073aa82 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -806,6 +806,7 @@ switch: level: !lambda 'return 0.5;' turn_off_action: - switch.turn_on: living_room_lights_off + restore_state: False - platform: restart name: "Living Room Restart" - platform: shutdown @@ -832,6 +833,7 @@ switch: // Switch is OFF, do something else here } optimistic: true + restore_state: True - platform: uart name: "UART String Output" data: 'DataToSend' From a9e799cb06b0c57198a94948d58749bdf7fe473b Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:08:16 +0100 Subject: [PATCH 06/11] 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) From 9fd4076ab878d4adfa573d993ca7f0a3b3504d69 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:08:35 +0100 Subject: [PATCH 07/11] Revert Add power on value to GPIO switch (#223) * Revert Add power on value to GPIO switch * Fix tests * Fix --- esphomeyaml/components/switch/gpio.py | 12 +++++------- tests/test1.yaml | 1 - 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/esphomeyaml/components/switch/gpio.py b/esphomeyaml/components/switch/gpio.py index dd58f4bc6e..6ad76e9bd6 100644 --- a/esphomeyaml/components/switch/gpio.py +++ b/esphomeyaml/components/switch/gpio.py @@ -1,17 +1,18 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv from esphomeyaml import pins from esphomeyaml.components import switch -from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_POWER_ON_VALUE -from esphomeyaml.helpers import App, Application, gpio_output_pin_expression, variable, add +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN +from esphomeyaml.helpers import App, Application, gpio_output_pin_expression, variable MakeGPIOSwitch = Application.MakeGPIOSwitch +GPIOSwitch = switch.switch_ns.GPIOSwitch PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(GPIOSwitch), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOSwitch), vol.Required(CONF_PIN): pins.gpio_output_pin_schema, - vol.Optional(CONF_POWER_ON_VALUE): cv.boolean, })) @@ -22,9 +23,6 @@ def to_code(config): rhs = App.make_gpio_switch(config[CONF_NAME], pin) gpio = variable(config[CONF_MAKE_ID], rhs) - if CONF_POWER_ON_VALUE in config: - add(gpio.Pswitch_.set_power_on_value(config[CONF_POWER_ON_VALUE])) - switch.setup_switch(gpio.Pswitch_, gpio.Pmqtt, config) diff --git a/tests/test1.yaml b/tests/test1.yaml index ee8073aa82..caefcee0fe 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -716,7 +716,6 @@ switch: icon: "mdi:restart" inverted: True command_topic: custom_command_topic - power_on_value: True - platform: remote_transmitter name: "Panasonic TV Off" nec: From 0ad61f4a9531f2cbe95cd6bb65b70f3ef700d4d9 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:18:04 +0100 Subject: [PATCH 08/11] Add binary sensor multi click trigger (#226) --- .../components/binary_sensor/__init__.py | 132 +++++++++++++++++- esphomeyaml/config_validation.py | 11 +- esphomeyaml/const.py | 4 + tests/test1.yaml | 25 ++++ 4 files changed, 163 insertions(+), 9 deletions(-) diff --git a/esphomeyaml/components/binary_sensor/__init__.py b/esphomeyaml/components/binary_sensor/__init__.py index 82da0a9ce9..232f6a8dbc 100644 --- a/esphomeyaml/components/binary_sensor/__init__.py +++ b/esphomeyaml/components/binary_sensor/__init__.py @@ -1,14 +1,15 @@ import voluptuous as vol +from esphomeyaml import automation, core from esphomeyaml.components import mqtt import esphomeyaml.config_validation as cv -from esphomeyaml import automation -from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, CONF_INTERNAL, CONF_INVERTED, \ - CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, CONF_ON_DOUBLE_CLICK, \ - CONF_ON_PRESS, CONF_ON_RELEASE, CONF_TRIGGER_ID, CONF_FILTERS, CONF_INVERT, CONF_DELAYED_ON, \ - CONF_DELAYED_OFF, CONF_LAMBDA, CONF_HEARTBEAT -from esphomeyaml.helpers import App, NoArg, Pvariable, add, add_job, esphomelib_ns, \ - setup_mqtt_component, bool_, process_lambda, ArrayInitializer +from esphomeyaml.const import CONF_DELAYED_OFF, CONF_DELAYED_ON, CONF_DEVICE_CLASS, CONF_FILTERS, \ + CONF_HEARTBEAT, CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERT, CONF_INVERTED, \ + CONF_LAMBDA, CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, \ + CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_STATE, \ + CONF_TIMING, CONF_TRIGGER_ID +from esphomeyaml.helpers import App, ArrayInitializer, NoArg, Pvariable, StructInitializer, add, \ + add_job, bool_, esphomelib_ns, process_lambda, setup_mqtt_component DEVICE_CLASSES = [ '', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas', @@ -26,6 +27,8 @@ PressTrigger = binary_sensor_ns.PressTrigger ReleaseTrigger = binary_sensor_ns.ReleaseTrigger ClickTrigger = binary_sensor_ns.ClickTrigger DoubleClickTrigger = binary_sensor_ns.DoubleClickTrigger +MultiClickTrigger = binary_sensor_ns.MultiClickTrigger +MultiClickTriggerEvent = binary_sensor_ns.MultiClickTriggerEvent BinarySensor = binary_sensor_ns.BinarySensor InvertFilter = binary_sensor_ns.InvertFilter LambdaFilter = binary_sensor_ns.LambdaFilter @@ -44,6 +47,99 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ vol.Optional(CONF_LAMBDA): cv.lambda_, }, cv.has_exactly_one_key(*FILTER_KEYS))]) +MULTI_CLICK_TIMING_SCHEMA = vol.Schema({ + vol.Optional(CONF_STATE): cv.boolean, + vol.Optional(CONF_MIN_LENGTH): cv.positive_time_period_milliseconds, + vol.Optional(CONF_MAX_LENGTH): cv.positive_time_period_milliseconds, +}) + + +def parse_multi_click_timing_str(value): + if not isinstance(value, basestring): + return value + + parts = value.lower().split(' ') + if len(parts) != 5: + raise vol.Invalid("Multi click timing grammar consists of exactly 5 words, not {}" + "".format(len(parts))) + try: + state = cv.boolean(parts[0]) + except vol.Invalid: + raise vol.Invalid(u"First word must either be ON or OFF, not {}".format(parts[0])) + + if parts[1] != 'for': + raise vol.Invalid(u"Second word must be 'for', got {}".format(parts[1])) + + if parts[2] == 'at': + if parts[3] == 'least': + key = CONF_MIN_LENGTH + elif parts[3] == 'most': + key = CONF_MAX_LENGTH + else: + raise vol.Invalid(u"Third word after at must either be 'least' or 'most', got {}" + u"".format(parts[3])) + try: + length = cv.positive_time_period_milliseconds(parts[4]) + except vol.Invalid as err: + raise vol.Invalid(u"Multi Click Grammar Parsing length failed: {}".format(err)) + return { + CONF_STATE: state, + key: str(length) + } + + if parts[3] != 'to': + raise vol.Invalid("Multi click grammar: 4th word must be 'to'") + + try: + min_length = cv.positive_time_period_milliseconds(parts[2]) + except vol.Invalid as err: + raise vol.Invalid(u"Multi Click Grammar Parsing minimum length failed: {}".format(err)) + + try: + max_length = cv.positive_time_period_milliseconds(parts[4]) + except vol.Invalid as err: + raise vol.Invalid(u"Multi Click Grammar Parsing minimum length failed: {}".format(err)) + + return { + CONF_STATE: state, + CONF_MIN_LENGTH: str(min_length), + CONF_MAX_LENGTH: str(max_length) + } + + +def validate_multi_click_timing(value): + if not isinstance(value, list): + raise vol.Invalid("Timing option must be a *list* of times!") + timings = [] + state = None + for i, v_ in enumerate(value): + v_ = MULTI_CLICK_TIMING_SCHEMA(v_) + min_length = v_.get(CONF_MIN_LENGTH) + max_length = v_.get(CONF_MAX_LENGTH) + if min_length is None and max_length is None: + raise vol.Invalid("At least one of min_length and max_length is required!") + if min_length is None and max_length is not None: + min_length = core.TimePeriodMilliseconds(milliseconds=0) + + new_state = v_.get(CONF_STATE, not state) + if new_state == state: + raise vol.Invalid("Timings must have alternating state. Indices {} and {} have " + "the same state {}".format(i, i + 1, state)) + if max_length is not None and max_length < min_length: + raise vol.Invalid("Max length ({}) must be larger than min length ({})." + "".format(max_length, min_length)) + + state = new_state + tim = { + CONF_STATE: new_state, + CONF_MIN_LENGTH: min_length, + } + if max_length is not None: + tim[CONF_MAX_LENGTH] = max_length + timings.append(tim) + return timings + + BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTBinarySensorComponent), cv.GenerateID(): cv.declare_variable_id(BinarySensor), @@ -66,6 +162,12 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ vol.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, vol.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, }), + vol.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation({ + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MultiClickTrigger), + vol.Required(CONF_TIMING): vol.All([parse_multi_click_timing_str], + validate_multi_click_timing), + vol.Optional(CONF_INVALID_COOLDOWN): cv.positive_time_period_milliseconds, + }), vol.Optional(CONF_INVERTED): cv.invalid( "The inverted binary_sensor property has been replaced by the " @@ -137,6 +239,22 @@ def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config): trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) automation.build_automation(trigger, NoArg, conf) + for conf in config.get(CONF_ON_MULTI_CLICK, []): + timings = [] + for tim in conf[CONF_TIMING]: + timings.append(StructInitializer( + MultiClickTriggerEvent, + ('state', tim[CONF_STATE]), + ('min_length', tim[CONF_MIN_LENGTH]), + ('max_length', tim.get(CONF_MAX_LENGTH, 4294967294)), + )) + timings = ArrayInitializer(*timings, multiline=False) + rhs = App.register_component(binary_sensor_var.make_multi_click_trigger(timings)) + trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) + if CONF_INVALID_COOLDOWN in conf: + add(trigger.set_invalid_cooldown(conf[CONF_INVALID_COOLDOWN])) + automation.build_automation(trigger, NoArg, conf) + setup_mqtt_component(mqtt_var, config) diff --git a/esphomeyaml/config_validation.py b/esphomeyaml/config_validation.py index 09a30dab6b..c521de4d09 100644 --- a/esphomeyaml/config_validation.py +++ b/esphomeyaml/config_validation.py @@ -296,7 +296,8 @@ def time_period_str_colon(value): def time_period_str_unit(value): """Validate and transform time period with time unit and integer value.""" if isinstance(value, int): - value = str(value) + raise vol.Invalid("Don't know what '{}' means as it has no time *unit*! Did you mean " + "'{}s'?".format(value, value)) elif not isinstance(value, (str, unicode)): raise vol.Invalid("Expected string for time period with unit.") @@ -555,8 +556,14 @@ i2c_address = hex_uint8_t def percentage(value): - if isinstance(value, (str, unicode)) and value.endswith('%'): + has_percent_sign = isinstance(value, (str, unicode)) and value.endswith('%') + if has_percent_sign: value = float(value[:-1].rstrip()) / 100.0 + if value > 1: + msg = "Percentage must not be higher than 100%." + if not has_percent_sign: + msg += " Please don't put to put a percent sign after the number!" + raise vol.Invalid(msg) return zero_to_one_float(value) diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index 0eacce7392..f487a819d4 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -222,6 +222,7 @@ CONF_ON_PRESS = 'on_press' CONF_ON_RELEASE = 'on_release' CONF_ON_CLICK = 'on_click' CONF_ON_DOUBLE_CLICK = 'on_double_click' +CONF_ON_MULTI_CLICK = 'on_multi_click' CONF_MIN_LENGTH = 'min_length' CONF_MAX_LENGTH = 'max_length' CONF_ON_VALUE = 'on_value' @@ -360,6 +361,9 @@ CONF_DIR_PIN = 'dir_pin' CONF_SLEEP_PIN = 'sleep_pin' CONF_SEND_FIRST_AT = 'send_first_at' CONF_RESTORE_STATE = 'restore_state' +CONF_TIMING = 'timing' +CONF_INVALID_COOLDOWN = 'invalid_cooldown' + ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' diff --git a/tests/test1.yaml b/tests/test1.yaml index caefcee0fe..6b75f7db26 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -498,6 +498,31 @@ binary_sensor: - then: - lambda: >- ESP_LOGD("main", "Double Clicked"); + on_multi_click: + - timing: + - ON for at most 1s + - OFF for at most 1s + - ON for at most 1s + - OFF for at least 0.2s + then: + - logger.log: + format: "Multi Clicked TWO" + level: warn + - timing: + - OFF for 1s to 2s + - ON for 1s to 2s + - OFF for at least 0.5s + then: + - logger.log: + format: "Multi Clicked LONG SINGLE" + level: warn + - timing: + - ON for at most 1s + - OFF for at least 0.5s + then: + - logger.log: + format: "Multi Clicked SINGLE" + level: warn id: binary_sensor1 - platform: status name: "Living Room Status" From 8203b8fcd36379aa63a30ad6bfc0997291279041 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 9 Nov 2018 20:27:19 +0100 Subject: [PATCH 09/11] Add total daily energy sensor (#220) * Add total daily energy sensor * Add test --- .../components/sensor/total_daily_energy.py | 37 +++++++++++++++++++ esphomeyaml/const.py | 1 + tests/test1.yaml | 4 ++ 3 files changed, 42 insertions(+) create mode 100644 esphomeyaml/components/sensor/total_daily_energy.py diff --git a/esphomeyaml/components/sensor/total_daily_energy.py b/esphomeyaml/components/sensor/total_daily_energy.py new file mode 100644 index 0000000000..644aa7d656 --- /dev/null +++ b/esphomeyaml/components/sensor/total_daily_energy.py @@ -0,0 +1,37 @@ +import voluptuous as vol + +from esphomeyaml.components import sensor +from esphomeyaml.components.time import sntp +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_TIME_ID +from esphomeyaml.helpers import App, Application, get_variable, variable + +DEPENDENCIES = ['time'] + +CONF_POWER_ID = 'power_id' +MakeTotalDailyEnergySensor = Application.MakeTotalDailyEnergySensor +TotalDailyEnergy = sensor.sensor_ns.TotalDailyEnergy + +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(TotalDailyEnergy), + cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTotalDailyEnergySensor), + cv.GenerateID(CONF_TIME_ID): cv.use_variable_id(sntp.SNTPComponent), + vol.Required(CONF_POWER_ID): cv.use_variable_id(None), +})) + + +def to_code(config): + for time in get_variable(config[CONF_TIME_ID]): + yield + for sens in get_variable(config[CONF_POWER_ID]): + yield + rhs = App.make_total_daily_energy_sensor(config[CONF_NAME], time, sens) + make = variable(config[CONF_MAKE_ID], rhs) + sensor.setup_sensor(make.Ptotal_energy, make.Pmqtt, config) + + +BUILD_FLAGS = '-DUSE_TOTAL_DAILY_ENERGY_SENSOR' + + +def to_hass_config(data, config): + return sensor.core_to_hass_config(data, config) diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index f487a819d4..337c1f8c96 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -360,6 +360,7 @@ CONF_STEP_PIN = 'step_pin' CONF_DIR_PIN = 'dir_pin' CONF_SLEEP_PIN = 'sleep_pin' CONF_SEND_FIRST_AT = 'send_first_at' +CONF_TIME_ID = 'time_id' CONF_RESTORE_STATE = 'restore_state' CONF_TIMING = 'timing' CONF_INVALID_COOLDOWN = 'invalid_cooldown' diff --git a/tests/test1.yaml b/tests/test1.yaml index 6b75f7db26..4ae2e3c665 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -310,10 +310,14 @@ sensor: name: "HLW8012 Voltage" power: name: "HLW8012 Power" + id: hlw8012_power update_interval: 15s current_resistor: 0.001 ohm voltage_divider: 2351 change_mode_every: 16 + - platform: total_daily_energy + power_id: hlw8012_power + name: "HLW8012 Total Daily Energy" - platform: hmc5883l address: 0x68 field_strength_x: From 04dc848620430bb5705e6bf770b953c6e5b109ed Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sat, 10 Nov 2018 11:45:38 +0100 Subject: [PATCH 10/11] Improve OTAv2 error messages --- esphomeyaml/espota2.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/esphomeyaml/espota2.py b/esphomeyaml/espota2.py index bb9963d8ff..92a7964ff4 100755 --- a/esphomeyaml/espota2.py +++ b/esphomeyaml/espota2.py @@ -3,6 +3,7 @@ import logging import random import socket import sys +import time from esphomeyaml.core import ESPHomeYAMLError @@ -75,9 +76,9 @@ def receive_exactly(sock, amount, msg, expect, decode=True): try: check_error(data, expect) - except OTAError: + except OTAError as err: sock.close() - raise + raise OTAError("Error {}: {}".format(msg, err)) while len(data) < amount: try: @@ -201,6 +202,7 @@ def perform_ota(sock, password, file_handle, filename): receive_exactly(sock, 1, 'receive OK', RESPONSE_RECEIVE_OK) receive_exactly(sock, 1, 'Update end', RESPONSE_UPDATE_END_OK) send_check(sock, RESPONSE_OK, 'end acknowledgement') + time.sleep(0.25) _LOGGER.info("OTA successful") From 58f4fa53d03d1b336c336a430aa2817493a416b8 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sat, 10 Nov 2018 14:07:11 +0100 Subject: [PATCH 11/11] Make Switch not inherit from Component --- esphomeyaml/components/switch/remote_transmitter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphomeyaml/components/switch/remote_transmitter.py b/esphomeyaml/components/switch/remote_transmitter.py index 2ac9ee8e75..95e56e1549 100644 --- a/esphomeyaml/components/switch/remote_transmitter.py +++ b/esphomeyaml/components/switch/remote_transmitter.py @@ -131,7 +131,7 @@ def to_code(config): remote = None for remote in get_variable(config[CONF_REMOTE_TRANSMITTER_ID]): yield - rhs = App.register_component(transmitter_base(config)) + rhs = transmitter_base(config) transmitter = Pvariable(config[CONF_TRANSMITTER_ID], rhs) if CONF_REPEAT in config: