def uart_selection(value): if CORE.is_esp32: if get_esp32_variant() in ESP32_REDUCED_VARIANTS: return cv.one_of(*UART_SELECTION_ESP32_REDUCED, upper=True)(value) return cv.one_of(*UART_SELECTION_ESP32, upper=True)(value) if CORE.is_esp8266: return cv.one_of(*UART_SELECTION_ESP8266, upper=True)(value) raise NotImplementedError
def uart_selection(value): if value.upper() in ESP_IDF_UARTS: if not CORE.using_esp_idf: raise cv.Invalid(f"Only esp-idf framework supports {value}.") if CORE.is_esp32: variant = get_esp32_variant() if variant in UART_SELECTION_ESP32: return cv.one_of(*UART_SELECTION_ESP32[variant], upper=True)(value) if CORE.is_esp8266: return cv.one_of(*UART_SELECTION_ESP8266, upper=True)(value) raise NotImplementedError
def validate_method(value): if value is None: if CORE.is_esp32: return "ESP32_I2S_1" if CORE.is_esp8266: return "ESP8266_DMA" raise NotImplementedError if CORE.is_esp32: return cv.one_of(*ESP32_METHODS, upper=True, space="_")(value) if CORE.is_esp8266: return cv.one_of(*ESP8266_METHODS, upper=True, space="_")(value) raise NotImplementedError
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' return cv.one_of(*values)(value)
def validate_gain(value): if isinstance(value, float): value = u'{:0.03f}'.format(value) elif not isinstance(value, string_types): raise vol.Invalid('invalid gain "{}"'.format(value)) return cv.one_of(*GAIN)(value)
def elevation(value): if isinstance(value, str): try: value = ELEVATION_MAP[cv.one_of(*ELEVATION_MAP, lower=True, space='_')] except cv.Invalid: pass value = cv.angle(value) return cv.float_range(min=-180, max=180)(value)
def validate_variant(value): value = cv.string(value).upper() if value == 'WS2813': value = 'WS2812X' if value == 'WS2812': value = '800KBPS' if value == 'LC8812': value = 'SK6812' return cv.one_of(*VARIANTS)(value)
def validate_rotation(value): value = cv.string(value) if value.endswith(u"°"): value = value[:-1] try: value = int(value) except ValueError: raise vol.Invalid(u"Expected integer for rotation") return cv.one_of(*DISPLAY_ROTATIONS)(value)
def valid_uart(uart): if CORE.is_esp8266: uarts = ["UART0"] # UART1 is tx-only elif CORE.is_esp32: uarts = ["UART0", "UART1", "UART2"] else: raise NotImplementedError return cv.one_of(*uarts, upper=True)(uart)
def validate_variant(value): value = cv.string(value).upper() if value == "WS2813": value = "WS2812X" if value == "WS2812": value = "800KBPS" if value == "LC8812": value = "SK6812" return cv.one_of(*VARIANTS)(value)
def pin_mode(value): if CORE.is_esp32: return cv.one_of(*PIN_MODES_ESP32, upper=True)(value) if CORE.is_esp8266: return cv.one_of(*PIN_MODES_ESP8266, upper=True)(value) raise NotImplementedError
OPERATION_BASE_SCHEMA.extend( { cv.Required(CONF_OPERATION): cv.templatable( cv.enum(SELECT_OPERATION_OPTIONS, upper=True) ), cv.Optional(CONF_CYCLE, default=True): cv.templatable(cv.boolean), } ), ) @automation.register_action( "select.next", SelectOperationAction, automation.maybe_simple_id( OPERATION_BASE_SCHEMA.extend( { cv.Optional(CONF_MODE, default="NEXT"): cv.one_of("NEXT", upper=True), cv.Optional(CONF_CYCLE, default=True): cv.boolean, } ) ), ) @automation.register_action( "select.previous", SelectOperationAction, automation.maybe_simple_id( OPERATION_BASE_SCHEMA.extend( { cv.Optional(CONF_MODE, default="PREVIOUS"): cv.one_of( "PREVIOUS", upper=True ), cv.Optional(CONF_CYCLE, default=True): cv.boolean,
CONFIG_SCHEMA = vol.All( vol.Schema({ cv.GenerateID(): cv.declare_variable_id(MQTTClientComponent), vol.Required(CONF_BROKER): cv.string_strict, vol.Optional(CONF_PORT): cv.port, vol.Optional(CONF_USERNAME, default=''): cv.string, vol.Optional(CONF_PASSWORD, default=''): cv.string, vol.Optional(CONF_CLIENT_ID): vol.All(cv.string, vol.Length(max=23)), vol.Optional(CONF_DISCOVERY): vol.Any(cv.boolean, cv.one_of("CLEAN", upper=True)), vol.Optional(CONF_DISCOVERY_RETAIN): cv.boolean, vol.Optional(CONF_DISCOVERY_PREFIX): cv.publish_topic, vol.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, vol.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, vol.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, vol.Optional(CONF_TOPIC_PREFIX): cv.publish_topic, vol.Optional(CONF_LOG_TOPIC): vol.Any( None,
'int': int32, 'float': float_, 'string': std_string, } CONFIG_SCHEMA = cv.Schema({ cv.GenerateID(): cv.declare_variable_id(APIServer), vol.Optional(CONF_PORT, default=6053): cv.port, vol.Optional(CONF_PASSWORD, default=''): cv.string_strict, vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds, vol.Optional(CONF_SERVICES): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(UserService), vol.Required(CONF_SERVICE): cv.valid_name, vol.Optional(CONF_VARIABLES, default={}): cv.Schema({ cv.validate_id_name: cv.one_of(*SERVICE_ARG_TYPES, lower=True), }), }), }).extend(cv.COMPONENT_SCHEMA.schema) def to_code(config): rhs = App.init_api_server() api = Pvariable(config[CONF_ID], rhs) if config[CONF_PORT] != 6053: add(api.set_port(config[CONF_PORT])) if config.get(CONF_PASSWORD): add(api.set_password(config[CONF_PASSWORD])) if CONF_REBOOT_TIMEOUT in config: add(api.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
def assign_declare_id(value): value = value.copy() value[CONF_ID] = cv.declare_id(SCRIPT_MODES[value[CONF_MODE]])( value[CONF_ID]) return value CONFIG_SCHEMA = automation.validate_automation( { # Don't declare id as cv.declare_id yet, because the ID type # dpeends on the mode. Will be checked later with assign_declare_id cv.Required(CONF_ID): cv.string_strict, cv.Optional(CONF_MODE, default=CONF_SINGLE): cv.one_of(*SCRIPT_MODES, lower=True), cv.Optional(CONF_MAX_RUNS): cv.positive_int, }, extra_validators=cv.All(check_max_runs, assign_declare_id), ) async def to_code(config): # Register all variables first, so that scripts can use other scripts triggers = [] for conf in config: trigger = cg.new_Pvariable(conf[CONF_ID]) # Add a human-readable name to the script cg.add(trigger.set_name(conf[CONF_ID].id))
config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js" return config def validate_local(config): if CONF_LOCAL in config and config[CONF_VERSION] == 1: raise cv.Invalid("'local' is not supported in version 1") return config CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(WebServer), cv.Optional(CONF_PORT, default=80): cv.port, cv.Optional(CONF_VERSION, default=2): cv.one_of(1, 2), cv.Optional(CONF_CSS_URL): cv.string, cv.Optional(CONF_CSS_INCLUDE): cv.file_, cv.Optional(CONF_JS_URL): cv.string, cv.Optional(CONF_JS_INCLUDE): cv.file_, cv.Optional(CONF_AUTH): cv.Schema( { cv.Required(CONF_USERNAME): cv.All( cv.string_strict, cv.Length(min=1) ), cv.Required(CONF_PASSWORD): cv.All( cv.string_strict, cv.Length(min=1) ), } ), cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id(
HTTP_REQUEST_ACTION_SCHEMA = cv.Schema({ cv.GenerateID(): cv.use_id(HttpRequestComponent), cv.Required(CONF_URL): cv.templatable(validate_url), cv.Optional(CONF_HEADERS): cv.All(cv.Schema({cv.string: cv.templatable(cv.string)})), cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, }).add_extra(validate_secure_url) HTTP_REQUEST_GET_ACTION_SCHEMA = automation.maybe_conf( CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend({ cv.Optional(CONF_METHOD, default='GET'): cv.one_of('GET', upper=True), })) HTTP_REQUEST_POST_ACTION_SCHEMA = automation.maybe_conf( CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend({ cv.Optional(CONF_METHOD, default='POST'): cv.one_of('POST', upper=True), cv.Exclusive(CONF_BODY, 'body'): cv.templatable(cv.string), cv.Exclusive(CONF_JSON, 'body'): cv.Any( cv.lambda_, cv.All(cv.Schema({cv.string: cv.templatable(cv.string_strict)})), ), })) HTTP_REQUEST_SEND_ACTION_SCHEMA = HTTP_REQUEST_ACTION_SCHEMA.extend({
return value if MODELS[value[CONF_MODEL]][0] == "b": raise cv.Invalid( "The 'full_update_every' option is only available for models " "'1.54in', '1.54inV2', '2.13in', '2.90in', and '2.90inV2'.") return value CONFIG_SCHEMA = cv.All( display.FULL_DISPLAY_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(WaveshareEPaper), cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, cv.Required(CONF_MODEL): cv.one_of(*MODELS, lower=True), cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, cv.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema, cv.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t, }).extend(cv.polling_component_schema("1s")).extend( spi.spi_device_schema()), validate_full_update_every_only_type_a, cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), ) async def to_code(config): model_type, model = MODELS[config[CONF_MODEL]]
cv.Optional(CONF_PORT, default=6053): cv.port, cv.Optional(CONF_PASSWORD, default=""): cv.string_strict, cv.Optional(CONF_REBOOT_TIMEOUT, default="15min"): cv.positive_time_period_milliseconds, cv.Optional(CONF_SERVICES): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), cv.Required(CONF_SERVICE): cv.valid_name, cv.Optional(CONF_VARIABLES, default={}): cv.Schema({ cv.validate_id_name: cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True), }), }), cv.Optional(CONF_ENCRYPTION): cv.Schema({ cv.Required(CONF_KEY): validate_encryption_key, }), }).extend(cv.COMPONENT_SCHEMA) @coroutine_with_priority(40.0) async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) cg.add(var.set_port(config[CONF_PORT]))
pass @register_action("jvc", JVCAction, JVC_SCHEMA) async def jvc_action(var, config, args): template_ = await cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) # LG LGData, LGBinarySensor, LGTrigger, LGAction, LGDumper = declare_protocol("LG") LG_SCHEMA = cv.Schema({ cv.Required(CONF_DATA): cv.hex_uint32_t, cv.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True), }) @register_binary_sensor("lg", LGBinarySensor, LG_SCHEMA) def lg_binary_sensor(var, config): cg.add( var.set_data( cg.StructInitializer( LGData, ("data", config[CONF_DATA]), ("nbits", config[CONF_NBITS]), ))) @register_trigger("lg", LGTrigger, LGData)
maybe_simple_preset_action( cv.Any( cv.Schema({ cv.GenerateID(CONF_PRESETS_ID): cv.use_id(PresetsContainer), cv.Required(CONF_GROUP): is_preset_group, cv.Optional(CONF_PRESET): is_preset }), cv.Schema({ cv.GenerateID(CONF_PRESETS_ID): cv.use_id(PresetsContainer), cv.Required(CONF_NEXT): cv.one_of(CONF_GROUP, CONF_PRESET, lower=True) }))))) def preset_activate_to_code(config, action_id, template_arg, args): presets_var = yield cg.get_variable(config[CONF_PRESETS_ID]) action_var = cg.new_Pvariable(action_id, template_arg, presets_var) if CONF_NEXT in config: cg.add(action_var.set_operation(f"next_{config[CONF_NEXT]}")) elif CONF_PRESET in config: cg.add(action_var.set_operation("activate_preset")) cg.add(action_var.set_group(config[CONF_GROUP])) cg.add(action_var.set_preset(config[CONF_PRESET])) else: cg.add(action_var.set_operation("activate_group")) cg.add(action_var.set_group(config[CONF_GROUP])) yield action_var
def validate_board(value): if CORE.is_esp8266: board_pins = pins.ESP8266_BOARD_PINS elif CORE.is_esp32: board_pins = pins.ESP32_BOARD_PINS else: raise NotImplementedError if value not in board_pins: raise cv.Invalid( "Could not find board '{}'. Valid boards are {}".format( value, ', '.join(sorted(board_pins.keys())))) return value validate_platform = cv.one_of(*ESP_PLATFORMS, upper=True) PLATFORMIO_ESP8266_LUT = { **ARDUINO_VERSION_ESP8266, 'RECOMMENDED': ARDUINO_VERSION_ESP8266['2.7.4'], 'LATEST': 'espressif8266', 'DEV': ARDUINO_VERSION_ESP8266['dev'], } PLATFORMIO_ESP32_LUT = { **ARDUINO_VERSION_ESP32, 'RECOMMENDED': ARDUINO_VERSION_ESP32['1.0.4'], 'LATEST': 'espressif32', 'DEV': ARDUINO_VERSION_ESP32['dev'], }
def validate_fingerprint(value): value = cv.string(value) if re.match(r'^[0-9a-f]{40}$', value) is None: raise cv.Invalid(u"fingerprint must be valid SHA1 hash") return value CONFIG_SCHEMA = cv.All(cv.Schema({ cv.GenerateID(): cv.declare_id(MQTTClientComponent), cv.Required(CONF_BROKER): cv.string_strict, cv.Optional(CONF_PORT, default=1883): cv.port, cv.Optional(CONF_USERNAME, default=''): cv.string, cv.Optional(CONF_PASSWORD, default=''): cv.string, cv.Optional(CONF_CLIENT_ID): cv.string, cv.Optional(CONF_DISCOVERY, default=True): cv.Any(cv.boolean, cv.one_of("CLEAN", upper=True)), cv.Optional(CONF_DISCOVERY_RETAIN, default=True): cv.boolean, cv.Optional(CONF_DISCOVERY_PREFIX, default="homeassistant"): cv.publish_topic, cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.publish_topic, cv.Optional(CONF_LOG_TOPIC): cv.Any(None, MQTT_MESSAGE_BASE.extend({ cv.Optional(CONF_LEVEL): logger.is_log_level, }), validate_message_just_topic), cv.Optional(CONF_SSL_FINGERPRINTS): cv.All(cv.only_on_esp8266, cv.ensure_list(validate_fingerprint)), cv.Optional(CONF_KEEPALIVE, default='15s'): cv.positive_time_period_seconds, cv.Optional(CONF_REBOOT_TIMEOUT, default='5min'): cv.positive_time_period_milliseconds,
def validate(config): if CONF_USE_ADDRESS not in config: if CONF_MANUAL_IP in config: use_address = str(config[CONF_MANUAL_IP][CONF_STATIC_IP]) else: use_address = CORE.name + config[CONF_DOMAIN] config[CONF_USE_ADDRESS] = use_address return config CONFIG_SCHEMA = vol.All( cv.Schema({ cv.GenerateID(): cv.declare_variable_id(EthernetComponent), vol.Required(CONF_TYPE): cv.one_of(*ETHERNET_TYPES, upper=True), vol.Required(CONF_MDC_PIN): pins.output_pin, vol.Required(CONF_MDIO_PIN): pins.input_output_pin, vol.Optional(CONF_CLK_MODE, default='GPIO0_IN'): cv.one_of(*CLK_MODES, upper=True, space='_'), vol.Optional(CONF_PHY_ADDR, default=0): vol.All(cv.int_, vol.Range(min=0, max=31)), vol.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema, vol.Optional(CONF_MANUAL_IP): wifi.STA_MANUAL_IP_SCHEMA, vol.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, vol.Optional(CONF_USE_ADDRESS):
from esphome.core import CORE from esphome.components.esp32 import add_idf_sdkconfig_option DEPENDENCIES = ["esp32"] CONFLICTS_WITH = ["esp32_ble_tracker"] esp32_ble_beacon_ns = cg.esphome_ns.namespace("esp32_ble_beacon") ESP32BLEBeacon = esp32_ble_beacon_ns.class_("ESP32BLEBeacon", cg.Component) CONF_MAJOR = "major" CONF_MINOR = "minor" CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(ESP32BLEBeacon), cv.Required(CONF_TYPE): cv.one_of("IBEACON", upper=True), cv.Required(CONF_UUID): cv.uuid, cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, cv.Optional(CONF_MINOR, default=61958): cv.uint16_t, } ).extend(cv.COMPONENT_SCHEMA) async def to_code(config): uuid = config[CONF_UUID].hex uuid_arr = [cg.RawExpression(f"0x{uuid[i:i + 2]}") for i in range(0, len(uuid), 2)] var = cg.new_Pvariable(config[CONF_ID], uuid_arr) await cg.register_component(var, config) cg.add(var.set_major(config[CONF_MAJOR])) cg.add(var.set_minor(config[CONF_MINOR]))
if vcc == 'VCC': return cv.only_on_esp8266(vcc) return pins.analog_pin(value) ADCSensorComponent = sensor.sensor_ns.class_('ADCSensorComponent', sensor.PollingSensorComponent) PLATFORM_SCHEMA = cv.nameable( sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(ADCSensorComponent), vol.Required(CONF_PIN): validate_adc_pin, vol.Optional(CONF_ATTENUATION): vol.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES, lower=True)), vol.Optional(CONF_UPDATE_INTERVAL): cv.update_interval, }).extend(cv.COMPONENT_SCHEMA.schema)) def to_code(config): pin = config[CONF_PIN] if pin == 'VCC': pin = 0 rhs = App.make_adc_sensor(config[CONF_NAME], pin, config.get(CONF_UPDATE_INTERVAL)) adc = Pvariable(config[CONF_ID], rhs) if CONF_ATTENUATION in config: add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]])) sensor.setup_sensor(adc, config)
from esphome.components import sensor from esphome.components.apds9960 import APDS9960, CONF_APDS9960_ID import esphome.config_validation as cv from esphome.const import CONF_NAME, CONF_TYPE from esphome.cpp_generator import get_variable DEPENDENCIES = ['apds9960'] TYPES = { 'CLEAR': 'make_clear_channel', 'RED': 'make_red_channel', 'GREEN': 'make_green_channel', 'BLUE': 'make_blue_channel', 'PROXIMITY': 'make_proximity', } PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(sensor.Sensor), vol.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True), cv.GenerateID(CONF_APDS9960_ID): cv.use_variable_id(APDS9960) })) def to_code(config): for hub in get_variable(config[CONF_APDS9960_ID]): yield func = getattr(hub, TYPES[config[CONF_TYPE]]) rhs = func(config[CONF_NAME]) sensor.register_sensor(rhs, config)
if re.match(r"^[0-9a-f]{40}$", value) is None: raise cv.Invalid("fingerprint must be valid SHA1 hash") return value CONFIG_SCHEMA = cv.All( cv.Schema( { cv.GenerateID(): cv.declare_id(MQTTClientComponent), cv.Required(CONF_BROKER): cv.string_strict, cv.Optional(CONF_PORT, default=1883): cv.port, cv.Optional(CONF_USERNAME, default=""): cv.string, cv.Optional(CONF_PASSWORD, default=""): cv.string, cv.Optional(CONF_CLIENT_ID): cv.string, cv.Optional(CONF_DISCOVERY, default=True): cv.Any( cv.boolean, cv.one_of("CLEAN", upper=True) ), cv.Optional(CONF_DISCOVERY_RETAIN, default=True): cv.boolean, cv.Optional( CONF_DISCOVERY_PREFIX, default="homeassistant" ): cv.publish_topic, cv.Optional(CONF_DISCOVERY_UNIQUE_ID_GENERATOR, default="legacy"): cv.enum( MQTT_DISCOVERY_UNIQUE_ID_GENERATOR_OPTIONS ), cv.Optional(CONF_USE_ABBREVIATIONS, default=True): cv.boolean, cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.publish_topic, cv.Optional(CONF_LOG_TOPIC): cv.Any( None,
"espressif32@<platformio version>") if value_ in PLATFORMIO_ESP32_LUT: return PLATFORMIO_ESP32_LUT[value_] return value raise NotImplementedError def default_build_path(): return CORE.name CONFIG_SCHEMA = cv.Schema({ vol.Required(CONF_NAME): cv.valid_name, vol.Required(CONF_PLATFORM): cv.one_of('ESP8266', 'ESPRESSIF8266', 'ESP32', 'ESPRESSIF32', upper=True), vol.Required(CONF_BOARD): validate_board, vol.Optional(CONF_ESPHOME_CORE_VERSION, default='latest'): ESPHOME_CORE_VERSION_SCHEMA, vol.Optional(CONF_ARDUINO_VERSION, default='recommended'): validate_arduino_version, vol.Optional(CONF_USE_CUSTOM_CODE, default=False): cv.boolean, vol.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string, vol.Optional(CONF_PLATFORMIO_OPTIONS): cv.Schema({ cv.string_strict: vol.Any([cv.string], cv.string), }), vol.Optional(CONF_ESP8266_RESTORE_FROM_FLASH):
Component) MULTI_CONF = True CONFIG_SCHEMA = vol.Schema({ cv.GenerateID(): cv.declare_variable_id(MY9231OutputComponent), vol.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, vol.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, vol.Optional(CONF_NUM_CHANNELS): vol.All(vol.Coerce(int), vol.Range(3, 1020)), vol.Optional(CONF_NUM_CHIPS): vol.All(vol.Coerce(int), vol.Range(1, 255)), vol.Optional(CONF_BIT_DEPTH): cv.one_of(8, 12, 14, 16, int=True), vol.Optional(CONF_UPDATE_ON_BOOT): vol.Coerce(bool), }).extend(cv.COMPONENT_SCHEMA.schema) def to_code(config): for di in gpio_output_pin_expression(config[CONF_DATA_PIN]): yield for dcki in gpio_output_pin_expression(config[CONF_CLOCK_PIN]): yield rhs = App.make_my9231_component(di, dcki) my9231 = Pvariable(config[CONF_ID], rhs) if CONF_NUM_CHANNELS in config: add(my9231.set_num_channels(config[CONF_NUM_CHANNELS])) if CONF_NUM_CHIPS in config: