diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 136c669300..783f1400b6 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -22,6 +22,8 @@ PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ # Base light_ns = esphome_ns.namespace('light') LightState = light_ns.class_('LightState', Nameable, Component) +# Fake class for addressable lights +AddressableLightState = light_ns.class_('LightState', LightState) MakeLight = Application.struct('MakeLight') LightOutput = light_ns.class_('LightOutput') AddressableLight = light_ns.class_('AddressableLight') diff --git a/esphome/components/light/fastled_clockless.py b/esphome/components/light/fastled_clockless.py index 3ce85cd338..5e46083c3c 100644 --- a/esphome/components/light/fastled_clockless.py +++ b/esphome/components/light/fastled_clockless.py @@ -57,6 +57,7 @@ def validate(value): MakeFastLEDLight = Application.struct('MakeFastLEDLight') PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(light.AddressableLightState), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight), vol.Required(CONF_CHIPSET): cv.one_of(*TYPES, upper=True), diff --git a/esphome/components/light/fastled_spi.py b/esphome/components/light/fastled_spi.py index 0975357ab0..49be646d9a 100644 --- a/esphome/components/light/fastled_spi.py +++ b/esphome/components/light/fastled_spi.py @@ -34,6 +34,7 @@ RGB_ORDERS = [ MakeFastLEDLight = Application.struct('MakeFastLEDLight') PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(light.AddressableLightState), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeFastLEDLight), vol.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), diff --git a/esphome/components/light/neopixelbus.py b/esphome/components/light/neopixelbus.py index a644110802..30d7ab7854 100644 --- a/esphome/components/light/neopixelbus.py +++ b/esphome/components/light/neopixelbus.py @@ -131,6 +131,7 @@ def validate(config): MakeNeoPixelBusLight = Application.struct('MakeNeoPixelBusLight') PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(light.AddressableLightState), cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeNeoPixelBusLight), vol.Optional(CONF_TYPE, default='GRB'): validate_type, diff --git a/esphome/components/light/partition.py b/esphome/components/light/partition.py new file mode 100644 index 0000000000..0495841765 --- /dev/null +++ b/esphome/components/light/partition.py @@ -0,0 +1,52 @@ +import voluptuous as vol + +from esphome.components import light +from esphome.components.light import AddressableLight +import esphome.config_validation as cv +from esphome.const import CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_FROM, CONF_ID, \ + CONF_MAKE_ID, CONF_NAME, CONF_SEGMENTS, CONF_TO +from esphome.cpp_generator import get_variable, variable +from esphome.cpp_types import App, Application + +AddressableSegment = light.light_ns.class_('AddressableSegment') +PartitionLightOutput = light.light_ns.class_('PartitionLightOutput', AddressableLight) +MakePartitionLight = Application.struct('MakePartitionLight') + + +def validate_from_to(value): + if value[CONF_FROM] > value[CONF_TO]: + raise vol.Invalid(u"From ({}) must not be larger than to ({})" + u"".format(value[CONF_FROM], value[CONF_TO])) + return value + + +PLATFORM_SCHEMA = cv.nameable(light.LIGHT_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(light.AddressableLightState), + cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakePartitionLight), + + vol.Required(CONF_SEGMENTS): vol.All(cv.ensure_list({ + vol.Required(CONF_ID): cv.use_variable_id(light.AddressableLightState), + vol.Required(CONF_FROM): cv.positive_int, + vol.Required(CONF_TO): cv.positive_int, + }, validate_from_to), vol.Length(min=1)), + + vol.Optional(CONF_DEFAULT_TRANSITION_LENGTH): cv.positive_time_period_milliseconds, + vol.Optional(CONF_EFFECTS): light.validate_effects(light.ADDRESSABLE_EFFECTS), +})) + + +def to_code(config): + segments = [] + for conf in config[CONF_SEGMENTS]: + for var in get_variable(conf[CONF_ID]): + yield + segments.append(AddressableSegment(var, conf[CONF_FROM], + conf[CONF_TO] - conf[CONF_FROM] + 1)) + + rhs = App.make_partition_light(config[CONF_NAME], segments) + make = variable(config[CONF_MAKE_ID], rhs) + light.setup_light(make.Pstate, config) + + +def to_hass_config(data, config): + return light.core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=False) diff --git a/esphome/const.py b/esphome/const.py index bf87d9de07..f3118ac062 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -406,6 +406,9 @@ CONF_INTERLOCK = 'interlock' CONF_ON_TURN_ON = 'on_turn_on' CONF_ON_TURN_OFF = 'on_turn_off' CONF_USE_ADDRESS = 'use_address' +CONF_FROM = 'from' +CONF_TO = 'to' +CONF_SEGMENTS = 'segments' ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' diff --git a/tests/test1.yaml b/tests/test1.yaml index a5d0686905..ff7b6f8168 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -738,6 +738,7 @@ light: cold_white_color_temperature: 153 mireds warm_white_color_temperature: 500 mireds - platform: fastled_clockless + id: addr1 chipset: WS2811 pin: GPIO23 num_leds: 60 @@ -788,6 +789,7 @@ light: update_interval: 16ms intensity: 5% - platform: fastled_spi + id: addr2 chipset: WS2801 data_pin: GPIO23 clock_pin: GPIO22 @@ -795,6 +797,7 @@ light: rgb_order: BRG name: "FastLED SPI Light" - platform: neopixelbus + id: addr3 name: "Neopixelbus Light" gamma_correct: 2.8 color_correct: [0.0, 0.0, 0.0, 0.0] @@ -810,6 +813,18 @@ light: method: ESP32_I2S_0 num_leds: 60 pin: GPIO23 + - platform: partition + name: "Partition Light" + segments: + - id: addr1 + from: 0 + to: 0 + - id: addr2 + from: 1 + to: 10 + - id: addr2 + from: 20 + to: 25 remote_transmitter: - pin: 32