- import esphome.codegen as cg
- import esphome.config_validation as cv
- from esphome import pins
- from esphome.components.ledc.output import LEDCOutput
- from esphome.components.gpio.output import GPIOBinaryOutput
- from esphome.components.i2c import I2CComponent, I2CDevice
- from esphome.core import coroutine
- from esphome.core import CORE
- from esphome.const import (
- CONF_ID, CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, CONF_TRIGGER_PIN,
- CONF_SDA, CONF_SCL, CONF_OUTPUT_ID, CONF_TRIGGER_ID, CONF_PIN,
- CONF_FREQUENCY, CONF_CHANNEL, CONF_PLATFORM,
- )
-
- CODEOWNERS = ["@mmakaay"]
-
- CONF_HUB_ID = "yeelight_bs2_hub_id"
- CONF_RED_ID = "red_id"
- CONF_GREEN_ID = "green_id"
- CONF_BLUE_ID = "blue_id"
- CONF_WHITE_ID = "white_id"
- CONF_MASTER1 = "master1"
- CONF_MASTER1_ID = "master1_id"
- CONF_MASTER2 = "master2"
- CONF_MASTER2_ID = "master2_id"
- CONF_FP_I2C_ID = "front_panel_i2c_id"
- CONF_LIGHT_HAL_ID = "light_hal"
- CONF_FRONT_PANEL_HAL_ID = "front_panel_hal_id"
-
- CONF_ON_BRIGHTNESS = "on_brightness"
-
- AUTO_LOAD = ["ledc", "output", "i2c"]
-
- yeelight_ns = cg.esphome_ns.namespace("yeelight")
- bs2_ns = yeelight_ns.namespace("bs2")
- LightHAL = bs2_ns.class_("LightHAL", cg.Component)
- FrontPanelHAL = bs2_ns.class_("FrontPanelHAL", cg.Component, I2CDevice)
-
- def make_config_schema():
- schema = cv.COMPONENT_SCHEMA.extend({
- # RGBWW Light
- cv.GenerateID(CONF_LIGHT_HAL_ID): cv.declare_id(LightHAL),
- cv.GenerateID(CONF_RED_ID): cv.declare_id(LEDCOutput),
- cv.Optional(CONF_RED, default="GPIO13"): pins.validate_gpio_pin,
- cv.GenerateID(CONF_GREEN_ID): cv.declare_id(LEDCOutput),
- cv.Optional(CONF_GREEN, default="GPIO14"): pins.validate_gpio_pin,
- cv.GenerateID(CONF_BLUE_ID): cv.declare_id(LEDCOutput),
- cv.Optional(CONF_BLUE, default="GPIO5"): pins.validate_gpio_pin,
- cv.GenerateID(CONF_WHITE_ID): cv.declare_id(LEDCOutput),
- cv.Optional(CONF_WHITE, default="GPIO12"): pins.validate_gpio_pin,
- cv.GenerateID(CONF_MASTER1_ID): cv.declare_id(GPIOBinaryOutput),
- cv.Optional(CONF_MASTER1, default="GPIO33"): pins.validate_gpio_pin,
- cv.GenerateID(CONF_MASTER2_ID): cv.declare_id(GPIOBinaryOutput),
- cv.Optional(CONF_MASTER2, default="GPIO4"): pins.validate_gpio_pin,
-
- # Front panel I2C
- cv.GenerateID(CONF_FRONT_PANEL_HAL_ID): cv.declare_id(FrontPanelHAL),
- cv.GenerateID(CONF_FP_I2C_ID): cv.use_id(I2CComponent),
- cv.Optional(CONF_SDA, default="GPIO21"): pins.validate_gpio_pin,
- cv.Optional(CONF_SCL, default="GPIO19"): pins.validate_gpio_pin,
- cv.Optional(CONF_TRIGGER_PIN, default="GPIO16"): cv.All(
- pins.validate_gpio_pin,
- pins.validate_has_interrupt
- ),
- })
-
- return schema;
-
- CONFIG_SCHEMA = make_config_schema()
-
- @coroutine
- def make_gpio(number, mode="OUTPUT"):
- yield from cg.gpio_pin_expression({ "number": number, "mode": mode });
-
- @coroutine
- def make_gpio_binary_output(id_, number):
- gpio_var = yield make_gpio(number)
- output_var = cg.new_Pvariable(id_)
- cg.add(output_var.set_pin(gpio_var))
- yield from cg.register_component(output_var, {})
-
- @coroutine
- def make_ledc_output(id_, number, frequency, channel):
- gpio_var = yield make_gpio(number)
- ledc_var = cg.new_Pvariable(id_, gpio_var)
- cg.add(ledc_var.set_frequency(frequency));
- cg.add(ledc_var.set_channel(channel));
- yield from cg.register_component(ledc_var, {})
-
- @coroutine
- def make_light_hal(config):
- r_var = yield make_ledc_output(config[CONF_RED_ID], config[CONF_RED], 3000, 0)
- g_var = yield make_ledc_output(config[CONF_GREEN_ID], config[CONF_GREEN], 3000, 1)
- b_var = yield make_ledc_output(config[CONF_BLUE_ID], config[CONF_BLUE], 3000, 2)
- w_var = yield make_ledc_output(config[CONF_WHITE_ID], config[CONF_WHITE], 10000, 4)
- m1_var = yield make_gpio_binary_output(config[CONF_MASTER1_ID], config[CONF_MASTER1])
- m2_var = yield make_gpio_binary_output(config[CONF_MASTER2_ID], config[CONF_MASTER2])
- light_hal = cg.new_Pvariable(config[CONF_LIGHT_HAL_ID])
- yield cg.register_component(light_hal, config)
- cg.add(light_hal.set_red_pin(r_var))
- cg.add(light_hal.set_green_pin(g_var))
- cg.add(light_hal.set_blue_pin(b_var))
- cg.add(light_hal.set_white_pin(w_var))
- cg.add(light_hal.set_master1_pin(m1_var))
- cg.add(light_hal.set_master2_pin(m2_var))
-
- @coroutine
- def make_front_panel_hal(config):
- trigger_pin = yield make_gpio(config[CONF_TRIGGER_PIN], "INPUT")
- fp_hal = cg.new_Pvariable(config[CONF_FRONT_PANEL_HAL_ID])
- yield cg.register_component(fp_hal, config)
- cg.add(fp_hal.set_trigger_pin(trigger_pin))
-
- # The i2c component automatically sets up one I2C bus.
- # Take that bus and update is to make it work for the
- # front panel I2C communication.
- fp_i2c_var = yield cg.get_variable(config[CONF_FP_I2C_ID])
- cg.add(fp_i2c_var.set_sda_pin(config[CONF_SDA]))
- cg.add(fp_i2c_var.set_scl_pin(config[CONF_SCL]))
- cg.add(fp_i2c_var.set_scan(True))
- cg.add(fp_hal.set_i2c_parent(fp_i2c_var))
-
- def to_code(config):
- # Dirty little hack to make the ESPHome component loader inlcude
- # the code for the "gpio" platform for the "output" domain.
- # Loading specific platform components is not possible using
- # the AUTO_LOAD feature unfortunately.
- CORE.config["output"].append({ CONF_PLATFORM: "gpio" })
-
- yield make_light_hal(config)
- yield make_front_panel_hal(config)
|