Merge branch 'dev' into ltr303

This commit is contained in:
Anton Viktorov 2024-04-29 10:00:38 +02:00 committed by GitHub
commit 0e5a829f86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 141 additions and 82 deletions

View File

@ -343,9 +343,10 @@ def upload_program(config, args, host):
password = ota_conf.get(CONF_PASSWORD, "") password = ota_conf.get(CONF_PASSWORD, "")
if ( if (
not is_ip_address(CORE.address) not is_ip_address(CORE.address) # pylint: disable=too-many-boolean-expressions
and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED]) and (get_port_type(host) == "MQTT" or config[CONF_MDNS][CONF_DISABLED])
and CONF_MQTT in config and CONF_MQTT in config
and (not args.device or args.device == "MQTT")
): ):
from esphome import mqtt from esphome import mqtt
@ -768,7 +769,9 @@ def parse_args(argv):
) )
parser_upload = subparsers.add_parser( parser_upload = subparsers.add_parser(
"upload", help="Validate the configuration and upload the latest binary." "upload",
help="Validate the configuration and upload the latest binary.",
parents=[mqtt_options],
) )
parser_upload.add_argument( parser_upload.add_argument(
"configuration", help="Your YAML configuration file(s).", nargs="+" "configuration", help="Your YAML configuration file(s).", nargs="+"

View File

@ -51,15 +51,15 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) {
MultiClickTriggerEvent evt = this->timing_[*this->at_index_]; MultiClickTriggerEvent evt = this->timing_[*this->at_index_];
if (evt.max_length != 4294967294UL) { if (evt.max_length != 4294967294UL) {
ESP_LOGV(TAG, "A i=%u min=%" PRIu32 " max=%" PRIu32, *this->at_index_, evt.min_length, evt.max_length); // NOLINT ESP_LOGV(TAG, "A i=%zu min=%" PRIu32 " max=%" PRIu32, *this->at_index_, evt.min_length, evt.max_length); // NOLINT
this->schedule_is_valid_(evt.min_length); this->schedule_is_valid_(evt.min_length);
this->schedule_is_not_valid_(evt.max_length); this->schedule_is_not_valid_(evt.max_length);
} else if (*this->at_index_ + 1 != this->timing_.size()) { } else if (*this->at_index_ + 1 != this->timing_.size()) {
ESP_LOGV(TAG, "B i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT ESP_LOGV(TAG, "B i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT
this->cancel_timeout("is_not_valid"); this->cancel_timeout("is_not_valid");
this->schedule_is_valid_(evt.min_length); this->schedule_is_valid_(evt.min_length);
} else { } else {
ESP_LOGV(TAG, "C i=%u min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT ESP_LOGV(TAG, "C i=%zu min=%" PRIu32, *this->at_index_, evt.min_length); // NOLINT
this->is_valid_ = false; this->is_valid_ = false;
this->cancel_timeout("is_not_valid"); this->cancel_timeout("is_not_valid");
this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); }); this->set_timeout("trigger", evt.min_length, [this]() { this->trigger_(); });

View File

@ -177,22 +177,26 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo
bool b = (trace->get_line_type() & bit) == bit; bool b = (trace->get_line_type() & bit) == bit;
if (b) { if (b) {
int16_t y = (int16_t) roundf((this->height_ - 1) * (1.0 - v)) - thick / 2 + y_offset; int16_t y = (int16_t) roundf((this->height_ - 1) * (1.0 - v)) - thick / 2 + y_offset;
auto draw_pixel_at = [&buff, c, y_offset, this](int16_t x, int16_t y) {
if (y >= y_offset && y < y_offset + this->height_)
buff->draw_pixel_at(x, y, c);
};
if (!continuous || !has_prev || !prev_b || (abs(y - prev_y) <= thick)) { if (!continuous || !has_prev || !prev_b || (abs(y - prev_y) <= thick)) {
for (int16_t t = 0; t < thick; t++) { for (int16_t t = 0; t < thick; t++) {
buff->draw_pixel_at(x, y + t, c); draw_pixel_at(x, y + t);
} }
} else { } else {
int16_t mid_y = (y + prev_y + thick) / 2; int16_t mid_y = (y + prev_y + thick) / 2;
if (y > prev_y) { if (y > prev_y) {
for (int16_t t = prev_y + thick; t <= mid_y; t++) for (int16_t t = prev_y + thick; t <= mid_y; t++)
buff->draw_pixel_at(x + 1, t, c); draw_pixel_at(x + 1, t);
for (int16_t t = mid_y + 1; t < y + thick; t++) for (int16_t t = mid_y + 1; t < y + thick; t++)
buff->draw_pixel_at(x, t, c); draw_pixel_at(x, t);
} else { } else {
for (int16_t t = prev_y - 1; t >= mid_y; t--) for (int16_t t = prev_y - 1; t >= mid_y; t--)
buff->draw_pixel_at(x + 1, t, c); draw_pixel_at(x + 1, t);
for (int16_t t = mid_y - 1; t >= y; t--) for (int16_t t = mid_y - 1; t >= y; t--)
buff->draw_pixel_at(x, t, c); draw_pixel_at(x, t);
} }
} }
prev_y = y; prev_y = y;

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "abstract_aqi_calculator.h" #include "abstract_aqi_calculator.h"
// https://www.airnow.gov/sites/default/files/2020-05/aqi-technical-assistance-document-sept2018.pdf
namespace esphome { namespace esphome {
namespace hm3301 { namespace hm3301 {
@ -15,14 +16,16 @@ class AQICalculator : public AbstractAQICalculator {
} }
protected: protected:
static const int AMOUNT_OF_LEVELS = 6; static const int AMOUNT_OF_LEVELS = 7;
int index_grid_[AMOUNT_OF_LEVELS][2] = {{0, 51}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 500}}; int index_grid_[AMOUNT_OF_LEVELS][2] = {{0, 50}, {51, 100}, {101, 150}, {151, 200},
{201, 300}, {301, 400}, {401, 500}};
int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 35}, {36, 55}, {56, 150}, {151, 250}, {251, 500}}; int pm2_5_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 12}, {13, 35}, {36, 55}, {56, 150},
{151, 250}, {251, 350}, {351, 500}};
int pm10_0_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, int pm10_0_calculation_grid_[AMOUNT_OF_LEVELS][2] = {{0, 54}, {55, 154}, {155, 254}, {255, 354},
{255, 354}, {355, 424}, {425, 604}}; {355, 424}, {425, 504}, {505, 604}};
int calculate_index_(uint16_t value, int array[AMOUNT_OF_LEVELS][2]) { int calculate_index_(uint16_t value, int array[AMOUNT_OF_LEVELS][2]) {
int grid_index = get_grid_index_(value, array); int grid_index = get_grid_index_(value, array);

View File

@ -61,28 +61,57 @@ void I2SAudioMicrophone::start_() {
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT,
}; };
esp_err_t err;
#if SOC_I2S_SUPPORTS_ADC #if SOC_I2S_SUPPORTS_ADC
if (this->adc_) { if (this->adc_) {
config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN);
i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
err = i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error setting ADC mode: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
err = i2s_adc_enable(this->parent_->get_port());
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error enabling ADC: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_);
i2s_adc_enable(this->parent_->get_port());
} else } else
#endif #endif
{ {
if (this->pdm_) if (this->pdm_)
config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM);
i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); err = i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error installing I2S driver: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
i2s_pin_config_t pin_config = this->parent_->get_pin_config(); i2s_pin_config_t pin_config = this->parent_->get_pin_config();
pin_config.data_in_num = this->din_pin_; pin_config.data_in_num = this->din_pin_;
i2s_set_pin(this->parent_->get_port(), &pin_config); err = i2s_set_pin(this->parent_->get_port(), &pin_config);
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error setting I2S pin: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
} }
this->state_ = microphone::STATE_RUNNING; this->state_ = microphone::STATE_RUNNING;
this->high_freq_.start(); this->high_freq_.start();
this->status_clear_error();
} }
void I2SAudioMicrophone::stop() { void I2SAudioMicrophone::stop() {
@ -96,11 +125,33 @@ void I2SAudioMicrophone::stop() {
} }
void I2SAudioMicrophone::stop_() { void I2SAudioMicrophone::stop_() {
i2s_stop(this->parent_->get_port()); esp_err_t err;
i2s_driver_uninstall(this->parent_->get_port()); #if SOC_I2S_SUPPORTS_ADC
if (this->adc_) {
err = i2s_adc_disable(this->parent_->get_port());
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error disabling ADC: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
}
#endif
err = i2s_stop(this->parent_->get_port());
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error stopping I2S microphone: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
err = i2s_driver_uninstall(this->parent_->get_port());
if (err != ESP_OK) {
ESP_LOGW(TAG, "Error uninstalling I2S driver: %s", esp_err_to_name(err));
this->status_set_error();
return;
}
this->parent_->unlock(); this->parent_->unlock();
this->state_ = microphone::STATE_STOPPED; this->state_ = microphone::STATE_STOPPED;
this->high_freq_.stop(); this->high_freq_.stop();
this->status_clear_error();
} }
size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) { size_t I2SAudioMicrophone::read(int16_t *buf, size_t len) {

View File

@ -150,6 +150,7 @@ class AutomationLightEffect : public LightEffect {
struct StrobeLightEffectColor { struct StrobeLightEffectColor {
LightColorValues color; LightColorValues color;
uint32_t duration; uint32_t duration;
uint32_t transition_length;
}; };
class StrobeLightEffect : public LightEffect { class StrobeLightEffect : public LightEffect {
@ -174,7 +175,7 @@ class StrobeLightEffect : public LightEffect {
} }
call.set_publish(false); call.set_publish(false);
call.set_save(false); call.set_save(false);
call.set_transition_length_if_supported(0); call.set_transition_length_if_supported(this->colors_[this->at_color_].transition_length);
call.perform(); call.perform();
this->last_switch_ = now; this->last_switch_ = now;
} }

View File

@ -266,6 +266,9 @@ async def random_effect_to_code(config, effect_id):
cv.Required( cv.Required(
CONF_DURATION CONF_DURATION
): cv.positive_time_period_milliseconds, ): cv.positive_time_period_milliseconds,
cv.Optional(
CONF_TRANSITION_LENGTH, default="0s"
): cv.positive_time_period_milliseconds,
} }
), ),
cv.has_at_least_one_key( cv.has_at_least_one_key(
@ -310,6 +313,7 @@ async def strobe_effect_to_code(config, effect_id):
), ),
), ),
("duration", color[CONF_DURATION]), ("duration", color[CONF_DURATION]),
("transition_length", color[CONF_TRANSITION_LENGTH]),
) )
) )
cg.add(var.set_colors(colors)) cg.add(var.set_colors(colors))

View File

@ -116,7 +116,7 @@ def do_substitution_pass(config, command_line_substitutions, ignore_missing=Fals
if CONF_SUBSTITUTIONS not in config and not command_line_substitutions: if CONF_SUBSTITUTIONS not in config and not command_line_substitutions:
return return
substitutions = config[CONF_SUBSTITUTIONS] substitutions = config.get(CONF_SUBSTITUTIONS)
if substitutions is None: if substitutions is None:
substitutions = command_line_substitutions substitutions = command_line_substitutions
elif command_line_substitutions: elif command_line_substitutions:

View File

@ -374,7 +374,10 @@ class LoadValidationStep(ConfigValidationStep):
path + [CONF_ID], path + [CONF_ID],
) )
continue continue
result.add_str_error("No platform specified! See 'platform' key.", path) result.add_str_error(
f"'{self.domain}' requires a 'platform' key but it was not specified.",
path,
)
continue continue
# Remove temp output path and construct new one # Remove temp output path and construct new one
result.remove_output_path(path, p_domain) result.remove_output_path(path, p_domain)
@ -449,9 +452,28 @@ class MetadataValidationStep(ConfigValidationStep):
success = True success = True
for dependency in self.comp.dependencies: for dependency in self.comp.dependencies:
if dependency not in result: dependency_parts = dependency.split(".")
if len(dependency_parts) > 2:
result.add_str_error( result.add_str_error(
f"Component {self.domain} requires component {dependency}", "Dependencies must be specified as a single component or in component.platform format only",
self.path,
)
return
component_dep = dependency_parts[0]
platform_dep = dependency_parts[-1]
if component_dep not in result:
result.add_str_error(
f"Component {self.domain} requires component {component_dep}",
self.path,
)
success = False
elif component_dep != platform_dep and (
not isinstance(platform_list := result.get(component_dep), list)
or not any(CONF_PLATFORM in p for p in platform_list)
or not any(p[CONF_PLATFORM] == platform_dep for p in platform_list)
):
result.add_str_error(
f"Component {self.domain} requires 'platform: {platform_dep}' in component '{component_dep}'",
self.path, self.path,
) )
success = False success = False
@ -756,11 +778,11 @@ def validate_config(
CORE.raw_config = config CORE.raw_config = config
# 1. Load substitutions # 1. Load substitutions
if CONF_SUBSTITUTIONS in config: if CONF_SUBSTITUTIONS in config or command_line_substitutions:
from esphome.components import substitutions from esphome.components import substitutions
result[CONF_SUBSTITUTIONS] = { result[CONF_SUBSTITUTIONS] = {
**config[CONF_SUBSTITUTIONS], **config.get(CONF_SUBSTITUTIONS, {}),
**command_line_substitutions, **command_line_substitutions,
} }
result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS) result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS)

View File

@ -437,7 +437,7 @@ static inline bool is_base64(char c) { return (isalnum(c) || (c == '+') || (c ==
std::string base64_encode(const std::vector<uint8_t> &buf) { return base64_encode(buf.data(), buf.size()); } std::string base64_encode(const std::vector<uint8_t> &buf) { return base64_encode(buf.data(), buf.size()); }
std::string base64_encode(const char *buf, unsigned int buf_len) { std::string base64_encode(const uint8_t *buf, size_t buf_len) {
std::string ret; std::string ret;
int i = 0; int i = 0;
int j = 0; int j = 0;

View File

@ -69,7 +69,9 @@ def create_components_graph():
sys.exit(1) sys.exit(1)
for dependency in comp.dependencies: for dependency in comp.dependencies:
add_item_to_components_graph(components_graph, dependency, name) add_item_to_components_graph(
components_graph, dependency.split(".")[0], name
)
for target_config in TARGET_CONFIGURATIONS: for target_config in TARGET_CONFIGURATIONS:
CORE.data[KEY_CORE] = target_config CORE.data[KEY_CORE] = target_config
@ -87,7 +89,9 @@ def create_components_graph():
add_item_to_components_graph(components_graph, platform_name, name) add_item_to_components_graph(components_graph, platform_name, name)
for dependency in platform.dependencies: for dependency in platform.dependencies:
add_item_to_components_graph(components_graph, dependency, name) add_item_to_components_graph(
components_graph, dependency.split(".")[0], name
)
for target_config in TARGET_CONFIGURATIONS: for target_config in TARGET_CONFIGURATIONS:
CORE.data[KEY_CORE] = target_config CORE.data[KEY_CORE] = target_config

View File

@ -37,9 +37,9 @@ start_esphome() {
# Start esphome process # Start esphome process
echo "> [$target_component] [$test_name] [$target_platform]" echo "> [$target_component] [$test_name] [$target_platform]"
echo "esphome -s component_name $target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file" echo "esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file"
# TODO: Validate escape of Command line substitution value # TODO: Validate escape of Command line substitution value
esphome -s component_name $target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file esphome -s component_name $target_component -s component_dir ../../components/$target_component -s test_name $test_name -s target_platform $target_platform $esphome_command $component_test_file
} }
# Find all test yaml files. # Find all test yaml files.

View File

@ -0,0 +1,15 @@
time:
- platform: sntp
id: esptime
timezone: Australia/Sydney
logger:
level: VERBOSE
logs:
lvgl: INFO
display: DEBUG
sensor: INFO
vnc: DEBUG
host:
mac_address: "62:23:45:AF:B3:DD"

View File

@ -12,8 +12,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -14,8 +14,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -14,8 +14,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -14,8 +14,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -14,8 +14,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -15,8 +15,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -15,8 +15,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -15,8 +15,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -15,8 +15,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -12,8 +12,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -12,8 +12,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"

View File

@ -15,8 +15,4 @@ packages:
component_under_test: !include component_under_test: !include
file: $component_test_file file: $component_test_file
vars: vars:
component_name: $component_name
test_name: $test_name
target_platform: $target_platform
component_test_file: $component_test_file component_test_file: $component_test_file
component_dir: "../../components/$component_name"