Merge branch 'dev' into hbridge-switch

This commit is contained in:
David Woodhouse 2024-09-14 07:09:58 +01:00 committed by GitHub
commit 911bcd62d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 77 additions and 57 deletions

View file

@ -36,7 +36,7 @@ jobs:
python ./script/sync-device_class.py python ./script/sync-device_class.py
- name: Commit changes - name: Commit changes
uses: peter-evans/create-pull-request@v7.0.0 uses: peter-evans/create-pull-request@v7.0.2
with: with:
commit-message: "Synchronise Device Classes from Home Assistant" commit-message: "Synchronise Device Classes from Home Assistant"
committer: esphomebot <esphome@nabucasa.com> committer: esphomebot <esphome@nabucasa.com>

View file

@ -1,26 +1,26 @@
import logging import logging
from esphome import automation, core from esphome import automation, core
import esphome.codegen as cg
from esphome.components import font from esphome.components import font
import esphome.components.image as espImage import esphome.components.image as espImage
from esphome.components.image import ( from esphome.components.image import (
CONF_USE_TRANSPARENCY, CONF_USE_TRANSPARENCY,
LOCAL_SCHEMA, LOCAL_SCHEMA,
WEB_SCHEMA,
SOURCE_WEB,
SOURCE_LOCAL, SOURCE_LOCAL,
SOURCE_WEB,
WEB_SCHEMA,
) )
import esphome.config_validation as cv import esphome.config_validation as cv
import esphome.codegen as cg
from esphome.const import ( from esphome.const import (
CONF_FILE, CONF_FILE,
CONF_ID, CONF_ID,
CONF_PATH,
CONF_RAW_DATA_ID, CONF_RAW_DATA_ID,
CONF_REPEAT, CONF_REPEAT,
CONF_RESIZE, CONF_RESIZE,
CONF_TYPE,
CONF_SOURCE, CONF_SOURCE,
CONF_PATH, CONF_TYPE,
CONF_URL, CONF_URL,
) )
from esphome.core import CORE, HexInt from esphome.core import CORE, HexInt
@ -172,6 +172,9 @@ async def to_code(config):
path = CORE.relative_config_path(conf_file[CONF_PATH]) path = CORE.relative_config_path(conf_file[CONF_PATH])
elif conf_file[CONF_SOURCE] == SOURCE_WEB: elif conf_file[CONF_SOURCE] == SOURCE_WEB:
path = espImage.compute_local_image_path(conf_file).as_posix() path = espImage.compute_local_image_path(conf_file).as_posix()
else:
raise core.EsphomeError(f"Unknown animation source: {conf_file[CONF_SOURCE]}")
try: try:
image = Image.open(path) image = Image.open(path)
except Exception as e: except Exception as e:
@ -183,8 +186,7 @@ async def to_code(config):
new_width_max, new_height_max = config[CONF_RESIZE] new_width_max, new_height_max = config[CONF_RESIZE]
ratio = min(new_width_max / width, new_height_max / height) ratio = min(new_width_max / width, new_height_max / height)
width, height = int(width * ratio), int(height * ratio) width, height = int(width * ratio), int(height * ratio)
else: elif width > 500 or height > 500:
if width > 500 or height > 500:
_LOGGER.warning( _LOGGER.warning(
'The image "%s" you requested is very big. Please consider' 'The image "%s" you requested is very big. Please consider'
" using the resize parameter.", " using the resize parameter.",
@ -306,6 +308,8 @@ async def to_code(config):
if transparent: if transparent:
alpha = image.split()[-1] alpha = image.split()[-1]
has_alpha = alpha.getextrema()[0] < 0xFF has_alpha = alpha.getextrema()[0] < 0xFF
else:
has_alpha = False
frame = image.convert("1", dither=Image.Dither.NONE) frame = image.convert("1", dither=Image.Dither.NONE)
if CONF_RESIZE in config: if CONF_RESIZE in config:
frame = frame.resize([width, height]) frame = frame.resize([width, height])

View file

@ -41,7 +41,7 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid,
cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MAJOR): cv.uint16_t,
cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t, cv.Optional(CONF_IBEACON_MINOR): cv.uint16_t,
cv.Optional(CONF_IBEACON_UUID): cv.uuid, cv.Optional(CONF_IBEACON_UUID): esp32_ble_tracker.bt_uuid,
cv.Optional(CONF_TIMEOUT, default="5min"): cv.positive_time_period, cv.Optional(CONF_TIMEOUT, default="5min"): cv.positive_time_period,
cv.Optional(CONF_MIN_RSSI): cv.All( cv.Optional(CONF_MIN_RSSI): cv.All(
cv.decibel, cv.int_range(min=-100, max=-30) cv.decibel, cv.int_range(min=-100, max=-30)
@ -83,7 +83,7 @@ async def to_code(config):
cg.add(var.set_service_uuid128(uuid128)) cg.add(var.set_service_uuid128(uuid128))
if ibeacon_uuid := config.get(CONF_IBEACON_UUID): if ibeacon_uuid := config.get(CONF_IBEACON_UUID):
ibeacon_uuid = esp32_ble_tracker.as_hex_array(str(ibeacon_uuid)) ibeacon_uuid = esp32_ble_tracker.as_reversed_hex_array(ibeacon_uuid)
cg.add(var.set_ibeacon_uuid(ibeacon_uuid)) cg.add(var.set_ibeacon_uuid(ibeacon_uuid))
if (ibeacon_major := config.get(CONF_IBEACON_MAJOR)) is not None: if (ibeacon_major := config.get(CONF_IBEACON_MAJOR)) is not None:

View file

@ -239,7 +239,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
# The default/recommended esp-idf framework version # The default/recommended esp-idf framework version
# - https://github.com/espressif/esp-idf/releases # - https://github.com/espressif/esp-idf/releases
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf # - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7) RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 8)
# The platformio/espressif32 version to use for esp-idf frameworks # The platformio/espressif32 version to use for esp-idf frameworks
# - https://github.com/platformio/platform-espressif32/releases # - https://github.com/platformio/platform-espressif32/releases
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32 # - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32

View file

@ -31,6 +31,13 @@ ESPBTUUID ESPBTUUID::from_raw(const uint8_t *data) {
memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128); memcpy(ret.uuid_.uuid.uuid128, data, ESP_UUID_LEN_128);
return ret; return ret;
} }
ESPBTUUID ESPBTUUID::from_raw_reversed(const uint8_t *data) {
ESPBTUUID ret;
ret.uuid_.len = ESP_UUID_LEN_128;
for (int i = 0; i < ESP_UUID_LEN_128; i++)
ret.uuid_.uuid.uuid128[ESP_UUID_LEN_128 - 1 - i] = data[i];
return ret;
}
ESPBTUUID ESPBTUUID::from_raw(const std::string &data) { ESPBTUUID ESPBTUUID::from_raw(const std::string &data) {
ESPBTUUID ret; ESPBTUUID ret;
if (data.length() == 4) { if (data.length() == 4) {

View file

@ -20,6 +20,7 @@ class ESPBTUUID {
static ESPBTUUID from_uint32(uint32_t uuid); static ESPBTUUID from_uint32(uint32_t uuid);
static ESPBTUUID from_raw(const uint8_t *data); static ESPBTUUID from_raw(const uint8_t *data);
static ESPBTUUID from_raw_reversed(const uint8_t *data);
static ESPBTUUID from_raw(const std::string &data); static ESPBTUUID from_raw(const std::string &data);

View file

@ -462,14 +462,16 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e
ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str()); ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str());
} }
for (auto &data : this->manufacturer_datas_) { for (auto &data : this->manufacturer_datas_) {
ESP_LOGVV(TAG, " Manufacturer data: %s", format_hex_pretty(data.data).c_str()); auto ibeacon = ESPBLEiBeacon::from_manufacturer_data(data);
if (this->get_ibeacon().has_value()) { if (ibeacon.has_value()) {
auto ibeacon = this->get_ibeacon().value(); ESP_LOGVV(TAG, " Manufacturer iBeacon:");
ESP_LOGVV(TAG, " iBeacon data:"); ESP_LOGVV(TAG, " UUID: %s", ibeacon.value().get_uuid().to_string().c_str());
ESP_LOGVV(TAG, " UUID: %s", ibeacon.get_uuid().to_string().c_str()); ESP_LOGVV(TAG, " Major: %u", ibeacon.value().get_major());
ESP_LOGVV(TAG, " Major: %u", ibeacon.get_major()); ESP_LOGVV(TAG, " Minor: %u", ibeacon.value().get_minor());
ESP_LOGVV(TAG, " Minor: %u", ibeacon.get_minor()); ESP_LOGVV(TAG, " TXPower: %d", ibeacon.value().get_signal_power());
ESP_LOGVV(TAG, " TXPower: %d", ibeacon.get_signal_power()); } else {
ESP_LOGVV(TAG, " Manufacturer ID: %s, data: %s", data.uuid.to_string().c_str(),
format_hex_pretty(data.data).c_str());
} }
} }
for (auto &data : this->service_datas_) { for (auto &data : this->service_datas_) {
@ -478,7 +480,7 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e
ESP_LOGVV(TAG, " Data: %s", format_hex_pretty(data.data).c_str()); ESP_LOGVV(TAG, " Data: %s", format_hex_pretty(data.data).c_str());
} }
ESP_LOGVV(TAG, "Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str()); ESP_LOGVV(TAG, " Adv data: %s", format_hex_pretty(param.ble_adv, param.adv_data_len + param.scan_rsp_len).c_str());
#endif #endif
} }
void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param) { void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param &param) {

View file

@ -44,10 +44,10 @@ class ESPBLEiBeacon {
ESPBLEiBeacon(const uint8_t *data); ESPBLEiBeacon(const uint8_t *data);
static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data); static optional<ESPBLEiBeacon> from_manufacturer_data(const ServiceData &data);
uint16_t get_major() { return ((this->beacon_data_.major & 0xFF) << 8) | (this->beacon_data_.major >> 8); } uint16_t get_major() { return byteswap(this->beacon_data_.major); }
uint16_t get_minor() { return ((this->beacon_data_.minor & 0xFF) << 8) | (this->beacon_data_.minor >> 8); } uint16_t get_minor() { return byteswap(this->beacon_data_.minor); }
int8_t get_signal_power() { return this->beacon_data_.signal_power; } int8_t get_signal_power() { return this->beacon_data_.signal_power; }
ESPBTUUID get_uuid() { return ESPBTUUID::from_raw(this->beacon_data_.proximity_uuid); } ESPBTUUID get_uuid() { return ESPBTUUID::from_raw_reversed(this->beacon_data_.proximity_uuid); }
protected: protected:
struct { struct {

View file

@ -1,18 +1,17 @@
from __future__ import annotations from __future__ import annotations
import logging
import hashlib import hashlib
import io import io
import logging
from pathlib import Path from pathlib import Path
import re import re
from magic import Magic from magic import Magic
from esphome import core from esphome import core, external_files
from esphome.components import font
from esphome import external_files
import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components import font
import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_DITHER, CONF_DITHER,
CONF_FILE, CONF_FILE,
@ -239,12 +238,11 @@ CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, IMAGE_SCHEMA)
def load_svg_image(file: bytes, resize: tuple[int, int]): def load_svg_image(file: bytes, resize: tuple[int, int]):
# Local import only to allow "validate_pillow_installed" to run *before* importing it # Local import only to allow "validate_pillow_installed" to run *before* importing it
from PIL import Image
# This import is only needed in case of SVG images; adding it # This import is only needed in case of SVG images; adding it
# to the top would force configurations not using SVG to also have it # to the top would force configurations not using SVG to also have it
# installed for no reason. # installed for no reason.
from cairosvg import svg2png from cairosvg import svg2png
from PIL import Image
if resize: if resize:
req_width, req_height = resize req_width, req_height = resize
@ -274,6 +272,9 @@ async def to_code(config):
elif conf_file[CONF_SOURCE] == SOURCE_WEB: elif conf_file[CONF_SOURCE] == SOURCE_WEB:
path = compute_local_image_path(conf_file).as_posix() path = compute_local_image_path(conf_file).as_posix()
else:
raise core.EsphomeError(f"Unknown image source: {conf_file[CONF_SOURCE]}")
try: try:
with open(path, "rb") as f: with open(path, "rb") as f:
file_contents = f.read() file_contents = f.read()

View file

@ -1,7 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation from esphome import automation
import esphome.codegen as cg
from esphome.components import climate, sensor from esphome.components import climate, sensor
import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_AUTO_MODE, CONF_AUTO_MODE,
CONF_AWAY_CONFIG, CONF_AWAY_CONFIG,
@ -15,15 +15,15 @@ from esphome.const import (
CONF_DRY_ACTION, CONF_DRY_ACTION,
CONF_DRY_MODE, CONF_DRY_MODE,
CONF_FAN_MODE, CONF_FAN_MODE,
CONF_FAN_MODE_ON_ACTION,
CONF_FAN_MODE_OFF_ACTION,
CONF_FAN_MODE_AUTO_ACTION, CONF_FAN_MODE_AUTO_ACTION,
CONF_FAN_MODE_DIFFUSE_ACTION,
CONF_FAN_MODE_FOCUS_ACTION,
CONF_FAN_MODE_HIGH_ACTION,
CONF_FAN_MODE_LOW_ACTION, CONF_FAN_MODE_LOW_ACTION,
CONF_FAN_MODE_MEDIUM_ACTION, CONF_FAN_MODE_MEDIUM_ACTION,
CONF_FAN_MODE_HIGH_ACTION,
CONF_FAN_MODE_MIDDLE_ACTION, CONF_FAN_MODE_MIDDLE_ACTION,
CONF_FAN_MODE_FOCUS_ACTION, CONF_FAN_MODE_OFF_ACTION,
CONF_FAN_MODE_DIFFUSE_ACTION, CONF_FAN_MODE_ON_ACTION,
CONF_FAN_MODE_QUIET_ACTION, CONF_FAN_MODE_QUIET_ACTION,
CONF_FAN_ONLY_ACTION, CONF_FAN_ONLY_ACTION,
CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER, CONF_FAN_ONLY_ACTION_USES_FAN_MODE_TIMER,
@ -50,8 +50,8 @@ from esphome.const import (
CONF_MIN_HEATING_RUN_TIME, CONF_MIN_HEATING_RUN_TIME,
CONF_MIN_IDLE_TIME, CONF_MIN_IDLE_TIME,
CONF_MIN_TEMPERATURE, CONF_MIN_TEMPERATURE,
CONF_NAME,
CONF_MODE, CONF_MODE,
CONF_NAME,
CONF_OFF_MODE, CONF_OFF_MODE,
CONF_PRESET, CONF_PRESET,
CONF_SENSOR, CONF_SENSOR,
@ -892,7 +892,7 @@ async def to_code(config):
if name.upper() in climate.CLIMATE_PRESETS: if name.upper() in climate.CLIMATE_PRESETS:
standard_preset = climate.CLIMATE_PRESETS[name.upper()] standard_preset = climate.CLIMATE_PRESETS[name.upper()]
if two_points_available is True: if two_points_available:
preset_target_config = ThermostatClimateTargetTempConfig( preset_target_config = ThermostatClimateTargetTempConfig(
preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW],
preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH],
@ -905,6 +905,8 @@ async def to_code(config):
preset_target_config = ThermostatClimateTargetTempConfig( preset_target_config = ThermostatClimateTargetTempConfig(
preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW] preset_config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW]
) )
else:
preset_target_config = None
preset_target_variable = cg.new_variable( preset_target_variable = cg.new_variable(
preset_config[CONF_ID], preset_target_config preset_config[CONF_ID], preset_target_config

View file

@ -1,8 +1,9 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import binary_sensor from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_KEY from esphome.const import CONF_KEY
from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID
from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns
TM1638Key = tm1638_ns.class_("TM1638Key", binary_sensor.BinarySensor) TM1638Key = tm1638_ns.class_("TM1638Key", binary_sensor.BinarySensor)

View file

@ -1,13 +1,13 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import pins from esphome import pins
import esphome.codegen as cg
from esphome.components import display from esphome.components import display
import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_CLK_PIN,
CONF_DIO_PIN,
CONF_ID, CONF_ID,
CONF_INTENSITY, CONF_INTENSITY,
CONF_LAMBDA, CONF_LAMBDA,
CONF_CLK_PIN,
CONF_DIO_PIN,
CONF_STB_PIN, CONF_STB_PIN,
) )

View file

@ -1,8 +1,9 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import output from esphome.components import output
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_LED from esphome.const import CONF_ID, CONF_LED
from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID
from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns
TM1638OutputLed = tm1638_ns.class_("TM1638OutputLed", output.BinaryOutput, cg.Component) TM1638OutputLed = tm1638_ns.class_("TM1638OutputLed", output.BinaryOutput, cg.Component)

View file

@ -1,8 +1,9 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import switch from esphome.components import switch
import esphome.config_validation as cv
from esphome.const import CONF_LED from esphome.const import CONF_LED
from ..display import tm1638_ns, TM1638Component, CONF_TM1638_ID
from ..display import CONF_TM1638_ID, TM1638Component, tm1638_ns
TM1638SwitchLed = tm1638_ns.class_("TM1638SwitchLed", switch.Switch, cg.Component) TM1638SwitchLed = tm1638_ns.class_("TM1638SwitchLed", switch.Switch, cg.Component)

View file

@ -139,7 +139,7 @@ extra_scripts = post:esphome/components/esp32/post_build.py.script
extends = common:idf extends = common:idf
platform = platformio/espressif32@5.4.0 platform = platformio/espressif32@5.4.0
platform_packages = platform_packages =
platformio/framework-espidf@~3.40407.0 platformio/framework-espidf@~3.40408.0
framework = espidf framework = espidf
lib_deps = lib_deps =