@ -1,28 +1,19 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins
from esphome.components.ledc.output import LEDCOutput , validate_frequency
from esphome.components.ledc.output import LEDCOutput
from esphome.components.gpio.output import GPIOBinaryOutput
from esphome.components.i2c import I2CComponent
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 ,
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 "
@ -33,105 +24,92 @@ CONF_MASTER1_ID = "master1_id"
CONF_MASTER2 = " master2 "
CONF_MASTER2_ID = " master2_id "
CONF_FP_I2C_ID = " front_panel_i2c_id "
CONF_ON_BRIGHTNESS = " on_brightness "
CONF_LIGHT_HAL_ID = " light_hal "
CONF_FRONT_PANEL_HAL_ID = " front_panel_hal_id "
CODEOWNERS = [ " @mmakaay " ]
CONF_ON_BRIGHTNESS = " on_brightness "
AUTO_LOAD = [ " ledc " , " output " , " i2c " ]
PINS = {
# Config key TYPE, ID GPIO, PARAMS
CONF_RED : ( LEDCOutput , CONF_RED_ID , " GPIO13 " , 3000 , 0 ) ,
CONF_GREEN : ( LEDCOutput , CONF_GREEN_ID , " GPIO14 " , 3000 , 1 ) ,
CONF_BLUE : ( LEDCOutput , CONF_BLUE_ID , " GPIO5 " , 3000 , 2 ) ,
CONF_WHITE : ( LEDCOutput , CONF_WHITE_ID , " GPIO12 " , 10000 , 4 ) ,
CONF_MASTER1 : ( GPIOBinaryOutput , CONF_MASTER1_ID , " GPIO33 " ) ,
CONF_MASTER2 : ( GPIOBinaryOutput , CONF_MASTER2_ID , " GPIO4 " )
}
FRONT_PANEL = {
CONF_SDA : " GPIO21 " ,
CONF_SCL : " GPIO19 " ,
CONF_TRIGGER_PIN : " GPIO16 "
}
yeelight_ns = cg . esphome_ns . namespace ( " yeelight " )
bs2_ns = yeelight_ns . namespace ( " bs2 " )
YeelightBS2Hub = bs2_ns . class_ ( " YeelightBS2Hub " , cg . Component )
LightHAL = bs2_ns . class_ ( " LightHAL " , cg . Component )
FrontPanelHAL = bs2_ns . class_ ( " FrontPanelHAL " , cg . Component , I2CDevice )
def make_config_schema ( ) :
schema = cv . COMPONENT_SCHEMA . extend ( {
cv . GenerateID ( ) : cv . declare_id ( YeelightBS2Hub ) ,
# 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 = FRONT_PANEL [ CONF_SDA ] ) : pins . validate_gpio_pin ,
cv . Optional ( CONF_SCL , default = FRONT_PANEL [ CONF_SCL ] ) : pins . validate_gpio_pin ,
cv . Optional ( CONF_TRIGGER_PIN , default = FRONT_PANEL [ CONF_TRIGGER_PIN ] ) : cv . All (
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
) ,
} )
for key , pin_config in PINS . items ( ) :
type_ , id_ , pin , * _ = pin_config
schema = schema . extend ( {
cv . GenerateID ( id_ ) : cv . declare_id ( type_ ) ,
cv . Optional ( key , default = pin ) : pins . validate_gpio_pin
} )
return schema ;
CONFIG_SCHEMA = make_config_schema ( )
@coroutine
def make_gpio_pin ( key , config ) :
type_ , id_ , * _ = PINS [ key ]
yield from cg.gpio_pin_expression ( {
" number " : config [ key ] ,
" mode " : " OUTPUT "
} ) ;
def make_gpio ( number , mode = " OUTPUT " ) :
yield from cg.gpio_pin_expression ( { " number " : number , " mode " : mode } ) ;
@coroutine
def make_gpio_binary_output ( key , config , gpio_va r) :
type_ , id_ , * _ = PINS [ key ]
output_var = cg . new_Pvariable ( config [ id_ ] )
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 ( key , config , gpio_var ) :
type_ , id_ , _ , frequency , channel = PINS [ key ]
ledc_var = cg . new_Pvariable ( config [ id_ ] , gpio_var )
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 , { } )
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 " } )
@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 ) )
hub_var = cg . new_Pvariable ( config [ CONF_ID ] )
yield cg . register_component ( hub_var , config )
for key in PINS :
type_ = PINS [ key ] [ 0 ]
gpio_var = yield make_gpio_pin ( key , config )
if type_ == LEDCOutput :
pin_var = yield make_ledc_output ( key , config , gpio_var )
if type_ == GPIOBinaryOutput :
pin_var = yield make_gpio_binary_output ( key , config , gpio_var )
setter = getattr ( hub_var , " set_ %s _pin " % key )
cg . add ( setter ( pin_var ) )
trigger_pin = yield cg . gpio_pin_expression ( {
" number " : config [ CONF_TRIGGER_PIN ] ,
" mode " : " INPUT " ,
" inverted " : False
} )
cg . add ( hub_var . set_trigger_pin ( trigger_pin ) )
@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
@ -140,9 +118,14 @@ def to_code(config):
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 ( hub_var . set_front_panel_i2c ( fp_i2c_var ) )
cg . add ( fp_hal . set_i2c_parent ( fp_i2c_var ) )
for conf in config . get ( CONF_ON_BRIGHTNESS , [ ] ) :
trigger = cg . new_Pvariable ( conf [ CONF_TRIGGER_ID ] , var )
yield automation . build_automation ( trigger , [ ( float , " x " ) ] , conf )
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 )