Merge branch 'esphome:dev' into dev

This commit is contained in:
optimusprimespace 2024-06-26 14:42:20 +02:00 committed by GitHub
commit a354816d29
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
48 changed files with 234 additions and 192 deletions

View file

@ -46,7 +46,7 @@ runs:
- name: Build and push to ghcr by digest - name: Build and push to ghcr by digest
id: build-ghcr id: build-ghcr
uses: docker/build-push-action@v6.0.1 uses: docker/build-push-action@v6.1.0
with: with:
context: . context: .
file: ./docker/Dockerfile file: ./docker/Dockerfile
@ -69,7 +69,7 @@ runs:
- name: Build and push to dockerhub by digest - name: Build and push to dockerhub by digest
id: build-dockerhub id: build-dockerhub
uses: docker/build-push-action@v6.0.1 uses: docker/build-push-action@v6.1.0
with: with:
context: . context: .
file: ./docker/Dockerfile file: ./docker/Dockerfile

View file

@ -60,6 +60,7 @@ from esphome.cpp_types import ( # noqa
std_ns, std_ns,
std_shared_ptr, std_shared_ptr,
std_string, std_string,
std_string_ref,
std_vector, std_vector,
uint8, uint8,
uint16, uint16,

View file

@ -145,10 +145,8 @@ bool DallasTemperatureSensor::check_scratch_pad_() {
float DallasTemperatureSensor::get_temp_c_() { float DallasTemperatureSensor::get_temp_c_() {
int16_t temp = (this->scratch_pad_[1] << 8) | this->scratch_pad_[0]; int16_t temp = (this->scratch_pad_[1] << 8) | this->scratch_pad_[0];
if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) { if ((this->address_ & 0xff) == DALLAS_MODEL_DS18S20) {
if (this->scratch_pad_[7] != 0x10) return (temp >> 1) + (this->scratch_pad_[7] - this->scratch_pad_[6]) / float(this->scratch_pad_[7]) - 0.25;
ESP_LOGE(TAG, "unexpected COUNT_PER_C value: %u", this->scratch_pad_[7]); }
temp = ((temp & 0xfff7) << 3) + (0x10 - this->scratch_pad_[6]) - 4;
} else {
switch (this->resolution_) { switch (this->resolution_) {
case 9: case 9:
temp &= 0xfff8; temp &= 0xfff8;
@ -163,7 +161,6 @@ float DallasTemperatureSensor::get_temp_c_() {
default: default:
break; break;
} }
}
return temp / 16.0f; return temp / 16.0f;
} }

View file

@ -37,14 +37,18 @@ void DS1307Component::read_time() {
ESP_LOGW(TAG, "RTC halted, not syncing to system clock."); ESP_LOGW(TAG, "RTC halted, not syncing to system clock.");
return; return;
} }
ESPTime rtc_time{.second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10), ESPTime rtc_time{
.second = uint8_t(ds1307_.reg.second + 10 * ds1307_.reg.second_10),
.minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10), .minute = uint8_t(ds1307_.reg.minute + 10u * ds1307_.reg.minute_10),
.hour = uint8_t(ds1307_.reg.hour + 10u * ds1307_.reg.hour_10), .hour = uint8_t(ds1307_.reg.hour + 10u * ds1307_.reg.hour_10),
.day_of_week = uint8_t(ds1307_.reg.weekday), .day_of_week = uint8_t(ds1307_.reg.weekday),
.day_of_month = uint8_t(ds1307_.reg.day + 10u * ds1307_.reg.day_10), .day_of_month = uint8_t(ds1307_.reg.day + 10u * ds1307_.reg.day_10),
.day_of_year = 1, // ignored by recalc_timestamp_utc(false) .day_of_year = 1, // ignored by recalc_timestamp_utc(false)
.month = uint8_t(ds1307_.reg.month + 10u * ds1307_.reg.month_10), .month = uint8_t(ds1307_.reg.month + 10u * ds1307_.reg.month_10),
.year = uint16_t(ds1307_.reg.year + 10u * ds1307_.reg.year_10 + 2000)}; .year = uint16_t(ds1307_.reg.year + 10u * ds1307_.reg.year_10 + 2000),
.is_dst = false, // not used
.timestamp = 0 // overwritten by recalc_timestamp_utc(false)
};
rtc_time.recalc_timestamp_utc(false); rtc_time.recalc_timestamp_utc(false);
if (!rtc_time.is_valid()) { if (!rtc_time.is_valid()) {
ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock."); ESP_LOGE(TAG, "Invalid RTC time, not syncing to system clock.");

View file

@ -1,10 +1,14 @@
import esphome.codegen as cg import esphome.codegen as cg
import esphome.config_validation as cv import esphome.config_validation as cv
import esphome.final_validate as fv
from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent from esphome.components.ota import BASE_OTA_SCHEMA, ota_to_code, OTAComponent
from esphome.const import ( from esphome.const import (
CONF_ESPHOME,
CONF_ID, CONF_ID,
CONF_NUM_ATTEMPTS, CONF_NUM_ATTEMPTS,
CONF_OTA,
CONF_PASSWORD, CONF_PASSWORD,
CONF_PLATFORM,
CONF_PORT, CONF_PORT,
CONF_REBOOT_TIMEOUT, CONF_REBOOT_TIMEOUT,
CONF_SAFE_MODE, CONF_SAFE_MODE,
@ -21,6 +25,19 @@ esphome = cg.esphome_ns.namespace("esphome")
ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent) ESPHomeOTAComponent = esphome.class_("ESPHomeOTAComponent", OTAComponent)
def ota_esphome_final_validate(config):
fconf = fv.full_config.get()[CONF_OTA]
used_ports = []
for ota_conf in fconf:
if ota_conf.get(CONF_PLATFORM) == CONF_ESPHOME:
if (plat_port := ota_conf.get(CONF_PORT)) not in used_ports:
used_ports.append(plat_port)
else:
raise cv.Invalid(
f"Only one instance of the {CONF_ESPHOME} {CONF_OTA} {CONF_PLATFORM} is allowed per port. Note that this error may result from OTA specified in packages"
)
CONFIG_SCHEMA = ( CONFIG_SCHEMA = (
cv.Schema( cv.Schema(
{ {
@ -50,6 +67,8 @@ CONFIG_SCHEMA = (
.extend(cv.COMPONENT_SCHEMA) .extend(cv.COMPONENT_SCHEMA)
) )
FINAL_VALIDATE_SCHEMA = ota_esphome_final_validate
@coroutine_with_priority(52.0) @coroutine_with_priority(52.0)
async def to_code(config): async def to_code(config):

View file

@ -17,7 +17,6 @@ from esphome.helpers import (
cpp_string_escape, cpp_string_escape,
) )
from esphome.const import ( from esphome.const import (
__version__,
CONF_FAMILY, CONF_FAMILY,
CONF_FILE, CONF_FILE,
CONF_GLYPHS, CONF_GLYPHS,
@ -185,31 +184,6 @@ def get_font_path(value, type) -> Path:
return None return None
def download_content(url: str, path: Path) -> None:
if not external_files.has_remote_file_changed(url, path):
_LOGGER.debug("Remote file has not changed %s", url)
return
_LOGGER.debug(
"Remote file has changed, downloading from %s to %s",
url,
path,
)
try:
req = requests.get(
url,
timeout=external_files.NETWORK_TIMEOUT,
headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"},
)
req.raise_for_status()
except requests.exceptions.RequestException as e:
raise cv.Invalid(f"Could not download from {url}: {e}")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(req.content)
def download_gfont(value): def download_gfont(value):
name = ( name = (
f"{value[CONF_FAMILY]}:ital,wght@{int(value[CONF_ITALIC])},{value[CONF_WEIGHT]}" f"{value[CONF_FAMILY]}:ital,wght@{int(value[CONF_ITALIC])},{value[CONF_WEIGHT]}"
@ -236,7 +210,7 @@ def download_gfont(value):
ttf_url = match.group(1) ttf_url = match.group(1)
_LOGGER.debug("download_gfont: ttf_url=%s", ttf_url) _LOGGER.debug("download_gfont: ttf_url=%s", ttf_url)
download_content(ttf_url, path) external_files.download_content(ttf_url, path)
return value return value
@ -244,7 +218,7 @@ def download_web_font(value):
url = value[CONF_URL] url = value[CONF_URL]
path = get_font_path(value, TYPE_WEB) path = get_font_path(value, TYPE_WEB)
download_content(url, path) external_files.download_content(url, path)
_LOGGER.debug("download_web_font: path=%s", path) _LOGGER.debug("download_web_font: path=%s", path)
return value return value

View file

@ -9,6 +9,10 @@ static const char *const TAG = "gpio.one_wire";
void GPIOOneWireBus::setup() { void GPIOOneWireBus::setup() {
ESP_LOGCONFIG(TAG, "Setting up 1-wire bus..."); ESP_LOGCONFIG(TAG, "Setting up 1-wire bus...");
this->t_pin_->setup();
// clear bus with 480µs high, otherwise initial reset in search might fail
this->t_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
delayMicroseconds(480);
this->search(); this->search();
} }
@ -90,13 +94,15 @@ bool HOT IRAM_ATTR GPIOOneWireBus::read_bit_() {
// measure from start value directly, to get best accurate timing no matter // measure from start value directly, to get best accurate timing no matter
// how long pin_mode/delayMicroseconds took // how long pin_mode/delayMicroseconds took
delayMicroseconds(12 - (micros() - start)); uint32_t now = micros();
if (now - start < 12)
delayMicroseconds(12 - (now - start));
// sample bus to read bit from peer // sample bus to read bit from peer
bool r = pin_.digital_read(); bool r = pin_.digital_read();
// read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked // read slot is at least 60µs; get as close to 60µs to spend less time with interrupts locked
uint32_t now = micros(); now = micros();
if (now - start < 60) if (now - start < 60)
delayMicroseconds(60 - (now - start)); delayMicroseconds(60 - (now - start));

View file

@ -56,7 +56,7 @@ SENSOR_TYPES = {
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate),
} }
).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()}) ).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()})
@ -64,8 +64,8 @@ CONFIG_SCHEMA = cv.Schema(
async def to_code(config): async def to_code(config):
paren = await cg.get_variable(config[CONF_HAIER_ID]) paren = await cg.get_variable(config[CONF_HAIER_ID])
for type, _ in SENSOR_TYPES.items(): for type_ in SENSOR_TYPES:
if conf := config.get(type): if conf := config.get(type_):
sens = await binary_sensor.new_binary_sensor(conf) sens = await binary_sensor.new_binary_sensor(conf)
binary_sensor_type = getattr(BinarySensorTypeEnum, type.upper()) binary_sensor_type = getattr(BinarySensorTypeEnum, type_.upper())
cg.add(paren.set_sub_binary_sensor(binary_sensor_type, sens)) cg.add(paren.set_sub_binary_sensor(binary_sensor_type, sens))

View file

@ -21,7 +21,7 @@ ICON_SPRAY_BOTTLE = "mdi:spray-bottle"
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate),
cv.Optional(CONF_SELF_CLEANING): button.button_schema( cv.Optional(CONF_SELF_CLEANING): button.button_schema(
SelfCleaningButton, SelfCleaningButton,
icon=ICON_SPRAY_BOTTLE, icon=ICON_SPRAY_BOTTLE,

View file

@ -183,7 +183,6 @@ BASE_CONFIG_SCHEMA = (
cv.Optional( cv.Optional(
CONF_SUPPORTED_SWING_MODES, CONF_SUPPORTED_SWING_MODES,
default=[ default=[
"OFF",
"VERTICAL", "VERTICAL",
"HORIZONTAL", "HORIZONTAL",
"BOTH", "BOTH",
@ -211,7 +210,7 @@ CONFIG_SCHEMA = cv.All(
): cv.boolean, ): cv.boolean,
cv.Optional( cv.Optional(
CONF_SUPPORTED_PRESETS, CONF_SUPPORTED_PRESETS,
default=list(["BOOST", "COMFORT"]), # No AWAY by default default=["BOOST", "COMFORT"], # No AWAY by default
): cv.ensure_list( ): cv.ensure_list(
cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True) cv.enum(SUPPORTED_CLIMATE_PRESETS_SMARTAIR2_OPTIONS, upper=True)
), ),
@ -231,7 +230,7 @@ CONFIG_SCHEMA = cv.All(
): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50), ): cv.int_range(min=PROTOCOL_CONTROL_PACKET_SIZE, max=50),
cv.Optional( cv.Optional(
CONF_SUPPORTED_PRESETS, CONF_SUPPORTED_PRESETS,
default=list(["BOOST", "ECO", "SLEEP"]), # No AWAY by default default=["BOOST", "ECO", "SLEEP"], # No AWAY by default
): cv.ensure_list( ): cv.ensure_list(
cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True) cv.enum(SUPPORTED_CLIMATE_PRESETS_HON_OPTIONS, upper=True)
), ),
@ -427,11 +426,7 @@ def _final_validate(config):
"No logger component found, logging for Haier protocol is disabled" "No logger component found, logging for Haier protocol is disabled"
) )
cg.add_build_flag("-DHAIER_LOG_LEVEL=0") cg.add_build_flag("-DHAIER_LOG_LEVEL=0")
if ( if config.get(CONF_WIFI_SIGNAL) and CONF_WIFI not in full_config:
(CONF_WIFI_SIGNAL in config)
and (config[CONF_WIFI_SIGNAL])
and CONF_WIFI not in full_config
):
raise cv.Invalid( raise cv.Invalid(
f"No WiFi configured, if you want to use haier climate without WiFi add {CONF_WIFI_SIGNAL}: false to climate configuration" f"No WiFi configured, if you want to use haier climate without WiFi add {CONF_WIFI_SIGNAL}: false to climate configuration"
) )

View file

@ -137,16 +137,16 @@ SENSOR_TYPES = {
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate),
} }
).extend({cv.Optional(type): schema for type, schema in SENSOR_TYPES.items()}) ).extend({cv.Optional(type_): schema for type_, schema in SENSOR_TYPES.items()})
async def to_code(config): async def to_code(config):
paren = await cg.get_variable(config[CONF_HAIER_ID]) paren = await cg.get_variable(config[CONF_HAIER_ID])
for type, _ in SENSOR_TYPES.items(): for type_ in SENSOR_TYPES:
if conf := config.get(type): if conf := config.get(type_):
sens = await sensor.new_sensor(conf) sens = await sensor.new_sensor(conf)
sensor_type = getattr(SensorTypeEnum, type.upper()) sensor_type = getattr(SensorTypeEnum, type_.upper())
cg.add(paren.set_sub_sensor(sensor_type, sens)) cg.add(paren.set_sub_sensor(sensor_type, sens))

View file

@ -39,7 +39,7 @@ TEXT_SENSOR_TYPES = {
CONFIG_SCHEMA = cv.Schema( CONFIG_SCHEMA = cv.Schema(
{ {
cv.Required(CONF_HAIER_ID): cv.use_id(HonClimate), cv.GenerateID(CONF_HAIER_ID): cv.use_id(HonClimate),
} }
).extend({cv.Optional(type): schema for type, schema in TEXT_SENSOR_TYPES.items()}) ).extend({cv.Optional(type): schema for type, schema in TEXT_SENSOR_TYPES.items()})
@ -47,8 +47,8 @@ CONFIG_SCHEMA = cv.Schema(
async def to_code(config): async def to_code(config):
paren = await cg.get_variable(config[CONF_HAIER_ID]) paren = await cg.get_variable(config[CONF_HAIER_ID])
for type, _ in TEXT_SENSOR_TYPES.items(): for type_ in TEXT_SENSOR_TYPES:
if conf := config.get(type): if conf := config.get(type_):
sens = await text_sensor.new_text_sensor(conf) sens = await text_sensor.new_text_sensor(conf)
text_sensor_type = getattr(TextSensorTypeEnum, type.upper()) text_sensor_type = getattr(TextSensorTypeEnum, type_.upper())
cg.add(paren.set_sub_text_sensor(text_sensor_type, sens)) cg.add(paren.set_sub_text_sensor(text_sensor_type, sens))

View file

@ -34,6 +34,7 @@ PROTOCOLS = {
"greeyan": Protocol.PROTOCOL_GREEYAN, "greeyan": Protocol.PROTOCOL_GREEYAN,
"greeyac": Protocol.PROTOCOL_GREEYAC, "greeyac": Protocol.PROTOCOL_GREEYAC,
"greeyt": Protocol.PROTOCOL_GREEYT, "greeyt": Protocol.PROTOCOL_GREEYT,
"greeyap": Protocol.PROTOCOL_GREEYAP,
"hisense_aud": Protocol.PROTOCOL_HISENSE_AUD, "hisense_aud": Protocol.PROTOCOL_HISENSE_AUD,
"hitachi": Protocol.PROTOCOL_HITACHI, "hitachi": Protocol.PROTOCOL_HITACHI,
"hyundai": Protocol.PROTOCOL_HYUNDAI, "hyundai": Protocol.PROTOCOL_HYUNDAI,
@ -61,6 +62,11 @@ PROTOCOLS = {
"toshiba_daiseikai": Protocol.PROTOCOL_TOSHIBA_DAISEIKAI, "toshiba_daiseikai": Protocol.PROTOCOL_TOSHIBA_DAISEIKAI,
"toshiba": Protocol.PROTOCOL_TOSHIBA, "toshiba": Protocol.PROTOCOL_TOSHIBA,
"zhlt01": Protocol.PROTOCOL_ZHLT01, "zhlt01": Protocol.PROTOCOL_ZHLT01,
"nibe": Protocol.PROTOCOL_NIBE,
"carrier_qlima_1": Protocol.PROTOCOL_QLIMA_1,
"carrier_qlima_2": Protocol.PROTOCOL_QLIMA_2,
"samsung_aqv12msan": Protocol.PROTOCOL_SAMSUNG_AQV12MSAN,
"zhjg01": Protocol.PROTOCOL_ZHJG01,
} }
CONF_HORIZONTAL_DEFAULT = "horizontal_default" CONF_HORIZONTAL_DEFAULT = "horizontal_default"
@ -116,7 +122,7 @@ def to_code(config):
cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE])) cg.add(var.set_max_temperature(config[CONF_MAX_TEMPERATURE]))
cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE])) cg.add(var.set_min_temperature(config[CONF_MIN_TEMPERATURE]))
cg.add_library("tonia/HeatpumpIR", "1.0.23") cg.add_library("tonia/HeatpumpIR", "1.0.26")
if CORE.is_esp8266 or CORE.is_esp32: if CORE.is_esp8266 or CORE.is_esp32:
cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.4") cg.add_library("crankyoldgit/IRremoteESP8266", "2.8.6")

View file

@ -28,6 +28,7 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
{PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYAN, []() { return new GreeYANHeatpumpIR(); }}, // NOLINT
{PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYAC, []() { return new GreeYACHeatpumpIR(); }}, // NOLINT
{PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }}, // NOLINT {PROTOCOL_GREEYT, []() { return new GreeYTHeatpumpIR(); }}, // NOLINT
{PROTOCOL_GREEYAP, []() { return new GreeYAPHeatpumpIR(); }}, // NOLINT
{PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }}, // NOLINT {PROTOCOL_HISENSE_AUD, []() { return new HisenseHeatpumpIR(); }}, // NOLINT
{PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }}, // NOLINT {PROTOCOL_HITACHI, []() { return new HitachiHeatpumpIR(); }}, // NOLINT
{PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }}, // NOLINT {PROTOCOL_HYUNDAI, []() { return new HyundaiHeatpumpIR(); }}, // NOLINT
@ -55,6 +56,11 @@ const std::map<Protocol, std::function<HeatpumpIR *()>> PROTOCOL_CONSTRUCTOR_MAP
{PROTOCOL_TOSHIBA_DAISEIKAI, []() { return new ToshibaDaiseikaiHeatpumpIR(); }}, // NOLINT {PROTOCOL_TOSHIBA_DAISEIKAI, []() { return new ToshibaDaiseikaiHeatpumpIR(); }}, // NOLINT
{PROTOCOL_TOSHIBA, []() { return new ToshibaHeatpumpIR(); }}, // NOLINT {PROTOCOL_TOSHIBA, []() { return new ToshibaHeatpumpIR(); }}, // NOLINT
{PROTOCOL_ZHLT01, []() { return new ZHLT01HeatpumpIR(); }}, // NOLINT {PROTOCOL_ZHLT01, []() { return new ZHLT01HeatpumpIR(); }}, // NOLINT
{PROTOCOL_NIBE, []() { return new NibeHeatpumpIR(); }}, // NOLINT
{PROTOCOL_QLIMA_1, []() { return new Qlima1HeatpumpIR(); }}, // NOLINT
{PROTOCOL_QLIMA_2, []() { return new Qlima2HeatpumpIR(); }}, // NOLINT
{PROTOCOL_SAMSUNG_AQV12MSAN, []() { return new SamsungAQV12MSANHeatpumpIR(); }}, // NOLINT
{PROTOCOL_ZHJG01, []() { return new ZHJG01HeatpumpIR(); }}, // NOLINT
}; };
void HeatpumpIRClimate::setup() { void HeatpumpIRClimate::setup() {

View file

@ -28,6 +28,7 @@ enum Protocol {
PROTOCOL_GREEYAN, PROTOCOL_GREEYAN,
PROTOCOL_GREEYAC, PROTOCOL_GREEYAC,
PROTOCOL_GREEYT, PROTOCOL_GREEYT,
PROTOCOL_GREEYAP,
PROTOCOL_HISENSE_AUD, PROTOCOL_HISENSE_AUD,
PROTOCOL_HITACHI, PROTOCOL_HITACHI,
PROTOCOL_HYUNDAI, PROTOCOL_HYUNDAI,
@ -55,6 +56,11 @@ enum Protocol {
PROTOCOL_TOSHIBA_DAISEIKAI, PROTOCOL_TOSHIBA_DAISEIKAI,
PROTOCOL_TOSHIBA, PROTOCOL_TOSHIBA,
PROTOCOL_ZHLT01, PROTOCOL_ZHLT01,
PROTOCOL_NIBE,
PROTOCOL_QLIMA_1,
PROTOCOL_QLIMA_2,
PROTOCOL_SAMSUNG_AQV12MSAN,
PROTOCOL_ZHJG01,
}; };
// Simple enum to represent horizontal directios // Simple enum to represent horizontal directios

View file

@ -257,7 +257,7 @@ async def http_request_action_to_code(config, action_id, template_arg, args):
trigger, trigger,
[ [
(cg.std_shared_ptr.template(HttpContainer), "response"), (cg.std_shared_ptr.template(HttpContainer), "response"),
(cg.std_string, "body"), (cg.std_string_ref, "body"),
], ],
conf, conf,
) )

View file

@ -43,10 +43,10 @@ class HttpContainer : public Parented<HttpRequestComponent> {
bool secure_{false}; bool secure_{false};
}; };
class HttpRequestResponseTrigger : public Trigger<std::shared_ptr<HttpContainer>, std::string> { class HttpRequestResponseTrigger : public Trigger<std::shared_ptr<HttpContainer>, std::string &> {
public: public:
void process(std::shared_ptr<HttpContainer> container, std::string response_body) { void process(std::shared_ptr<HttpContainer> container, std::string &response_body) {
this->trigger(std::move(container), std::move(response_body)); this->trigger(std::move(container), response_body);
} }
}; };
@ -149,11 +149,21 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
} }
response_body.reserve(read_index); response_body.reserve(read_index);
response_body.assign((char *) buf, read_index); response_body.assign((char *) buf, read_index);
allocator.deallocate(buf, max_length);
} }
} }
if (this->response_triggers_.size() == 1) {
// if there is only one trigger, no need to copy the response body
this->response_triggers_[0]->process(container, response_body);
} else {
for (auto *trigger : this->response_triggers_) { for (auto *trigger : this->response_triggers_) {
trigger->process(container, response_body); // with multiple triggers, pass a copy of the response body to each
// one so that modifications made in one trigger are not visible to
// the others
auto response_body_copy = std::string(response_body);
trigger->process(container, response_body_copy);
}
} }
container->end(); container->end();
} }

View file

@ -90,7 +90,7 @@ std::shared_ptr<HttpContainer> HttpRequestIDF::start(std::string url, std::strin
int write_left = body_len; int write_left = body_len;
int write_index = 0; int write_index = 0;
const char *buf = body.c_str(); const char *buf = body.c_str();
while (body_len > 0) { while (write_left > 0) {
int written = esp_http_client_write(client, buf + write_index, write_left); int written = esp_http_client_write(client, buf + write_index, write_left);
if (written < 0) { if (written < 0) {
err = ESP_FAIL; err = ESP_FAIL;

View file

@ -46,7 +46,7 @@ void WatchdogManager::set_timeout_(uint32_t timeout_ms) {
}; };
esp_task_wdt_reconfigure(&wdt_config); esp_task_wdt_reconfigure(&wdt_config);
#else #else
esp_task_wdt_init(timeout_ms, true); esp_task_wdt_init(timeout_ms / 1000, true);
#endif // ESP_IDF_VERSION_MAJOR #endif // ESP_IDF_VERSION_MAJOR
#endif // USE_ESP32 #endif // USE_ESP32

View file

@ -6,7 +6,6 @@ import hashlib
import io import io
from pathlib import Path from pathlib import Path
import re import re
import requests
from magic import Magic from magic import Magic
from esphome import core from esphome import core
@ -15,7 +14,6 @@ from esphome import external_files
import esphome.config_validation as cv import esphome.config_validation as cv
import esphome.codegen as cg import esphome.codegen as cg
from esphome.const import ( from esphome.const import (
__version__,
CONF_DITHER, CONF_DITHER,
CONF_FILE, CONF_FILE,
CONF_ICON, CONF_ICON,
@ -75,31 +73,6 @@ def compute_local_image_path(value: dict) -> Path:
return base_dir / key return base_dir / key
def download_content(url: str, path: Path) -> None:
if not external_files.has_remote_file_changed(url, path):
_LOGGER.debug("Remote file has not changed %s", url)
return
_LOGGER.debug(
"Remote file has changed, downloading from %s to %s",
url,
path,
)
try:
req = requests.get(
url,
timeout=IMAGE_DOWNLOAD_TIMEOUT,
headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"},
)
req.raise_for_status()
except requests.exceptions.RequestException as e:
raise cv.Invalid(f"Could not download from {url}: {e}")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(req.content)
def download_mdi(value): def download_mdi(value):
validate_cairosvg_installed(value) validate_cairosvg_installed(value)
@ -108,7 +81,7 @@ def download_mdi(value):
url = f"https://raw.githubusercontent.com/Templarian/MaterialDesign/master/svg/{mdi_id}.svg" url = f"https://raw.githubusercontent.com/Templarian/MaterialDesign/master/svg/{mdi_id}.svg"
download_content(url, path) external_files.download_content(url, path, IMAGE_DOWNLOAD_TIMEOUT)
return value return value
@ -117,7 +90,7 @@ def download_image(value):
url = value[CONF_URL] url = value[CONF_URL]
path = compute_local_image_path(value) path = compute_local_image_path(value)
download_content(url, path) external_files.download_content(url, path, IMAGE_DOWNLOAD_TIMEOUT)
return value return value

View file

@ -74,6 +74,9 @@ def mdns_service(
@coroutine_with_priority(55.0) @coroutine_with_priority(55.0)
async def to_code(config): async def to_code(config):
if config[CONF_DISABLED] is True:
return
if CORE.using_arduino: if CORE.using_arduino:
if CORE.is_esp32: if CORE.is_esp32:
cg.add_library("ESPmDNS", None) cg.add_library("ESPmDNS", None)
@ -92,9 +95,6 @@ async def to_code(config):
path="components/mdns", path="components/mdns",
) )
if config[CONF_DISABLED]:
return
cg.add_define("USE_MDNS") cg.add_define("USE_MDNS")
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])

View file

@ -1,5 +1,6 @@
#include "mdns_component.h"
#include "esphome/core/defines.h" #include "esphome/core/defines.h"
#ifdef USE_MDNS
#include "mdns_component.h"
#include "esphome/core/version.h" #include "esphome/core/version.h"
#include "esphome/core/application.h" #include "esphome/core/application.h"
#include "esphome/core/log.h" #include "esphome/core/log.h"
@ -125,3 +126,4 @@ void MDNSComponent::dump_config() {
} // namespace mdns } // namespace mdns
} // namespace esphome } // namespace esphome
#endif

View file

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "esphome/core/defines.h"
#ifdef USE_MDNS
#include <string> #include <string>
#include <vector> #include <vector>
#include "esphome/core/component.h" #include "esphome/core/component.h"
@ -46,3 +47,4 @@ class MDNSComponent : public Component {
} // namespace mdns } // namespace mdns
} // namespace esphome } // namespace esphome
#endif

View file

@ -1,4 +1,5 @@
#ifdef USE_ESP32 #include "esphome/core/defines.h"
#if defined(USE_ESP32) && defined(USE_MDNS)
#include <mdns.h> #include <mdns.h>
#include <cstring> #include <cstring>

View file

@ -1,4 +1,5 @@
#if defined(USE_ESP8266) && defined(USE_ARDUINO) #include "esphome/core/defines.h"
#if defined(USE_ESP8266) && defined(USE_ARDUINO) && defined(USE_MDNS)
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#include "esphome/components/network/ip_address.h" #include "esphome/components/network/ip_address.h"

View file

@ -1,4 +1,5 @@
#ifdef USE_HOST #include "esphome/core/defines.h"
#if defined(USE_HOST) && defined(USE_MDNS)
#include "esphome/components/network/ip_address.h" #include "esphome/components/network/ip_address.h"
#include "esphome/components/network/util.h" #include "esphome/components/network/util.h"

View file

@ -1,4 +1,5 @@
#ifdef USE_LIBRETINY #include "esphome/core/defines.h"
#if defined(USE_LIBRETINY) && defined(USE_MDNS)
#include "esphome/components/network/ip_address.h" #include "esphome/components/network/ip_address.h"
#include "esphome/components/network/util.h" #include "esphome/components/network/util.h"

View file

@ -1,4 +1,5 @@
#ifdef USE_RP2040 #include "esphome/core/defines.h"
#if defined(USE_RP2040) && defined(USE_MDNS)
#include "esphome/components/network/ip_address.h" #include "esphome/components/network/ip_address.h"
#include "esphome/components/network/util.h" #include "esphome/components/network/util.h"

View file

@ -293,4 +293,4 @@ async def to_code(config):
if CONF_HUMIDITY_SETPOINT in config: if CONF_HUMIDITY_SETPOINT in config:
sens = await sensor.new_sensor(config[CONF_HUMIDITY_SETPOINT]) sens = await sensor.new_sensor(config[CONF_HUMIDITY_SETPOINT])
cg.add(var.set_humidity_setpoint_sensor(sens)) cg.add(var.set_humidity_setpoint_sensor(sens))
cg.add_library("dudanov/MideaUART", "1.1.8") cg.add_library("dudanov/MideaUART", "1.1.9")

View file

@ -116,7 +116,8 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.", ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.",
server_register->address, static_cast<uint8_t>(server_register->value_type), server_register->address, static_cast<uint8_t>(server_register->value_type),
server_register->register_count, value); server_register->register_count, value);
number_to_payload(sixteen_bit_response, value, server_register->value_type); std::vector<uint16_t> payload = float_to_payload(value, server_register->value_type);
sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend());
current_address += server_register->register_count; current_address += server_register->register_count;
found = true; found = true;
break; break;

View file

@ -15,7 +15,7 @@ void ModbusTextSensor::parse_and_publish(const std::vector<uint8_t> &data) {
std::ostringstream output; std::ostringstream output;
uint8_t items_left = this->response_bytes; uint8_t items_left = this->response_bytes;
uint8_t index = this->offset; uint8_t index = this->offset;
char buffer[4]; char buffer[5];
while ((items_left > 0) && index < data.size()) { while ((items_left > 0) && index < data.size()) {
uint8_t b = data[index]; uint8_t b = data[index];
switch (this->encode_) { switch (this->encode_) {

View file

@ -26,6 +26,7 @@ from esphome.const import (
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_DIOXIDE,
DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CARBON_MONOXIDE,
DEVICE_CLASS_CONDUCTIVITY,
DEVICE_CLASS_CURRENT, DEVICE_CLASS_CURRENT,
DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_RATE,
DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATA_SIZE,
@ -82,6 +83,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_DIOXIDE,
DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CARBON_MONOXIDE,
DEVICE_CLASS_CONDUCTIVITY,
DEVICE_CLASS_CURRENT, DEVICE_CLASS_CURRENT,
DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_RATE,
DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATA_SIZE,

View file

@ -65,13 +65,10 @@ class QspiAmoLed : public display::DisplayBuffer,
void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; } void set_reset_pin(GPIOPin *reset_pin) { this->reset_pin_ = reset_pin; }
void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; } void set_enable_pin(GPIOPin *enable_pin) { this->enable_pin_ = enable_pin; }
void set_width(uint16_t width) { this->width_ = width; }
void set_dimensions(uint16_t width, uint16_t height) { void set_dimensions(uint16_t width, uint16_t height) {
this->width_ = width; this->width_ = width;
this->height_ = height; this->height_ = height;
} }
int get_width() override { return this->width_; }
int get_height() override { return this->height_; }
void set_invert_colors(bool invert_colors) { void set_invert_colors(bool invert_colors) {
this->invert_colors_ = invert_colors; this->invert_colors_ = invert_colors;
this->reset_params_(); this->reset_params_();

View file

@ -56,9 +56,7 @@ CONFIG_SCHEMA = cv.All(
@coroutine_with_priority(50.0) @coroutine_with_priority(50.0)
async def to_code(config): async def to_code(config):
if config[CONF_DISABLED]: if not config[CONF_DISABLED]:
return
var = cg.new_Pvariable(config[CONF_ID]) var = cg.new_Pvariable(config[CONF_ID])
await cg.register_component(var, config) await cg.register_component(var, config)
@ -72,5 +70,6 @@ async def to_code(config):
config[CONF_BOOT_IS_GOOD_AFTER], config[CONF_BOOT_IS_GOOD_AFTER],
) )
cg.add(RawExpression(f"if ({condition}) return")) cg.add(RawExpression(f"if ({condition}) return"))
CORE.data[CONF_SAFE_MODE] = {} CORE.data[CONF_SAFE_MODE] = {}
CORE.data[CONF_SAFE_MODE][KEY_PAST_SAFE_MODE] = True CORE.data[CONF_SAFE_MODE][KEY_PAST_SAFE_MODE] = True

View file

@ -88,7 +88,7 @@ def validate_parameter_name(value):
raise cv.Invalid(f"Script's parameter name cannot be {CONF_ID}") raise cv.Invalid(f"Script's parameter name cannot be {CONF_ID}")
ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]") ALLOWED_PARAM_TYPE_CHARSET = set("abcdefghijklmnopqrstuvwxyz0123456789_:*&[]<>")
def validate_parameter_type(value): def validate_parameter_type(value):

View file

@ -43,6 +43,7 @@ from esphome.const import (
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_DIOXIDE,
DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CARBON_MONOXIDE,
DEVICE_CLASS_CONDUCTIVITY,
DEVICE_CLASS_CURRENT, DEVICE_CLASS_CURRENT,
DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_RATE,
DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATA_SIZE,
@ -103,6 +104,7 @@ DEVICE_CLASSES = [
DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY,
DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_DIOXIDE,
DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CARBON_MONOXIDE,
DEVICE_CLASS_CONDUCTIVITY,
DEVICE_CLASS_CURRENT, DEVICE_CLASS_CURRENT,
DEVICE_CLASS_DATA_RATE, DEVICE_CLASS_DATA_RATE,
DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATA_SIZE,

View file

@ -69,7 +69,7 @@ async def setup_update_core_(var, config):
await mqtt.register_mqtt_component(mqtt_, config) await mqtt.register_mqtt_component(mqtt_, config)
if web_server_id_config := config.get(CONF_WEB_SERVER_ID): if web_server_id_config := config.get(CONF_WEB_SERVER_ID):
web_server_ = cg.get_variable(web_server_id_config) web_server_ = await cg.get_variable(web_server_id_config)
web_server.add_entity_to_sorting_list(web_server_, var, config) web_server.add_entity_to_sorting_list(web_server_, var, config)

View file

@ -1070,6 +1070,7 @@ DEVICE_CLASS_BUTTON = "button"
DEVICE_CLASS_CARBON_DIOXIDE = "carbon_dioxide" DEVICE_CLASS_CARBON_DIOXIDE = "carbon_dioxide"
DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide" DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide"
DEVICE_CLASS_COLD = "cold" DEVICE_CLASS_COLD = "cold"
DEVICE_CLASS_CONDUCTIVITY = "conductivity"
DEVICE_CLASS_CONNECTIVITY = "connectivity" DEVICE_CLASS_CONNECTIVITY = "connectivity"
DEVICE_CLASS_CURRENT = "current" DEVICE_CLASS_CURRENT = "current"
DEVICE_CLASS_CURTAIN = "curtain" DEVICE_CLASS_CURTAIN = "curtain"

View file

@ -10,6 +10,7 @@ int_ = global_ns.namespace("int")
std_ns = global_ns.namespace("std") std_ns = global_ns.namespace("std")
std_shared_ptr = std_ns.class_("shared_ptr") std_shared_ptr = std_ns.class_("shared_ptr")
std_string = std_ns.class_("string") std_string = std_ns.class_("string")
std_string_ref = std_ns.namespace("string &")
std_vector = std_ns.class_("vector") std_vector = std_ns.class_("vector")
uint8 = global_ns.namespace("uint8_t") uint8 = global_ns.namespace("uint8_t")
uint16 = global_ns.namespace("uint16_t") uint16 = global_ns.namespace("uint16_t")

View file

@ -7,6 +7,7 @@ from datetime import datetime
import requests import requests
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.core import CORE, TimePeriodSeconds from esphome.core import CORE, TimePeriodSeconds
from esphome.const import __version__
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CODEOWNERS = ["@landonr"] CODEOWNERS = ["@landonr"]
@ -75,3 +76,28 @@ def compute_local_file_dir(domain: str) -> Path:
base_directory.mkdir(parents=True, exist_ok=True) base_directory.mkdir(parents=True, exist_ok=True)
return base_directory return base_directory
def download_content(url: str, path: Path, timeout=NETWORK_TIMEOUT) -> None:
if not has_remote_file_changed(url, path):
_LOGGER.debug("Remote file has not changed %s", url)
return
_LOGGER.debug(
"Remote file has changed, downloading from %s to %s",
url,
path,
)
try:
req = requests.get(
url,
timeout=timeout,
headers={"User-agent": f"ESPHome/{__version__} (https://esphome.io)"},
)
req.raise_for_status()
except requests.exceptions.RequestException as e:
raise cv.Invalid(f"Could not download from {url}: {e}")
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(req.content)

View file

@ -64,8 +64,8 @@ lib_deps =
freekode/TM1651@1.0.1 ; tm1651 freekode/TM1651@1.0.1 ; tm1651
glmnet/Dsmr@0.7 ; dsmr glmnet/Dsmr@0.7 ; dsmr
rweather/Crypto@0.4.0 ; dsmr rweather/Crypto@0.4.0 ; dsmr
dudanov/MideaUART@1.1.8 ; midea dudanov/MideaUART@1.1.9 ; midea
tonia/HeatpumpIR@1.0.23 ; heatpumpir tonia/HeatpumpIR@1.0.26 ; heatpumpir
build_flags = build_flags =
${common.build_flags} ${common.build_flags}
-DUSE_ARDUINO -DUSE_ARDUINO
@ -93,7 +93,7 @@ lib_deps =
ESP8266HTTPClient ; http_request (Arduino built-in) ESP8266HTTPClient ; http_request (Arduino built-in)
ESP8266mDNS ; mdns (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in)
DNSServer ; captive_portal (Arduino built-in) DNSServer ; captive_portal (Arduino built-in)
crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir
droscy/esp_wireguard@0.4.1 ; wireguard droscy/esp_wireguard@0.4.1 ; wireguard
build_flags = build_flags =
${common:arduino.build_flags} ${common:arduino.build_flags}
@ -123,7 +123,7 @@ lib_deps =
ESPmDNS ; mdns (Arduino built-in) ESPmDNS ; mdns (Arduino built-in)
DNSServer ; captive_portal (Arduino built-in) DNSServer ; captive_portal (Arduino built-in)
esphome/ESP32-audioI2S@2.0.7 ; i2s_audio esphome/ESP32-audioI2S@2.0.7 ; i2s_audio
crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir crankyoldgit/IRremoteESP8266@2.8.6 ; heatpumpir
droscy/esp_wireguard@0.4.1 ; wireguard droscy/esp_wireguard@0.4.1 ; wireguard
build_flags = build_flags =
${common:arduino.build_flags} ${common:arduino.build_flags}

25
script/extract_automations.py Executable file
View file

@ -0,0 +1,25 @@
#!/usr/bin/env python3
import json
from helpers import git_ls_files
from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY
from esphome.pins import PIN_SCHEMA_REGISTRY
list_components = __import__("list-components")
if __name__ == "__main__":
files = git_ls_files()
files = filter(list_components.filter_component_files, files)
components = list_components.get_components(files, True)
dump = {
"actions": sorted(list(ACTION_REGISTRY.keys())),
"conditions": sorted(list(CONDITION_REGISTRY.keys())),
"pin_providers": sorted(list(PIN_SCHEMA_REGISTRY.keys())),
}
print(json.dumps(dump, indent=2))

View file

@ -50,6 +50,7 @@ def create_components_graph():
{KEY_TARGET_FRAMEWORK: "arduino", KEY_TARGET_PLATFORM: None}, {KEY_TARGET_FRAMEWORK: "arduino", KEY_TARGET_PLATFORM: None},
{KEY_TARGET_FRAMEWORK: "esp-idf", KEY_TARGET_PLATFORM: None}, {KEY_TARGET_FRAMEWORK: "esp-idf", KEY_TARGET_PLATFORM: None},
{KEY_TARGET_FRAMEWORK: None, KEY_TARGET_PLATFORM: PLATFORM_ESP32}, {KEY_TARGET_FRAMEWORK: None, KEY_TARGET_PLATFORM: PLATFORM_ESP32},
{KEY_TARGET_FRAMEWORK: None, KEY_TARGET_PLATFORM: PLATFORM_ESP8266},
] ]
CORE.data[KEY_CORE] = TARGET_CONFIGURATIONS[0] CORE.data[KEY_CORE] = TARGET_CONFIGURATIONS[0]
@ -119,6 +120,23 @@ def find_children_of_component(components_graph, component_name, depth=0):
return list(set(children)) return list(set(children))
def get_components(files: list[str], get_dependencies: bool = False):
components = extract_component_names_array_from_files_array(files)
if get_dependencies:
components_graph = create_components_graph()
all_components = components.copy()
for c in components:
all_components.extend(find_children_of_component(components_graph, c))
# Remove duplicate values
all_changed_components = list(set(all_components))
return sorted(all_changed_components)
return sorted(components)
def main(): def main():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
@ -142,23 +160,7 @@ def main():
changed = changed_files() changed = changed_files()
files = [f for f in files if f in changed] files = [f for f in files if f in changed]
components = extract_component_names_array_from_files_array(files) for c in get_components(files, args.changed):
if args.changed:
components_graph = create_components_graph()
all_changed_components = components.copy()
for c in components:
all_changed_components.extend(
find_children_of_component(components_graph, c)
)
# Remove duplicate values
all_changed_components = list(set(all_changed_components))
for c in sorted(all_changed_components):
print(c)
else:
for c in sorted(components):
print(c) print(c)

View file

@ -54,7 +54,6 @@ climate:
sensor: sensor:
- platform: haier - platform: haier
haier_id: haier_ac
outdoor_temperature: outdoor_temperature:
name: Haier outdoor temperature name: Haier outdoor temperature
humidity: humidity:
@ -80,7 +79,6 @@ sensor:
binary_sensor: binary_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
compressor_status: compressor_status:
name: Haier Outdoor Compressor Status name: Haier Outdoor Compressor Status
defrost_status: defrost_status:
@ -96,7 +94,6 @@ binary_sensor:
button: button:
- platform: haier - platform: haier
haier_id: haier_ac
self_cleaning: self_cleaning:
name: Haier start self cleaning name: Haier start self cleaning
steri_cleaning: steri_cleaning:
@ -104,7 +101,6 @@ button:
text_sensor: text_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
appliance_name: appliance_name:
name: Haier appliance name name: Haier appliance name
cleaning_status: cleaning_status:

View file

@ -54,7 +54,6 @@ climate:
sensor: sensor:
- platform: haier - platform: haier
haier_id: haier_ac
outdoor_temperature: outdoor_temperature:
name: Haier outdoor temperature name: Haier outdoor temperature
humidity: humidity:
@ -80,7 +79,6 @@ sensor:
binary_sensor: binary_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
compressor_status: compressor_status:
name: Haier Outdoor Compressor Status name: Haier Outdoor Compressor Status
defrost_status: defrost_status:
@ -96,7 +94,6 @@ binary_sensor:
button: button:
- platform: haier - platform: haier
haier_id: haier_ac
self_cleaning: self_cleaning:
name: Haier start self cleaning name: Haier start self cleaning
steri_cleaning: steri_cleaning:
@ -104,7 +101,6 @@ button:
text_sensor: text_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
appliance_name: appliance_name:
name: Haier appliance name name: Haier appliance name
cleaning_status: cleaning_status:

View file

@ -54,7 +54,6 @@ climate:
sensor: sensor:
- platform: haier - platform: haier
haier_id: haier_ac
outdoor_temperature: outdoor_temperature:
name: Haier outdoor temperature name: Haier outdoor temperature
humidity: humidity:
@ -80,7 +79,6 @@ sensor:
binary_sensor: binary_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
compressor_status: compressor_status:
name: Haier Outdoor Compressor Status name: Haier Outdoor Compressor Status
defrost_status: defrost_status:
@ -96,7 +94,6 @@ binary_sensor:
button: button:
- platform: haier - platform: haier
haier_id: haier_ac
self_cleaning: self_cleaning:
name: Haier start self cleaning name: Haier start self cleaning
steri_cleaning: steri_cleaning:
@ -104,7 +101,6 @@ button:
text_sensor: text_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
appliance_name: appliance_name:
name: Haier appliance name name: Haier appliance name
cleaning_status: cleaning_status:

View file

@ -54,7 +54,6 @@ climate:
sensor: sensor:
- platform: haier - platform: haier
haier_id: haier_ac
outdoor_temperature: outdoor_temperature:
name: Haier outdoor temperature name: Haier outdoor temperature
humidity: humidity:
@ -80,7 +79,6 @@ sensor:
binary_sensor: binary_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
compressor_status: compressor_status:
name: Haier Outdoor Compressor Status name: Haier Outdoor Compressor Status
defrost_status: defrost_status:
@ -96,7 +94,6 @@ binary_sensor:
button: button:
- platform: haier - platform: haier
haier_id: haier_ac
self_cleaning: self_cleaning:
name: Haier start self cleaning name: Haier start self cleaning
steri_cleaning: steri_cleaning:
@ -104,7 +101,6 @@ button:
text_sensor: text_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
appliance_name: appliance_name:
name: Haier appliance name name: Haier appliance name
cleaning_status: cleaning_status:

View file

@ -54,7 +54,6 @@ climate:
sensor: sensor:
- platform: haier - platform: haier
haier_id: haier_ac
outdoor_temperature: outdoor_temperature:
name: Haier outdoor temperature name: Haier outdoor temperature
humidity: humidity:
@ -80,7 +79,6 @@ sensor:
binary_sensor: binary_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
compressor_status: compressor_status:
name: Haier Outdoor Compressor Status name: Haier Outdoor Compressor Status
defrost_status: defrost_status:
@ -96,7 +94,6 @@ binary_sensor:
button: button:
- platform: haier - platform: haier
haier_id: haier_ac
self_cleaning: self_cleaning:
name: Haier start self cleaning name: Haier start self cleaning
steri_cleaning: steri_cleaning:
@ -104,7 +101,6 @@ button:
text_sensor: text_sensor:
- platform: haier - platform: haier
haier_id: haier_ac
appliance_name: appliance_name:
name: Haier appliance name name: Haier appliance name
cleaning_status: cleaning_status: