diff --git a/esphome/components/color/__init__.py b/esphome/components/color/__init__.py index 47679fcc68..9a85eace75 100644 --- a/esphome/components/color/__init__.py +++ b/esphome/components/color/__init__.py @@ -10,23 +10,42 @@ CONF_RED_INT = "red_int" CONF_GREEN_INT = "green_int" CONF_BLUE_INT = "blue_int" CONF_WHITE_INT = "white_int" - -CONFIG_SCHEMA = cv.Schema( - { - cv.Required(CONF_ID): cv.declare_id(ColorStruct), - cv.Exclusive(CONF_RED, "red"): cv.percentage, - cv.Exclusive(CONF_RED_INT, "red"): cv.uint8_t, - cv.Exclusive(CONF_GREEN, "green"): cv.percentage, - cv.Exclusive(CONF_GREEN_INT, "green"): cv.uint8_t, - cv.Exclusive(CONF_BLUE, "blue"): cv.percentage, - cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t, - cv.Exclusive(CONF_WHITE, "white"): cv.percentage, - cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t, - } -).extend(cv.COMPONENT_SCHEMA) +CONF_HEX = "hex" -async def to_code(config): +def hex_color(value): + if len(value) != 6: + raise cv.Invalid("Color must have six digits") + try: + return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16)) + except ValueError as exc: + raise cv.Invalid("Color must be hexadecimal") from exc + + +CONFIG_SCHEMA = cv.Any( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(ColorStruct), + cv.Exclusive(CONF_RED, "red"): cv.percentage, + cv.Exclusive(CONF_RED_INT, "red"): cv.uint8_t, + cv.Exclusive(CONF_GREEN, "green"): cv.percentage, + cv.Exclusive(CONF_GREEN_INT, "green"): cv.uint8_t, + cv.Exclusive(CONF_BLUE, "blue"): cv.percentage, + cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t, + cv.Exclusive(CONF_WHITE, "white"): cv.percentage, + cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(ColorStruct), + cv.Required(CONF_HEX): hex_color, + } + ).extend(cv.COMPONENT_SCHEMA), +) + + +def from_rgbw(config): r = 0 if CONF_RED in config: r = int(config[CONF_RED] * 255) @@ -51,6 +70,16 @@ async def to_code(config): elif CONF_WHITE_INT in config: w = config[CONF_WHITE_INT] + return (r, g, b, w) + + +async def to_code(config): + if CONF_HEX in config: + r, g, b = config[CONF_HEX] + w = 0 + else: + r, g, b, w = from_rgbw(config) + cg.new_variable( config[CONF_ID], cg.StructInitializer(ColorStruct, ("r", r), ("g", g), ("b", b), ("w", w)), diff --git a/esphome/components/esp32_touch/binary_sensor.py b/esphome/components/esp32_touch/binary_sensor.py index 326f559830..2cdf1343c3 100644 --- a/esphome/components/esp32_touch/binary_sensor.py +++ b/esphome/components/esp32_touch/binary_sensor.py @@ -1,5 +1,6 @@ import esphome.codegen as cg import esphome.config_validation as cv +from esphome.core import CORE from esphome.components import binary_sensor from esphome.const import ( CONF_PIN, @@ -7,6 +8,13 @@ from esphome.const import ( CONF_ID, ) from esphome.components.esp32 import gpio +from esphome.components.esp32.const import ( + KEY_ESP32, + KEY_VARIANT, + VARIANT_ESP32, + VARIANT_ESP32S2, + VARIANT_ESP32S3, +) from . import esp32_touch_ns, ESP32TouchComponent DEPENDENCIES = ["esp32_touch", "esp32"] @@ -15,24 +23,63 @@ CONF_ESP32_TOUCH_ID = "esp32_touch_id" CONF_WAKEUP_THRESHOLD = "wakeup_threshold" TOUCH_PADS = { - 4: cg.global_ns.TOUCH_PAD_NUM0, - 0: cg.global_ns.TOUCH_PAD_NUM1, - 2: cg.global_ns.TOUCH_PAD_NUM2, - 15: cg.global_ns.TOUCH_PAD_NUM3, - 13: cg.global_ns.TOUCH_PAD_NUM4, - 12: cg.global_ns.TOUCH_PAD_NUM5, - 14: cg.global_ns.TOUCH_PAD_NUM6, - 27: cg.global_ns.TOUCH_PAD_NUM7, - 33: cg.global_ns.TOUCH_PAD_NUM8, - 32: cg.global_ns.TOUCH_PAD_NUM9, + VARIANT_ESP32: { + 4: cg.global_ns.TOUCH_PAD_NUM0, + 0: cg.global_ns.TOUCH_PAD_NUM1, + 2: cg.global_ns.TOUCH_PAD_NUM2, + 15: cg.global_ns.TOUCH_PAD_NUM3, + 13: cg.global_ns.TOUCH_PAD_NUM4, + 12: cg.global_ns.TOUCH_PAD_NUM5, + 14: cg.global_ns.TOUCH_PAD_NUM6, + 27: cg.global_ns.TOUCH_PAD_NUM7, + 33: cg.global_ns.TOUCH_PAD_NUM8, + 32: cg.global_ns.TOUCH_PAD_NUM9, + }, + VARIANT_ESP32S2: { + 1: cg.global_ns.TOUCH_PAD_NUM1, + 2: cg.global_ns.TOUCH_PAD_NUM2, + 3: cg.global_ns.TOUCH_PAD_NUM3, + 4: cg.global_ns.TOUCH_PAD_NUM4, + 5: cg.global_ns.TOUCH_PAD_NUM5, + 6: cg.global_ns.TOUCH_PAD_NUM6, + 7: cg.global_ns.TOUCH_PAD_NUM7, + 8: cg.global_ns.TOUCH_PAD_NUM8, + 9: cg.global_ns.TOUCH_PAD_NUM9, + 10: cg.global_ns.TOUCH_PAD_NUM10, + 11: cg.global_ns.TOUCH_PAD_NUM11, + 12: cg.global_ns.TOUCH_PAD_NUM12, + 13: cg.global_ns.TOUCH_PAD_NUM13, + 14: cg.global_ns.TOUCH_PAD_NUM14, + }, + VARIANT_ESP32S3: { + 1: cg.global_ns.TOUCH_PAD_NUM1, + 2: cg.global_ns.TOUCH_PAD_NUM2, + 3: cg.global_ns.TOUCH_PAD_NUM3, + 4: cg.global_ns.TOUCH_PAD_NUM4, + 5: cg.global_ns.TOUCH_PAD_NUM5, + 6: cg.global_ns.TOUCH_PAD_NUM6, + 7: cg.global_ns.TOUCH_PAD_NUM7, + 8: cg.global_ns.TOUCH_PAD_NUM8, + 9: cg.global_ns.TOUCH_PAD_NUM9, + 10: cg.global_ns.TOUCH_PAD_NUM10, + 11: cg.global_ns.TOUCH_PAD_NUM11, + 12: cg.global_ns.TOUCH_PAD_NUM12, + 13: cg.global_ns.TOUCH_PAD_NUM13, + 14: cg.global_ns.TOUCH_PAD_NUM14, + }, } def validate_touch_pad(value): value = gpio.validate_gpio_pin(value) - if value not in TOUCH_PADS: + variant = CORE.data[KEY_ESP32][KEY_VARIANT] + if variant not in TOUCH_PADS: + raise cv.Invalid(f"ESP32 variant {variant} does not support touch pads.") + + pads = TOUCH_PADS[variant] + if value not in pads: raise cv.Invalid(f"Pin {value} does not support touch pads.") - return value + return cv.enum(pads)(value) ESP32TouchBinarySensor = esp32_touch_ns.class_( @@ -53,7 +100,7 @@ async def to_code(config): hub = await cg.get_variable(config[CONF_ESP32_TOUCH_ID]) var = cg.new_Pvariable( config[CONF_ID], - TOUCH_PADS[config[CONF_PIN]], + config[CONF_PIN], config[CONF_THRESHOLD], config[CONF_WAKEUP_THRESHOLD], ) diff --git a/esphome/components/ili9xxx/display.py b/esphome/components/ili9xxx/display.py index 437fc93b89..780c64ec70 100644 --- a/esphome/components/ili9xxx/display.py +++ b/esphome/components/ili9xxx/display.py @@ -16,7 +16,13 @@ from esphome.const import ( ) DEPENDENCIES = ["spi"] -AUTO_LOAD = ["psram"] + + +def AUTO_LOAD(): + if CORE.is_esp32: + return ["psram"] + return [] + CODEOWNERS = ["@nielsnl68"] @@ -60,6 +66,16 @@ def _validate(config): raise cv.Invalid( "Providing color palette images requires palette mode to be 'IMAGE_ADAPTIVE'" ) + if CORE.is_esp8266 and config.get(CONF_MODEL) not in [ + "M5STACK", + "TFT_2.4", + "TFT_2.4R", + "ILI9341", + "ILI9342", + ]: + raise cv.Invalid( + "Provided model can't run on ESP8266. Use an ESP32 with PSRAM onboard" + ) return config diff --git a/esphome/components/mpu6050/mpu6050.cpp b/esphome/components/mpu6050/mpu6050.cpp index cc426e58a2..51e3ec2383 100644 --- a/esphome/components/mpu6050/mpu6050.cpp +++ b/esphome/components/mpu6050/mpu6050.cpp @@ -23,7 +23,8 @@ const float GRAVITY_EARTH = 9.80665f; void MPU6050Component::setup() { ESP_LOGCONFIG(TAG, "Setting up MPU6050..."); uint8_t who_am_i; - if (!this->read_byte(MPU6050_REGISTER_WHO_AM_I, &who_am_i) || (who_am_i != 0x68 && who_am_i != 0x98)) { + if (!this->read_byte(MPU6050_REGISTER_WHO_AM_I, &who_am_i) || + (who_am_i != 0x68 && who_am_i != 0x70 && who_am_i != 0x98)) { this->mark_failed(); return; } diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index ffbf90338f..1ddf0f1e85 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -10,6 +10,7 @@ from esphome.const import ( CONF_CO2, CONF_UPDATE_INTERVAL, CONF_VALUE, + DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT, @@ -46,6 +47,7 @@ CONFIG_SCHEMA = ( unit_of_measurement=UNIT_PARTS_PER_MILLION, icon=ICON_MOLECULE_CO2, accuracy_decimals=0, + device_class=DEVICE_CLASS_CARBON_DIOXIDE, state_class=STATE_CLASS_MEASUREMENT, ), cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( diff --git a/esphome/const.py b/esphome/const.py index a66dfbc0fd..3fa46f788e 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2023.3.0b2" +__version__ = "2023.3.0b3" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" diff --git a/esphome/loader.py b/esphome/loader.py index b245fa1610..cd21e5a509 100644 --- a/esphome/loader.py +++ b/esphome/loader.py @@ -71,7 +71,10 @@ class ComponentManifest: @property def auto_load(self) -> list[str]: - return getattr(self.module, "AUTO_LOAD", []) + al = getattr(self.module, "AUTO_LOAD", []) + if callable(al): + return al() + return al @property def codeowners(self) -> list[str]: diff --git a/tests/test1.yaml b/tests/test1.yaml index 21cdb6bc6f..25c481db04 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -2528,6 +2528,8 @@ color: red: 0% green: 1% blue: 100% + - id: kbx_green + hex: "3DEC55" display: - platform: lcd_gpio