mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-04 09:01:49 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					dc516f7537 | ||
| 
						 | 
					44f2b582b5 | ||
| 
						 | 
					262855ff62 | 
@@ -13,10 +13,6 @@ COPY docker/platformio.ini /usr/src/app/
 | 
			
		||||
RUN platformio settings set enable_telemetry No && \
 | 
			
		||||
    platformio run -e espressif32 -e espressif8266; exit 0
 | 
			
		||||
 | 
			
		||||
# Fix issue with static IP on ESP32: https://github.com/espressif/arduino-esp32/issues/1081
 | 
			
		||||
RUN curl https://github.com/espressif/arduino-esp32/commit/144480637a718844b8f48f4392da8d4f622f2e5e.patch | \
 | 
			
		||||
    patch /root/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src/WiFiGeneric.cpp
 | 
			
		||||
 | 
			
		||||
COPY . .
 | 
			
		||||
RUN pip install -e .
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -156,6 +156,10 @@ def upload_program(config, args, port):
 | 
			
		||||
        return run_platformio('platformio', 'run', '-d', get_base_path(config),
 | 
			
		||||
                              '-t', 'upload', '--upload-port', port)
 | 
			
		||||
 | 
			
		||||
    if 'ota' not in config:
 | 
			
		||||
        _LOGGER.error("No serial port found and OTA not enabled. Can't upload!")
 | 
			
		||||
        return -1
 | 
			
		||||
 | 
			
		||||
    if CONF_MANUAL_IP in config[CONF_WIFI]:
 | 
			
		||||
        host = str(config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP])
 | 
			
		||||
    elif CONF_HOSTNAME in config[CONF_WIFI]:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,27 +2,19 @@ import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_RATE
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable, RawExpression, add, HexIntLiteral
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
ADS1115_COMPONENT_CLASS = 'sensor::ADS1115Component'
 | 
			
		||||
 | 
			
		||||
RATES = {
 | 
			
		||||
    8: 'ADS1115_RATE_8',
 | 
			
		||||
    16: 'ADS1115_RATE_16',
 | 
			
		||||
    32: 'ADS1115_RATE_32',
 | 
			
		||||
    64: 'ADS1115_RATE_64',
 | 
			
		||||
    128: 'ADS1115_RATE_128',
 | 
			
		||||
    250: 'ADS1115_RATE_250',
 | 
			
		||||
    475: 'ADS1115_RATE_475',
 | 
			
		||||
    860: 'ADS1115_RATE_860',
 | 
			
		||||
}
 | 
			
		||||
RATE_REMOVE_MESSAGE = """The rate option has been removed in 1.5.0 and is no longer required."""
 | 
			
		||||
 | 
			
		||||
ADS1115_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('ads1115'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_ADDRESS): cv.i2c_address,
 | 
			
		||||
    vol.Optional(CONF_RATE): vol.All(vol.Coerce(int), vol.Any(*list(RATES.keys()))),
 | 
			
		||||
 | 
			
		||||
    vol.Optional(CONF_RATE): cv.invalid(RATE_REMOVE_MESSAGE)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
 | 
			
		||||
@@ -30,11 +22,8 @@ CONFIG_SCHEMA = vol.All(cv.ensure_list, [ADS1115_SCHEMA])
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    for conf in config:
 | 
			
		||||
        address = HexIntLiteral(conf[CONF_ADDRESS])
 | 
			
		||||
        rhs = App.make_ads1115_component(address)
 | 
			
		||||
        ads1115 = Pvariable(ADS1115_COMPONENT_CLASS, conf[CONF_ID], rhs)
 | 
			
		||||
        if CONF_RATE in conf:
 | 
			
		||||
            add(ads1115.set_rate(RawExpression(RATES[conf[CONF_RATE]])))
 | 
			
		||||
        rhs = App.make_ads1115_component(conf[CONF_ADDRESS])
 | 
			
		||||
        Pvariable(ADS1115_COMPONENT_CLASS, conf[CONF_ID], rhs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_ADS1115_SENSOR'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_INVERTED
 | 
			
		||||
from esphomeyaml.helpers import add, setup_mqtt_component
 | 
			
		||||
from esphomeyaml.const import CONF_DEVICE_CLASS, CONF_INVERTED, CONF_MQTT_ID
 | 
			
		||||
from esphomeyaml.helpers import add, setup_mqtt_component, App, Pvariable
 | 
			
		||||
 | 
			
		||||
DEVICE_CLASSES = [
 | 
			
		||||
    '', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas',
 | 
			
		||||
@@ -23,6 +23,10 @@ MQTT_BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
MQTT_BINARY_SENSOR_ID_SCHEMA = MQTT_BINARY_SENSOR_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('mqtt_binary_sensor', CONF_MQTT_ID): cv.register_variable_id,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def setup_binary_sensor(obj, config):
 | 
			
		||||
    if CONF_DEVICE_CLASS in config:
 | 
			
		||||
@@ -35,4 +39,11 @@ def setup_mqtt_binary_sensor(obj, config):
 | 
			
		||||
    setup_mqtt_component(obj, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def register_binary_sensor(var, config):
 | 
			
		||||
    setup_binary_sensor(var, config)
 | 
			
		||||
    rhs = App.register_binary_sensor(var)
 | 
			
		||||
    mqtt_sensor = Pvariable('binary_sensor::MQTTBinarySensorComponent', config[CONF_MQTT_ID], rhs)
 | 
			
		||||
    setup_mqtt_binary_sensor(mqtt_sensor, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_BINARY_SENSOR'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								esphomeyaml/components/binary_sensor/esp32_ble.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								esphomeyaml/components/binary_sensor/esp32_ble.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import binary_sensor
 | 
			
		||||
from esphomeyaml.const import CONF_ID, CONF_MAC_ADDRESS, CONF_NAME, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.core import HexInt, MACAddress
 | 
			
		||||
from esphomeyaml.helpers import ArrayInitializer, Pvariable, get_variable
 | 
			
		||||
 | 
			
		||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
 | 
			
		||||
DEPENDENCIES = ['esp32_ble']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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({
 | 
			
		||||
    cv.GenerateID('esp32_ble_device'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_MAC_ADDRESS): validate_mac,
 | 
			
		||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_ID_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    hub = get_variable(None, type='ESP32BLETracker')
 | 
			
		||||
    addr = [HexInt(i) for i in config[CONF_MAC_ADDRESS].parts]
 | 
			
		||||
    rhs = hub.make_device(config[CONF_NAME], ArrayInitializer(*addr, multiline=False))
 | 
			
		||||
    device = Pvariable('ESP32BLEDevice', config[CONF_ID], rhs)
 | 
			
		||||
    binary_sensor.register_binary_sensor(device, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
 | 
			
		||||
							
								
								
									
										49
									
								
								esphomeyaml/components/binary_sensor/esp32_touch.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								esphomeyaml/components/binary_sensor/esp32_touch.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import binary_sensor
 | 
			
		||||
from esphomeyaml.const import CONF_ID, CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.helpers import Pvariable, RawExpression, get_variable
 | 
			
		||||
from esphomeyaml.pins import validate_gpio_pin
 | 
			
		||||
 | 
			
		||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['esp32_touch']
 | 
			
		||||
 | 
			
		||||
TOUCH_PADS = {
 | 
			
		||||
    4: 'TOUCH_PAD_NUM0',
 | 
			
		||||
    0: 'TOUCH_PAD_NUM1',
 | 
			
		||||
    2: 'TOUCH_PAD_NUM2',
 | 
			
		||||
    15: 'TOUCH_PAD_NUM3',
 | 
			
		||||
    13: 'TOUCH_PAD_NUM4',
 | 
			
		||||
    12: 'TOUCH_PAD_NUM5',
 | 
			
		||||
    14: 'TOUCH_PAD_NUM6',
 | 
			
		||||
    27: 'TOUCH_PAD_NUM7',
 | 
			
		||||
    33: 'TOUCH_PAD_NUM8',
 | 
			
		||||
    32: 'TOUCH_PAD_NUM9',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validate_touch_pad(value):
 | 
			
		||||
    value = validate_gpio_pin(value)
 | 
			
		||||
    if value not in TOUCH_PADS:
 | 
			
		||||
        raise vol.Invalid("Pin {} does not support touch pads.".format(value))
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('esp32_touch_pad'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_PIN): validate_touch_pad,
 | 
			
		||||
    vol.Required(CONF_THRESHOLD): cv.uint16_t,
 | 
			
		||||
}).extend(binary_sensor.MQTT_BINARY_SENSOR_ID_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    hub = get_variable(None, type='binary_sensor::ESP32TouchComponent')
 | 
			
		||||
    touch_pad = RawExpression(TOUCH_PADS[config[CONF_PIN]])
 | 
			
		||||
    rhs = hub.make_touch_pad(config[CONF_NAME], touch_pad, config[CONF_THRESHOLD])
 | 
			
		||||
    device = Pvariable('ESP32TouchBinarySensor', config[CONF_ID], rhs)
 | 
			
		||||
    binary_sensor.register_binary_sensor(device, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_ESP32_TOUCH_BINARY_SENSOR'
 | 
			
		||||
@@ -10,7 +10,7 @@ DALLAS_COMPONENT_CLASS = 'sensor::DallasComponent'
 | 
			
		||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
 | 
			
		||||
    cv.GenerateID('dallas'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_PIN): pins.input_output_pin,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,11 +16,11 @@ def validate_pin_number(value):
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('deep_sleep'): cv.register_variable_id,
 | 
			
		||||
    vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds,
 | 
			
		||||
    vol.Optional(CONF_WAKEUP_PIN): vol.All(cv.only_on_esp32, pins.GPIO_INPUT_PIN_SCHEMA,
 | 
			
		||||
                                           pins.schema_validate_number(validate_pin_number)),
 | 
			
		||||
    vol.Optional(CONF_RUN_CYCLES): cv.positive_int,
 | 
			
		||||
    vol.Optional(CONF_RUN_DURATION): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								esphomeyaml/components/esp32_ble.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								esphomeyaml/components/esp32_ble.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
from esphomeyaml import config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_ID, CONF_SCAN_INTERVAL, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable, add
 | 
			
		||||
 | 
			
		||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('esp32_ble'): cv.register_variable_id,
 | 
			
		||||
    vol.Optional(CONF_SCAN_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_esp32_ble_tracker()
 | 
			
		||||
    ble = Pvariable('ESP32BLETracker', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_SCAN_INTERVAL in config:
 | 
			
		||||
        add(ble.set_scan_interval(config[CONF_SCAN_INTERVAL]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_ESP32_BLE_TRACKER'
 | 
			
		||||
							
								
								
									
										83
									
								
								esphomeyaml/components/esp32_touch.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								esphomeyaml/components/esp32_touch.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
from esphomeyaml import config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_ID, CONF_SETUP_MODE, CONF_IIR_FILTER, \
 | 
			
		||||
    CONF_SLEEP_DURATION, CONF_MEASUREMENT_DURATION, CONF_LOW_VOLTAGE_REFERENCE, \
 | 
			
		||||
    CONF_HIGH_VOLTAGE_REFERENCE, CONF_VOLTAGE_ATTENUATION, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.core import TimePeriod
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable, add
 | 
			
		||||
 | 
			
		||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validate_voltage(values):
 | 
			
		||||
    def validator(value):
 | 
			
		||||
        if isinstance(value, float) and value.is_integer():
 | 
			
		||||
            value = int(value)
 | 
			
		||||
        value = cv.string(value)
 | 
			
		||||
        if not value.endswith('V'):
 | 
			
		||||
            value += 'V'
 | 
			
		||||
        if value not in values:
 | 
			
		||||
            raise vol.Invalid('Must be one of {}'.format(values))
 | 
			
		||||
        return value
 | 
			
		||||
    return validator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LOW_VOLTAGE_REFERENCE = {
 | 
			
		||||
    '0.5V': 'TOUCH_LVOLT_0V5',
 | 
			
		||||
    '0.6V': 'TOUCH_LVOLT_0V6',
 | 
			
		||||
    '0.7V': 'TOUCH_LVOLT_0V7',
 | 
			
		||||
    '0.8V': 'TOUCH_LVOLT_0V8',
 | 
			
		||||
}
 | 
			
		||||
HIGH_VOLTAGE_REFERENCE = {
 | 
			
		||||
    '2.4V': 'TOUCH_HVOLT_2V4',
 | 
			
		||||
    '2.5V': 'TOUCH_HVOLT_2V5',
 | 
			
		||||
    '2.6V': 'TOUCH_HVOLT_2V6',
 | 
			
		||||
    '2.7V': 'TOUCH_HVOLT_2V7',
 | 
			
		||||
}
 | 
			
		||||
VOLTAGE_ATTENUATION = {
 | 
			
		||||
    '1.5V': 'TOUCH_HVOLT_ATTEN_1V5',
 | 
			
		||||
    '1V': 'TOUCH_HVOLT_ATTEN_1V',
 | 
			
		||||
    '0.5V': 'TOUCH_HVOLT_ATTEN_0V5',
 | 
			
		||||
    '0V': 'TOUCH_HVOLT_ATTEN_0V',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('esp32_ble'): cv.register_variable_id,
 | 
			
		||||
    vol.Optional(CONF_SETUP_MODE): cv.boolean,
 | 
			
		||||
    vol.Optional(CONF_IIR_FILTER): cv.positive_time_period_milliseconds,
 | 
			
		||||
    vol.Optional(CONF_SLEEP_DURATION):
 | 
			
		||||
        vol.All(cv.positive_time_period, vol.Range(max=TimePeriod(microseconds=436906))),
 | 
			
		||||
    vol.Optional(CONF_MEASUREMENT_DURATION):
 | 
			
		||||
        vol.All(cv.positive_time_period, vol.Range(max=TimePeriod(microseconds=8192))),
 | 
			
		||||
    vol.Optional(CONF_LOW_VOLTAGE_REFERENCE): validate_voltage(LOW_VOLTAGE_REFERENCE),
 | 
			
		||||
    vol.Optional(CONF_HIGH_VOLTAGE_REFERENCE): validate_voltage(HIGH_VOLTAGE_REFERENCE),
 | 
			
		||||
    vol.Optional(CONF_VOLTAGE_ATTENUATION): validate_voltage(VOLTAGE_ATTENUATION),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_esp32_touch_component()
 | 
			
		||||
    touch = Pvariable('binary_sensor::ESP32TouchComponent', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_SETUP_MODE in config:
 | 
			
		||||
        add(touch.set_setup_mode(config[CONF_SETUP_MODE]))
 | 
			
		||||
    if CONF_IIR_FILTER in config:
 | 
			
		||||
        add(touch.set_iir_filter(config[CONF_IIR_FILTER]))
 | 
			
		||||
    if CONF_SLEEP_DURATION in config:
 | 
			
		||||
        sleep_duration = int(config[CONF_SLEEP_DURATION].total_microseconds * 6.6667)
 | 
			
		||||
        add(touch.set_sleep_duration(sleep_duration))
 | 
			
		||||
    if CONF_MEASUREMENT_DURATION in config:
 | 
			
		||||
        measurement_duration = int(config[CONF_MEASUREMENT_DURATION].total_microseconds * 0.125)
 | 
			
		||||
        add(touch.set_measurement_duration(measurement_duration))
 | 
			
		||||
    if CONF_LOW_VOLTAGE_REFERENCE in config:
 | 
			
		||||
        value = LOW_VOLTAGE_REFERENCE[config[CONF_LOW_VOLTAGE_REFERENCE]]
 | 
			
		||||
        add(touch.set_low_voltage_reference(value))
 | 
			
		||||
    if CONF_HIGH_VOLTAGE_REFERENCE in config:
 | 
			
		||||
        value = HIGH_VOLTAGE_REFERENCE[config[CONF_HIGH_VOLTAGE_REFERENCE]]
 | 
			
		||||
        add(touch.set_high_voltage_reference(value))
 | 
			
		||||
    if CONF_VOLTAGE_ATTENUATION in config:
 | 
			
		||||
        value = VOLTAGE_ATTENUATION[config[CONF_VOLTAGE_ATTENUATION]]
 | 
			
		||||
        add(touch.set_voltage_attenuation(value))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_ESP32_TOUCH_BINARY_SENSOR'
 | 
			
		||||
@@ -2,14 +2,16 @@ import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml import pins
 | 
			
		||||
from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CONF_ID
 | 
			
		||||
from esphomeyaml.const import CONF_FREQUENCY, CONF_SCL, CONF_SDA, CONF_SCAN, CONF_ID, \
 | 
			
		||||
    CONF_RECEIVE_TIMEOUT
 | 
			
		||||
from esphomeyaml.helpers import App, add, Pvariable
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('i2c'): cv.register_variable_id,
 | 
			
		||||
    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.only_on_esp32, cv.positive_int),
 | 
			
		||||
    vol.Optional(CONF_FREQUENCY): cv.positive_int,
 | 
			
		||||
    vol.Optional(CONF_RECEIVE_TIMEOUT): cv.positive_time_period_milliseconds,
 | 
			
		||||
    vol.Optional(CONF_SCAN): cv.boolean,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@@ -19,6 +21,10 @@ def to_code(config):
 | 
			
		||||
    i2c = Pvariable('I2CComponent', 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'
 | 
			
		||||
 | 
			
		||||
LIB_DEPS = 'Wire'
 | 
			
		||||
 
 | 
			
		||||
@@ -2,17 +2,16 @@ 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, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable, exp_gpio_output_pin
 | 
			
		||||
 | 
			
		||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
 | 
			
		||||
 | 
			
		||||
IR_TRANSMITTER_COMPONENT_CLASS = 'switch_::IRTransmitterComponent'
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [vol.Schema({
 | 
			
		||||
    cv.GenerateID('ir_transmitter'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int), vol.Range(min=0, max=100)),
 | 
			
		||||
    vol.Optional(CONF_CARRIER_DUTY_PERCENT): vol.All(vol.Coerce(int),
 | 
			
		||||
                                                     vol.Range(min=1, max=100)),
 | 
			
		||||
})])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH
 | 
			
		||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT
 | 
			
		||||
from esphomeyaml.helpers import add
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
 | 
			
		||||
@@ -10,6 +10,8 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({
 | 
			
		||||
def setup_light_component(obj, config):
 | 
			
		||||
    if CONF_DEFAULT_TRANSITION_LENGTH in config:
 | 
			
		||||
        add(obj.set_default_transition_length(config[CONF_DEFAULT_TRANSITION_LENGTH]))
 | 
			
		||||
    if CONF_GAMMA_CORRECT in config:
 | 
			
		||||
        add(obj.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_LIGHT'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								esphomeyaml/components/light/fastled_clockless.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								esphomeyaml/components/light/fastled_clockless.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml import pins
 | 
			
		||||
from esphomeyaml.components import light
 | 
			
		||||
from esphomeyaml.const import CONF_CHIPSET, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
 | 
			
		||||
    CONF_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, TemplateArguments, add, setup_mqtt_component, \
 | 
			
		||||
    variable
 | 
			
		||||
 | 
			
		||||
TYPES = [
 | 
			
		||||
    'NEOPIXEL',
 | 
			
		||||
    'TM1829',
 | 
			
		||||
    'TM1809',
 | 
			
		||||
    'TM1804',
 | 
			
		||||
    'TM1803',
 | 
			
		||||
    'UCS1903',
 | 
			
		||||
    'UCS1903B',
 | 
			
		||||
    'UCS1904',
 | 
			
		||||
    'UCS2903',
 | 
			
		||||
    'WS2812',
 | 
			
		||||
    'WS2852',
 | 
			
		||||
    'WS2812B',
 | 
			
		||||
    'SK6812',
 | 
			
		||||
    'SK6822',
 | 
			
		||||
    'APA106',
 | 
			
		||||
    'PL9823',
 | 
			
		||||
    'WS2811',
 | 
			
		||||
    'WS2813',
 | 
			
		||||
    'APA104',
 | 
			
		||||
    'WS2811_400',
 | 
			
		||||
    'GW6205',
 | 
			
		||||
    'GW6205_400',
 | 
			
		||||
    'LPD1886',
 | 
			
		||||
    'LPD1886_8BIT',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
RGB_ORDERS = [
 | 
			
		||||
    'RGB',
 | 
			
		||||
    'RBG',
 | 
			
		||||
    'GRB',
 | 
			
		||||
    'GBR',
 | 
			
		||||
    'BRG',
 | 
			
		||||
    'BGR',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validate(value):
 | 
			
		||||
    if value[CONF_CHIPSET] == 'NEOPIXEL' and CONF_RGB_ORDER in value:
 | 
			
		||||
        raise vol.Invalid("NEOPIXEL doesn't support RGB order")
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = vol.All(light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('fast_led_clockless_light'): cv.register_variable_id,
 | 
			
		||||
 | 
			
		||||
    vol.Required(CONF_CHIPSET): vol.All(vol.Upper, vol.Any(*TYPES)),
 | 
			
		||||
    vol.Required(CONF_PIN): pins.output_pin,
 | 
			
		||||
 | 
			
		||||
    vol.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
 | 
			
		||||
    vol.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
 | 
			
		||||
    vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, vol.Any(*RGB_ORDERS)),
 | 
			
		||||
 | 
			
		||||
    vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
 | 
			
		||||
}), validate)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_fast_led_light(config[CONF_NAME])
 | 
			
		||||
    make = variable('Application::MakeFastLEDLight', config[CONF_ID], rhs)
 | 
			
		||||
    fast_led = make.Pfast_led
 | 
			
		||||
 | 
			
		||||
    rgb_order = None
 | 
			
		||||
    if CONF_RGB_ORDER in config:
 | 
			
		||||
        rgb_order = RawExpression(config[CONF_RGB_ORDER])
 | 
			
		||||
    template_args = TemplateArguments(RawExpression(config[CONF_CHIPSET]),
 | 
			
		||||
                                      config[CONF_PIN], rgb_order)
 | 
			
		||||
    add(fast_led.add_leds(template_args, config[CONF_NUM_LEDS]))
 | 
			
		||||
 | 
			
		||||
    if CONF_MAX_REFRESH_RATE in config:
 | 
			
		||||
        add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
 | 
			
		||||
 | 
			
		||||
    setup_mqtt_component(make.Pmqtt, config)
 | 
			
		||||
    light.setup_light_component(make.Pstate, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
 | 
			
		||||
							
								
								
									
										69
									
								
								esphomeyaml/components/light/fastled_spi.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								esphomeyaml/components/light/fastled_spi.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml import pins
 | 
			
		||||
from esphomeyaml.components import light
 | 
			
		||||
from esphomeyaml.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, \
 | 
			
		||||
    CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, CONF_MAX_REFRESH_RATE, CONF_NAME, \
 | 
			
		||||
    CONF_NUM_LEDS, CONF_RGB_ORDER
 | 
			
		||||
from esphomeyaml.helpers import App, TemplateArguments, add, setup_mqtt_component, variable, \
 | 
			
		||||
    RawExpression
 | 
			
		||||
 | 
			
		||||
CHIPSETS = [
 | 
			
		||||
    'LPD8806',
 | 
			
		||||
    'WS2801',
 | 
			
		||||
    'WS2803',
 | 
			
		||||
    'SM16716',
 | 
			
		||||
    'P9813',
 | 
			
		||||
    'APA102',
 | 
			
		||||
    'SK9822',
 | 
			
		||||
    'DOTSTAR',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
RGB_ORDERS = [
 | 
			
		||||
    'RGB',
 | 
			
		||||
    'RBG',
 | 
			
		||||
    'GRB',
 | 
			
		||||
    'GBR',
 | 
			
		||||
    'BRG',
 | 
			
		||||
    'BGR',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('fast_led_spi_light'): cv.register_variable_id,
 | 
			
		||||
 | 
			
		||||
    vol.Required(CONF_CHIPSET): vol.All(vol.Upper, vol.Any(*CHIPSETS)),
 | 
			
		||||
    vol.Required(CONF_DATA_PIN): pins.output_pin,
 | 
			
		||||
    vol.Required(CONF_CLOCK_PIN): pins.output_pin,
 | 
			
		||||
 | 
			
		||||
    vol.Required(CONF_NUM_LEDS): cv.positive_not_null_int,
 | 
			
		||||
    vol.Optional(CONF_RGB_ORDER): vol.All(vol.Upper, vol.Any(*RGB_ORDERS)),
 | 
			
		||||
    vol.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds,
 | 
			
		||||
 | 
			
		||||
    vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_fast_led_light(config[CONF_NAME])
 | 
			
		||||
    make = variable('Application::MakeFastLEDLight', config[CONF_ID], rhs)
 | 
			
		||||
    fast_led = make.Pfast_led
 | 
			
		||||
 | 
			
		||||
    rgb_order = None
 | 
			
		||||
    if CONF_RGB_ORDER in config:
 | 
			
		||||
        rgb_order = RawExpression(config[CONF_RGB_ORDER])
 | 
			
		||||
    template_args = TemplateArguments(RawExpression(config[CONF_CHIPSET]),
 | 
			
		||||
                                      config[CONF_DATA_PIN],
 | 
			
		||||
                                      config[CONF_CLOCK_PIN],
 | 
			
		||||
                                      rgb_order)
 | 
			
		||||
    add(fast_led.add_leds(template_args, config[CONF_NUM_LEDS]))
 | 
			
		||||
 | 
			
		||||
    if CONF_MAX_REFRESH_RATE in config:
 | 
			
		||||
        add(fast_led.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE]))
 | 
			
		||||
 | 
			
		||||
    setup_mqtt_component(make.Pmqtt, config)
 | 
			
		||||
    light.setup_light_component(make.Pstate, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_FAST_LED_LIGHT'
 | 
			
		||||
@@ -4,13 +4,13 @@ import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import light
 | 
			
		||||
from esphomeyaml.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, CONF_ID, \
 | 
			
		||||
    CONF_NAME, CONF_OUTPUT
 | 
			
		||||
from esphomeyaml.helpers import App, add, get_variable, variable, setup_mqtt_component
 | 
			
		||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('monochromatic_light'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_OUTPUT): cv.variable_id,
 | 
			
		||||
    vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -18,7 +18,5 @@ def to_code(config):
 | 
			
		||||
    output = get_variable(config[CONF_OUTPUT])
 | 
			
		||||
    rhs = App.make_monochromatic_light(config[CONF_NAME], output)
 | 
			
		||||
    light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_GAMMA_CORRECT in config:
 | 
			
		||||
        add(light_struct.Poutput.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
 | 
			
		||||
    setup_mqtt_component(light_struct.Pmqtt, config)
 | 
			
		||||
    light.setup_light_component(light_struct.Pstate, config)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import light
 | 
			
		||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
 | 
			
		||||
    CONF_GREEN, CONF_ID, CONF_NAME, CONF_RED
 | 
			
		||||
from esphomeyaml.helpers import App, add, get_variable, variable, setup_mqtt_component
 | 
			
		||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('rgb_light'): cv.register_variable_id,
 | 
			
		||||
@@ -12,7 +12,7 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_GREEN): cv.variable_id,
 | 
			
		||||
    vol.Required(CONF_BLUE): cv.variable_id,
 | 
			
		||||
    vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -22,7 +22,5 @@ def to_code(config):
 | 
			
		||||
    blue = get_variable(config[CONF_BLUE])
 | 
			
		||||
    rhs = App.make_rgb_light(config[CONF_NAME], red, green, blue)
 | 
			
		||||
    light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_GAMMA_CORRECT in config:
 | 
			
		||||
        add(light_struct.Poutput.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
 | 
			
		||||
    setup_mqtt_component(light_struct.Pmqtt, config)
 | 
			
		||||
    light.setup_light_component(light_struct.Pstate, config)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import light
 | 
			
		||||
from esphomeyaml.const import CONF_BLUE, CONF_DEFAULT_TRANSITION_LENGTH, CONF_GAMMA_CORRECT, \
 | 
			
		||||
    CONF_GREEN, CONF_ID, CONF_NAME, CONF_RED, CONF_WHITE
 | 
			
		||||
from esphomeyaml.helpers import App, add, get_variable, setup_mqtt_component, variable
 | 
			
		||||
from esphomeyaml.helpers import App, get_variable, setup_mqtt_component, variable
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('rgbw_light'): cv.register_variable_id,
 | 
			
		||||
@@ -13,7 +13,7 @@ PLATFORM_SCHEMA = light.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_BLUE): cv.variable_id,
 | 
			
		||||
    vol.Required(CONF_WHITE): cv.variable_id,
 | 
			
		||||
    vol.Optional(CONF_GAMMA_CORRECT): cv.positive_float,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -24,7 +24,5 @@ def to_code(config):
 | 
			
		||||
    white = get_variable(config[CONF_WHITE])
 | 
			
		||||
    rhs = App.make_rgbw_light(config[CONF_NAME], red, green, blue, white)
 | 
			
		||||
    light_struct = variable('Application::MakeLight', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_GAMMA_CORRECT in config:
 | 
			
		||||
        add(light_struct.Poutput.set_gamma_correct(config[CONF_GAMMA_CORRECT]))
 | 
			
		||||
    setup_mqtt_component(light_struct.Pmqtt, config)
 | 
			
		||||
    light.setup_light_component(light_struct.Pstate, config)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ from esphomeyaml.const import CONF_BAUD_RATE, CONF_ID, CONF_LEVEL, CONF_LOGGER,
 | 
			
		||||
from esphomeyaml.core import ESPHomeYAMLError
 | 
			
		||||
from esphomeyaml.helpers import App, Pvariable, RawExpression, add
 | 
			
		||||
 | 
			
		||||
LOG_LEVELS = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE']
 | 
			
		||||
LOG_LEVELS = ['NONE', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'VERBOSE', 'VERY_VERBOSE']
 | 
			
		||||
 | 
			
		||||
# pylint: disable=invalid-name
 | 
			
		||||
is_log_level = vol.All(vol.Upper, vol.Any(*LOG_LEVELS))
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ CONFIG_SCHEMA = vol.Schema({
 | 
			
		||||
    vol.Optional(CONF_LOG_TOPIC): MQTT_MESSAGE_TEMPLATE_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_SSL_FINGERPRINTS): vol.All(cv.only_on_esp8266,
 | 
			
		||||
                                                 cv.ensure_list, [validate_fingerprint]),
 | 
			
		||||
    vol.Optional(CONF_KEEPALIVE): vol.All(cv.positive_time_period, cv.time_period_to_seconds)
 | 
			
		||||
    vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,3 +46,9 @@ def get_auth(config):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_OTA'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def lib_deps(config):
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        return ['ArduinoOTA', 'Update', 'ESPmDNS']
 | 
			
		||||
    return ['Hash', 'ESP8266mDNS', 'ArduinoOTA']
 | 
			
		||||
 
 | 
			
		||||
@@ -10,12 +10,16 @@ PHASE_BALANCERS = ['None', 'Linear', 'Weaved']
 | 
			
		||||
 | 
			
		||||
PCA9685_COMPONENT_TYPE = 'output::PCA9685OutputComponent'
 | 
			
		||||
 | 
			
		||||
PHASE_BALANCER_MESSAGE = ("The phase_balancer option has been removed in version 1.5.0. "
 | 
			
		||||
                          "esphomelib will now automatically choose a suitable phase balancer.")
 | 
			
		||||
 | 
			
		||||
PCA9685_SCHEMA = vol.Schema({
 | 
			
		||||
    cv.GenerateID('pca9685'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_FREQUENCY): vol.All(cv.frequency,
 | 
			
		||||
                                          vol.Range(min=24, max=1526)),
 | 
			
		||||
    vol.Optional(CONF_PHASE_BALANCER): vol.All(vol.Title, vol.Any(*PHASE_BALANCERS)),
 | 
			
		||||
                                          vol.Range(min=23.84, max=1525.88)),
 | 
			
		||||
    vol.Optional(CONF_ADDRESS): cv.i2c_address,
 | 
			
		||||
 | 
			
		||||
    vol.Optional(CONF_PHASE_BALANCER): cv.invalid(PHASE_BALANCER_MESSAGE),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [PCA9685_SCHEMA])
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@ from esphomeyaml.helpers import App, Pvariable, add, exp_gpio_output_pin
 | 
			
		||||
 | 
			
		||||
POWER_SUPPLY_SCHEMA = cv.REQUIRED_ID_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period,
 | 
			
		||||
    vol.Optional(CONF_ENABLE_TIME): cv.positive_time_period_milliseconds,
 | 
			
		||||
    vol.Optional(CONF_KEEP_ON_TIME): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
CONFIG_SCHEMA = vol.All(cv.ensure_list, [POWER_SUPPLY_SCHEMA])
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ MQTT_SENSOR_SCHEMA = vol.Schema({
 | 
			
		||||
    vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string_strict,
 | 
			
		||||
    vol.Optional(CONF_ICON): cv.icon,
 | 
			
		||||
    vol.Optional(CONF_ACCURACY_DECIMALS): vol.Coerce(int),
 | 
			
		||||
    vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period),
 | 
			
		||||
    vol.Optional(CONF_EXPIRE_AFTER): vol.Any(None, cv.positive_time_period_milliseconds),
 | 
			
		||||
    vol.Optional(CONF_FILTERS): FILTERS_SCHEMA
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('adc'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_PIN): pins.analog_pin,
 | 
			
		||||
    vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, ATTENUATION_MODE_SCHEMA),
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -9,23 +9,23 @@ from esphomeyaml.helpers import RawExpression, get_variable, Pvariable
 | 
			
		||||
DEPENDENCIES = ['ads1115']
 | 
			
		||||
 | 
			
		||||
MUX = {
 | 
			
		||||
    'A0_A1': 'ADS1115_MUX_P0_N1',
 | 
			
		||||
    'A0_A3': 'ADS1115_MUX_P0_N3',
 | 
			
		||||
    'A1_A3': 'ADS1115_MUX_P1_N3',
 | 
			
		||||
    'A2_A3': 'ADS1115_MUX_P2_N3',
 | 
			
		||||
    'A0_GND': 'ADS1115_MUX_P0_NG',
 | 
			
		||||
    'A1_GND': 'ADS1115_MUX_P1_NG',
 | 
			
		||||
    'A2_GND': 'ADS1115_MUX_P2_NG',
 | 
			
		||||
    'A3_GND': 'ADS1115_MUX_P3_NG',
 | 
			
		||||
    'A0_A1': 'sensor::ADS1115_MULTIPLEXER_P0_N1',
 | 
			
		||||
    'A0_A3': 'sensor::ADS1115_MULTIPLEXER_P0_N3',
 | 
			
		||||
    'A1_A3': 'sensor::ADS1115_MULTIPLEXER_P1_N3',
 | 
			
		||||
    'A2_A3': 'sensor::ADS1115_MULTIPLEXER_P2_N3',
 | 
			
		||||
    'A0_GND': 'sensor::ADS1115_MULTIPLEXER_P0_NG',
 | 
			
		||||
    'A1_GND': 'sensor::ADS1115_MULTIPLEXER_P1_NG',
 | 
			
		||||
    'A2_GND': 'sensor::ADS1115_MULTIPLEXER_P2_NG',
 | 
			
		||||
    'A3_GND': 'sensor::ADS1115_MULTIPLEXER_P3_NG',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GAIN = {
 | 
			
		||||
    '6.144': 'ADS1115_PGA_6P144',
 | 
			
		||||
    '4.096': 'ADS1115_PGA_6P096',
 | 
			
		||||
    '2.048': 'ADS1115_PGA_2P048',
 | 
			
		||||
    '1.024': 'ADS1115_PGA_1P024',
 | 
			
		||||
    '0.512': 'ADS1115_PGA_0P512',
 | 
			
		||||
    '0.256': 'ADS1115_PGA_0P256',
 | 
			
		||||
    '6.144': 'sensor::ADS1115_GAIN_6P144',
 | 
			
		||||
    '4.096': 'sensor::ADS1115_GAIN_6P096',
 | 
			
		||||
    '2.048': 'sensor::ADS1115_GAIN_2P048',
 | 
			
		||||
    '1.024': 'sensor::ADS1115_GAIN_1P024',
 | 
			
		||||
    '0.512': 'sensor::ADS1115_GAIN_0P512',
 | 
			
		||||
    '0.256': 'sensor::ADS1115_GAIN_0P256',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +45,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_MULTIPLEXER): vol.All(vol.Upper, vol.Any(*list(MUX.keys()))),
 | 
			
		||||
    vol.Required(CONF_GAIN): validate_gain,
 | 
			
		||||
    vol.Optional(CONF_ADS1115_ID): cv.variable_id,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_ID_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								esphomeyaml/components/sensor/bh1750.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								esphomeyaml/components/sensor/bh1750.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_NAME, CONF_RESOLUTION, \
 | 
			
		||||
    CONF_UPDATE_INTERVAL
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
BH1750_RESOLUTIONS = {
 | 
			
		||||
    4.0: 'sensor::BH1750_RESOLUTION_4P0_LX',
 | 
			
		||||
    1.0: 'sensor::BH1750_RESOLUTION_1P0_LX',
 | 
			
		||||
    0.5: 'sensor::BH1750_RESOLUTION_0P5_LX',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('bh1750_sensor'): cv.register_variable_id,
 | 
			
		||||
    vol.Optional(CONF_ADDRESS, default=0x23): cv.i2c_address,
 | 
			
		||||
    vol.Optional(CONF_RESOLUTION): vol.All(cv.positive_float, vol.Any(*BH1750_RESOLUTIONS)),
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_bh1750_sensor(config[CONF_NAME], config[CONF_ADDRESS],
 | 
			
		||||
                                 config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    make_bh1750 = variable('Application::MakeBH1750Sensor', config[CONF_ID], rhs)
 | 
			
		||||
    bh1750 = make_bh1750.Pbh1750
 | 
			
		||||
    if CONF_RESOLUTION in config:
 | 
			
		||||
        constant = BH1750_RESOLUTIONS[config[CONF_RESOLUTION]]
 | 
			
		||||
        add(bh1750.set_resolution(RawExpression(constant)))
 | 
			
		||||
    sensor.setup_sensor(bh1750, config)
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make_bh1750.Pmqtt, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_BH1750'
 | 
			
		||||
							
								
								
									
										75
									
								
								esphomeyaml/components/sensor/bme280.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								esphomeyaml/components/sensor/bme280.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_NAME, \
 | 
			
		||||
    CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
OVERSAMPLING_OPTIONS = {
 | 
			
		||||
    'NONE': 'sensor::BME280_OVERSAMPLING_NONE',
 | 
			
		||||
    '1X': 'sensor::BME280_OVERSAMPLING_1X',
 | 
			
		||||
    '2X': 'sensor::BME280_OVERSAMPLING_2X',
 | 
			
		||||
    '4X': 'sensor::BME280_OVERSAMPLING_4X',
 | 
			
		||||
    '8X': 'sensor::BME280_OVERSAMPLING_8X',
 | 
			
		||||
    '16X': 'sensor::BME280_OVERSAMPLING_16X',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IIR_FILTER_OPTIONS = {
 | 
			
		||||
    'OFF': 'sensor::BME280_IIR_FILTER_OFF',
 | 
			
		||||
    '2X': 'sensor::BME280_IIR_FILTER_2X',
 | 
			
		||||
    '4X': 'sensor::BME280_IIR_FILTER_4X',
 | 
			
		||||
    '8X': 'sensor::BME280_IIR_FILTER_8X',
 | 
			
		||||
    '16X': 'sensor::BME280_IIR_FILTER_16X',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BME280_OVERSAMPLING_SENSOR_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
 | 
			
		||||
    vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, vol.Any(*OVERSAMPLING_OPTIONS)),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('bme280'): cv.register_variable_id,
 | 
			
		||||
    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.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, vol.Any(*IIR_FILTER_OPTIONS)),
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_bme280_sensor(config[CONF_TEMPERATURE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_PRESSURE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_HUMIDITY][CONF_NAME],
 | 
			
		||||
                                 config[CONF_ADDRESS],
 | 
			
		||||
                                 config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    make = variable('Application::MakeBME280Sensor', config[CONF_ID], rhs)
 | 
			
		||||
    bme280 = make.Pbme280
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme280.set_temperature_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_PRESSURE]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_PRESSURE][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme280.set_pressure_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_HUMIDITY]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_HUMIDITY][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme280.set_humidity_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_IIR_FILTER in config:
 | 
			
		||||
        constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
 | 
			
		||||
        add(bme280.set_iir_filter(RawExpression(constant)))
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme280.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_temperature, config[CONF_TEMPERATURE])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme280.Pget_pressure_sensor(), config[CONF_PRESSURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_pressure, config[CONF_PRESSURE])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme280.Pget_humidity_sensor(), config[CONF_HUMIDITY])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_humidity, config[CONF_HUMIDITY])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_BME280'
 | 
			
		||||
							
								
								
									
										84
									
								
								esphomeyaml/components/sensor/bme680.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								esphomeyaml/components/sensor/bme680.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_NAME, \
 | 
			
		||||
    CONF_OVERSAMPLING, CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, CONF_GAS_RESISTANCE
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
OVERSAMPLING_OPTIONS = {
 | 
			
		||||
    'NONE': 'sensor::BME680_OVERSAMPLING_NONE',
 | 
			
		||||
    '1X': 'sensor::BME680_OVERSAMPLING_1X',
 | 
			
		||||
    '2X': 'sensor::BME680_OVERSAMPLING_2X',
 | 
			
		||||
    '4X': 'sensor::BME680_OVERSAMPLING_4X',
 | 
			
		||||
    '8X': 'sensor::BME680_OVERSAMPLING_8X',
 | 
			
		||||
    '16X': 'sensor::BME680_OVERSAMPLING_16X',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IIR_FILTER_OPTIONS = {
 | 
			
		||||
    'OFF': 'sensor::BME680_IIR_FILTER_OFF',
 | 
			
		||||
    '1X': 'sensor::BME680_IIR_FILTER_1X',
 | 
			
		||||
    '3X': 'sensor::BME680_IIR_FILTER_3X',
 | 
			
		||||
    '7X': 'sensor::BME680_IIR_FILTER_7X',
 | 
			
		||||
    '15X': 'sensor::BME680_IIR_FILTER_15X',
 | 
			
		||||
    '31X': 'sensor::BME680_IIR_FILTER_31X',
 | 
			
		||||
    '63X': 'sensor::BME680_IIR_FILTER_63X',
 | 
			
		||||
    '127X': 'sensor::BME680_IIR_FILTER_127X',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
BME680_OVERSAMPLING_SENSOR_SCHEMA = MQTT_SENSOR_SCHEMA.extend({
 | 
			
		||||
    vol.Optional(CONF_OVERSAMPLING): vol.All(vol.Upper, vol.Any(*OVERSAMPLING_OPTIONS)),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('bme680'): cv.register_variable_id,
 | 
			
		||||
    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): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_IIR_FILTER): vol.All(vol.Upper, vol.Any(*IIR_FILTER_OPTIONS)),
 | 
			
		||||
    # TODO: Heater
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_bme680_sensor(config[CONF_TEMPERATURE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_PRESSURE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_HUMIDITY][CONF_NAME],
 | 
			
		||||
                                 config[CONF_GAS_RESISTANCE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_ADDRESS],
 | 
			
		||||
                                 config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    make = variable('Application::MakeBME680Sensor', config[CONF_ID], rhs)
 | 
			
		||||
    bme680 = make.Pbme680
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_TEMPERATURE]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_TEMPERATURE][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme680.set_temperature_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_PRESSURE]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_PRESSURE][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme680.set_pressure_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_OVERSAMPLING in config[CONF_HUMIDITY]:
 | 
			
		||||
        constant = OVERSAMPLING_OPTIONS[config[CONF_HUMIDITY][CONF_OVERSAMPLING]]
 | 
			
		||||
        add(bme680.set_humidity_oversampling(RawExpression(constant)))
 | 
			
		||||
    if CONF_IIR_FILTER in config:
 | 
			
		||||
        constant = IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]]
 | 
			
		||||
        add(bme680.set_iir_filter(RawExpression(constant)))
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme680.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_temperature, config[CONF_TEMPERATURE])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme680.Pget_pressure_sensor(), config[CONF_PRESSURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_pressure, config[CONF_PRESSURE])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme680.Pget_humidity_sensor(), config[CONF_HUMIDITY])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_humidity, config[CONF_HUMIDITY])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(bme680.Pget_gas_resistance_sensor(), config[CONF_GAS_RESISTANCE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make.Pmqtt_gas_resistance, config[CONF_GAS_RESISTANCE])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_BME680'
 | 
			
		||||
@@ -14,7 +14,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_PRESSURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_ADDRESS): cv.i2c_address,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,13 +8,13 @@ from esphomeyaml.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAM
 | 
			
		||||
    CONF_UPDATE_INTERVAL, CONF_ID
 | 
			
		||||
from esphomeyaml.helpers import HexIntLiteral, get_variable, Pvariable
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
PLATFORM_SCHEMA = vol.All(sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('dallas_sensor'): cv.register_variable_id,
 | 
			
		||||
    vol.Exclusive(CONF_ADDRESS, 'dallas'): cv.hex_int,
 | 
			
		||||
    vol.Exclusive(CONF_INDEX, 'dallas'): cv.positive_int,
 | 
			
		||||
    vol.Optional(CONF_DALLAS_ID): cv.variable_id,
 | 
			
		||||
    vol.Optional(CONF_RESOLUTION): vol.All(vol.Coerce(int), vol.Range(min=8, max=12)),
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_ID_SCHEMA.schema)
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_ID_SCHEMA.schema), cv.has_at_least_one_key(CONF_ADDRESS, CONF_INDEX))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
 
 | 
			
		||||
@@ -1,33 +1,40 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml import pins
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
 | 
			
		||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_NAME, CONF_PIN, \
 | 
			
		||||
    CONF_TEMPERATURE, CONF_UPDATE_INTERVAL
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable, exp_gpio_output_pin
 | 
			
		||||
from esphomeyaml.pins import GPIO_OUTPUT_PIN_SCHEMA
 | 
			
		||||
 | 
			
		||||
DHT_MODELS = ['AUTO_DETECT', 'DHT11', 'DHT22', 'AM2302', 'RHT03']
 | 
			
		||||
DHT_MODELS = {
 | 
			
		||||
    'AUTO_DETECT': 'sensor::DHT_MODEL_AUTO_DETECT',
 | 
			
		||||
    'DHT11': 'sensor::DHT_MODEL_DHT11',
 | 
			
		||||
    'DHT22': 'sensor::DHT_MODEL_DHT22',
 | 
			
		||||
    'AM2302': 'sensor::DHT_MODEL_AM2302',
 | 
			
		||||
    'RHT03': 'sensor::DHT_MODEL_RHT03',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('dht_sensor'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_PIN): pins.input_output_pin,
 | 
			
		||||
    vol.Required(CONF_PIN): GPIO_OUTPUT_PIN_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_MODEL): vol.All(vol.Upper, vol.Any(*DHT_MODELS)),
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    pin = exp_gpio_output_pin(config[CONF_PIN])
 | 
			
		||||
    rhs = App.make_dht_sensor(config[CONF_TEMPERATURE][CONF_NAME],
 | 
			
		||||
                              config[CONF_HUMIDITY][CONF_NAME],
 | 
			
		||||
                              config[CONF_PIN], config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
                              pin, config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    dht = variable('Application::MakeDHTSensor', config[CONF_ID], rhs)
 | 
			
		||||
    if CONF_MODEL in config:
 | 
			
		||||
        model = RawExpression('DHT::{}'.format(config[CONF_MODEL]))
 | 
			
		||||
        add(dht.Pdht.set_dht_model(model))
 | 
			
		||||
        constant = DHT_MODELS[config[CONF_MODEL]]
 | 
			
		||||
        add(dht.Pdht.set_dht_model(RawExpression(constant)))
 | 
			
		||||
    sensor.setup_sensor(dht.Pdht.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(dht.Pmqtt_temperature, config[CONF_TEMPERATURE])
 | 
			
		||||
    sensor.setup_sensor(dht.Pdht.Pget_humidity_sensor(), config[CONF_HUMIDITY])
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('dht_sensor'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('htu21d'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Optional(CONF_GYRO_Y): MQTT_SENSOR_ID_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_GYRO_Z): MQTT_SENSOR_ID_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_TEMPERATURE): MQTT_SENSOR_ID_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,7 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
        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_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								esphomeyaml/components/sensor/sht3xd.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								esphomeyaml/components/sensor/sht3xd.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.components.sensor import MQTT_SENSOR_SCHEMA
 | 
			
		||||
from esphomeyaml.const import CONF_HUMIDITY, CONF_ID, CONF_NAME, CONF_TEMPERATURE, \
 | 
			
		||||
    CONF_UPDATE_INTERVAL, CONF_ADDRESS, CONF_ACCURACY
 | 
			
		||||
from esphomeyaml.helpers import App, variable, RawExpression, add
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
SHT_ACCURACIES = {
 | 
			
		||||
    'LOW': 'sensor::SHT3XD_ACCURACY_LOW',
 | 
			
		||||
    'MEDIUM': 'sensor::SHT3XD_ACCURACY_MEDIUM',
 | 
			
		||||
    'HIGH': 'sensor::SHT3XD_ACCURACY_HIGH',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('sht3xd'): cv.register_variable_id,
 | 
			
		||||
    vol.Required(CONF_TEMPERATURE): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_HUMIDITY): MQTT_SENSOR_SCHEMA,
 | 
			
		||||
    vol.Optional(CONF_ADDRESS, default=0x44): cv.i2c_address,
 | 
			
		||||
    vol.Optional(CONF_ACCURACY): vol.All(vol.Upper, vol.Any(*SHT_ACCURACIES)),
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_sht3xd_sensor(config[CONF_TEMPERATURE][CONF_NAME],
 | 
			
		||||
                                 config[CONF_HUMIDITY][CONF_NAME],
 | 
			
		||||
                                 config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    sht3xd = variable('Application::MakeSHT3XDSensor', config[CONF_ID], rhs)
 | 
			
		||||
 | 
			
		||||
    if CONF_ACCURACY in config:
 | 
			
		||||
        constant = RawExpression(SHT_ACCURACIES[config[CONF_ACCURACY]])
 | 
			
		||||
        add(sht3xd.Psht3xd.set_accuracy(constant))
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(sht3xd.Psht3xd.Pget_temperature_sensor(), config[CONF_TEMPERATURE])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(sht3xd.Pmqtt_temperature, config[CONF_TEMPERATURE])
 | 
			
		||||
 | 
			
		||||
    sensor.setup_sensor(sht3xd.PPsht3xd.Pget_humidity_sensor(), config[CONF_HUMIDITY])
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(sht3xd.Pmqtt_humidity, config[CONF_HUMIDITY])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_SHT3XD'
 | 
			
		||||
							
								
								
									
										58
									
								
								esphomeyaml/components/sensor/tsl2561.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								esphomeyaml/components/sensor/tsl2561.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import sensor
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_GAIN, CONF_ID, CONF_INTEGRATION_TIME, CONF_NAME, \
 | 
			
		||||
    CONF_UPDATE_INTERVAL
 | 
			
		||||
from esphomeyaml.helpers import App, RawExpression, add, variable
 | 
			
		||||
 | 
			
		||||
DEPENDENCIES = ['i2c']
 | 
			
		||||
 | 
			
		||||
INTEGRATION_TIMES = {
 | 
			
		||||
    14: 'sensor::TSL2561_INTEGRATION_14MS',
 | 
			
		||||
    101: 'sensor::TSL2561_INTEGRATION_101MS',
 | 
			
		||||
    402: 'sensor::TSL2561_INTEGRATION_402MS',
 | 
			
		||||
}
 | 
			
		||||
GAINS = {
 | 
			
		||||
    '1X': 'sensor::TSL2561_GAIN_1X',
 | 
			
		||||
    '16X': 'sensor::TSL2561_GAIN_16X',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CONF_IS_CS_PACKAGE = 'is_cs_package'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def validate_integration_time(value):
 | 
			
		||||
    value = cv.positive_time_period_milliseconds(value).total_milliseconds
 | 
			
		||||
    if value not in INTEGRATION_TIMES:
 | 
			
		||||
        raise vol.Invalid(u"Unsupported integration time {}.".format(value))
 | 
			
		||||
    return value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    cv.GenerateID('tsl2561_sensor'): cv.register_variable_id,
 | 
			
		||||
    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, vol.Any(*GAINS)),
 | 
			
		||||
    vol.Optional(CONF_IS_CS_PACKAGE): cv.boolean,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def to_code(config):
 | 
			
		||||
    rhs = App.make_tsl2561_sensor(config[CONF_NAME], config[CONF_ADDRESS],
 | 
			
		||||
                                  config.get(CONF_UPDATE_INTERVAL))
 | 
			
		||||
    make_tsl = variable('Application::MakeTSL2561Sensor', config[CONF_ID], rhs)
 | 
			
		||||
    tsl2561 = make_tsl.Ptsl2561
 | 
			
		||||
    if CONF_INTEGRATION_TIME in config:
 | 
			
		||||
        constant = INTEGRATION_TIMES[config[CONF_INTEGRATION_TIME]]
 | 
			
		||||
        add(tsl2561.set_integration_time(RawExpression(constant)))
 | 
			
		||||
    if CONF_GAIN in config:
 | 
			
		||||
        constant = GAINS[config[CONF_GAIN]]
 | 
			
		||||
        add(tsl2561.set_gain(RawExpression(constant)))
 | 
			
		||||
    if CONF_IS_CS_PACKAGE in config:
 | 
			
		||||
        add(tsl2561.set_is_cs_package(config[CONF_IS_CS_PACKAGE]))
 | 
			
		||||
    sensor.setup_sensor(tsl2561, config)
 | 
			
		||||
    sensor.setup_mqtt_sensor_component(make_tsl.Pmqtt, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_TSL2561'
 | 
			
		||||
@@ -13,8 +13,8 @@ PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    vol.Required(CONF_TRIGGER_PIN): pins.GPIO_OUTPUT_PIN_SCHEMA,
 | 
			
		||||
    vol.Required(CONF_ECHO_PIN): pins.GPIO_INPUT_PIN_SCHEMA,
 | 
			
		||||
    vol.Exclusive(CONF_TIMEOUT_METER, 'timeout'): cv.positive_float,
 | 
			
		||||
    vol.Exclusive(CONF_TIMEOUT_TIME, 'timeout'): cv.positive_int,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_not_null_time_period,
 | 
			
		||||
    vol.Exclusive(CONF_TIMEOUT_TIME, 'timeout'): cv.positive_time_period_microseconds,
 | 
			
		||||
    vol.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_milliseconds,
 | 
			
		||||
}).extend(sensor.MQTT_SENSOR_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,20 @@ import voluptuous as vol
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.components import switch
 | 
			
		||||
from esphomeyaml.components.ir_transmitter import IR_TRANSMITTER_COMPONENT_CLASS
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_COMMAND, CONF_DATA, CONF_IR_TRANSMITTER_ID, \
 | 
			
		||||
    CONF_LG, CONF_NBITS, CONF_NEC, CONF_PANASONIC, CONF_REPEAT, CONF_SONY, CONF_TIMES, \
 | 
			
		||||
    CONF_WAIT_TIME_US, CONF_RAW, CONF_CARRIER_FREQUENCY, CONF_NAME, CONF_ID
 | 
			
		||||
from esphomeyaml.const import CONF_ADDRESS, CONF_CARRIER_FREQUENCY, CONF_COMMAND, CONF_DATA, \
 | 
			
		||||
    CONF_ID, 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 HexIntLiteral, MockObj, get_variable, ArrayInitializer, Pvariable
 | 
			
		||||
from esphomeyaml.helpers import ArrayInitializer, HexIntLiteral, MockObj, Pvariable, get_variable
 | 
			
		||||
 | 
			
		||||
PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
 | 
			
		||||
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({
 | 
			
		||||
    cv.GenerateID('ir_transmitter_switch'): cv.register_variable_id,
 | 
			
		||||
    vol.Exclusive(CONF_NEC, 'code'): vol.Schema({
 | 
			
		||||
        vol.Required(CONF_ADDRESS): cv.hex_uint16_t,
 | 
			
		||||
@@ -33,11 +40,12 @@ PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({
 | 
			
		||||
    }),
 | 
			
		||||
    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_US): cv.uint32_t,
 | 
			
		||||
        vol.Required(CONF_WAIT_TIME): cv.positive_time_period_microseconds,
 | 
			
		||||
 | 
			
		||||
        vol.Optional('wait_time_us'): cv.invalid(WAIT_TIME_MESSAGE),
 | 
			
		||||
    })),
 | 
			
		||||
    vol.Optional(CONF_IR_TRANSMITTER_ID): cv.variable_id,
 | 
			
		||||
}).extend(switch.MQTT_SWITCH_ID_SCHEMA.schema)
 | 
			
		||||
 | 
			
		||||
}).extend(switch.MQTT_SWITCH_ID_SCHEMA.schema), cv.has_at_least_one_key(*IR_KEYS))
 | 
			
		||||
 | 
			
		||||
# pylint: disable=invalid-name
 | 
			
		||||
SendData = MockObj('switch_::ir::SendData', '::')
 | 
			
		||||
@@ -77,7 +85,7 @@ def exp_send_data(config):
 | 
			
		||||
            wait_us = None
 | 
			
		||||
        else:
 | 
			
		||||
            times = config[CONF_REPEAT][CONF_TIMES]
 | 
			
		||||
            wait_us = config[CONF_REPEAT][CONF_WAIT_TIME_US]
 | 
			
		||||
            wait_us = config[CONF_REPEAT][CONF_WAIT_TIME]
 | 
			
		||||
        base = MockObj(unicode(base), u'.')
 | 
			
		||||
        base = base.repeat(times, wait_us)
 | 
			
		||||
    return base
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,8 @@ import logging
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml.const import CONF_PORT, CONF_JS_URL, CONF_CSS_URL, CONF_ID
 | 
			
		||||
from esphomeyaml import core
 | 
			
		||||
from esphomeyaml.const import CONF_PORT, CONF_JS_URL, CONF_CSS_URL, CONF_ID, ESP_PLATFORM_ESP32
 | 
			
		||||
from esphomeyaml.helpers import App, add, Pvariable
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
@@ -26,3 +27,9 @@ def to_code(config):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
BUILD_FLAGS = '-DUSE_WEB_SERVER'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def lib_deps(config):
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        return 'FS'
 | 
			
		||||
    return ''
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
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_GATEWAY, \
 | 
			
		||||
    CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET
 | 
			
		||||
    CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET, \
 | 
			
		||||
    ESP_PLATFORM_ESP8266
 | 
			
		||||
from esphomeyaml.helpers import App, MockObj, Pvariable, StructInitializer, add
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -87,3 +89,9 @@ def to_code(config):
 | 
			
		||||
 | 
			
		||||
    if CONF_HOSTNAME in config:
 | 
			
		||||
        add(wifi.set_hostname(config[CONF_HOSTNAME]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def lib_deps(config):
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
 | 
			
		||||
        return 'ESP8266WiFi'
 | 
			
		||||
    return None
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ CORE_SCHEMA = vol.Schema({
 | 
			
		||||
    vol.Required(CONF_BOARD): cv.string,
 | 
			
		||||
    vol.Optional(CONF_LIBRARY_URI, default=DEFAULT_LIBRARY_URI): cv.string,
 | 
			
		||||
    vol.Optional(CONF_SIMPLIFY, default=True): cv.boolean,
 | 
			
		||||
    vol.Optional(CONF_USE_BUILD_FLAGS, default=False): cv.boolean,
 | 
			
		||||
    vol.Optional(CONF_USE_BUILD_FLAGS, default=True): cv.boolean,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
REQUIRED_COMPONENTS = [
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ from __future__ import print_function
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
import re
 | 
			
		||||
from datetime import timedelta
 | 
			
		||||
 | 
			
		||||
import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
@@ -13,7 +12,8 @@ from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOV
 | 
			
		||||
    CONF_NAME, CONF_PAYLOAD_AVAILABLE, \
 | 
			
		||||
    CONF_PAYLOAD_NOT_AVAILABLE, CONF_PLATFORM, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC, \
 | 
			
		||||
    ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
 | 
			
		||||
from esphomeyaml.core import HexInt, IPAddress
 | 
			
		||||
from esphomeyaml.core import HexInt, IPAddress, TimePeriod, TimePeriodMilliseconds, \
 | 
			
		||||
    TimePeriodMicroseconds, TimePeriodSeconds
 | 
			
		||||
from esphomeyaml.helpers import ensure_unique_string
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
@@ -178,19 +178,28 @@ def has_at_least_one_key(*keys):
 | 
			
		||||
    return validate
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TIME_PERIOD_ERROR = "Time period {} should be format 5ms, 5s, 5min, 5h"
 | 
			
		||||
TIME_PERIOD_ERROR = "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h"
 | 
			
		||||
 | 
			
		||||
time_period_dict = vol.All(
 | 
			
		||||
    dict, vol.Schema({
 | 
			
		||||
        'days': vol.Coerce(int),
 | 
			
		||||
        'hours': vol.Coerce(int),
 | 
			
		||||
        'minutes': vol.Coerce(int),
 | 
			
		||||
        'seconds': vol.Coerce(int),
 | 
			
		||||
        'milliseconds': vol.Coerce(int),
 | 
			
		||||
        'days': vol.Coerce(float),
 | 
			
		||||
        'hours': vol.Coerce(float),
 | 
			
		||||
        'minutes': vol.Coerce(float),
 | 
			
		||||
        'seconds': vol.Coerce(float),
 | 
			
		||||
        'milliseconds': vol.Coerce(float),
 | 
			
		||||
        'microseconds': vol.Coerce(float),
 | 
			
		||||
    }),
 | 
			
		||||
    has_at_least_one_key('days', 'hours', 'minutes',
 | 
			
		||||
                         'seconds', 'milliseconds'),
 | 
			
		||||
    lambda value: timedelta(**value))
 | 
			
		||||
                         'seconds', 'milliseconds', 'microseconds'),
 | 
			
		||||
    lambda value: TimePeriod(**value))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TIME_PERIOD_EXPLICIT_MESSAGE = ("The old way of being able to write time values without a "
 | 
			
		||||
                                "time unit (like \"1000\" for 1000 milliseconds) has been "
 | 
			
		||||
                                "removed in 1.5.0 as it was ambiguous in some places. Please "
 | 
			
		||||
                                "now explicitly specify the time unit (like \"1000ms\"). See "
 | 
			
		||||
                                "https://esphomelib.com/esphomeyaml/configuration-types.html#time "
 | 
			
		||||
                                "for more information.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def time_period_str_colon(value):
 | 
			
		||||
@@ -220,7 +229,7 @@ def time_period_str_colon(value):
 | 
			
		||||
    else:
 | 
			
		||||
        raise vol.Invalid(TIME_PERIOD_ERROR.format(value))
 | 
			
		||||
 | 
			
		||||
    offset = timedelta(hours=hour, minutes=minute, seconds=second)
 | 
			
		||||
    offset = TimePeriod(hours=hour, minutes=minute, seconds=second)
 | 
			
		||||
 | 
			
		||||
    if negative_offset:
 | 
			
		||||
        offset *= -1
 | 
			
		||||
@@ -232,10 +241,19 @@ def time_period_str_unit(value):
 | 
			
		||||
    """Validate and transform time period with time unit and integer value."""
 | 
			
		||||
    if isinstance(value, int):
 | 
			
		||||
        value = str(value)
 | 
			
		||||
    elif not isinstance(value, str):
 | 
			
		||||
    elif not isinstance(value, (str, unicode)):
 | 
			
		||||
        raise vol.Invalid("Expected string for time period with unit.")
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        float(value)
 | 
			
		||||
    except ValueError:
 | 
			
		||||
        pass
 | 
			
		||||
    else:
 | 
			
		||||
        raise vol.Invalid(TIME_PERIOD_EXPLICIT_MESSAGE)
 | 
			
		||||
 | 
			
		||||
    unit_to_kwarg = {
 | 
			
		||||
        'us': 'microseconds',
 | 
			
		||||
        'microseconds': 'microseconds',
 | 
			
		||||
        'ms': 'milliseconds',
 | 
			
		||||
        'milliseconds': 'milliseconds',
 | 
			
		||||
        's': 'seconds',
 | 
			
		||||
@@ -256,51 +274,57 @@ def time_period_str_unit(value):
 | 
			
		||||
                          u"got {}".format(value))
 | 
			
		||||
 | 
			
		||||
    kwarg = unit_to_kwarg[match.group(2)]
 | 
			
		||||
    return timedelta(**{kwarg: float(match.group(1))})
 | 
			
		||||
    return TimePeriod(**{kwarg: float(match.group(1))})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def time_period_to_milliseconds(value):
 | 
			
		||||
    if isinstance(value, (int, long)):
 | 
			
		||||
        return value
 | 
			
		||||
    if isinstance(value, float):
 | 
			
		||||
        return int(value)
 | 
			
		||||
    return int(value.total_seconds() * 1000)
 | 
			
		||||
def time_period_in_milliseconds(value):
 | 
			
		||||
    if value.microseconds is not None and value.microseconds != 0:
 | 
			
		||||
        raise vol.Invalid("Maximum precision is milliseconds")
 | 
			
		||||
    return TimePeriodMilliseconds(**value.as_dict())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def time_period_to_seconds(value):
 | 
			
		||||
    if value / 1000 != value // 1000:
 | 
			
		||||
        raise vol.Invalid("Fractions of seconds are not supported here.")
 | 
			
		||||
    return value / 1000
 | 
			
		||||
def time_period_in_microseconds(value):
 | 
			
		||||
    return TimePeriodMicroseconds(**value.as_dict())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
time_period = vol.All(vol.Any(time_period_str_colon, time_period_str_unit, timedelta,
 | 
			
		||||
                              time_period_dict),
 | 
			
		||||
                      time_period_to_milliseconds)
 | 
			
		||||
positive_time_period = vol.All(time_period, vol.Range(min=0))
 | 
			
		||||
positive_not_null_time_period = vol.All(time_period, vol.Range(min=0, min_included=False))
 | 
			
		||||
def time_period_in_seconds(value):
 | 
			
		||||
    if value.microseconds is not None and value.microseconds != 0:
 | 
			
		||||
        raise vol.Invalid("Maximum precision is seconds")
 | 
			
		||||
    if value.milliseconds is not None and value.milliseconds != 0:
 | 
			
		||||
        raise vol.Invalid("Maximum precision is seconds")
 | 
			
		||||
    return TimePeriodSeconds(**value.as_dict())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
time_period = vol.Any(time_period_str_unit, time_period_str_colon, time_period_dict)
 | 
			
		||||
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)
 | 
			
		||||
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))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
    '': 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def frequency(value):
 | 
			
		||||
    value = string(value).replace(' ', '').lower()
 | 
			
		||||
    if value.endswith('Hz') or value.endswith('hz') or value.endswith('HZ'):
 | 
			
		||||
        value = value[:-2]
 | 
			
		||||
    if not value:
 | 
			
		||||
        raise vol.Invalid(u"Frequency must have value")
 | 
			
		||||
    multiplier = 1
 | 
			
		||||
    if value[:-1] in METRIC_SUFFIXES:
 | 
			
		||||
        multiplier = METRIC_SUFFIXES[value[:-1]]
 | 
			
		||||
        value = value[:-1]
 | 
			
		||||
    elif len(value) >= 2 and value[:-2] in METRIC_SUFFIXES:
 | 
			
		||||
        multiplier = METRIC_SUFFIXES[value[:-2]]
 | 
			
		||||
        value = value[:-2]
 | 
			
		||||
    float_val = vol.Coerce(float)(value)
 | 
			
		||||
    return float_val * multiplier
 | 
			
		||||
    value = string(value)
 | 
			
		||||
    match = re.match(r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*?)(?:Hz|HZ|hz)?$", value)
 | 
			
		||||
 | 
			
		||||
    if match is None:
 | 
			
		||||
        raise vol.Invalid(u"Expected frequency with unit, "
 | 
			
		||||
                          u"got {}".format(value))
 | 
			
		||||
 | 
			
		||||
    mantissa = float(match.group(1))
 | 
			
		||||
    if match.group(2) not in METRIC_SUFFIXES:
 | 
			
		||||
        raise vol.Invalid(u"Invalid frequency suffix {}".format(match.group(2)))
 | 
			
		||||
 | 
			
		||||
    multiplier = METRIC_SUFFIXES[match.group(2)]
 | 
			
		||||
    return mantissa * multiplier
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hostname(value):
 | 
			
		||||
@@ -407,8 +431,10 @@ hex_uint32_t = vol.All(hex_int, vol.Range(min=0, max=4294967295))
 | 
			
		||||
i2c_address = hex_uint8_t
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def invalid(_):
 | 
			
		||||
    raise vol.Invalid("This shouldn't happen.")
 | 
			
		||||
def invalid(message):
 | 
			
		||||
    def validator(value):
 | 
			
		||||
        raise vol.Invalid(message)
 | 
			
		||||
    return validator
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def valid(value):
 | 
			
		||||
 
 | 
			
		||||
@@ -135,7 +135,7 @@ CONF_SONY = 'sony'
 | 
			
		||||
CONF_PANASONIC = 'panasonic'
 | 
			
		||||
CONF_REPEAT = 'repeat'
 | 
			
		||||
CONF_TIMES = 'times'
 | 
			
		||||
CONF_WAIT_TIME_US = 'wait_time_us'
 | 
			
		||||
CONF_WAIT_TIME = 'wait_time'
 | 
			
		||||
CONF_OSCILLATION_OUTPUT = 'oscillation_output'
 | 
			
		||||
CONF_SPEED = 'speed'
 | 
			
		||||
CONF_OSCILLATION_STATE_TOPIC = 'oscillation_state_topic'
 | 
			
		||||
@@ -161,9 +161,30 @@ CONF_AP = 'ap'
 | 
			
		||||
CONF_CSS_URL = 'css_url'
 | 
			
		||||
CONF_JS_URL = 'js_url'
 | 
			
		||||
CONF_SSL_FINGERPRINTS = 'ssl_fingerprints'
 | 
			
		||||
CONF_PCF8574 = 'pcf8574'
 | 
			
		||||
CONF_PCF8575 = 'pcf8575'
 | 
			
		||||
CONF_SCAN = 'scan'
 | 
			
		||||
CONF_KEEPALIVE = 'keepalive'
 | 
			
		||||
CONF_INTEGRATION_TIME = 'integration_time'
 | 
			
		||||
CONF_RECEIVE_TIMEOUT = 'receive_timeout'
 | 
			
		||||
CONF_SCAN_INTERVAL = 'scan_interval'
 | 
			
		||||
CONF_MAC_ADDRESS = 'mac_address'
 | 
			
		||||
CONF_SETUP_MODE = 'setup_mode'
 | 
			
		||||
CONF_IIR_FILTER = 'iir_filter'
 | 
			
		||||
CONF_MEASUREMENT_DURATION = 'measurement_duration'
 | 
			
		||||
CONF_LOW_VOLTAGE_REFERENCE = 'low_voltage_reference'
 | 
			
		||||
CONF_HIGH_VOLTAGE_REFERENCE = 'high_voltage_reference'
 | 
			
		||||
CONF_VOLTAGE_ATTENUATION = 'voltage_attenuation'
 | 
			
		||||
CONF_THRESHOLD = 'threshold'
 | 
			
		||||
CONF_OVERSAMPLING = 'oversampling'
 | 
			
		||||
CONF_GAS_RESISTANCE = 'gas_resistance'
 | 
			
		||||
CONF_NUM_LEDS = 'num_leds'
 | 
			
		||||
CONF_MAX_REFRESH_RATE = 'max_refresh_rate'
 | 
			
		||||
CONF_CHIPSET = 'chipset'
 | 
			
		||||
CONF_DATA_PIN = 'data_pin'
 | 
			
		||||
CONF_CLOCK_PIN = 'clock_pin'
 | 
			
		||||
CONF_RGB_ORDER = 'rgb_order'
 | 
			
		||||
CONF_ACCURACY = 'accuracy'
 | 
			
		||||
 | 
			
		||||
ESP32_BOARDS = [
 | 
			
		||||
    'featheresp32', 'node32s', 'espea32', 'firebeetle32', 'esp32doit-devkit-v1',
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,7 @@
 | 
			
		||||
import math
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ESPHomeYAMLError(Exception):
 | 
			
		||||
    """General esphomeyaml exception occurred."""
 | 
			
		||||
    pass
 | 
			
		||||
@@ -18,6 +22,155 @@ class IPAddress(object):
 | 
			
		||||
        return '.'.join(str(x) for x in self.args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MACAddress(object):
 | 
			
		||||
    def __init__(self, *parts):
 | 
			
		||||
        if len(parts) != 6:
 | 
			
		||||
            raise ValueError(u"MAC Address must consist of 6 items")
 | 
			
		||||
        self.parts = parts
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return ':'.join('{:02X}'.format(part) for part in self.parts)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_approximately_integer(value):
 | 
			
		||||
    if isinstance(value, (int, long)):
 | 
			
		||||
        return True
 | 
			
		||||
    return abs(value - round(value)) < 0.001
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TimePeriod(object):
 | 
			
		||||
    def __init__(self, microseconds=None, milliseconds=None, seconds=None,
 | 
			
		||||
                 minutes=None, hours=None, days=None):
 | 
			
		||||
        if days is not None:
 | 
			
		||||
            if not is_approximately_integer(days):
 | 
			
		||||
                frac_days, days = math.modf(days)
 | 
			
		||||
                hours = (hours or 0) + frac_days * 24
 | 
			
		||||
            self.days = int(round(days))
 | 
			
		||||
        else:
 | 
			
		||||
            self.days = None
 | 
			
		||||
 | 
			
		||||
        if hours is not None:
 | 
			
		||||
            if not is_approximately_integer(hours):
 | 
			
		||||
                frac_hours, hours = math.modf(hours)
 | 
			
		||||
                minutes = (minutes or 0) + frac_hours * 60
 | 
			
		||||
            self.hours = int(round(hours))
 | 
			
		||||
        else:
 | 
			
		||||
            self.hours = None
 | 
			
		||||
 | 
			
		||||
        if minutes is not None:
 | 
			
		||||
            if not is_approximately_integer(minutes):
 | 
			
		||||
                frac_minutes, minutes = math.modf(minutes)
 | 
			
		||||
                seconds = (seconds or 0) + frac_minutes * 60
 | 
			
		||||
            self.minutes = int(round(minutes))
 | 
			
		||||
        else:
 | 
			
		||||
            self.minutes = None
 | 
			
		||||
 | 
			
		||||
        if seconds is not None:
 | 
			
		||||
            if not is_approximately_integer(seconds):
 | 
			
		||||
                frac_seconds, seconds = math.modf(seconds)
 | 
			
		||||
                milliseconds = (milliseconds or 0) + frac_seconds * 1000
 | 
			
		||||
            self.seconds = int(round(seconds))
 | 
			
		||||
        else:
 | 
			
		||||
            self.seconds = None
 | 
			
		||||
 | 
			
		||||
        if milliseconds is not None:
 | 
			
		||||
            if not is_approximately_integer(milliseconds):
 | 
			
		||||
                frac_milliseconds, milliseconds = math.modf(milliseconds)
 | 
			
		||||
                microseconds = (microseconds or 0) + frac_milliseconds * 1000
 | 
			
		||||
            self.milliseconds = int(round(milliseconds))
 | 
			
		||||
        else:
 | 
			
		||||
            self.milliseconds = None
 | 
			
		||||
 | 
			
		||||
        if microseconds is not None:
 | 
			
		||||
            if not is_approximately_integer(microseconds):
 | 
			
		||||
                raise ValueError("Maximum precision is microseconds")
 | 
			
		||||
            self.microseconds = int(round(microseconds))
 | 
			
		||||
        else:
 | 
			
		||||
            self.microseconds = None
 | 
			
		||||
 | 
			
		||||
    def as_dict(self):
 | 
			
		||||
        out = OrderedDict()
 | 
			
		||||
        if self.microseconds is not None:
 | 
			
		||||
            out['microseconds'] = self.microseconds
 | 
			
		||||
        if self.milliseconds is not None:
 | 
			
		||||
            out['milliseconds'] = self.milliseconds
 | 
			
		||||
        if self.seconds is not None:
 | 
			
		||||
            out['seconds'] = self.seconds
 | 
			
		||||
        if self.minutes is not None:
 | 
			
		||||
            out['minutes'] = self.minutes
 | 
			
		||||
        if self.hours is not None:
 | 
			
		||||
            out['hours'] = self.hours
 | 
			
		||||
        if self.days is not None:
 | 
			
		||||
            out['days'] = self.days
 | 
			
		||||
        return out
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_microseconds(self):
 | 
			
		||||
        return self.total_milliseconds * 1000 + (self.microseconds or 0)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_milliseconds(self):
 | 
			
		||||
        return self.total_seconds * 1000 + (self.milliseconds or 0)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_seconds(self):
 | 
			
		||||
        return self.total_minutes * 60 + (self.seconds or 0)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_minutes(self):
 | 
			
		||||
        return self.total_hours * 60 + (self.minutes or 0)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_hours(self):
 | 
			
		||||
        return self.total_days * 24 + (self.hours or 0)
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def total_days(self):
 | 
			
		||||
        return self.days or 0
 | 
			
		||||
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds == other.total_microseconds
 | 
			
		||||
 | 
			
		||||
    def __ne__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds != other.total_microseconds
 | 
			
		||||
 | 
			
		||||
    def __lt__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds < other.total_microseconds
 | 
			
		||||
 | 
			
		||||
    def __gt__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds > other.total_microseconds
 | 
			
		||||
 | 
			
		||||
    def __le__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds <= other.total_microseconds
 | 
			
		||||
 | 
			
		||||
    def __ge__(self, other):
 | 
			
		||||
        if not isinstance(other, TimePeriod):
 | 
			
		||||
            raise ValueError("other must be TimePeriod")
 | 
			
		||||
        return self.total_microseconds >= other.total_microseconds
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TimePeriodMicroseconds(TimePeriod):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TimePeriodMilliseconds(TimePeriod):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TimePeriodSeconds(TimePeriod):
 | 
			
		||||
    pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CONFIG_PATH = None
 | 
			
		||||
SIMPLIFY = True
 | 
			
		||||
ESP_PLATFORM = ''
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,9 @@ from esphomeyaml import core
 | 
			
		||||
from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, \
 | 
			
		||||
    CONF_INVERTED, \
 | 
			
		||||
    CONF_MODE, CONF_NUMBER, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_RETAIN, \
 | 
			
		||||
    CONF_STATE_TOPIC, CONF_TOPIC
 | 
			
		||||
from esphomeyaml.core import ESPHomeYAMLError, HexInt
 | 
			
		||||
    CONF_STATE_TOPIC, CONF_TOPIC, CONF_PCF8574
 | 
			
		||||
from esphomeyaml.core import ESPHomeYAMLError, HexInt, TimePeriodMicroseconds, \
 | 
			
		||||
    TimePeriodMilliseconds, TimePeriodSeconds
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
@@ -103,14 +104,32 @@ class ExpressionList(Expression):
 | 
			
		||||
        return indent_all_but_first_and_last(text)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CallExpression(Expression):
 | 
			
		||||
    def __init__(self, base, *args):
 | 
			
		||||
        super(CallExpression, self).__init__()
 | 
			
		||||
        self.base = base
 | 
			
		||||
class TemplateArguments(Expression):
 | 
			
		||||
    def __init__(self, *args):
 | 
			
		||||
        super(TemplateArguments, self).__init__()
 | 
			
		||||
        self.args = ExpressionList(*args)
 | 
			
		||||
        self.requires.append(self.args)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return u'<{}>'.format(self.args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CallExpression(Expression):
 | 
			
		||||
    def __init__(self, base, *args):
 | 
			
		||||
        super(CallExpression, self).__init__()
 | 
			
		||||
        self.base = base
 | 
			
		||||
        if args and isinstance(args[0], TemplateArguments):
 | 
			
		||||
            self.template_args = args[0]
 | 
			
		||||
            self.requires.append(self.template_args)
 | 
			
		||||
            args = args[1:]
 | 
			
		||||
        else:
 | 
			
		||||
            self.template_args = None
 | 
			
		||||
        self.args = ExpressionList(*args)
 | 
			
		||||
        self.requires.append(self.args)
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        if self.template_args is not None:
 | 
			
		||||
            return u'{}{}({})'.format(self.base, self.template_args, self.args)
 | 
			
		||||
        return u'{}({})'.format(self.base, self.args)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -218,10 +237,18 @@ def safe_exp(obj):
 | 
			
		||||
        return BoolLiteral(obj)
 | 
			
		||||
    elif isinstance(obj, (str, unicode)):
 | 
			
		||||
        return StringLiteral(obj)
 | 
			
		||||
    elif isinstance(obj, HexInt):
 | 
			
		||||
        return HexIntLiteral(obj)
 | 
			
		||||
    elif isinstance(obj, (int, long)):
 | 
			
		||||
        return IntLiteral(obj)
 | 
			
		||||
    elif isinstance(obj, float):
 | 
			
		||||
        return FloatLiteral(obj)
 | 
			
		||||
    elif isinstance(obj, TimePeriodMicroseconds):
 | 
			
		||||
        return IntLiteral(int(obj.total_microseconds))
 | 
			
		||||
    elif isinstance(obj, TimePeriodMilliseconds):
 | 
			
		||||
        return IntLiteral(int(obj.total_milliseconds))
 | 
			
		||||
    elif isinstance(obj, TimePeriodSeconds):
 | 
			
		||||
        return IntLiteral(int(obj.total_seconds))
 | 
			
		||||
    raise ValueError(u"Object is not an expression", obj)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -300,6 +327,7 @@ def get_variable(id, type=None):
 | 
			
		||||
        return None
 | 
			
		||||
    if result is None:
 | 
			
		||||
        if id is not None:
 | 
			
		||||
            if id in _VARIABLES:
 | 
			
		||||
                result = _VARIABLES[id][0]
 | 
			
		||||
        elif type is not None:
 | 
			
		||||
            result = next((x[0] for x in _VARIABLES.itervalues() if x[1] == type), None)
 | 
			
		||||
@@ -371,8 +399,8 @@ def exp_gpio_pin_(obj, conf, default_mode):
 | 
			
		||||
    if isinstance(conf, int):
 | 
			
		||||
        return conf
 | 
			
		||||
 | 
			
		||||
    if 'pcf8574' in conf:
 | 
			
		||||
        hub = get_variable(conf['pcf8574'])
 | 
			
		||||
    if CONF_PCF8574 in conf:
 | 
			
		||||
        hub = get_variable(conf[CONF_PCF8574], 'io::PCF8574Component')
 | 
			
		||||
        if default_mode == u'INPUT':
 | 
			
		||||
            return hub.make_input_pin(conf[CONF_NUMBER],
 | 
			
		||||
                                      RawExpression('PCF8574_' + conf[CONF_MODE]),
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ import voluptuous as vol
 | 
			
		||||
 | 
			
		||||
import esphomeyaml.config_validation as cv
 | 
			
		||||
from esphomeyaml import core
 | 
			
		||||
from esphomeyaml.const import ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266, CONF_NUMBER, CONF_MODE, \
 | 
			
		||||
    CONF_INVERTED, CONF_ID, CONF_PCF8575
 | 
			
		||||
from esphomeyaml.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_PCF8574, \
 | 
			
		||||
    ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
@@ -96,7 +96,7 @@ def _translate_pin(value):
 | 
			
		||||
    raise vol.Invalid(u"Invalid ESP platform.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _validate_gpio_pin(value):
 | 
			
		||||
def validate_gpio_pin(value):
 | 
			
		||||
    value = _translate_pin(value)
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        if value < 0 or value > 39:
 | 
			
		||||
@@ -119,7 +119,7 @@ def _validate_gpio_pin(value):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def input_pin(value):
 | 
			
		||||
    value = _validate_gpio_pin(value)
 | 
			
		||||
    value = validate_gpio_pin(value)
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        return value
 | 
			
		||||
    elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
 | 
			
		||||
@@ -128,21 +128,19 @@ def input_pin(value):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def output_pin(value):
 | 
			
		||||
    value = _validate_gpio_pin(value)
 | 
			
		||||
    value = validate_gpio_pin(value)
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        if 34 <= value <= 39:
 | 
			
		||||
            raise vol.Invalid(u"ESP32: Pin {} (34-39) can only be used as "
 | 
			
		||||
                              u"input pins.".format(value))
 | 
			
		||||
        return value
 | 
			
		||||
    elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
 | 
			
		||||
        if value == 16:
 | 
			
		||||
            raise vol.Invalid(u"Pin {} doesn't support output mode".format(value))
 | 
			
		||||
        return value
 | 
			
		||||
    raise vol.Invalid("Invalid ESP platform.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def analog_pin(value):
 | 
			
		||||
    value = _validate_gpio_pin(value)
 | 
			
		||||
    value = validate_gpio_pin(value)
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        if 32 <= value <= 39:  # ADC1
 | 
			
		||||
            return value
 | 
			
		||||
@@ -179,57 +177,23 @@ def pin_mode(value):
 | 
			
		||||
    raise vol.Invalid(u"Invalid ESP platform.")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pcf8574_pin(value, default_mode):
 | 
			
		||||
    if 'pcf8574' not in core.RAW_CONFIG:
 | 
			
		||||
        raise vol.Invalid("PCF8574 not loaded, ignore this.")
 | 
			
		||||
PCF8574_OUTPUT_PIN_SCHEMA = vol.Schema({
 | 
			
		||||
    vol.Required(CONF_PCF8574): cv.variable_id,
 | 
			
		||||
    vol.Required(CONF_NUMBER): vol.Coerce(int),
 | 
			
		||||
    vol.Optional(CONF_INVERTED): cv.boolean,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
    if isinstance(value, (str, unicode)):
 | 
			
		||||
        value = {CONF_NUMBER: value}
 | 
			
		||||
PCF8574_INPUT_PIN_SCHEMA = PCF8574_OUTPUT_PIN_SCHEMA.extend({
 | 
			
		||||
    vol.Optional(CONF_MODE, default='INPUT'): vol.All(vol.Upper, vol.Any("INPUT", "INPUT_PULLUP")),
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
    if not isinstance(value, dict) or not isinstance(value.get(CONF_NUMBER), (str, unicode)) or \
 | 
			
		||||
            value[CONF_NUMBER].count('.') != 1:
 | 
			
		||||
        raise vol.Invalid("Not PCF8574 pin")
 | 
			
		||||
 | 
			
		||||
    pcf_id, pin = value[CONF_NUMBER].split('.')
 | 
			
		||||
    pin = vol.Coerce(int)(pin)
 | 
			
		||||
 | 
			
		||||
    pcf_conf = cv.ensure_list(core.RAW_CONFIG['pcf8574'])
 | 
			
		||||
    pcf = next((conf for conf in pcf_conf if conf[CONF_ID] == pcf_id), None)
 | 
			
		||||
    if pcf is None:
 | 
			
		||||
        raise vol.Invalid("Unknown PCF8574 id: {}".format(pcf_id))
 | 
			
		||||
 | 
			
		||||
    if pcf.get(CONF_PCF8575, False):
 | 
			
		||||
        pin = vol.Range(min=0, max=15)(pin)
 | 
			
		||||
    else:
 | 
			
		||||
        pin = vol.Range(min=0, max=7)(pin)
 | 
			
		||||
 | 
			
		||||
    mode = vol.All(vol.Coerce(str), vol.Upper)(value.get(CONF_MODE, default_mode))
 | 
			
		||||
    if mode not in ['INPUT', 'INPUT_PULLUP', 'OUTPUT']:
 | 
			
		||||
        raise vol.Invalid("Invalid pin mode for PCF8575: {}".format(mode))
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        'pcf8574': pcf[CONF_ID],
 | 
			
		||||
        CONF_NUMBER: pin,
 | 
			
		||||
        CONF_INVERTED: value.get(CONF_INVERTED, False),
 | 
			
		||||
        CONF_MODE: mode
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pcf8574_output_pin(value):
 | 
			
		||||
    return pcf8574_pin(value, 'OUTPUT')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def pcf8574_input_pin(value):
 | 
			
		||||
    return pcf8574_pin(value, 'INPUT')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GPIO_OUTPUT_PIN_SCHEMA = vol.Any(output_pin, pcf8574_output_pin, vol.Schema({
 | 
			
		||||
GPIO_OUTPUT_PIN_SCHEMA = vol.Any(output_pin, PCF8574_OUTPUT_PIN_SCHEMA, vol.Schema({
 | 
			
		||||
    vol.Required(CONF_NUMBER): output_pin,
 | 
			
		||||
    vol.Optional(CONF_MODE): pin_mode,
 | 
			
		||||
    vol.Optional(CONF_INVERTED): cv.boolean,
 | 
			
		||||
}))
 | 
			
		||||
 | 
			
		||||
GPIO_INPUT_PIN_SCHEMA = vol.Any(input_pin, pcf8574_input_pin, vol.Schema({
 | 
			
		||||
GPIO_INPUT_PIN_SCHEMA = vol.Any(input_pin, PCF8574_INPUT_PIN_SCHEMA, vol.Schema({
 | 
			
		||||
    vol.Required(CONF_NUMBER): input_pin,
 | 
			
		||||
    vol.Optional(CONF_MODE): pin_mode,
 | 
			
		||||
    vol.Optional(CONF_INVERTED): cv.boolean,
 | 
			
		||||
 
 | 
			
		||||
@@ -96,6 +96,7 @@ def get_ini_content(config):
 | 
			
		||||
        build_flags |= get_build_flags(config, 'BUILD_FLAGS')
 | 
			
		||||
        build_flags.add(u"-DESPHOMEYAML_USE")
 | 
			
		||||
    build_flags |= get_build_flags(config, 'required_build_flags')
 | 
			
		||||
    build_flags |= get_build_flags(config, 'REQUIRED_BUILD_FLAGS')
 | 
			
		||||
 | 
			
		||||
    # avoid changing build flags order
 | 
			
		||||
    build_flags = sorted(list(build_flags))
 | 
			
		||||
@@ -104,27 +105,16 @@ def get_ini_content(config):
 | 
			
		||||
 | 
			
		||||
    lib_deps = set()
 | 
			
		||||
    lib_deps.add(config[CONF_ESPHOMEYAML][CONF_LIBRARY_URI])
 | 
			
		||||
    lib_deps |= get_build_flags(config, 'LIB_DEPS')
 | 
			
		||||
    lib_deps |= get_build_flags(config, 'lib_deps')
 | 
			
		||||
    if core.ESP_PLATFORM == ESP_PLATFORM_ESP32:
 | 
			
		||||
        lib_deps |= {
 | 
			
		||||
            'ArduinoOTA',
 | 
			
		||||
            'Update',
 | 
			
		||||
            'ESPmDNS',
 | 
			
		||||
            'Wire',
 | 
			
		||||
            'FS',
 | 
			
		||||
            'Preferences',
 | 
			
		||||
 | 
			
		||||
            'Preferences',  # Preferences helper
 | 
			
		||||
        }
 | 
			
		||||
    elif core.ESP_PLATFORM == ESP_PLATFORM_ESP8266:
 | 
			
		||||
        lib_deps |= {
 | 
			
		||||
            'ESP8266WiFi',
 | 
			
		||||
            'Wire',
 | 
			
		||||
            'Hash',
 | 
			
		||||
            'ESP8266mDNS',
 | 
			
		||||
            'ArduinoOTA',
 | 
			
		||||
        }
 | 
			
		||||
    else:
 | 
			
		||||
        raise ESPHomeYAMLError("Unsupported platform {}".format(core.ESP_PLATFORM))
 | 
			
		||||
    options[u'lib_deps'] = u'\n    '.join(sorted(list(lib_deps)))
 | 
			
		||||
    # avoid changing build flags order
 | 
			
		||||
    lib_deps = sorted(x for x in lib_deps if x)
 | 
			
		||||
    if lib_deps:
 | 
			
		||||
        options[u'lib_deps'] = u'\n    '.join(lib_deps)
 | 
			
		||||
 | 
			
		||||
    return INI_CONTENT_FORMAT.format(**options)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,8 @@ from collections import OrderedDict
 | 
			
		||||
 | 
			
		||||
import yaml
 | 
			
		||||
 | 
			
		||||
from esphomeyaml.core import ESPHomeYAMLError, HexInt, IPAddress
 | 
			
		||||
from esphomeyaml.core import ESPHomeYAMLError, HexInt, IPAddress, MACAddress, TimePeriod, \
 | 
			
		||||
    TimePeriodMicroseconds, TimePeriodMilliseconds, TimePeriodSeconds
 | 
			
		||||
 | 
			
		||||
_LOGGER = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
@@ -245,11 +246,30 @@ def hex_int_representer(_, data):
 | 
			
		||||
    return node
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def ipaddress_representer(_, data):
 | 
			
		||||
def stringify_representer(_, data):
 | 
			
		||||
    node = yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=str(data))
 | 
			
		||||
    return node
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TIME_PERIOD_UNIT_MAP = {
 | 
			
		||||
    'microseconds': 'us',
 | 
			
		||||
    'milliseconds': 'ms',
 | 
			
		||||
    'seconds': 's',
 | 
			
		||||
    'minutes': 'min',
 | 
			
		||||
    'hours': 'h',
 | 
			
		||||
    'days': 'd',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def represent_time_period(dumper, data):
 | 
			
		||||
    dictionary = data.as_dict()
 | 
			
		||||
    if len(dictionary) == 1:
 | 
			
		||||
        unit, value = dictionary.popitem()
 | 
			
		||||
        out = '{}{}'.format(value, TIME_PERIOD_UNIT_MAP[unit])
 | 
			
		||||
        return yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=out)
 | 
			
		||||
    return represent_odict(dumper, 'tag:yaml.org,2002:map', dictionary)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
yaml.SafeDumper.add_representer(
 | 
			
		||||
    OrderedDict,
 | 
			
		||||
    lambda dumper, value:
 | 
			
		||||
@@ -264,4 +284,9 @@ yaml.SafeDumper.add_representer(
 | 
			
		||||
 | 
			
		||||
yaml.SafeDumper.add_representer(unicode, unicode_representer)
 | 
			
		||||
yaml.SafeDumper.add_representer(HexInt, hex_int_representer)
 | 
			
		||||
yaml.SafeDumper.add_representer(IPAddress, ipaddress_representer)
 | 
			
		||||
yaml.SafeDumper.add_representer(IPAddress, stringify_representer)
 | 
			
		||||
yaml.SafeDumper.add_representer(MACAddress, stringify_representer)
 | 
			
		||||
yaml.SafeDumper.add_representer(TimePeriod, represent_time_period)
 | 
			
		||||
yaml.SafeDumper.add_representer(TimePeriodMicroseconds, represent_time_period)
 | 
			
		||||
yaml.SafeDumper.add_representer(TimePeriodMilliseconds, represent_time_period)
 | 
			
		||||
yaml.SafeDumper.add_representer(TimePeriodSeconds, represent_time_period)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user