mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Preparations for 1.5.0
This commit is contained in:
		| @@ -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='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=436900))), | ||||
|     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=0, max=100, min_included=False)), | ||||
| })]) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -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' | ||||
|   | ||||
							
								
								
									
										98
									
								
								esphomeyaml/components/light/fastled_clockless.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								esphomeyaml/components/light/fastled_clockless.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| import voluptuous as vol | ||||
|  | ||||
| import esphomeyaml.config_validation as cv | ||||
| from esphomeyaml import pins, core | ||||
| 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, \ | ||||
|     ESP_PLATFORM_ESP32 | ||||
| from esphomeyaml.helpers import App, TemplateArguments, add, setup_mqtt_component, variable, \ | ||||
|     RawExpression | ||||
|  | ||||
| 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', | ||||
|     'PIXIE', | ||||
| ] | ||||
|  | ||||
| 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") | ||||
|     if value[CONF_CHIPSET] == 'PIXIE' and core.ESP_PLATFORM == ESP_PLATFORM_ESP32: | ||||
|         raise vol.Invalid("PIXIE lights are not supported with the ESP32") | ||||
|     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' | ||||
|  | ||||
|  | ||||
| def required_build_flags(config): | ||||
|     if config[CONF_CHIPSET] == 'PIXIE': | ||||
|         return '-DUSE_FAST_LED_LIGHT_PIXIE' | ||||
|     return None | ||||
							
								
								
									
										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) | ||||
|   | ||||
| @@ -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, | ||||
| }).extend(sensor.MQTT_SENSOR_SCHEMA.schema) | ||||
|  | ||||
|  | ||||
| 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, | ||||
| }).extend(sensor.MQTT_SENSOR_SCHEMA.schema) | ||||
|  | ||||
|  | ||||
| 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) | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										52
									
								
								esphomeyaml/components/sensor/tsl2561.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								esphomeyaml/components/sensor/tsl2561.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| 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.core import TimePeriod | ||||
| from esphomeyaml.helpers import App, RawExpression, add, variable | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
|  | ||||
| INTEGRATION_TIMES = { | ||||
|     TimePeriod(milliseconds=14): 'sensor::TSL2561_INTEGRATION_14MS', | ||||
|     TimePeriod(milliseconds=101): 'sensor::TSL2561_INTEGRATION_101MS', | ||||
|     TimePeriod(milliseconds=402): 'sensor::TSL2561_INTEGRATION_402MS', | ||||
| } | ||||
| GAINS = { | ||||
|     '1X': 'sensor::TSL2561_GAIN_1X', | ||||
|     '16X': 'sensor::TSL2561_GAIN_16X', | ||||
| } | ||||
|  | ||||
| CONF_IS_CS_PACKAGE = 'is_cs_package' | ||||
|  | ||||
| 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): vol.All(cv.positive_time_period_milliseconds, | ||||
|                                                  vol.Any(*INTEGRATION_TIMES)), | ||||
|     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,56 @@ 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 | ||||
|     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 +430,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,29 @@ 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' | ||||
|  | ||||
| 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,7 +327,8 @@ def get_variable(id, type=None): | ||||
|         return None | ||||
|     if result is None: | ||||
|         if id is not None: | ||||
|             result = _VARIABLES[id][0] | ||||
|             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,7 +128,7 @@ 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 " | ||||
| @@ -142,7 +142,7 @@ def output_pin(value): | ||||
|  | ||||
|  | ||||
| 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 +179,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