From 6aa449115fc41179d37ae0e8528e9bd42868b1a2 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Mon, 11 Jun 2018 10:01:54 +0200 Subject: [PATCH] Add internal modifier. Fixes ottowinter/esphomelib#77 --- esphomeyaml/__main__.py | 8 +- .../components/binary_sensor/__init__.py | 6 +- .../components/binary_sensor/esp32_ble.py | 26 +---- .../components/binary_sensor/esp32_touch.py | 4 +- esphomeyaml/components/binary_sensor/gpio.py | 4 +- .../components/binary_sensor/status.py | 4 +- .../components/binary_sensor/template.py | 4 +- esphomeyaml/components/cover/__init__.py | 8 +- esphomeyaml/components/cover/template.py | 4 +- esphomeyaml/components/fan/__init__.py | 7 +- esphomeyaml/components/fan/binary.py | 4 +- esphomeyaml/components/fan/speed.py | 4 +- esphomeyaml/components/i2c.py | 7 +- esphomeyaml/components/ir_transmitter.py | 28 +---- esphomeyaml/components/light/__init__.py | 6 +- esphomeyaml/components/light/binary.py | 4 +- .../components/light/fastled_clockless.py | 4 +- esphomeyaml/components/light/fastled_spi.py | 4 +- esphomeyaml/components/light/monochromatic.py | 4 +- esphomeyaml/components/light/rgb.py | 4 +- esphomeyaml/components/light/rgbw.py | 4 +- esphomeyaml/components/logger.py | 2 +- esphomeyaml/components/output/__init__.py | 4 + esphomeyaml/components/output/esp8266_pwm.py | 4 +- esphomeyaml/components/output/gpio.py | 4 +- esphomeyaml/components/output/ledc.py | 4 +- esphomeyaml/components/output/pca9685.py | 4 +- esphomeyaml/components/remote_receiver.py | 51 +++++++++ esphomeyaml/components/remote_transmitter.py | 31 ++++++ esphomeyaml/components/sensor/__init__.py | 9 +- esphomeyaml/components/sensor/adc.py | 4 +- esphomeyaml/components/sensor/ads1115.py | 4 +- esphomeyaml/components/sensor/bh1750.py | 4 +- esphomeyaml/components/sensor/bme280.py | 6 +- esphomeyaml/components/sensor/bme680.py | 8 +- esphomeyaml/components/sensor/bmp085.py | 4 +- esphomeyaml/components/sensor/dallas.py | 4 +- esphomeyaml/components/sensor/dht.py | 4 +- esphomeyaml/components/sensor/dht12.py | 4 +- esphomeyaml/components/sensor/duty_cycle.py | 28 +++++ esphomeyaml/components/sensor/esp32_hall.py | 4 +- esphomeyaml/components/sensor/hdc1080.py | 4 +- esphomeyaml/components/sensor/htu21d.py | 4 +- esphomeyaml/components/sensor/max6675.py | 4 +- esphomeyaml/components/sensor/mpu6050.py | 14 +-- .../components/sensor/pulse_counter.py | 62 ++++++----- .../components/sensor/rotary_encoder.py | 4 +- esphomeyaml/components/sensor/sht3xd.py | 4 +- esphomeyaml/components/sensor/template.py | 4 +- esphomeyaml/components/sensor/tsl2561.py | 4 +- esphomeyaml/components/sensor/ultrasonic.py | 4 +- esphomeyaml/components/sensor/wifi_signal.py | 4 +- esphomeyaml/components/switch/__init__.py | 6 +- esphomeyaml/components/switch/gpio.py | 4 +- .../components/switch/ir_transmitter.py | 104 ------------------ esphomeyaml/components/switch/output.py | 4 +- .../components/switch/remote_transmitter.py | 98 +++++++++++++++++ esphomeyaml/components/switch/restart.py | 4 +- esphomeyaml/components/switch/shutdown.py | 4 +- esphomeyaml/components/switch/template.py | 4 +- esphomeyaml/components/wifi.py | 91 ++++++++++----- esphomeyaml/config.py | 2 +- esphomeyaml/config_validation.py | 64 ++++++++++- esphomeyaml/const.py | 8 +- esphomeyaml/core.py | 6 + 65 files changed, 530 insertions(+), 316 deletions(-) create mode 100644 esphomeyaml/components/remote_receiver.py create mode 100644 esphomeyaml/components/remote_transmitter.py create mode 100644 esphomeyaml/components/sensor/duty_cycle.py delete mode 100644 esphomeyaml/components/switch/ir_transmitter.py create mode 100644 esphomeyaml/components/switch/remote_transmitter.py diff --git a/esphomeyaml/__main__.py b/esphomeyaml/__main__.py index 6c288b291c..c2cd2aa3f3 100644 --- a/esphomeyaml/__main__.py +++ b/esphomeyaml/__main__.py @@ -10,7 +10,8 @@ from datetime import datetime from esphomeyaml import const, core, mqtt, wizard, writer, yaml_util from esphomeyaml.config import core_to_code, get_component, iter_components, read_config from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, CONF_HOSTNAME, \ - CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, ESP_PLATFORM_ESP8266 + CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_WIFI, ESP_PLATFORM_ESP8266, \ + CONF_NETWORKS from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, _EXPRESSIONS, add, \ add_job, color, flush_tasks, indent, quote, statement @@ -160,8 +161,9 @@ def compile_program(args, config): def get_upload_host(config): - if CONF_MANUAL_IP in config[CONF_WIFI]: - host = str(config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP]) + has_networks = bool(config[CONF_WIFI].get(CONF_NETWORKS)) + if has_networks and CONF_MANUAL_IP in config[CONF_WIFI][CONF_NETWORKS][0]: + host = str(config[CONF_WIFI][CONF_NETWORKS][0][CONF_MANUAL_IP][CONF_STATIC_IP]) elif CONF_HOSTNAME in config[CONF_WIFI]: host = config[CONF_WIFI][CONF_HOSTNAME] + config[CONF_WIFI][CONF_DOMAIN] else: diff --git a/esphomeyaml/components/binary_sensor/__init__.py b/esphomeyaml/components/binary_sensor/__init__.py index 04be11d173..226eb70ee0 100644 --- a/esphomeyaml/components/binary_sensor/__init__.py +++ b/esphomeyaml/components/binary_sensor/__init__.py @@ -4,7 +4,7 @@ import esphomeyaml.config_validation as cv from esphomeyaml import automation from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_ID, 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_ON_RELEASE, CONF_TRIGGER_ID, CONF_INTERNAL from esphomeyaml.helpers import App, NoArg, Pvariable, add, esphomelib_ns, setup_mqtt_component, \ add_job @@ -51,8 +51,12 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ })]), }) +BINARY_SENSOR_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_SENSOR_SCHEMA.schema) + def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(binary_sensor_var.set_internal(CONF_INTERNAL)) if CONF_DEVICE_CLASS in config: add(binary_sensor_var.set_device_class(config[CONF_DEVICE_CLASS])) if CONF_INVERTED in config: diff --git a/esphomeyaml/components/binary_sensor/esp32_ble.py b/esphomeyaml/components/binary_sensor/esp32_ble.py index d080a96dfe..9fce2f042a 100644 --- a/esphomeyaml/components/binary_sensor/esp32_ble.py +++ b/esphomeyaml/components/binary_sensor/esp32_ble.py @@ -4,7 +4,7 @@ import esphomeyaml.config_validation as cv from esphomeyaml.components import binary_sensor from esphomeyaml.components.esp32_ble import ESP32BLETracker from esphomeyaml.const import CONF_MAC_ADDRESS, CONF_NAME, ESP_PLATFORM_ESP32 -from esphomeyaml.core import HexInt, MACAddress +from esphomeyaml.core import HexInt from esphomeyaml.helpers import ArrayInitializer, get_variable ESP_PLATFORMS = [ESP_PLATFORM_ESP32] @@ -12,28 +12,10 @@ DEPENDENCIES = ['esp32_ble'] CONF_ESP32_BLE_ID = 'esp32_ble_id' - -def validate_mac(value): - value = cv.string_strict(value) - parts = value.split(':') - if len(parts) != 6: - raise vol.Invalid("MAC Address must consist of 6 : (colon) separated parts") - parts_int = [] - if any(len(part) != 2 for part in parts): - raise vol.Invalid("MAC Address must be format XX:XX:XX:XX:XX:XX") - for part in parts: - try: - parts_int.append(int(part, 16)) - except ValueError: - raise vol.Invalid("MAC Address parts must be hexadecimal values from 00 to FF") - - return MACAddress(*parts_int) - - -PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ - vol.Required(CONF_MAC_ADDRESS): validate_mac, +PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ + vol.Required(CONF_MAC_ADDRESS): cv.mac_address, cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker) -}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/binary_sensor/esp32_touch.py b/esphomeyaml/components/binary_sensor/esp32_touch.py index 922467cc1c..c22f6150da 100644 --- a/esphomeyaml/components/binary_sensor/esp32_touch.py +++ b/esphomeyaml/components/binary_sensor/esp32_touch.py @@ -34,11 +34,11 @@ def validate_touch_pad(value): return value -PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ 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), -}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/binary_sensor/gpio.py b/esphomeyaml/components/binary_sensor/gpio.py index 478e461d8d..4bca5fd329 100644 --- a/esphomeyaml/components/binary_sensor/gpio.py +++ b/esphomeyaml/components/binary_sensor/gpio.py @@ -8,10 +8,10 @@ from esphomeyaml.helpers import App, gpio_input_pin_expression, variable, Applic MakeGPIOBinarySensor = Application.MakeGPIOBinarySensor -PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOBinarySensor), vol.Required(CONF_PIN): pins.gpio_input_pin_schema -}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/binary_sensor/status.py b/esphomeyaml/components/binary_sensor/status.py index 82548aa46f..fb3169217a 100644 --- a/esphomeyaml/components/binary_sensor/status.py +++ b/esphomeyaml/components/binary_sensor/status.py @@ -7,9 +7,9 @@ DEPENDENCIES = ['mqtt'] MakeStatusBinarySensor = Application.MakeStatusBinarySensor -PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeStatusBinarySensor), -}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/binary_sensor/template.py b/esphomeyaml/components/binary_sensor/template.py index 29e5e7a8ad..7838a0f4b3 100644 --- a/esphomeyaml/components/binary_sensor/template.py +++ b/esphomeyaml/components/binary_sensor/template.py @@ -7,10 +7,10 @@ from esphomeyaml.helpers import App, Application, process_lambda, variable, opti MakeTemplateBinarySensor = Application.MakeTemplateBinarySensor -PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateBinarySensor), vol.Required(CONF_LAMBDA): cv.lambda_, -}).extend(binary_sensor.BINARY_SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/cover/__init__.py b/esphomeyaml/components/cover/__init__.py index a33b1cace5..f258c0b2b7 100644 --- a/esphomeyaml/components/cover/__init__.py +++ b/esphomeyaml/components/cover/__init__.py @@ -1,6 +1,6 @@ import esphomeyaml.config_validation as cv -from esphomeyaml.const import CONF_ID, CONF_MQTT_ID -from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component +from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_INTERNAL +from esphomeyaml.helpers import Pvariable, esphomelib_ns, setup_mqtt_component, add PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ @@ -21,8 +21,12 @@ COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTCoverComponent), }) +COVER_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(COVER_SCHEMA.schema) + def setup_cover_core_(cover_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(cover_var.set_internal(config[CONF_INTERNAL])) setup_mqtt_component(mqtt_var, config) diff --git a/esphomeyaml/components/cover/template.py b/esphomeyaml/components/cover/template.py index f771f89074..1f6c0643f5 100644 --- a/esphomeyaml/components/cover/template.py +++ b/esphomeyaml/components/cover/template.py @@ -9,14 +9,14 @@ from esphomeyaml.helpers import App, Application, NoArg, add, process_lambda, va MakeTemplateCover = Application.MakeTemplateCover -PLATFORM_SCHEMA = vol.All(cover.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(cover.COVER_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateCover), vol.Optional(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_OPTIMISTIC): cv.boolean, vol.Optional(CONF_OPEN_ACTION): automation.ACTIONS_SCHEMA, vol.Optional(CONF_CLOSE_ACTION): automation.ACTIONS_SCHEMA, vol.Optional(CONF_STOP_ACTION): automation.ACTIONS_SCHEMA, -}).extend(cover.COVER_SCHEMA.schema), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) +}), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) def to_code(config): diff --git a/esphomeyaml/components/fan/__init__.py b/esphomeyaml/components/fan/__init__.py index 02cd479ac0..e2cb24dfdb 100644 --- a/esphomeyaml/components/fan/__init__.py +++ b/esphomeyaml/components/fan/__init__.py @@ -2,7 +2,7 @@ import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_ID, CONF_MQTT_ID, CONF_OSCILLATION_COMMAND_TOPIC, \ - CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC + CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_INTERNAL from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ @@ -29,6 +29,8 @@ FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ vol.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.subscribe_topic, }) +FAN_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FAN_SCHEMA.schema) + FAN_SPEEDS = { 'OFF': FAN_SPEED_OFF, @@ -43,6 +45,9 @@ def validate_fan_speed(value): def setup_fan_core_(fan_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(fan_var.set_internal(config[CONF_INTERNAL])) + if CONF_OSCILLATION_STATE_TOPIC in config: add(mqtt_var.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC])) if CONF_OSCILLATION_COMMAND_TOPIC in config: diff --git a/esphomeyaml/components/fan/binary.py b/esphomeyaml/components/fan/binary.py index ab1516d091..05c833dbdd 100644 --- a/esphomeyaml/components/fan/binary.py +++ b/esphomeyaml/components/fan/binary.py @@ -5,11 +5,11 @@ from esphomeyaml.components import fan from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OSCILLATION_OUTPUT, CONF_OUTPUT from esphomeyaml.helpers import App, add, get_variable, variable -PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), vol.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(None), -}).extend(fan.FAN_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/fan/speed.py b/esphomeyaml/components/fan/speed.py index 68fe2e6644..2756a80e4a 100644 --- a/esphomeyaml/components/fan/speed.py +++ b/esphomeyaml/components/fan/speed.py @@ -7,7 +7,7 @@ from esphomeyaml.const import CONF_HIGH, CONF_LOW, CONF_MAKE_ID, CONF_MEDIUM, CO CONF_SPEED_STATE_TOPIC from esphomeyaml.helpers import App, add, get_variable, variable -PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(fan.FAN_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(fan.MakeFan), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), vol.Optional(CONF_SPEED_STATE_TOPIC): cv.publish_topic, @@ -18,7 +18,7 @@ PLATFORM_SCHEMA = fan.PLATFORM_SCHEMA.extend({ vol.Required(CONF_MEDIUM): cv.percentage, vol.Required(CONF_HIGH): cv.percentage, }), -}).extend(fan.FAN_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/i2c.py b/esphomeyaml/components/i2c.py index 6987bb17e2..647530b25b 100644 --- a/esphomeyaml/components/i2c.py +++ b/esphomeyaml/components/i2c.py @@ -13,8 +13,11 @@ CONFIG_SCHEMA = vol.Schema({ vol.Required(CONF_SDA, default='SDA'): pins.input_output_pin, vol.Required(CONF_SCL, default='SCL'): pins.input_output_pin, vol.Optional(CONF_FREQUENCY): vol.All(cv.frequency, vol.Range(min=0, min_included=False)), - vol.Optional(CONF_RECEIVE_TIMEOUT): cv.positive_time_period_milliseconds, vol.Optional(CONF_SCAN): cv.boolean, + + vol.Optional(CONF_RECEIVE_TIMEOUT): cv.invalid("The receive_timeout option has been removed " + "because timeouts are already handled by the " + "low-level i2c interface.") }) @@ -23,8 +26,6 @@ def to_code(config): i2c = Pvariable(config[CONF_ID], rhs) if CONF_FREQUENCY in config: add(i2c.set_frequency(config[CONF_FREQUENCY])) - if CONF_RECEIVE_TIMEOUT in config: - add(i2c.set_receive_timeout(config[CONF_RECEIVE_TIMEOUT])) BUILD_FLAGS = '-DUSE_I2C' diff --git a/esphomeyaml/components/ir_transmitter.py b/esphomeyaml/components/ir_transmitter.py index e1b6cbd1aa..6e50f78870 100644 --- a/esphomeyaml/components/ir_transmitter.py +++ b/esphomeyaml/components/ir_transmitter.py @@ -1,28 +1,6 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv -from esphomeyaml import pins -from esphomeyaml.components import switch -from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN -from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression -IRTransmitterComponent = switch.switch_ns.namespace('IRTransmitterComponent') - -CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ - cv.GenerateID(): cv.declare_variable_id(IRTransmitterComponent), - vol.Required(CONF_PIN): pins.gpio_output_pin_schema, - vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int), - vol.Range(min=1, max=100)), -})]) - - -def to_code(config): - for conf in config: - pin = None - for pin in gpio_output_pin_expression(conf[CONF_PIN]): - yield - rhs = App.make_ir_transmitter(pin, conf.get(CONF_CARRIER_DUTY_PERCENT)) - Pvariable(conf[CONF_ID], rhs) - - -BUILD_FLAGS = '-DUSE_IR_TRANSMITTER' +def CONFIG_SCHEMA(config): + raise vol.Invalid("The ir_transmitter component has been renamed to " + "remote_transmitter because of 433MHz signal support.") diff --git a/esphomeyaml/components/light/__init__.py b/esphomeyaml/components/light/__init__.py index 6ce4567ef8..89151b0a48 100644 --- a/esphomeyaml/components/light/__init__.py +++ b/esphomeyaml/components/light/__init__.py @@ -1,6 +1,6 @@ import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, \ - CONF_MQTT_ID + CONF_MQTT_ID, CONF_INTERNAL from esphomeyaml.helpers import Application, Pvariable, add, esphomelib_ns, setup_mqtt_component PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ @@ -20,8 +20,12 @@ LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ cv.GenerateID(CONF_MQTT_ID): cv.declare_variable_id(MQTTJSONLightComponent), }) +LIGHT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(LIGHT_SCHEMA.schema) + def setup_light_core_(light_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(light_var.set_internal(config[CONF_INTERNAL])) if CONF_DEFAULT_TRANSITION_LENGTH in config: add(light_var.set_default_transition_length(config[CONF_DEFAULT_TRANSITION_LENGTH])) if CONF_GAMMA_CORRECT in config: diff --git a/esphomeyaml/components/light/binary.py b/esphomeyaml/components/light/binary.py index 6a92837021..b32de62950 100644 --- a/esphomeyaml/components/light/binary.py +++ b/esphomeyaml/components/light/binary.py @@ -5,10 +5,10 @@ from esphomeyaml.components import light from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_OUTPUT from esphomeyaml.helpers import App, get_variable, variable -PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), -}).extend(light.LIGHT_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/light/fastled_clockless.py b/esphomeyaml/components/light/fastled_clockless.py index 878254bde1..4cb5c5580e 100644 --- a/esphomeyaml/components/light/fastled_clockless.py +++ b/esphomeyaml/components/light/fastled_clockless.py @@ -55,7 +55,7 @@ def validate(value): MakeFastLEDLight = Application.MakeFastLEDLight -PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight), vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*TYPES)), @@ -68,7 +68,7 @@ PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({ vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float, vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent), -}).extend(light.LIGHT_SCHEMA.schema), validate) +}), validate) def to_code(config): diff --git a/esphomeyaml/components/light/fastled_spi.py b/esphomeyaml/components/light/fastled_spi.py index 84d848dbff..fb5d86ed73 100644 --- a/esphomeyaml/components/light/fastled_spi.py +++ b/esphomeyaml/components/light/fastled_spi.py @@ -32,7 +32,7 @@ RGB_ORDERS = [ MakeFastLEDLight = Application.MakeFastLEDLight -PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight), vol.Required(CONF_CHIPSET): vol.All(vol.Upper, cv.one_of(*CHIPSETS)), @@ -46,7 +46,7 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float, vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, vol.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(PowerSupplyComponent), -}).extend(light.LIGHT_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/light/monochromatic.py b/esphomeyaml/components/light/monochromatic.py index 75a8a9a71b..ce9a88bbfb 100644 --- a/esphomeyaml/components/light/monochromatic.py +++ b/esphomeyaml/components/light/monochromatic.py @@ -6,12 +6,12 @@ from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT CONF_NAME, CONF_OUTPUT from esphomeyaml.helpers import App, get_variable, variable -PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float, vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, -}).extend(light.LIGHT_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/light/rgb.py b/esphomeyaml/components/light/rgb.py index 1506fa957c..aeeb97ff4f 100644 --- a/esphomeyaml/components/light/rgb.py +++ b/esphomeyaml/components/light/rgb.py @@ -6,14 +6,14 @@ from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GA CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED from esphomeyaml.helpers import App, get_variable, variable -PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), vol.Required(CONF_RED): cv.use_variable_id(None), vol.Required(CONF_GREEN): cv.use_variable_id(None), vol.Required(CONF_BLUE): cv.use_variable_id(None), vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float, vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, -}).extend(light.LIGHT_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/light/rgbw.py b/esphomeyaml/components/light/rgbw.py index 8617db5bca..6186390f2a 100644 --- a/esphomeyaml/components/light/rgbw.py +++ b/esphomeyaml/components/light/rgbw.py @@ -6,7 +6,7 @@ from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GA CONF_GREEN, CONF_MAKE_ID, CONF_NAME, CONF_RED, CONF_WHITE from esphomeyaml.helpers import App, get_variable, variable -PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(light.MakeLight), vol.Required(CONF_RED): cv.use_variable_id(None), vol.Required(CONF_GREEN): cv.use_variable_id(None), @@ -14,7 +14,7 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({ vol.Required(CONF_WHITE): cv.use_variable_id(None), vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float, vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, -}).extend(light.LIGHT_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/logger.py b/esphomeyaml/components/logger.py index 6741ca95f8..14a19db739 100644 --- a/esphomeyaml/components/logger.py +++ b/esphomeyaml/components/logger.py @@ -36,7 +36,7 @@ LogComponent = esphomelib_ns.LogComponent CONFIG_SCHEMA = vol.All(vol.Schema({ cv.GenerateID(): cv.declare_variable_id(LogComponent), vol.Optional(CONF_BAUD_RATE): cv.positive_int, - vol.Optional(CONF_TX_BUFFER_SIZE): cv.positive_int, + vol.Optional(CONF_TX_BUFFER_SIZE): cv.validate_bytes, vol.Optional(CONF_LEVEL): is_log_level, vol.Optional(CONF_LOGS): vol.Schema({ cv.string: is_log_level, diff --git a/esphomeyaml/components/output/__init__.py b/esphomeyaml/components/output/__init__.py index 22cfaffffa..faf8825bd1 100644 --- a/esphomeyaml/components/output/__init__.py +++ b/esphomeyaml/components/output/__init__.py @@ -14,10 +14,14 @@ BINARY_OUTPUT_SCHEMA = vol.Schema({ vol.Optional(CONF_INVERTED): cv.boolean, }) +BINARY_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BINARY_OUTPUT_SCHEMA.schema) + FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({ vol.Optional(CONF_MAX_POWER): cv.percentage, }) +FLOAT_OUTPUT_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(FLOAT_OUTPUT_SCHEMA.schema) + output_ns = esphomelib_ns.namespace('output') diff --git a/esphomeyaml/components/output/esp8266_pwm.py b/esphomeyaml/components/output/esp8266_pwm.py index b477d1cb5f..84eae94241 100644 --- a/esphomeyaml/components/output/esp8266_pwm.py +++ b/esphomeyaml/components/output/esp8266_pwm.py @@ -18,10 +18,10 @@ def valid_pwm_pin(value): ESP8266PWMOutput = output.output_ns.ESP8266PWMOutput -PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({ vol.Required(CONF_ID): cv.declare_variable_id(ESP8266PWMOutput), vol.Required(CONF_PIN): vol.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin), -}).extend(output.FLOAT_OUTPUT_SCHEMA.schema) +}) def to_code(config): diff --git a/esphomeyaml/components/output/gpio.py b/esphomeyaml/components/output/gpio.py index c082edc5ce..3f471e74b5 100644 --- a/esphomeyaml/components/output/gpio.py +++ b/esphomeyaml/components/output/gpio.py @@ -8,10 +8,10 @@ from esphomeyaml.helpers import App, Pvariable, gpio_output_pin_expression GPIOBinaryOutputComponent = output.output_ns.GPIOBinaryOutputComponent -PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = output.BINARY_OUTPUT_PLATFORM_SCHEMA.extend({ vol.Required(CONF_ID): cv.declare_variable_id(GPIOBinaryOutputComponent), vol.Required(CONF_PIN): pins.gpio_output_pin_schema, -}).extend(output.BINARY_OUTPUT_SCHEMA.schema) +}) def to_code(config): diff --git a/esphomeyaml/components/output/ledc.py b/esphomeyaml/components/output/ledc.py index 107e788737..5db2a207c2 100644 --- a/esphomeyaml/components/output/ledc.py +++ b/esphomeyaml/components/output/ledc.py @@ -21,13 +21,13 @@ def validate_frequency_bit_depth(obj): LEDCOutputComponent = output.output_ns.LEDCOutputComponent -PLATFORM_SCHEMA = vol.All(output.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = vol.All(output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({ vol.Required(CONF_ID): cv.declare_variable_id(LEDCOutputComponent), vol.Required(CONF_PIN): pins.output_pin, vol.Optional(CONF_FREQUENCY): cv.frequency, vol.Optional(CONF_BIT_DEPTH): vol.All(vol.Coerce(int), vol.Range(min=1, max=15)), vol.Optional(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15)) -}).extend(output.FLOAT_OUTPUT_SCHEMA.schema), validate_frequency_bit_depth) +}), validate_frequency_bit_depth) def to_code(config): diff --git a/esphomeyaml/components/output/pca9685.py b/esphomeyaml/components/output/pca9685.py index dbb2a2fec9..55c57377b9 100644 --- a/esphomeyaml/components/output/pca9685.py +++ b/esphomeyaml/components/output/pca9685.py @@ -10,12 +10,12 @@ DEPENDENCIES = ['pca9685'] Channel = PCA9685OutputComponent.Channel -PLATFORM_SCHEMA = output.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({ vol.Required(CONF_ID): cv.declare_variable_id(Channel), vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15)), cv.GenerateID(CONF_PCA9685_ID): cv.use_variable_id(PCA9685OutputComponent), -}).extend(output.FLOAT_OUTPUT_SCHEMA.schema) +}) def to_code(config): diff --git a/esphomeyaml/components/remote_receiver.py b/esphomeyaml/components/remote_receiver.py new file mode 100644 index 0000000000..081b5d38e4 --- /dev/null +++ b/esphomeyaml/components/remote_receiver.py @@ -0,0 +1,51 @@ +import voluptuous as vol + +import esphomeyaml.config_validation as cv +from esphomeyaml import pins +from esphomeyaml.const import CONF_DUMP, CONF_ID, CONF_PIN, CONF_TOLERANCE, CONF_BUFFER_SIZE, \ + CONF_FILTER, CONF_IDLE +from esphomeyaml.helpers import App, Pvariable, esphomelib_ns, gpio_input_pin_expression, add + +remote_ns = esphomelib_ns.namespace('remote') + +RemoteReceiverComponent = remote_ns.RemoteReceiverComponent + +DUMPERS = { + 'lg': remote_ns.LGDumper, + 'nec': remote_ns.NECDumper, + 'panasonic': remote_ns.PanasonicDumper, + 'raw': remote_ns.RawDumper, + 'sony': remote_ns.SonyDumper, +} + +CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ + cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent), + vol.Required(CONF_PIN): pins.gpio_input_pin_schema, + vol.Optional(CONF_DUMP, default=[]): vol.All(vol.Lower, cv.one_of(*DUMPERS)), + vol.Optional(CONF_TOLERANCE): vol.All(cv.percentage_int, vol.Range(min=0)), + vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes, + vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds, + vol.Optional(CONF_IDLE): cv.positive_time_period_microseconds, +})]) + + +def to_code(config): + for conf in config: + pin = None + for pin in gpio_input_pin_expression(conf[CONF_PIN]): + yield + rhs = App.make_remote_receiver_component(pin) + receiver = Pvariable(conf[CONF_ID], rhs) + for dumper in conf[CONF_DUMP]: + add(receiver.add_dumper(DUMPERS[dumper].new())) + if CONF_TOLERANCE in conf: + add(receiver.set_tolerance(conf[CONF_TOLERANCE])) + if CONF_BUFFER_SIZE in conf: + add(receiver.set_buffer_size(conf[CONF_BUFFER_SIZE])) + if CONF_FILTER in conf: + add(receiver.set_filter_us(conf[CONF_FILTER])) + if CONF_IDLE in conf: + add(receiver.set_idle_us(conf[CONF_IDLE])) + + +BUILD_FLAGS = '-DUSE_REMOTE_RECEIVER' diff --git a/esphomeyaml/components/remote_transmitter.py b/esphomeyaml/components/remote_transmitter.py new file mode 100644 index 0000000000..6bf1794534 --- /dev/null +++ b/esphomeyaml/components/remote_transmitter.py @@ -0,0 +1,31 @@ +import voluptuous as vol + +import esphomeyaml.config_validation as cv +from esphomeyaml import pins +from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN +from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, gpio_output_pin_expression + +remote_ns = esphomelib_ns.namespace('remote') + +RemoteTransmitterComponent = remote_ns.RemoteTransmitterComponent + +CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({ + cv.GenerateID(): cv.declare_variable_id(RemoteTransmitterComponent), + vol.Required(CONF_PIN): pins.gpio_output_pin_schema, + vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int), + vol.Range(min=1, max=100)), +})]) + + +def to_code(config): + for conf in config: + pin = None + for pin in gpio_output_pin_expression(conf[CONF_PIN]): + yield + rhs = App.make_remote_transmitter_component(pin) + transmitter = Pvariable(conf[CONF_ID], rhs) + if CONF_CARRIER_DUTY_PERCENT in conf: + add(transmitter.set_carrier_duty_percent(conf[CONF_CARRIER_DUTY_PERCENT])) + + +BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER' diff --git a/esphomeyaml/components/sensor/__init__.py b/esphomeyaml/components/sensor/__init__.py index 1dae6cc50c..de7cf06625 100644 --- a/esphomeyaml/components/sensor/__init__.py +++ b/esphomeyaml/components/sensor/__init__.py @@ -5,9 +5,10 @@ from esphomeyaml import automation from esphomeyaml.const import CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, CONF_BELOW, \ CONF_DEBOUNCE, CONF_DELTA, CONF_EXPIRE_AFTER, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_FILTERS, \ CONF_FILTER_NAN, CONF_FILTER_OUT, CONF_HEARTBEAT, CONF_ICON, CONF_ID, CONF_LAMBDA, \ - CONF_MQTT_ID, CONF_MULTIPLY, CONF_NAME, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE,\ + CONF_MQTT_ID, CONF_MULTIPLY, CONF_NAME, CONF_OFFSET, CONF_ON_RAW_VALUE, CONF_ON_VALUE, \ CONF_ON_VALUE_RANGE, CONF_OR, CONF_SEND_EVERY, CONF_SLIDING_WINDOW_MOVING_AVERAGE, \ - CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE + CONF_THROTTLE, CONF_TRIGGER_ID, CONF_UNIQUE, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, \ + CONF_INTERNAL from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, add, esphomelib_ns, float_, \ process_lambda, setup_mqtt_component, templatable, add_job @@ -91,6 +92,8 @@ SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ }), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW))]), }) +SENSOR_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(SENSOR_SCHEMA.schema) + def setup_filter(config): if CONF_OFFSET in config: @@ -140,6 +143,8 @@ def setup_filters(config): def setup_sensor_core_(sensor_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(sensor_var.set_internal(config[CONF_INTERNAL])) if CONF_UNIT_OF_MEASUREMENT in config: add(sensor_var.set_unit_of_measurement(config[CONF_UNIT_OF_MEASUREMENT])) if CONF_ICON in config: diff --git a/esphomeyaml/components/sensor/adc.py b/esphomeyaml/components/sensor/adc.py index ea8531d918..b8ce2ccc8c 100644 --- a/esphomeyaml/components/sensor/adc.py +++ b/esphomeyaml/components/sensor/adc.py @@ -24,12 +24,12 @@ def validate_adc_pin(value): MakeADCSensor = Application.MakeADCSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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)), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/ads1115.py b/esphomeyaml/components/sensor/ads1115.py index 8dbdf6238a..3630953d2b 100644 --- a/esphomeyaml/components/sensor/ads1115.py +++ b/esphomeyaml/components/sensor/ads1115.py @@ -45,12 +45,12 @@ def validate_mux(value): return cv.one_of(*MUX)(value) -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ vol.Required(CONF_MULTIPLEXER): validate_mux, vol.Required(CONF_GAIN): validate_gain, cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/bh1750.py b/esphomeyaml/components/sensor/bh1750.py index 30a33192b4..3aaf8e116f 100644 --- a/esphomeyaml/components/sensor/bh1750.py +++ b/esphomeyaml/components/sensor/bh1750.py @@ -16,12 +16,12 @@ BH1750_RESOLUTIONS = { MakeBH1750Sensor = Application.MakeBH1750Sensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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)), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/bme280.py b/esphomeyaml/components/sensor/bme280.py index 0920e95807..882cec4891 100644 --- a/esphomeyaml/components/sensor/bme280.py +++ b/esphomeyaml/components/sensor/bme280.py @@ -34,9 +34,9 @@ MakeBME280Sensor = Application.MakeBME280Sensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME280Sensor), vol.Optional(CONF_ADDRESS, default=0x77): cv.i2c_address, - vol.Required(CONF_TEMPERATURE): BME280_OVERSAMPLING_SENSOR_SCHEMA, - vol.Required(CONF_PRESSURE): BME280_OVERSAMPLING_SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): BME280_OVERSAMPLING_SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA), + vol.Required(CONF_PRESSURE): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(BME280_OVERSAMPLING_SENSOR_SCHEMA), vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/bme680.py b/esphomeyaml/components/sensor/bme680.py index 82ed3ee7ad..ce8ff45e6d 100644 --- a/esphomeyaml/components/sensor/bme680.py +++ b/esphomeyaml/components/sensor/bme680.py @@ -38,10 +38,10 @@ MakeBME680Sensor = Application.MakeBME680Sensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBME680Sensor), vol.Optional(CONF_ADDRESS, default=0x76): cv.i2c_address, - vol.Required(CONF_TEMPERATURE): BME680_OVERSAMPLING_SENSOR_SCHEMA, - vol.Required(CONF_PRESSURE): BME680_OVERSAMPLING_SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): BME680_OVERSAMPLING_SENSOR_SCHEMA, - vol.Required(CONF_GAS_RESISTANCE): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA), + vol.Required(CONF_PRESSURE): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(BME680_OVERSAMPLING_SENSOR_SCHEMA), + vol.Required(CONF_GAS_RESISTANCE): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, cv.one_of(*IIR_FILTER_OPTIONS)), # TODO: Heater vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, diff --git a/esphomeyaml/components/sensor/bmp085.py b/esphomeyaml/components/sensor/bmp085.py index bca0d51a33..a7f6ed4553 100644 --- a/esphomeyaml/components/sensor/bmp085.py +++ b/esphomeyaml/components/sensor/bmp085.py @@ -12,8 +12,8 @@ MakeBMP085Sensor = Application.MakeBMP085Sensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeBMP085Sensor), - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_PRESSURE): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_PRESSURE): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_ADDRESS): cv.i2c_address, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/dallas.py b/esphomeyaml/components/sensor/dallas.py index a0446abacb..bbf1e7429c 100644 --- a/esphomeyaml/components/sensor/dallas.py +++ b/esphomeyaml/components/sensor/dallas.py @@ -7,12 +7,12 @@ from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAM CONF_RESOLUTION from esphomeyaml.helpers import HexIntLiteral, get_variable -PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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), vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=9, max=12)), -}).extend(sensor.SENSOR_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX)) +}), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX)) def to_code(config): diff --git a/esphomeyaml/components/sensor/dht.py b/esphomeyaml/components/sensor/dht.py index 59871086fd..14d2c3dd85 100644 --- a/esphomeyaml/components/sensor/dht.py +++ b/esphomeyaml/components/sensor/dht.py @@ -20,8 +20,8 @@ MakeDHTSensor = Application.MakeDHTSensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHTSensor), vol.Required(CONF_PIN): gpio_output_pin_schema, - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_MODEL): vol.All(vol.Upper, cv.one_of(*DHT_MODELS)), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/dht12.py b/esphomeyaml/components/sensor/dht12.py index f35aafbfd6..1bc42ddbb2 100644 --- a/esphomeyaml/components/sensor/dht12.py +++ b/esphomeyaml/components/sensor/dht12.py @@ -12,8 +12,8 @@ MakeDHT12Sensor = Application.MakeDHT12Sensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeDHT12Sensor), - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/duty_cycle.py b/esphomeyaml/components/sensor/duty_cycle.py new file mode 100644 index 0000000000..f4d0e17053 --- /dev/null +++ b/esphomeyaml/components/sensor/duty_cycle.py @@ -0,0 +1,28 @@ +import voluptuous as vol + +import esphomeyaml.config_validation as cv +from esphomeyaml import pins +from esphomeyaml.components import sensor +from esphomeyaml.const import CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL +from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, variable + +MakeDutyCycleSensor = Application.MakeDutyCycleSensor + +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + 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.positive_time_period_milliseconds, +})) + + +def to_code(config): + pin = None + for pin in gpio_input_pin_expression(config[CONF_PIN]): + yield + rhs = App.make_duty_cycle_sensor(config[CONF_NAME], pin, + config.get(CONF_UPDATE_INTERVAL)) + make = variable(config[CONF_MAKE_ID], rhs) + sensor.setup_sensor(make.Pduty, make.Pmqtt, config) + + +BUILD_FLAGS = '-DUSE_DUTY_CYCLE_SENSOR' diff --git a/esphomeyaml/components/sensor/esp32_hall.py b/esphomeyaml/components/sensor/esp32_hall.py index dfa0a7d570..b454b7b3b0 100644 --- a/esphomeyaml/components/sensor/esp32_hall.py +++ b/esphomeyaml/components/sensor/esp32_hall.py @@ -9,10 +9,10 @@ ESP_PLATFORMS = [ESP_PLATFORM_ESP32] MakeESP32HallSensor = Application.MakeESP32HallSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeESP32HallSensor), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/hdc1080.py b/esphomeyaml/components/sensor/hdc1080.py index ccad75970c..6484d07354 100644 --- a/esphomeyaml/components/sensor/hdc1080.py +++ b/esphomeyaml/components/sensor/hdc1080.py @@ -12,8 +12,8 @@ MakeHDC1080Sensor = Application.MakeHDC1080Sensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHDC1080Sensor), - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/htu21d.py b/esphomeyaml/components/sensor/htu21d.py index 631f389314..596d2de697 100644 --- a/esphomeyaml/components/sensor/htu21d.py +++ b/esphomeyaml/components/sensor/htu21d.py @@ -12,8 +12,8 @@ MakeHTU21DSensor = Application.MakeHTU21DSensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHTU21DSensor), - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }) diff --git a/esphomeyaml/components/sensor/max6675.py b/esphomeyaml/components/sensor/max6675.py index 45f98bfbb8..1737b5c5b2 100644 --- a/esphomeyaml/components/sensor/max6675.py +++ b/esphomeyaml/components/sensor/max6675.py @@ -10,13 +10,13 @@ from esphomeyaml.helpers import App, Application, gpio_input_pin_expression, \ MakeMAX6675Sensor = Application.MakeMAX6675Sensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeMAX6675Sensor), vol.Required(CONF_PIN_CS): pins.gpio_output_pin_schema, vol.Required(CONF_PIN_CLOCK): pins.gpio_output_pin_schema, vol.Required(CONF_PIN_MISO): pins.gpio_input_pin_schema, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/mpu6050.py b/esphomeyaml/components/sensor/mpu6050.py index dbb61f828d..0af2772d25 100644 --- a/esphomeyaml/components/sensor/mpu6050.py +++ b/esphomeyaml/components/sensor/mpu6050.py @@ -23,13 +23,13 @@ MPU6050TemperatureSensor = sensor.sensor_ns.MPU6050TemperatureSensor PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(MPU6050Component), vol.Optional(CONF_ADDRESS, default=0x68): cv.i2c_address, - vol.Optional(CONF_ACCEL_X): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_ACCEL_Y): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_ACCEL_Z): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_GYRO_X): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_GYRO_Y): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_GYRO_Z): sensor.SENSOR_SCHEMA, - vol.Optional(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, + vol.Optional(CONF_ACCEL_X): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_ACCEL_Y): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_ACCEL_Z): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_GYRO_X): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_GYRO_Y): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_GYRO_Z): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Optional(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, }), cv.has_at_least_one_key(CONF_ACCEL_X, CONF_ACCEL_Y, CONF_ACCEL_Z, CONF_GYRO_X, CONF_GYRO_Y, CONF_GYRO_Z)) diff --git a/esphomeyaml/components/sensor/pulse_counter.py b/esphomeyaml/components/sensor/pulse_counter.py index 8733795589..f7c2700ea9 100644 --- a/esphomeyaml/components/sensor/pulse_counter.py +++ b/esphomeyaml/components/sensor/pulse_counter.py @@ -1,62 +1,66 @@ import voluptuous as vol import esphomeyaml.config_validation as cv -from esphomeyaml import pins +from esphomeyaml import core, pins from esphomeyaml.components import sensor from esphomeyaml.const import CONF_COUNT_MODE, CONF_FALLING_EDGE, CONF_INTERNAL_FILTER, \ CONF_MAKE_ID, CONF_NAME, CONF_PIN, CONF_PULL_MODE, CONF_RISING_EDGE, CONF_UPDATE_INTERVAL, \ ESP_PLATFORM_ESP32 -from esphomeyaml.helpers import App, add, global_ns, variable, Application - -ESP_PLATFORMS = [ESP_PLATFORM_ESP32] - -GPIO_PULL_MODES = { - 'PULLUP': global_ns.GPIO_PULLUP_ONLY, - 'PULLDOWN': global_ns.GPIO_PULLDOWN_ONLY, - 'PULLUP_PULLDOWN': global_ns.GPIO_PULLUP_PULLDOWN, - 'FLOATING': global_ns.GPIO_FLOATING, -} - -GPIO_PULL_MODE_SCHEMA = vol.All(vol.Upper, cv.one_of(*GPIO_PULL_MODES)) +from esphomeyaml.helpers import App, Application, add, variable, gpio_input_pin_expression COUNT_MODES = { - 'DISABLE': global_ns.PCNT_COUNT_DIS, - 'INCREMENT': global_ns.PCNT_COUNT_INC, - 'DECREMENT': global_ns.PCNT_COUNT_DEC, + 'DISABLE': sensor.sensor_ns.PULSE_COUNTER_DISABLE, + 'INCREMENT': sensor.sensor_ns.PULSE_COUNTER_INCREMENT, + 'DECREMENT': sensor.sensor_ns.PULSE_COUNTER_DECREMENT, } COUNT_MODE_SCHEMA = vol.All(vol.Upper, cv.one_of(*COUNT_MODES)) MakePulseCounterSensor = Application.MakePulseCounterSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ + +def validate_internal_filter(value): + if core.ESP_PLATFORM == ESP_PLATFORM_ESP32: + if isinstance(value, int): + raise vol.Invalid("Please specify the internal filter in microseconds now " + "(since 1.7.0). For example '17ms'") + value = cv.positive_time_period_microseconds(value) + if value.total_microseconds > 13: + raise vol.Invalid("Maximum internal filter value for ESP32 is 13us") + return value + else: + return cv.positive_time_period_microseconds(value) + + +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakePulseCounterSensor), - vol.Required(CONF_PIN): pins.input_pin, - vol.Optional(CONF_PULL_MODE): GPIO_PULL_MODE_SCHEMA, + vol.Required(CONF_PIN): pins.internal_gpio_input_pin_schema, vol.Optional(CONF_COUNT_MODE): vol.Schema({ vol.Required(CONF_RISING_EDGE): COUNT_MODE_SCHEMA, vol.Required(CONF_FALLING_EDGE): COUNT_MODE_SCHEMA, }), - vol.Optional(CONF_INTERNAL_FILTER): vol.All(vol.Coerce(int), vol.Range(min=0, max=1023)), + vol.Optional(CONF_INTERNAL_FILTER): validate_internal_filter, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) + + vol.Optional(CONF_PULL_MODE): cv.invalid("The pull_mode option has been removed in 1.7.0, " + "please use the pin mode schema now.") +})) def to_code(config): - rhs = App.make_pulse_counter_sensor(config[CONF_NAME], config[CONF_PIN], + pin = None + for pin in gpio_input_pin_expression(config[CONF_PIN]): + yield + rhs = App.make_pulse_counter_sensor(config[CONF_NAME], pin, config.get(CONF_UPDATE_INTERVAL)) make = variable(config[CONF_MAKE_ID], rhs) pcnt = make.Ppcnt - if CONF_PULL_MODE in config: - pull_mode = GPIO_PULL_MODES[config[CONF_PULL_MODE]] - add(pcnt.set_pull_mode(pull_mode)) if CONF_COUNT_MODE in config: - count_mode = config[CONF_COUNT_MODE] - rising_edge = COUNT_MODES[count_mode[CONF_RISING_EDGE]] - falling_edge = COUNT_MODES[count_mode[CONF_FALLING_EDGE]] + rising_edge = COUNT_MODES[config[CONF_COUNT_MODE][CONF_RISING_EDGE]] + falling_edge = COUNT_MODES[config[CONF_COUNT_MODE][CONF_FALLING_EDGE]] add(pcnt.set_edge_mode(rising_edge, falling_edge)) if CONF_INTERNAL_FILTER in config: - add(pcnt.set_filter(config[CONF_INTERNAL_FILTER])) + add(pcnt.set_filter_us(config[CONF_INTERNAL_FILTER])) sensor.setup_sensor(make.Ppcnt, make.Pmqtt, config) diff --git a/esphomeyaml/components/sensor/rotary_encoder.py b/esphomeyaml/components/sensor/rotary_encoder.py index bd4fb77dfc..d872ed9c69 100644 --- a/esphomeyaml/components/sensor/rotary_encoder.py +++ b/esphomeyaml/components/sensor/rotary_encoder.py @@ -18,13 +18,13 @@ CONF_PIN_RESET = 'pin_reset' MakeRotaryEncoderSensor = Application.MakeRotaryEncoderSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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, vol.Optional(CONF_PIN_RESET): pins.internal_gpio_input_pin_schema, vol.Optional(CONF_RESOLUTION): vol.All(cv.string, cv.one_of(*RESOLUTIONS)), -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/sht3xd.py b/esphomeyaml/components/sensor/sht3xd.py index 99f4cb03a5..108b010038 100644 --- a/esphomeyaml/components/sensor/sht3xd.py +++ b/esphomeyaml/components/sensor/sht3xd.py @@ -12,8 +12,8 @@ MakeSHT3XDSensor = Application.MakeSHT3XDSensor PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSHT3XDSensor), - vol.Required(CONF_TEMPERATURE): sensor.SENSOR_SCHEMA, - vol.Required(CONF_HUMIDITY): sensor.SENSOR_SCHEMA, + vol.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA), + vol.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA), vol.Optional(CONF_ADDRESS, default=0x44): cv.i2c_address, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, diff --git a/esphomeyaml/components/sensor/template.py b/esphomeyaml/components/sensor/template.py index 6b2ced2d5b..8a8841fccd 100644 --- a/esphomeyaml/components/sensor/template.py +++ b/esphomeyaml/components/sensor/template.py @@ -7,11 +7,11 @@ from esphomeyaml.helpers import App, process_lambda, variable, Application, floa MakeTemplateSensor = Application.MakeTemplateSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeTemplateSensor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/tsl2561.py b/esphomeyaml/components/sensor/tsl2561.py index bca7c0420a..20e8257d08 100644 --- a/esphomeyaml/components/sensor/tsl2561.py +++ b/esphomeyaml/components/sensor/tsl2561.py @@ -30,14 +30,14 @@ def validate_integration_time(value): MakeTSL2561Sensor = Application.MakeTSL2561Sensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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, vol.Optional(CONF_GAIN): vol.All(vol.Upper, cv.one_of(*GAINS)), vol.Optional(CONF_IS_CS_PACKAGE): cv.boolean, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/ultrasonic.py b/esphomeyaml/components/sensor/ultrasonic.py index a3c5850aa8..353ce4a471 100644 --- a/esphomeyaml/components/sensor/ultrasonic.py +++ b/esphomeyaml/components/sensor/ultrasonic.py @@ -10,14 +10,14 @@ from esphomeyaml.helpers import App, Application, add, gpio_input_pin_expression MakeUltrasonicSensor = Application.MakeUltrasonicSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ 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, vol.Exclusive(CONF_TIMEOUT_METER, 'timeout'): cv.positive_float, vol.Exclusive(CONF_TIMEOUT_TIME, 'timeout'): cv.positive_time_period_microseconds, vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/sensor/wifi_signal.py b/esphomeyaml/components/sensor/wifi_signal.py index 2b920a6403..0f070c1e61 100644 --- a/esphomeyaml/components/sensor/wifi_signal.py +++ b/esphomeyaml/components/sensor/wifi_signal.py @@ -7,10 +7,10 @@ from esphomeyaml.helpers import App, Application, variable MakeWiFiSignalSensor = Application.MakeWiFiSignalSensor -PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeWiFiSignalSensor), vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(sensor.SENSOR_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/switch/__init__.py b/esphomeyaml/components/switch/__init__.py index 554d147381..46feeaa9e0 100644 --- a/esphomeyaml/components/switch/__init__.py +++ b/esphomeyaml/components/switch/__init__.py @@ -1,7 +1,7 @@ import voluptuous as vol import esphomeyaml.config_validation as cv -from esphomeyaml.const import CONF_ICON, CONF_ID, CONF_INVERTED, CONF_MQTT_ID +from esphomeyaml.const import CONF_ICON, CONF_ID, CONF_INVERTED, CONF_MQTT_ID, CONF_INTERNAL from esphomeyaml.helpers import App, Pvariable, add, esphomelib_ns, setup_mqtt_component PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ @@ -22,8 +22,12 @@ SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ vol.Optional(CONF_INVERTED): cv.boolean, }) +SWITCH_PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(SWITCH_SCHEMA.schema) + def setup_switch_core_(switch_var, mqtt_var, config): + if CONF_INTERNAL in config: + add(switch_var.set_internal(config[CONF_INTERNAL])) if CONF_ICON in config: add(switch_var.set_icon(config[CONF_ICON])) if CONF_INVERTED in config: diff --git a/esphomeyaml/components/switch/gpio.py b/esphomeyaml/components/switch/gpio.py index 5641c21a91..58700c67e9 100644 --- a/esphomeyaml/components/switch/gpio.py +++ b/esphomeyaml/components/switch/gpio.py @@ -8,10 +8,10 @@ from esphomeyaml.helpers import App, Application, gpio_output_pin_expression, va MakeGPIOSwitch = Application.MakeGPIOSwitch -PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeGPIOSwitch), vol.Required(CONF_PIN): pins.gpio_output_pin_schema, -}).extend(switch.SWITCH_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/switch/ir_transmitter.py b/esphomeyaml/components/switch/ir_transmitter.py deleted file mode 100644 index 0a9ba4109e..0000000000 --- a/esphomeyaml/components/switch/ir_transmitter.py +++ /dev/null @@ -1,104 +0,0 @@ -import voluptuous as vol - -import esphomeyaml.config_validation as cv -from esphomeyaml.components import switch -from esphomeyaml.components.ir_transmitter import IRTransmitterComponent -from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_FREQUENCY, CONF_COMMAND, CONF_DATA, \ - CONF_INVERTED, CONF_IR_TRANSMITTER_ID, CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, \ - CONF_PANASONIC, CONF_RAW, CONF_REPEAT, CONF_SONY, CONF_TIMES, CONF_WAIT_TIME -from esphomeyaml.core import ESPHomeYAMLError -from esphomeyaml.helpers import App, ArrayInitializer, HexIntLiteral, get_variable - -DEPENDENCIES = ['ir_transmitter'] - -IR_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW] - -WAIT_TIME_MESSAGE = "The wait_time_us option has been renamed to wait_time in order to decrease " \ - "ambiguity. " - -PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({ - vol.Exclusive(CONF_NEC, 'code'): vol.Schema({ - vol.Required(CONF_ADDRESS): cv.hex_uint16_t, - vol.Required(CONF_COMMAND): cv.hex_uint16_t, - }), - vol.Exclusive(CONF_LG, 'code'): vol.Schema({ - vol.Required(CONF_DATA): cv.hex_uint32_t, - vol.Optional(CONF_NBITS, default=28): vol.All(vol.Coerce(int), vol.Range(min=0, max=32)), - }), - vol.Exclusive(CONF_SONY, 'code'): vol.Schema({ - vol.Required(CONF_DATA): cv.hex_uint32_t, - vol.Optional(CONF_NBITS, default=12): vol.All(vol.Coerce(int), vol.Range(min=0, max=32)), - }), - vol.Exclusive(CONF_PANASONIC, 'code'): vol.Schema({ - vol.Required(CONF_ADDRESS): cv.hex_uint16_t, - vol.Required(CONF_COMMAND): cv.hex_uint32_t, - }), - vol.Exclusive(CONF_RAW, 'code'): vol.Schema({ - vol.Required(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)), - vol.Required(CONF_DATA): [vol.Coerce(int)], - }), - vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({ - vol.Required(CONF_TIMES): cv.positive_not_null_int, - vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds, - - vol.Optional('wait_time_us'): cv.invalid(WAIT_TIME_MESSAGE), - })), - cv.GenerateID(CONF_IR_TRANSMITTER_ID): cv.use_variable_id(IRTransmitterComponent), - vol.Optional(CONF_INVERTED): cv.invalid("IR Transmitters do not support inverted mode!"), -}).extend(switch.SWITCH_SCHEMA.schema), cv.has_at_least_one_key(*IR_KEYS)) - -# pylint: disable=invalid-name -ir_ns = switch.switch_ns.namespace('ir') -SendData = ir_ns.namespace('SendData') -DataTransmitter = IRTransmitterComponent.DataTransmitter - - -def safe_hex(value): - if value is None: - return None - return HexIntLiteral(value) - - -def exp_send_data(config): - if CONF_NEC in config: - conf = config[CONF_NEC] - base = SendData.from_nec(safe_hex(conf[CONF_ADDRESS]), - safe_hex(conf[CONF_COMMAND])) - elif CONF_LG in config: - conf = config[CONF_LG] - base = SendData.from_lg(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS)) - elif CONF_SONY in config: - conf = config[CONF_SONY] - base = SendData.from_sony(safe_hex(conf[CONF_DATA]), conf.get(CONF_NBITS)) - elif CONF_PANASONIC in config: - conf = config[CONF_PANASONIC] - base = SendData.from_panasonic(safe_hex(conf[CONF_ADDRESS]), - safe_hex(conf[CONF_COMMAND])) - elif CONF_RAW in config: - conf = config[CONF_RAW] - data = ArrayInitializer(*conf[CONF_DATA]) - base = SendData.from_raw(data, conf[CONF_CARRIER_FREQUENCY]) - else: - raise ESPHomeYAMLError(u"Unsupported IR mode {}".format(config)) - - if CONF_REPEAT in config: - if isinstance(config[CONF_REPEAT], int): - times = config[CONF_REPEAT] - wait_us = None - else: - times = config[CONF_REPEAT][CONF_TIMES] - wait_us = config[CONF_REPEAT][CONF_WAIT_TIME] - base = base.repeat(times, wait_us) - return base - - -def to_code(config): - ir = None - for ir in get_variable(config[CONF_IR_TRANSMITTER_ID]): - yield - send_data = exp_send_data(config) - rhs = App.register_component(ir.create_transmitter(config[CONF_NAME], send_data)) - switch.register_switch(rhs, config) - - -BUILD_FLAGS = '-DUSE_IR_TRANSMITTER' diff --git a/esphomeyaml/components/switch/output.py b/esphomeyaml/components/switch/output.py index d676497458..6c47b750b4 100644 --- a/esphomeyaml/components/switch/output.py +++ b/esphomeyaml/components/switch/output.py @@ -7,10 +7,10 @@ from esphomeyaml.helpers import App, Application, get_variable, variable MakeSimpleSwitch = Application.MakeSimpleSwitch -PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeSimpleSwitch), vol.Required(CONF_OUTPUT): cv.use_variable_id(None), -}).extend(switch.SWITCH_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/switch/remote_transmitter.py b/esphomeyaml/components/switch/remote_transmitter.py new file mode 100644 index 0000000000..c594810adf --- /dev/null +++ b/esphomeyaml/components/switch/remote_transmitter.py @@ -0,0 +1,98 @@ +import voluptuous as vol + +import esphomeyaml.config_validation as cv +from esphomeyaml.components import switch +from esphomeyaml.components.remote_transmitter import RemoteTransmitterComponent, remote_ns +from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_FREQUENCY, CONF_COMMAND, CONF_DATA, \ + CONF_INVERTED, CONF_LG, CONF_NAME, CONF_NBITS, CONF_NEC, \ + CONF_PANASONIC, CONF_RAW, CONF_REPEAT, CONF_SONY, CONF_TIMES, CONF_WAIT_TIME +from esphomeyaml.core import ESPHomeYAMLError +from esphomeyaml.helpers import App, ArrayInitializer, HexIntLiteral, get_variable, Pvariable, add + +DEPENDENCIES = ['remote_transmitter'] + +IR_KEYS = [CONF_NEC, CONF_LG, CONF_SONY, CONF_PANASONIC, CONF_RAW] + +CONF_REMOTE_TRANSMITTER_ID = 'remote_transmitter_id' +CONF_TRANSMITTER_ID = 'transmitter_id' + +RemoteTransmitter = remote_ns.RemoteTransmitter +LGTransmitter = remote_ns.LGTransmitter +NECTransmitter = remote_ns.NECTransmitter +PanasonicTransmitter = remote_ns.PanasonicTransmitter +RawTransmitter = remote_ns.RawTransmitter +SonyTransmitter = remote_ns.SonyTransmitter + +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ + 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)), + }), + vol.Optional(CONF_NEC): vol.Schema({ + vol.Required(CONF_ADDRESS): cv.hex_uint16_t, + vol.Required(CONF_COMMAND): cv.hex_uint16_t, + }), + vol.Optional(CONF_SONY): vol.Schema({ + vol.Required(CONF_DATA): cv.hex_uint32_t, + vol.Optional(CONF_NBITS, default=12): vol.All(vol.Coerce(int), cv.one_of(12, 15, 20)), + }), + vol.Optional(CONF_PANASONIC): vol.Schema({ + vol.Required(CONF_ADDRESS): cv.hex_uint16_t, + vol.Required(CONF_COMMAND): cv.hex_uint32_t, + }), + vol.Optional(CONF_RAW): vol.Schema({ + vol.Required(CONF_DATA): [vol.Any(vol.Coerce(int), cv.time_period_microseconds)], + vol.Optional(CONF_CARRIER_FREQUENCY): vol.All(cv.frequency, vol.Coerce(int)), + }), + vol.Optional(CONF_REPEAT): vol.Any(cv.positive_not_null_int, vol.Schema({ + vol.Required(CONF_TIMES): cv.positive_not_null_int, + vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds, + })), + cv.GenerateID(CONF_REMOTE_TRANSMITTER_ID): cv.use_variable_id(RemoteTransmitterComponent), + cv.GenerateID(CONF_TRANSMITTER_ID): cv.declare_variable_id(RemoteTransmitter), + + vol.Optional(CONF_INVERTED): cv.invalid("Remote Transmitters do not support inverted mode!"), +}), cv.has_exactly_one_key(*IR_KEYS)) + + +def transmitter_base(config): + if CONF_LG in config: + conf = config[CONF_LG] + return LGTransmitter.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS]) + elif CONF_NEC in config: + conf = config[CONF_NEC] + return NECTransmitter.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND]) + elif CONF_PANASONIC in config: + conf = config[CONF_PANASONIC] + return PanasonicTransmitter.new(config[CONF_NAME], conf[CONF_ADDRESS], conf[CONF_COMMAND]) + elif CONF_SONY in config: + conf = config[CONF_SONY] + return SonyTransmitter.new(config[CONF_NAME], conf[CONF_DATA], conf[CONF_NBITS]) + elif CONF_RAW in config: + conf = config[CONF_RAW] + data = ArrayInitializer(*conf[CONF_DATA]) + return RawTransmitter.new(data, conf[CONF_CARRIER_FREQUENCY]) + else: + raise ValueError("Unknown transmitter type {}".format(config)) + + +def to_code(config): + remote = None + for remote in get_variable(config[CONF_REMOTE_TRANSMITTER_ID]): + yield + rhs = App.register_component(transmitter_base(config)) + transmitter = Pvariable(config[CONF_TRANSMITTER_ID], rhs) + + if CONF_REPEAT in config: + if isinstance(config[CONF_REPEAT], int): + times = config[CONF_REPEAT] + wait_us = 1000 + else: + times = config[CONF_REPEAT][CONF_TIMES] + wait_us = config[CONF_REPEAT][CONF_WAIT_TIME] + add(transmitter.set_repeat(times, wait_us)) + + switch.register_switch(remote.add_transmitter(transmitter), config) + + +BUILD_FLAGS = '-DUSE_REMOTE_TRANSMITTER' diff --git a/esphomeyaml/components/switch/restart.py b/esphomeyaml/components/switch/restart.py index e28a601307..5edd01dab9 100644 --- a/esphomeyaml/components/switch/restart.py +++ b/esphomeyaml/components/switch/restart.py @@ -7,10 +7,10 @@ from esphomeyaml.helpers import App, Application, variable MakeRestartSwitch = Application.MakeRestartSwitch -PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeRestartSwitch), vol.Optional(CONF_INVERTED): cv.invalid("Restart switches do not support inverted mode!"), -}).extend(switch.SWITCH_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/switch/shutdown.py b/esphomeyaml/components/switch/shutdown.py index 8e8d98fbfa..641b84108c 100644 --- a/esphomeyaml/components/switch/shutdown.py +++ b/esphomeyaml/components/switch/shutdown.py @@ -7,10 +7,10 @@ from esphomeyaml.helpers import App, Application, variable MakeShutdownSwitch = Application.MakeShutdownSwitch -PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeShutdownSwitch), vol.Optional(CONF_INVERTED): cv.invalid("Shutdown switches do not support inverted mode!"), -}).extend(switch.SWITCH_SCHEMA.schema) +})) def to_code(config): diff --git a/esphomeyaml/components/switch/template.py b/esphomeyaml/components/switch/template.py index cbad5833c6..811b3b9343 100644 --- a/esphomeyaml/components/switch/template.py +++ b/esphomeyaml/components/switch/template.py @@ -10,13 +10,13 @@ from esphomeyaml.helpers import App, Application, process_lambda, variable, NoAr MakeTemplateSwitch = Application.MakeTemplateSwitch -PLATFORM_SCHEMA = vol.All(switch.PLATFORM_SCHEMA.extend({ +PLATFORM_SCHEMA = cv.nameable(switch.SWITCH_PLATFORM_SCHEMA.extend({ 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.ACTIONS_SCHEMA, vol.Optional(CONF_TURN_ON_ACTION): automation.ACTIONS_SCHEMA, -}).extend(switch.SWITCH_SCHEMA.schema), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) +}), cv.has_at_least_one_key(CONF_LAMBDA, CONF_OPTIMISTIC)) def to_code(config): diff --git a/esphomeyaml/components/wifi.py b/esphomeyaml/components/wifi.py index a929d16a26..3c8d81ed47 100644 --- a/esphomeyaml/components/wifi.py +++ b/esphomeyaml/components/wifi.py @@ -3,7 +3,7 @@ import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml import core from esphomeyaml.const import CONF_AP, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \ - CONF_GATEWAY, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_SSID, \ + CONF_GATEWAY, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_NETWORKS, CONF_PASSWORD, CONF_SSID, \ CONF_STATIC_IP, CONF_SUBNET, ESP_PLATFORM_ESP8266 from esphomeyaml.helpers import App, Pvariable, StructInitializer, add, esphomelib_ns, global_ns @@ -19,6 +19,15 @@ def validate_password(value): return value +def validate_channel(value): + value = cv.positive_int(value) + if value < 1: + raise vol.Invalid("Minimum WiFi channel is 1") + if value > 14: + raise vol.Invalid("Maximum WiFi channel is 14") + return value + + AP_MANUAL_IP_SCHEMA = vol.Schema({ vol.Required(CONF_STATIC_IP): cv.ipv4, vol.Required(CONF_GATEWAY): cv.ipv4, @@ -30,34 +39,64 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({ vol.Inclusive(CONF_DNS2, 'dns'): cv.ipv4, }) +CONF_BSSID = 'bssid' + +WIFI_NETWORK_BASE = vol.Schema({ + vol.Optional(CONF_SSID): cv.ssid, + vol.Optional(CONF_PASSWORD): validate_password, + vol.Optional(CONF_BSSID): cv.mac_address, + vol.Optional(CONF_CHANNEL): validate_channel, + vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA, +}) + +WIFI_NETWORK_AP = vol.All(WIFI_NETWORK_BASE.extend({ + vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA, +}), cv.has_at_least_one_key(CONF_SSID, CONF_BSSID)) + +WIFI_NETWORK_STA = vol.All(WIFI_NETWORK_BASE.extend({ + vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, +}), cv.has_at_least_one_key(CONF_SSID, CONF_BSSID)) + + +def validate_multi_wifi(config): + if CONF_PASSWORD in config and CONF_SSID not in config: + raise vol.Invalid("Cannot have WiFi password without SSID!") + if CONF_SSID in config and CONF_NETWORKS in config: + raise vol.Invalid("For multi-wifi mode (with 'networks:'), please specify all " + "networks within the 'networks:' key!") + + return config + + # pylint: disable=invalid-name IPAddress = global_ns.IPAddress ManualIP = esphomelib_ns.ManualIP WiFiComponent = esphomelib_ns.WiFiComponent +WiFiAp = esphomelib_ns.WiFiAp -CONFIG_SCHEMA = vol.Schema({ +CONFIG_SCHEMA = vol.All(vol.Schema({ cv.GenerateID(): cv.declare_variable_id(WiFiComponent), vol.Optional(CONF_SSID): cv.ssid, vol.Optional(CONF_PASSWORD): validate_password, - vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, - vol.Optional(CONF_AP): vol.Schema({ - vol.Required(CONF_SSID): cv.ssid, - vol.Optional(CONF_PASSWORD): validate_password, - vol.Optional(CONF_CHANNEL): vol.All(cv.positive_int, vol.Range(min=1, max=14)), - vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA, - }), + vol.Optional(CONF_NETWORKS): vol.All(cv.ensure_list, [WIFI_NETWORK_STA]), + vol.Optional(CONF_AP): WIFI_NETWORK_AP, vol.Optional(CONF_HOSTNAME): cv.hostname, vol.Optional(CONF_DOMAIN, default='.local'): cv.domainname, -}) + + vol.Optional(CONF_MANUAL_IP): cv.invalid("Manual IPs can only be specified in the 'networks:' " + "section of the WiFi configuration since 1.7.0"), +}), validate_multi_wifi) def safe_ip(ip): if ip is None: - return None + return IPAddress(0, 0, 0, 0) return IPAddress(*ip.args) def manual_ip(config): + if config is None: + return None return StructInitializer( ManualIP, ('static_ip', safe_ip(config[CONF_STATIC_IP])), @@ -68,27 +107,29 @@ def manual_ip(config): ) +def wifi_network(config): + return StructInitializer( + WiFiAp, + ('ssid', config.get(CONF_SSID, "")), + ('password', config.get(CONF_PASSWORD, "")), + ('bssid', config.get(CONF_BSSID, core.MACAddress(0, 0, 0, 0, 0, 0)).as_hex()), + ('channel', config.get(CONF_CHANNEL, -1)), + ('manual_ip', manual_ip(config.get(CONF_MANUAL_IP))), + ) + + def to_code(config): - sta = CONF_SSID in config - ap = CONF_AP in config - if sta: + if CONF_SSID in config: rhs = App.init_wifi(config[CONF_SSID], config.get(CONF_PASSWORD)) else: rhs = App.init_wifi() wifi = Pvariable(config[CONF_ID], rhs) - if sta and CONF_MANUAL_IP in config: - add(wifi.set_sta_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) + for network in config.get(CONF_NETWORKS, []): + add(wifi.add_sta(wifi_network(network))) - if ap: - conf = config[CONF_AP] - password = config.get(CONF_PASSWORD) - if password is None and CONF_CHANNEL in conf: - password = u"" - add(wifi.set_ap(conf[CONF_SSID], password, conf.get(CONF_CHANNEL))) - - if CONF_MANUAL_IP in conf: - add(wifi.set_ap_manual_ip(manual_ip(conf[CONF_MANUAL_IP]))) + if CONF_AP in config: + add(wifi.set_ap(wifi_network(config[CONF_AP]))) if CONF_HOSTNAME in config: add(wifi.set_hostname(config[CONF_HOSTNAME])) diff --git a/esphomeyaml/config.py b/esphomeyaml/config.py index 6aa2489097..e109e09049 100644 --- a/esphomeyaml/config.py +++ b/esphomeyaml/config.py @@ -220,7 +220,7 @@ def validate_config(config): continue platform = get_platform(domain, p_name) if platform is None: - result.add_error(u"Platform not found: {}.{}") + result.add_error(u"Platform not found: {}.{}".format(domain, p_name)) continue success = True diff --git a/esphomeyaml/config_validation.py b/esphomeyaml/config_validation.py index 7bb848435c..9b3aa4c3d7 100644 --- a/esphomeyaml/config_validation.py +++ b/esphomeyaml/config_validation.py @@ -11,7 +11,7 @@ from esphomeyaml import core from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_ID, \ CONF_NAME, CONF_PAYLOAD_AVAILABLE, \ CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \ - ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 + ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, CONF_INTERNAL from esphomeyaml.core import HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \ TimePeriodMilliseconds, TimePeriodSeconds @@ -325,10 +325,29 @@ time_period = vol.Any(time_period_str_unit, time_period_str_colon, time_period_d positive_time_period = vol.All(time_period, vol.Range(min=TimePeriod())) positive_time_period_milliseconds = vol.All(positive_time_period, time_period_in_milliseconds_) positive_time_period_seconds = vol.All(positive_time_period, time_period_in_seconds_) +time_period_microseconds = vol.All(time_period, time_period_in_microseconds_) positive_time_period_microseconds = vol.All(positive_time_period, time_period_in_microseconds_) positive_not_null_time_period = vol.All(time_period, vol.Range(min=TimePeriod(), min_included=False)) + +def mac_address(value): + value = string_strict(value) + parts = value.split(':') + if len(parts) != 6: + raise vol.Invalid("MAC Address must consist of 6 : (colon) separated parts") + parts_int = [] + if any(len(part) != 2 for part in parts): + raise vol.Invalid("MAC Address must be format XX:XX:XX:XX:XX:XX") + for part in parts: + try: + parts_int.append(int(part, 16)) + except ValueError: + raise vol.Invalid("MAC Address parts must be hexadecimal values from 00 to FF") + + return core.MACAddress(*parts_int) + + METRIC_SUFFIXES = { 'E': 1e18, 'P': 1e15, 'T': 1e12, 'G': 1e9, 'M': 1e6, 'k': 1e3, 'da': 10, 'd': 1e-1, 'c': 1e-2, 'm': 0.001, u'ยต': 1e-6, 'u': 1e-6, 'n': 1e-9, 'p': 1e-12, 'f': 1e-15, 'a': 1e-18, @@ -352,6 +371,23 @@ def frequency(value): return mantissa * multiplier +def validate_bytes(value): + value = string(value) + match = re.match(r"^([0-9]+)\s*(\w*?)(?:byte|B|b)?s?$", value) + + if match is None: + raise vol.Invalid(u"Expected number of bytes with unit, got {}".format(value)) + + mantissa = int(match.group(1)) + if match.group(2) not in METRIC_SUFFIXES: + raise vol.Invalid(u"Invalid metric suffix {}".format(match.group(2))) + multiplier = METRIC_SUFFIXES[match.group(2)] + if multiplier < 1: + raise vol.Invalid(u"Only suffixes with positive exponents are supported. " + u"Got {}".format(match.group(2))) + return int(mantissa * multiplier) + + def hostname(value): value = string(value) if len(value) > 63: @@ -482,6 +518,12 @@ def percentage(value): return zero_to_one_float(value) +def percentage_int(value): + if isinstance(value, (str, unicode)) and value.endswith('%'): + value = int(value[:-1].rstrip()) + return value + + def invalid(message): def validator(value): raise vol.Invalid(message) @@ -518,6 +560,23 @@ class GenerateID(vol.Optional): super(GenerateID, self).__init__(key, default=lambda: None) +def nameable(*schemas): + def validator(config): + config = vol.All(*schemas)(config) + if CONF_NAME not in config and CONF_ID not in config: + raise vol.Invalid("At least one of 'id:' or 'name:' is required!") + if CONF_NAME not in config: + id = config[CONF_ID] + if not id.is_manual: + raise vol.Invalid("At least one of 'id:' or 'name:' is required!") + config[CONF_NAME] = id.id + config[CONF_INTERNAL] = True + return config + return config + + return validator + + PLATFORM_SCHEMA = vol.Schema({ vol.Required(CONF_PLATFORM): valid, }) @@ -529,11 +588,12 @@ MQTT_COMPONENT_AVAILABILITY_SCHEMA = vol.Schema({ }) MQTT_COMPONENT_SCHEMA = vol.Schema({ - vol.Required(CONF_NAME): string, + vol.Optional(CONF_NAME): string, vol.Optional(CONF_RETAIN): boolean, vol.Optional(CONF_DISCOVERY): boolean, vol.Optional(CONF_STATE_TOPIC): publish_topic, vol.Optional(CONF_AVAILABILITY): vol.Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA), + vol.Optional(CONF_INTERNAL): boolean, }) MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend({ diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index 8e94a3b09c..94b8521662 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -148,7 +148,6 @@ CONF_TRIGGER_PIN = 'trigger_pin' CONF_ECHO_PIN = 'echo_pin' CONF_TIMEOUT_METER = 'timeout_meter' CONF_TIMEOUT_TIME = 'timeout_time' -CONF_IR_TRANSMITTER_ID = 'ir_transmitter_id' CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent' CONF_NEC = 'nec' CONF_COMMAND = 'command' @@ -234,6 +233,13 @@ CONF_OPTIMISTIC = 'optimistic' CONF_ON_BOOT = 'on_boot' CONF_ON_SHUTDOWN = 'on_shutdown' CONF_PRIORITY = 'priority' +CONF_DUMP = 'dump' +CONF_BUFFER_SIZE = 'buffer_size' +CONF_TOLERANCE = 'tolerance' +CONF_FILTER = 'filter' +CONF_IDLE = 'idle' +CONF_NETWORKS = 'networks' +CONF_INTERNAL = 'internal' ESP32_BOARDS = [ 'featheresp32', 'node32s', 'espea32', 'firebeetle32', 'esp32doit-devkit-v1', diff --git a/esphomeyaml/core.py b/esphomeyaml/core.py index ba0fd1a636..fd437263c6 100644 --- a/esphomeyaml/core.py +++ b/esphomeyaml/core.py @@ -32,6 +32,12 @@ class MACAddress(object): def __str__(self): return ':'.join('{:02X}'.format(part) for part in self.parts) + def as_hex(self): + import esphomeyaml.helpers + + num = ''.join('{:02X}'.format(part) for part in self.parts) + return esphomeyaml.helpers.RawExpression('0x{}ULL'.format(num)) + def is_approximately_integer(value): if isinstance(value, (int, long)):