mirror of
https://github.com/esphome/esphome.git
synced 2025-10-31 23:21:54 +00:00
Merge branch 'integration' into memory_api
This commit is contained in:
@@ -207,14 +207,14 @@ def choose_upload_log_host(
|
|||||||
if has_mqtt_logging():
|
if has_mqtt_logging():
|
||||||
resolved.append("MQTT")
|
resolved.append("MQTT")
|
||||||
|
|
||||||
if has_api() and has_non_ip_address():
|
if has_api() and has_non_ip_address() and has_resolvable_address():
|
||||||
resolved.extend(_resolve_with_cache(CORE.address, purpose))
|
resolved.extend(_resolve_with_cache(CORE.address, purpose))
|
||||||
|
|
||||||
elif purpose == Purpose.UPLOADING:
|
elif purpose == Purpose.UPLOADING:
|
||||||
if has_ota() and has_mqtt_ip_lookup():
|
if has_ota() and has_mqtt_ip_lookup():
|
||||||
resolved.append("MQTTIP")
|
resolved.append("MQTTIP")
|
||||||
|
|
||||||
if has_ota() and has_non_ip_address():
|
if has_ota() and has_non_ip_address() and has_resolvable_address():
|
||||||
resolved.extend(_resolve_with_cache(CORE.address, purpose))
|
resolved.extend(_resolve_with_cache(CORE.address, purpose))
|
||||||
else:
|
else:
|
||||||
resolved.append(device)
|
resolved.append(device)
|
||||||
@@ -318,7 +318,17 @@ def has_resolvable_address() -> bool:
|
|||||||
"""Check if CORE.address is resolvable (via mDNS, DNS, or is an IP address)."""
|
"""Check if CORE.address is resolvable (via mDNS, DNS, or is an IP address)."""
|
||||||
# Any address (IP, mDNS hostname, or regular DNS hostname) is resolvable
|
# Any address (IP, mDNS hostname, or regular DNS hostname) is resolvable
|
||||||
# The resolve_ip_address() function in helpers.py handles all types via AsyncResolver
|
# The resolve_ip_address() function in helpers.py handles all types via AsyncResolver
|
||||||
return CORE.address is not None
|
if CORE.address is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if has_ip_address():
|
||||||
|
return True
|
||||||
|
|
||||||
|
if has_mdns():
|
||||||
|
return True
|
||||||
|
|
||||||
|
# .local mDNS hostnames are only resolvable if mDNS is enabled
|
||||||
|
return not CORE.address.endswith(".local")
|
||||||
|
|
||||||
|
|
||||||
def mqtt_get_ip(config: ConfigType, username: str, password: str, client_id: str):
|
def mqtt_get_ip(config: ConfigType, username: str, password: str, client_id: str):
|
||||||
|
|||||||
@@ -877,7 +877,7 @@ uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection
|
|||||||
bool is_single) {
|
bool is_single) {
|
||||||
auto *select = static_cast<select::Select *>(entity);
|
auto *select = static_cast<select::Select *>(entity);
|
||||||
SelectStateResponse resp;
|
SelectStateResponse resp;
|
||||||
resp.set_state(StringRef(select->state));
|
resp.set_state(StringRef(select->current_option()));
|
||||||
resp.missing_state = !select->has_state();
|
resp.missing_state = !select->has_state();
|
||||||
return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
return fill_and_encode_entity_state(select, resp, SelectStateResponse::MESSAGE_TYPE, conn, remaining_size, is_single);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ namespace copy {
|
|||||||
static const char *const TAG = "copy.select";
|
static const char *const TAG = "copy.select";
|
||||||
|
|
||||||
void CopySelect::setup() {
|
void CopySelect::setup() {
|
||||||
source_->add_on_state_callback([this](const std::string &value, size_t index) { this->publish_state(value); });
|
source_->add_on_state_callback([this](const std::string &value, size_t index) { this->publish_state(index); });
|
||||||
|
|
||||||
traits.set_options(source_->traits.get_options());
|
traits.set_options(source_->traits.get_options());
|
||||||
|
|
||||||
if (source_->has_state())
|
if (source_->has_state())
|
||||||
this->publish_state(source_->state);
|
this->publish_state(source_->active_index().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CopySelect::dump_config() { LOG_SELECT("", "Copy Select", this); }
|
void CopySelect::dump_config() { LOG_SELECT("", "Copy Select", this); }
|
||||||
|
|
||||||
void CopySelect::control(const std::string &value) {
|
void CopySelect::control(size_t index) {
|
||||||
auto call = source_->make_call();
|
auto call = source_->make_call();
|
||||||
call.set_option(value);
|
call.set_index(index);
|
||||||
call.perform();
|
call.perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class CopySelect : public select::Select, public Component {
|
|||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
|
|
||||||
select::Select *source_;
|
select::Select *source_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ std::string MenuItemSelect::get_value_text() const {
|
|||||||
result = this->value_getter_.value()(this);
|
result = this->value_getter_.value()(this);
|
||||||
} else {
|
} else {
|
||||||
if (this->select_var_ != nullptr) {
|
if (this->select_var_ != nullptr) {
|
||||||
result = this->select_var_->state;
|
result = this->select_var_->current_option();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,9 +121,9 @@ constexpr Uint8ToString OUT_PIN_LEVELS_BY_UINT[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Helper functions for lookups
|
// Helper functions for lookups
|
||||||
template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const std::string &str) {
|
template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const char *str) {
|
||||||
for (const auto &entry : arr) {
|
for (const auto &entry : arr) {
|
||||||
if (str == entry.str)
|
if (strcmp(str, entry.str) == 0)
|
||||||
return entry.value;
|
return entry.value;
|
||||||
}
|
}
|
||||||
return 0xFF; // Not found
|
return 0xFF; // Not found
|
||||||
@@ -441,7 +441,7 @@ bool LD2410Component::handle_ack_data_() {
|
|||||||
ESP_LOGV(TAG, "Baud rate change");
|
ESP_LOGV(TAG, "Baud rate change");
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->baud_rate_select_ != nullptr) {
|
if (this->baud_rate_select_ != nullptr) {
|
||||||
ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->state.c_str());
|
ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -626,14 +626,14 @@ void LD2410Component::set_bluetooth(bool enable) {
|
|||||||
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2410Component::set_distance_resolution(const std::string &state) {
|
void LD2410Component::set_distance_resolution(const char *state) {
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
const uint8_t cmd_value[2] = {find_uint8(DISTANCE_RESOLUTIONS_BY_STR, state), 0x00};
|
const uint8_t cmd_value[2] = {find_uint8(DISTANCE_RESOLUTIONS_BY_STR, state), 0x00};
|
||||||
this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, sizeof(cmd_value));
|
this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, sizeof(cmd_value));
|
||||||
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2410Component::set_baud_rate(const std::string &state) {
|
void LD2410Component::set_baud_rate(const char *state) {
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
||||||
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
||||||
@@ -759,10 +759,10 @@ void LD2410Component::set_light_out_control() {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) {
|
if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) {
|
||||||
this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->state);
|
this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option());
|
||||||
}
|
}
|
||||||
if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->has_state()) {
|
if (this->out_pin_level_select_ != nullptr && this->out_pin_level_select_->has_state()) {
|
||||||
this->out_pin_level_ = find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->state);
|
this->out_pin_level_ = find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ class LD2410Component : public Component, public uart::UARTDevice {
|
|||||||
void read_all_info();
|
void read_all_info();
|
||||||
void restart_and_read_all_info();
|
void restart_and_read_all_info();
|
||||||
void set_bluetooth(bool enable);
|
void set_bluetooth(bool enable);
|
||||||
void set_distance_resolution(const std::string &state);
|
void set_distance_resolution(const char *state);
|
||||||
void set_baud_rate(const std::string &state);
|
void set_baud_rate(const char *state);
|
||||||
void factory_reset();
|
void factory_reset();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2410 {
|
namespace ld2410 {
|
||||||
|
|
||||||
void BaudRateSelect::control(const std::string &value) {
|
void BaudRateSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_baud_rate(state);
|
this->parent_->set_baud_rate(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2410
|
} // namespace ld2410
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class BaudRateSelect : public select::Select, public Parented<LD2410Component> {
|
|||||||
BaudRateSelect() = default;
|
BaudRateSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2410
|
} // namespace ld2410
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2410 {
|
namespace ld2410 {
|
||||||
|
|
||||||
void DistanceResolutionSelect::control(const std::string &value) {
|
void DistanceResolutionSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_distance_resolution(state);
|
this->parent_->set_distance_resolution(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2410
|
} // namespace ld2410
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class DistanceResolutionSelect : public select::Select, public Parented<LD2410Co
|
|||||||
DistanceResolutionSelect() = default;
|
DistanceResolutionSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2410
|
} // namespace ld2410
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2410 {
|
namespace ld2410 {
|
||||||
|
|
||||||
void LightOutControlSelect::control(const std::string &value) {
|
void LightOutControlSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_light_out_control();
|
this->parent_->set_light_out_control();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class LightOutControlSelect : public select::Select, public Parented<LD2410Compo
|
|||||||
LightOutControlSelect() = default;
|
LightOutControlSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2410
|
} // namespace ld2410
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ constexpr Uint8ToString OUT_PIN_LEVELS_BY_UINT[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Helper functions for lookups
|
// Helper functions for lookups
|
||||||
template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const std::string &str) {
|
template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const char *str) {
|
||||||
for (const auto &entry : arr) {
|
for (const auto &entry : arr) {
|
||||||
if (str == entry.str) {
|
if (strcmp(str, entry.str) == 0) {
|
||||||
return entry.value;
|
return entry.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,7 +485,7 @@ bool LD2412Component::handle_ack_data_() {
|
|||||||
ESP_LOGV(TAG, "Baud rate change");
|
ESP_LOGV(TAG, "Baud rate change");
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->baud_rate_select_ != nullptr) {
|
if (this->baud_rate_select_ != nullptr) {
|
||||||
ESP_LOGW(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->state.c_str());
|
ESP_LOGW(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -699,14 +699,14 @@ void LD2412Component::set_bluetooth(bool enable) {
|
|||||||
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2412Component::set_distance_resolution(const std::string &state) {
|
void LD2412Component::set_distance_resolution(const char *state) {
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
const uint8_t cmd_value[6] = {find_uint8(DISTANCE_RESOLUTIONS_BY_STR, state), 0x00, 0x00, 0x00, 0x00, 0x00};
|
const uint8_t cmd_value[6] = {find_uint8(DISTANCE_RESOLUTIONS_BY_STR, state), 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, sizeof(cmd_value));
|
this->send_command_(CMD_SET_DISTANCE_RESOLUTION, cmd_value, sizeof(cmd_value));
|
||||||
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
this->set_timeout(200, [this]() { this->restart_and_read_all_info(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2412Component::set_baud_rate(const std::string &state) {
|
void LD2412Component::set_baud_rate(const char *state) {
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
||||||
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
||||||
@@ -783,7 +783,7 @@ void LD2412Component::set_basic_config() {
|
|||||||
1, TOTAL_GATES, DEFAULT_PRESENCE_TIMEOUT, 0,
|
1, TOTAL_GATES, DEFAULT_PRESENCE_TIMEOUT, 0,
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->state),
|
find_uint8(OUT_PIN_LEVELS_BY_STR, this->out_pin_level_select_->current_option()),
|
||||||
#else
|
#else
|
||||||
0x01, // Default value if not using select
|
0x01, // Default value if not using select
|
||||||
#endif
|
#endif
|
||||||
@@ -837,7 +837,7 @@ void LD2412Component::set_light_out_control() {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) {
|
if (this->light_function_select_ != nullptr && this->light_function_select_->has_state()) {
|
||||||
this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->state);
|
this->light_function_ = find_uint8(LIGHT_FUNCTIONS_BY_STR, this->light_function_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint8_t value[2] = {this->light_function_, this->light_threshold_};
|
uint8_t value[2] = {this->light_function_, this->light_threshold_};
|
||||||
|
|||||||
@@ -99,8 +99,8 @@ class LD2412Component : public Component, public uart::UARTDevice {
|
|||||||
void read_all_info();
|
void read_all_info();
|
||||||
void restart_and_read_all_info();
|
void restart_and_read_all_info();
|
||||||
void set_bluetooth(bool enable);
|
void set_bluetooth(bool enable);
|
||||||
void set_distance_resolution(const std::string &state);
|
void set_distance_resolution(const char *state);
|
||||||
void set_baud_rate(const std::string &state);
|
void set_baud_rate(const char *state);
|
||||||
void factory_reset();
|
void factory_reset();
|
||||||
void start_dynamic_background_correction();
|
void start_dynamic_background_correction();
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2412 {
|
namespace ld2412 {
|
||||||
|
|
||||||
void BaudRateSelect::control(const std::string &value) {
|
void BaudRateSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_baud_rate(state);
|
this->parent_->set_baud_rate(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2412
|
} // namespace ld2412
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class BaudRateSelect : public select::Select, public Parented<LD2412Component> {
|
|||||||
BaudRateSelect() = default;
|
BaudRateSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2412
|
} // namespace ld2412
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2412 {
|
namespace ld2412 {
|
||||||
|
|
||||||
void DistanceResolutionSelect::control(const std::string &value) {
|
void DistanceResolutionSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_distance_resolution(state);
|
this->parent_->set_distance_resolution(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2412
|
} // namespace ld2412
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class DistanceResolutionSelect : public select::Select, public Parented<LD2412Co
|
|||||||
DistanceResolutionSelect() = default;
|
DistanceResolutionSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2412
|
} // namespace ld2412
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2412 {
|
namespace ld2412 {
|
||||||
|
|
||||||
void LightOutControlSelect::control(const std::string &value) {
|
void LightOutControlSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_light_out_control();
|
this->parent_->set_light_out_control();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class LightOutControlSelect : public select::Select, public Parented<LD2412Compo
|
|||||||
LightOutControlSelect() = default;
|
LightOutControlSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2412
|
} // namespace ld2412
|
||||||
|
|||||||
@@ -379,7 +379,7 @@ void LD2420Component::report_gate_data() {
|
|||||||
ESP_LOGI(TAG, "Total samples: %d", this->total_sample_number_counter);
|
ESP_LOGI(TAG, "Total samples: %d", this->total_sample_number_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::set_operating_mode(const std::string &state) {
|
void LD2420Component::set_operating_mode(const char *state) {
|
||||||
// If unsupported firmware ignore mode select
|
// If unsupported firmware ignore mode select
|
||||||
if (ld2420::get_firmware_int(firmware_ver_) >= CALIBRATE_VERSION_MIN) {
|
if (ld2420::get_firmware_int(firmware_ver_) >= CALIBRATE_VERSION_MIN) {
|
||||||
this->current_operating_mode = find_uint8(OP_MODE_BY_STR, state);
|
this->current_operating_mode = find_uint8(OP_MODE_BY_STR, state);
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class LD2420Component : public Component, public uart::UARTDevice {
|
|||||||
int send_cmd_from_array(CmdFrameT cmd_frame);
|
int send_cmd_from_array(CmdFrameT cmd_frame);
|
||||||
void report_gate_data();
|
void report_gate_data();
|
||||||
void handle_cmd_error(uint8_t error);
|
void handle_cmd_error(uint8_t error);
|
||||||
void set_operating_mode(const std::string &state);
|
void set_operating_mode(const char *state);
|
||||||
void auto_calibrate_sensitivity();
|
void auto_calibrate_sensitivity();
|
||||||
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
|
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
|
||||||
uint8_t set_config_mode(bool enable);
|
uint8_t set_config_mode(bool enable);
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ namespace ld2420 {
|
|||||||
|
|
||||||
static const char *const TAG = "ld2420.select";
|
static const char *const TAG = "ld2420.select";
|
||||||
|
|
||||||
void LD2420Select::control(const std::string &value) {
|
void LD2420Select::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_operating_mode(value);
|
this->parent_->set_operating_mode(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2420
|
} // namespace ld2420
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class LD2420Select : public Component, public select::Select, public Parented<LD
|
|||||||
LD2420Select() = default;
|
LD2420Select() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2420
|
} // namespace ld2420
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ void LD2450Component::read_all_info() {
|
|||||||
this->set_config_mode_(false);
|
this->set_config_mode_(false);
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
const auto baud_rate = std::to_string(this->parent_->get_baud_rate());
|
const auto baud_rate = std::to_string(this->parent_->get_baud_rate());
|
||||||
if (this->baud_rate_select_ != nullptr && this->baud_rate_select_->state != baud_rate) {
|
if (this->baud_rate_select_ != nullptr && strcmp(this->baud_rate_select_->current_option(), baud_rate.c_str()) != 0) {
|
||||||
this->baud_rate_select_->publish_state(baud_rate);
|
this->baud_rate_select_->publish_state(baud_rate);
|
||||||
}
|
}
|
||||||
this->publish_zone_type();
|
this->publish_zone_type();
|
||||||
@@ -635,7 +635,7 @@ bool LD2450Component::handle_ack_data_() {
|
|||||||
ESP_LOGV(TAG, "Baud rate change");
|
ESP_LOGV(TAG, "Baud rate change");
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->baud_rate_select_ != nullptr) {
|
if (this->baud_rate_select_ != nullptr) {
|
||||||
ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->state.c_str());
|
ESP_LOGE(TAG, "Change baud rate to %s and reinstall", this->baud_rate_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@@ -716,7 +716,7 @@ bool LD2450Component::handle_ack_data_() {
|
|||||||
this->publish_zone_type();
|
this->publish_zone_type();
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->zone_type_select_ != nullptr) {
|
if (this->zone_type_select_ != nullptr) {
|
||||||
ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->state.c_str());
|
ESP_LOGV(TAG, "Change zone type to: %s", this->zone_type_select_->current_option());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (this->buffer_data_[10] == 0x00) {
|
if (this->buffer_data_[10] == 0x00) {
|
||||||
@@ -790,7 +790,7 @@ void LD2450Component::set_bluetooth(bool enable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set Baud rate
|
// Set Baud rate
|
||||||
void LD2450Component::set_baud_rate(const std::string &state) {
|
void LD2450Component::set_baud_rate(const char *state) {
|
||||||
this->set_config_mode_(true);
|
this->set_config_mode_(true);
|
||||||
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
const uint8_t cmd_value[2] = {find_uint8(BAUD_RATES_BY_STR, state), 0x00};
|
||||||
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
this->send_command_(CMD_SET_BAUD_RATE, cmd_value, sizeof(cmd_value));
|
||||||
@@ -798,8 +798,8 @@ void LD2450Component::set_baud_rate(const std::string &state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set Zone Type - one of: Disabled, Detection, Filter
|
// Set Zone Type - one of: Disabled, Detection, Filter
|
||||||
void LD2450Component::set_zone_type(const std::string &state) {
|
void LD2450Component::set_zone_type(const char *state) {
|
||||||
ESP_LOGV(TAG, "Set zone type: %s", state.c_str());
|
ESP_LOGV(TAG, "Set zone type: %s", state);
|
||||||
uint8_t zone_type = find_uint8(ZONE_TYPE_BY_STR, state);
|
uint8_t zone_type = find_uint8(ZONE_TYPE_BY_STR, state);
|
||||||
this->zone_type_ = zone_type;
|
this->zone_type_ = zone_type;
|
||||||
this->send_set_zone_command_();
|
this->send_set_zone_command_();
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ class LD2450Component : public Component, public uart::UARTDevice {
|
|||||||
void restart_and_read_all_info();
|
void restart_and_read_all_info();
|
||||||
void set_bluetooth(bool enable);
|
void set_bluetooth(bool enable);
|
||||||
void set_multi_target(bool enable);
|
void set_multi_target(bool enable);
|
||||||
void set_baud_rate(const std::string &state);
|
void set_baud_rate(const char *state);
|
||||||
void set_zone_type(const std::string &state);
|
void set_zone_type(const char *state);
|
||||||
void publish_zone_type();
|
void publish_zone_type();
|
||||||
void factory_reset();
|
void factory_reset();
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2450 {
|
namespace ld2450 {
|
||||||
|
|
||||||
void BaudRateSelect::control(const std::string &value) {
|
void BaudRateSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_baud_rate(state);
|
this->parent_->set_baud_rate(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2450
|
} // namespace ld2450
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class BaudRateSelect : public select::Select, public Parented<LD2450Component> {
|
|||||||
BaudRateSelect() = default;
|
BaudRateSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2450
|
} // namespace ld2450
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace ld2450 {
|
namespace ld2450 {
|
||||||
|
|
||||||
void ZoneTypeSelect::control(const std::string &value) {
|
void ZoneTypeSelect::control(size_t index) {
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
this->parent_->set_zone_type(state);
|
this->parent_->set_zone_type(this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ld2450
|
} // namespace ld2450
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class ZoneTypeSelect : public select::Select, public Parented<LD2450Component> {
|
|||||||
ZoneTypeSelect() = default;
|
ZoneTypeSelect() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ld2450
|
} // namespace ld2450
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
namespace esphome::logger {
|
namespace esphome::logger {
|
||||||
|
|
||||||
void LoggerLevelSelect::publish_state(int level) {
|
void LoggerLevelSelect::publish_state(int level) {
|
||||||
const auto &option = this->at(level_to_index(level));
|
auto index = level_to_index(level);
|
||||||
if (!option)
|
if (!this->has_index(index))
|
||||||
return;
|
return;
|
||||||
Select::publish_state(option.value());
|
Select::publish_state(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerLevelSelect::setup() {
|
void LoggerLevelSelect::setup() {
|
||||||
@@ -14,11 +14,6 @@ void LoggerLevelSelect::setup() {
|
|||||||
this->publish_state(this->parent_->get_log_level());
|
this->publish_state(this->parent_->get_log_level());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerLevelSelect::control(const std::string &value) {
|
void LoggerLevelSelect::control(size_t index) { this->parent_->set_log_level(index_to_level(index)); }
|
||||||
const auto index = this->index_of(value);
|
|
||||||
if (!index)
|
|
||||||
return;
|
|
||||||
this->parent_->set_log_level(index_to_level(index.value()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace esphome::logger
|
} // namespace esphome::logger
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class LoggerLevelSelect : public Component, public select::Select, public Parent
|
|||||||
public:
|
public:
|
||||||
void publish_state(int level);
|
void publish_state(int level);
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Convert log level to option index (skip CONFIG at level 4)
|
// Convert log level to option index (skip CONFIG at level 4)
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ void MQTTSelectComponent::setup() {
|
|||||||
call.set_option(state);
|
call.set_option(state);
|
||||||
call.perform();
|
call.perform();
|
||||||
});
|
});
|
||||||
this->select_->add_on_state_callback([this](const std::string &state, size_t index) { this->publish_state(state); });
|
this->select_->add_on_state_callback(
|
||||||
|
[this](const std::string &state, size_t index) { this->publish_state(this->select_->option_at(index)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MQTTSelectComponent::dump_config() {
|
void MQTTSelectComponent::dump_config() {
|
||||||
@@ -44,7 +45,7 @@ void MQTTSelectComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCon
|
|||||||
}
|
}
|
||||||
bool MQTTSelectComponent::send_initial_state() {
|
bool MQTTSelectComponent::send_initial_state() {
|
||||||
if (this->select_->has_state()) {
|
if (this->select_->has_state()) {
|
||||||
return this->publish_state(this->select_->state);
|
return this->publish_state(this->select_->current_option());
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -435,12 +435,12 @@ void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *da
|
|||||||
} else if ((this->existence_boundary_select_ != nullptr) &&
|
} else if ((this->existence_boundary_select_ != nullptr) &&
|
||||||
((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) {
|
((data[FRAME_COMMAND_WORD_INDEX] == 0x0a) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8a))) {
|
||||||
if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
|
if (this->existence_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
|
||||||
this->existence_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]);
|
this->existence_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1);
|
||||||
}
|
}
|
||||||
} else if ((this->motion_boundary_select_ != nullptr) &&
|
} else if ((this->motion_boundary_select_ != nullptr) &&
|
||||||
((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) {
|
((data[FRAME_COMMAND_WORD_INDEX] == 0x0b) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8b))) {
|
||||||
if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
|
if (this->motion_boundary_select_->has_index(data[FRAME_DATA_INDEX] - 1)) {
|
||||||
this->motion_boundary_select_->publish_state(S_BOUNDARY_STR[data[FRAME_DATA_INDEX] - 1]);
|
this->motion_boundary_select_->publish_state(data[FRAME_DATA_INDEX] - 1);
|
||||||
}
|
}
|
||||||
} else if ((this->motion_trigger_number_ != nullptr) &&
|
} else if ((this->motion_trigger_number_ != nullptr) &&
|
||||||
((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) {
|
((data[FRAME_COMMAND_WORD_INDEX] == 0x0c) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8c))) {
|
||||||
@@ -515,7 +515,7 @@ void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) {
|
|||||||
ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
|
ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
|
||||||
} else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) {
|
} else if (data[FRAME_COMMAND_WORD_INDEX] == 0x07) {
|
||||||
if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
|
if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
|
||||||
this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]);
|
this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
|
ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
|
||||||
}
|
}
|
||||||
@@ -538,7 +538,7 @@ void MR24HPC1Component::r24_frame_parse_work_status_(uint8_t *data) {
|
|||||||
ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
|
ESP_LOGD(TAG, "Reply: get radar init status 0x%02X", data[FRAME_DATA_INDEX]);
|
||||||
} else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) {
|
} else if (data[FRAME_COMMAND_WORD_INDEX] == 0x87) {
|
||||||
if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
|
if ((this->scene_mode_select_ != nullptr) && (this->scene_mode_select_->has_index(data[FRAME_DATA_INDEX]))) {
|
||||||
this->scene_mode_select_->publish_state(S_SCENE_STR[data[FRAME_DATA_INDEX]]);
|
this->scene_mode_select_->publish_state(data[FRAME_DATA_INDEX]);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
|
ESP_LOGD(TAG, "Select has index offset %d Error", data[FRAME_DATA_INDEX]);
|
||||||
}
|
}
|
||||||
@@ -581,7 +581,7 @@ void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
|
|||||||
((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) {
|
((data[FRAME_COMMAND_WORD_INDEX] == 0x0A) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8A))) {
|
||||||
// none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08
|
// none:0x00 1s:0x01 30s:0x02 1min:0x03 2min:0x04 5min:0x05 10min:0x06 30min:0x07 1hour:0x08
|
||||||
if (data[FRAME_DATA_INDEX] < 9) {
|
if (data[FRAME_DATA_INDEX] < 9) {
|
||||||
this->unman_time_select_->publish_state(S_UNMANNED_TIME_STR[data[FRAME_DATA_INDEX]]);
|
this->unman_time_select_->publish_state(data[FRAME_DATA_INDEX]);
|
||||||
}
|
}
|
||||||
} else if ((this->keep_away_text_sensor_ != nullptr) &&
|
} else if ((this->keep_away_text_sensor_ != nullptr) &&
|
||||||
((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) {
|
((data[FRAME_COMMAND_WORD_INDEX] == 0x0B) || (data[FRAME_COMMAND_WORD_INDEX] == 0x8B))) {
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ void MR60FDA2Component::process_frame_() {
|
|||||||
|
|
||||||
install_height_float = bit_cast<float>(current_install_height_int);
|
install_height_float = bit_cast<float>(current_install_height_int);
|
||||||
uint32_t select_index = find_nearest_index(install_height_float, INSTALL_HEIGHT, 7);
|
uint32_t select_index = find_nearest_index(install_height_float, INSTALL_HEIGHT, 7);
|
||||||
this->install_height_select_->publish_state(this->install_height_select_->at(select_index).value());
|
this->install_height_select_->publish_state(select_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->height_threshold_select_ != nullptr) {
|
if (this->height_threshold_select_ != nullptr) {
|
||||||
@@ -301,7 +301,7 @@ void MR60FDA2Component::process_frame_() {
|
|||||||
|
|
||||||
height_threshold_float = bit_cast<float>(current_height_threshold_int);
|
height_threshold_float = bit_cast<float>(current_height_threshold_int);
|
||||||
size_t select_index = find_nearest_index(height_threshold_float, HEIGHT_THRESHOLD, 7);
|
size_t select_index = find_nearest_index(height_threshold_float, HEIGHT_THRESHOLD, 7);
|
||||||
this->height_threshold_select_->publish_state(this->height_threshold_select_->at(select_index).value());
|
this->height_threshold_select_->publish_state(select_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->sensitivity_select_ != nullptr) {
|
if (this->sensitivity_select_ != nullptr) {
|
||||||
@@ -309,7 +309,7 @@ void MR60FDA2Component::process_frame_() {
|
|||||||
encode_uint32(current_data_buf_[11], current_data_buf_[10], current_data_buf_[9], current_data_buf_[8]);
|
encode_uint32(current_data_buf_[11], current_data_buf_[10], current_data_buf_[9], current_data_buf_[8]);
|
||||||
|
|
||||||
uint32_t select_index = find_nearest_index(current_sensitivity, SENSITIVITY, 3);
|
uint32_t select_index = find_nearest_index(current_sensitivity, SENSITIVITY, 3);
|
||||||
this->sensitivity_select_->publish_state(this->sensitivity_select_->at(select_index).value());
|
this->sensitivity_select_->publish_state(select_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Mounting height: %.2f, Height threshold: %.2f, Sensitivity: %" PRIu32, install_height_float,
|
ESP_LOGD(TAG, "Mounting height: %.2f, Height threshold: %.2f, Sensitivity: %" PRIu32, install_height_float,
|
||||||
|
|||||||
@@ -7,24 +7,39 @@ namespace select {
|
|||||||
|
|
||||||
static const char *const TAG = "select";
|
static const char *const TAG = "select";
|
||||||
|
|
||||||
void Select::publish_state(const std::string &state) {
|
void Select::publish_state(const std::string &state) { this->publish_state(state.c_str()); }
|
||||||
|
|
||||||
|
void Select::publish_state(const char *state) {
|
||||||
auto index = this->index_of(state);
|
auto index = this->index_of(state);
|
||||||
const auto *name = this->get_name().c_str();
|
|
||||||
if (index.has_value()) {
|
if (index.has_value()) {
|
||||||
this->set_has_state(true);
|
this->publish_state(index.value());
|
||||||
this->state = state;
|
|
||||||
ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", name, state.c_str(), index.value());
|
|
||||||
this->state_callback_.call(state, index.value());
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "'%s': invalid state for publish_state(): %s", name, state.c_str());
|
ESP_LOGE(TAG, "'%s': Invalid option %s", this->get_name().c_str(), state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Select::publish_state(size_t index) {
|
||||||
|
if (!this->has_index(index)) {
|
||||||
|
ESP_LOGE(TAG, "'%s': Invalid index %zu", this->get_name().c_str(), index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *option = this->option_at(index);
|
||||||
|
this->set_has_state(true);
|
||||||
|
this->active_index_ = index;
|
||||||
|
ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", this->get_name().c_str(), option, index);
|
||||||
|
// Callback signature requires std::string, create temporary for compatibility
|
||||||
|
this->state_callback_.call(std::string(option), index);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Select::current_option() const { return this->option_at(this->active_index_); }
|
||||||
|
|
||||||
void Select::add_on_state_callback(std::function<void(std::string, size_t)> &&callback) {
|
void Select::add_on_state_callback(std::function<void(std::string, size_t)> &&callback) {
|
||||||
this->state_callback_.add(std::move(callback));
|
this->state_callback_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Select::has_option(const std::string &option) const { return this->index_of(option).has_value(); }
|
bool Select::has_option(const std::string &option) const { return this->index_of(option.c_str()).has_value(); }
|
||||||
|
|
||||||
|
bool Select::has_option(const char *option) const { return this->index_of(option).has_value(); }
|
||||||
|
|
||||||
bool Select::has_index(size_t index) const { return index < this->size(); }
|
bool Select::has_index(size_t index) const { return index < this->size(); }
|
||||||
|
|
||||||
@@ -33,10 +48,12 @@ size_t Select::size() const {
|
|||||||
return options.size();
|
return options.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<size_t> Select::index_of(const std::string &option) const {
|
optional<size_t> Select::index_of(const std::string &option) const { return this->index_of(option.c_str()); }
|
||||||
|
|
||||||
|
optional<size_t> Select::index_of(const char *option) const {
|
||||||
const auto &options = traits.get_options();
|
const auto &options = traits.get_options();
|
||||||
for (size_t i = 0; i < options.size(); i++) {
|
for (size_t i = 0; i < options.size(); i++) {
|
||||||
if (strcmp(options[i], option.c_str()) == 0) {
|
if (strcmp(options[i], option) == 0) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,19 +62,17 @@ optional<size_t> Select::index_of(const std::string &option) const {
|
|||||||
|
|
||||||
optional<size_t> Select::active_index() const {
|
optional<size_t> Select::active_index() const {
|
||||||
if (this->has_state()) {
|
if (this->has_state()) {
|
||||||
return this->index_of(this->state);
|
return this->active_index_;
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<std::string> Select::at(size_t index) const {
|
optional<std::string> Select::at(size_t index) const {
|
||||||
if (this->has_index(index)) {
|
if (this->has_index(index)) {
|
||||||
const auto &options = traits.get_options();
|
const auto &options = traits.get_options();
|
||||||
return std::string(options.at(index));
|
return std::string(options.at(index));
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Select::option_at(size_t index) const { return traits.get_options().at(index); }
|
const char *Select::option_at(size_t index) const { return traits.get_options().at(index); }
|
||||||
|
|||||||
@@ -30,16 +30,21 @@ namespace select {
|
|||||||
*/
|
*/
|
||||||
class Select : public EntityBase {
|
class Select : public EntityBase {
|
||||||
public:
|
public:
|
||||||
std::string state;
|
|
||||||
SelectTraits traits;
|
SelectTraits traits;
|
||||||
|
|
||||||
void publish_state(const std::string &state);
|
void publish_state(const std::string &state);
|
||||||
|
void publish_state(const char *state);
|
||||||
|
void publish_state(size_t index);
|
||||||
|
|
||||||
|
/// Return the currently selected option (as const char* from flash).
|
||||||
|
const char *current_option() const;
|
||||||
|
|
||||||
/// Instantiate a SelectCall object to modify this select component's state.
|
/// Instantiate a SelectCall object to modify this select component's state.
|
||||||
SelectCall make_call() { return SelectCall(this); }
|
SelectCall make_call() { return SelectCall(this); }
|
||||||
|
|
||||||
/// Return whether this select component contains the provided option.
|
/// Return whether this select component contains the provided option.
|
||||||
bool has_option(const std::string &option) const;
|
bool has_option(const std::string &option) const;
|
||||||
|
bool has_option(const char *option) const;
|
||||||
|
|
||||||
/// Return whether this select component contains the provided index offset.
|
/// Return whether this select component contains the provided index offset.
|
||||||
bool has_index(size_t index) const;
|
bool has_index(size_t index) const;
|
||||||
@@ -49,6 +54,7 @@ class Select : public EntityBase {
|
|||||||
|
|
||||||
/// Find the (optional) index offset of the provided option value.
|
/// Find the (optional) index offset of the provided option value.
|
||||||
optional<size_t> index_of(const std::string &option) const;
|
optional<size_t> index_of(const std::string &option) const;
|
||||||
|
optional<size_t> index_of(const char *option) const;
|
||||||
|
|
||||||
/// Return the (optional) index offset of the currently active option.
|
/// Return the (optional) index offset of the currently active option.
|
||||||
optional<size_t> active_index() const;
|
optional<size_t> active_index() const;
|
||||||
@@ -61,12 +67,30 @@ class Select : public EntityBase {
|
|||||||
|
|
||||||
void add_on_state_callback(std::function<void(std::string, size_t)> &&callback);
|
void add_on_state_callback(std::function<void(std::string, size_t)> &&callback);
|
||||||
|
|
||||||
|
/** Set the value of the select by index, this is an optional virtual method.
|
||||||
|
*
|
||||||
|
* This method is called by the SelectCall when the index is already known.
|
||||||
|
* Default implementation converts to string and calls control().
|
||||||
|
* Override this to work directly with indices and avoid string conversions.
|
||||||
|
*
|
||||||
|
* @param index The index as validated by the SelectCall.
|
||||||
|
*/
|
||||||
|
virtual void control(size_t index) { this->control(this->option_at(index)); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class SelectCall;
|
friend class SelectCall;
|
||||||
|
|
||||||
|
size_t active_index_{0};
|
||||||
|
|
||||||
/** Set the value of the select, this is a virtual method that each select integration must implement.
|
/** Set the value of the select, this is a virtual method that each select integration must implement.
|
||||||
*
|
*
|
||||||
* This method is called by the SelectCall.
|
* This method is called by control(size_t) when not overridden, or directly by external code.
|
||||||
|
* All existing integrations implement this method. New integrations can optionally override
|
||||||
|
* control(size_t) instead to work with indices directly and avoid string conversions.
|
||||||
|
*
|
||||||
|
* Delegation chain:
|
||||||
|
* - SelectCall::perform() → control(size_t) → [if not overridden] → control(string)
|
||||||
|
* - External code → control(string) → publish_state(string) → publish_state(size_t)
|
||||||
*
|
*
|
||||||
* @param value The value as validated by the SelectCall.
|
* @param value The value as validated by the SelectCall.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ SelectCall &SelectCall::set_option(const std::string &option) {
|
|||||||
return with_operation(SELECT_OP_SET).with_option(option);
|
return with_operation(SELECT_OP_SET).with_option(option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectCall &SelectCall::set_option(const char *option) { return with_operation(SELECT_OP_SET).with_option(option); }
|
||||||
|
|
||||||
SelectCall &SelectCall::set_index(size_t index) { return with_operation(SELECT_OP_SET_INDEX).with_index(index); }
|
SelectCall &SelectCall::set_index(size_t index) { return with_operation(SELECT_OP_SET_INDEX).with_index(index); }
|
||||||
|
|
||||||
SelectCall &SelectCall::select_next(bool cycle) { return with_operation(SELECT_OP_NEXT).with_cycle(cycle); }
|
SelectCall &SelectCall::select_next(bool cycle) { return with_operation(SELECT_OP_NEXT).with_cycle(cycle); }
|
||||||
@@ -31,8 +33,11 @@ SelectCall &SelectCall::with_cycle(bool cycle) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectCall &SelectCall::with_option(const std::string &option) {
|
SelectCall &SelectCall::with_option(const std::string &option) { return this->with_option(option.c_str()); }
|
||||||
this->option_ = option;
|
|
||||||
|
SelectCall &SelectCall::with_option(const char *option) {
|
||||||
|
// Find the option index - this validates the option exists
|
||||||
|
this->index_ = this->parent_->index_of(option);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,64 +61,52 @@ void SelectCall::perform() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string target_value;
|
size_t target_index;
|
||||||
|
|
||||||
if (this->operation_ == SELECT_OP_SET) {
|
if (this->operation_ == SELECT_OP_SET || this->operation_ == SELECT_OP_SET_INDEX) {
|
||||||
ESP_LOGD(TAG, "'%s' - Setting", name);
|
if (this->operation_ == SELECT_OP_SET) {
|
||||||
if (!this->option_.has_value()) {
|
ESP_LOGD(TAG, "'%s' - Setting", name);
|
||||||
ESP_LOGW(TAG, "'%s' - No option value set for SelectCall", name);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
target_value = this->option_.value();
|
|
||||||
} else if (this->operation_ == SELECT_OP_SET_INDEX) {
|
|
||||||
if (!this->index_.has_value()) {
|
if (!this->index_.has_value()) {
|
||||||
ESP_LOGW(TAG, "'%s' - No index value set for SelectCall", name);
|
ESP_LOGW(TAG, "'%s' - No option value set for SelectCall", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->index_.value() >= options.size()) {
|
if (this->index_.value() >= options.size()) {
|
||||||
ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", name, this->index_.value());
|
ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", name, this->index_.value());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
target_value = options[this->index_.value()];
|
target_index = this->index_.value();
|
||||||
} else if (this->operation_ == SELECT_OP_FIRST) {
|
} else if (this->operation_ == SELECT_OP_FIRST) {
|
||||||
target_value = options.front();
|
target_index = 0;
|
||||||
} else if (this->operation_ == SELECT_OP_LAST) {
|
} else if (this->operation_ == SELECT_OP_LAST) {
|
||||||
target_value = options.back();
|
target_index = options.size() - 1;
|
||||||
} else if (this->operation_ == SELECT_OP_NEXT || this->operation_ == SELECT_OP_PREVIOUS) {
|
} else if (this->operation_ == SELECT_OP_NEXT || this->operation_ == SELECT_OP_PREVIOUS) {
|
||||||
auto cycle = this->cycle_;
|
auto cycle = this->cycle_;
|
||||||
ESP_LOGD(TAG, "'%s' - Selecting %s, with%s cycling", name, this->operation_ == SELECT_OP_NEXT ? "next" : "previous",
|
ESP_LOGD(TAG, "'%s' - Selecting %s, with%s cycling", name, this->operation_ == SELECT_OP_NEXT ? "next" : "previous",
|
||||||
cycle ? "" : "out");
|
cycle ? "" : "out");
|
||||||
if (!parent->has_state()) {
|
if (!parent->has_state()) {
|
||||||
target_value = this->operation_ == SELECT_OP_NEXT ? options.front() : options.back();
|
target_index = this->operation_ == SELECT_OP_NEXT ? 0 : options.size() - 1;
|
||||||
} else {
|
} else {
|
||||||
auto index = parent->index_of(parent->state);
|
// Use cached active_index_ instead of index_of() lookup
|
||||||
if (index.has_value()) {
|
auto index = parent->active_index_;
|
||||||
auto size = options.size();
|
auto size = options.size();
|
||||||
if (cycle) {
|
if (cycle) {
|
||||||
auto use_index = (size + index.value() + (this->operation_ == SELECT_OP_NEXT ? +1 : -1)) % size;
|
target_index = (size + index + (this->operation_ == SELECT_OP_NEXT ? +1 : -1)) % size;
|
||||||
target_value = options[use_index];
|
|
||||||
} else {
|
|
||||||
if (this->operation_ == SELECT_OP_PREVIOUS && index.value() > 0) {
|
|
||||||
target_value = options[index.value() - 1];
|
|
||||||
} else if (this->operation_ == SELECT_OP_NEXT && index.value() < options.size() - 1) {
|
|
||||||
target_value = options[index.value() + 1];
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
target_value = this->operation_ == SELECT_OP_NEXT ? options.front() : options.back();
|
if (this->operation_ == SELECT_OP_PREVIOUS && index > 0) {
|
||||||
|
target_index = index - 1;
|
||||||
|
} else if (this->operation_ == SELECT_OP_NEXT && index < options.size() - 1) {
|
||||||
|
target_index = index + 1;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parent->has_option(target_value)) {
|
// All operations use indices, call control() by index to avoid string conversion
|
||||||
ESP_LOGW(TAG, "'%s' - Option %s is not a valid option", name, target_value.c_str());
|
ESP_LOGD(TAG, "'%s' - Set selected option to: %s", name, options[target_index]);
|
||||||
return;
|
parent->control(target_index);
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGD(TAG, "'%s' - Set selected option to: %s", name, target_value.c_str());
|
|
||||||
parent->control(target_value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace select
|
} // namespace select
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class SelectCall {
|
|||||||
void perform();
|
void perform();
|
||||||
|
|
||||||
SelectCall &set_option(const std::string &option);
|
SelectCall &set_option(const std::string &option);
|
||||||
|
SelectCall &set_option(const char *option);
|
||||||
SelectCall &set_index(size_t index);
|
SelectCall &set_index(size_t index);
|
||||||
|
|
||||||
SelectCall &select_next(bool cycle);
|
SelectCall &select_next(bool cycle);
|
||||||
@@ -33,11 +34,11 @@ class SelectCall {
|
|||||||
SelectCall &with_operation(SelectOperation operation);
|
SelectCall &with_operation(SelectOperation operation);
|
||||||
SelectCall &with_cycle(bool cycle);
|
SelectCall &with_cycle(bool cycle);
|
||||||
SelectCall &with_option(const std::string &option);
|
SelectCall &with_option(const std::string &option);
|
||||||
|
SelectCall &with_option(const char *option);
|
||||||
SelectCall &with_index(size_t index);
|
SelectCall &with_index(size_t index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Select *const parent_;
|
Select *const parent_;
|
||||||
optional<std::string> option_;
|
|
||||||
optional<size_t> index_;
|
optional<size_t> index_;
|
||||||
SelectOperation operation_{SELECT_OP_NONE};
|
SelectOperation operation_{SELECT_OP_NONE};
|
||||||
bool cycle_;
|
bool cycle_;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ void TemplateSelect::setup() {
|
|||||||
ESP_LOGD(TAG, "State from initial: %s", this->option_at(index));
|
ESP_LOGD(TAG, "State from initial: %s", this->option_at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
this->publish_state(this->at(index).value());
|
this->publish_state(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateSelect::update() {
|
void TemplateSelect::update() {
|
||||||
@@ -41,16 +41,14 @@ void TemplateSelect::update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateSelect::control(const std::string &value) {
|
void TemplateSelect::control(size_t index) {
|
||||||
this->set_trigger_->trigger(value);
|
this->set_trigger_->trigger(std::string(this->option_at(index)));
|
||||||
|
|
||||||
if (this->optimistic_)
|
if (this->optimistic_)
|
||||||
this->publish_state(value);
|
this->publish_state(index);
|
||||||
|
|
||||||
if (this->restore_value_) {
|
if (this->restore_value_)
|
||||||
auto index = this->index_of(value);
|
this->pref_.save(&index);
|
||||||
this->pref_.save(&index.value());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemplateSelect::dump_config() {
|
void TemplateSelect::dump_config() {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class TemplateSelect : public select::Select, public PollingComponent {
|
|||||||
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void control(const std::string &value) override;
|
void control(size_t index) override;
|
||||||
bool optimistic_ = false;
|
bool optimistic_ = false;
|
||||||
size_t initial_option_index_{0};
|
size_t initial_option_index_{0};
|
||||||
bool restore_value_ = false;
|
bool restore_value_ = false;
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ void TuyaSelect::setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t mapping_idx = std::distance(mappings.cbegin(), it);
|
size_t mapping_idx = std::distance(mappings.cbegin(), it);
|
||||||
auto value = this->at(mapping_idx);
|
this->publish_state(mapping_idx);
|
||||||
this->publish_state(value.value());
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1185,7 +1185,7 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
|
|||||||
|
|
||||||
if (request->method() == HTTP_GET && match.method_empty()) {
|
if (request->method() == HTTP_GET && match.method_empty()) {
|
||||||
auto detail = get_request_detail(request);
|
auto detail = get_request_detail(request);
|
||||||
std::string data = this->select_json(obj, obj->state, detail);
|
std::string data = this->select_json(obj, obj->has_state() ? obj->current_option() : "", detail);
|
||||||
request->send(200, "application/json", data.c_str());
|
request->send(200, "application/json", data.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1205,12 +1205,14 @@ void WebServer::handle_select_request(AsyncWebServerRequest *request, const UrlM
|
|||||||
request->send(404);
|
request->send(404);
|
||||||
}
|
}
|
||||||
std::string WebServer::select_state_json_generator(WebServer *web_server, void *source) {
|
std::string WebServer::select_state_json_generator(WebServer *web_server, void *source) {
|
||||||
return web_server->select_json((select::Select *) (source), ((select::Select *) (source))->state, DETAIL_STATE);
|
auto *obj = (select::Select *) (source);
|
||||||
|
return web_server->select_json(obj, obj->has_state() ? obj->current_option() : "", DETAIL_STATE);
|
||||||
}
|
}
|
||||||
std::string WebServer::select_all_json_generator(WebServer *web_server, void *source) {
|
std::string WebServer::select_all_json_generator(WebServer *web_server, void *source) {
|
||||||
return web_server->select_json((select::Select *) (source), ((select::Select *) (source))->state, DETAIL_ALL);
|
auto *obj = (select::Select *) (source);
|
||||||
|
return web_server->select_json(obj, obj->has_state() ? obj->current_option() : "", DETAIL_ALL);
|
||||||
}
|
}
|
||||||
std::string WebServer::select_json(select::Select *obj, const std::string &value, JsonDetail start_config) {
|
std::string WebServer::select_json(select::Select *obj, const char *value, JsonDetail start_config) {
|
||||||
json::JsonBuilder builder;
|
json::JsonBuilder builder;
|
||||||
JsonObject root = builder.root();
|
JsonObject root = builder.root();
|
||||||
|
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ class WebServer : public Controller, public Component, public AsyncWebHandler {
|
|||||||
static std::string select_state_json_generator(WebServer *web_server, void *source);
|
static std::string select_state_json_generator(WebServer *web_server, void *source);
|
||||||
static std::string select_all_json_generator(WebServer *web_server, void *source);
|
static std::string select_all_json_generator(WebServer *web_server, void *source);
|
||||||
/// Dump the select state with its value as a JSON string.
|
/// Dump the select state with its value as a JSON string.
|
||||||
std::string select_json(select::Select *obj, const std::string &value, JsonDetail start_config);
|
std::string select_json(select::Select *obj, const char *value, JsonDetail start_config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_CLIMATE
|
#ifdef USE_CLIMATE
|
||||||
|
|||||||
@@ -744,7 +744,7 @@ def test_choose_upload_log_host_ota_local_all_options() -> None:
|
|||||||
check_default=None,
|
check_default=None,
|
||||||
purpose=Purpose.UPLOADING,
|
purpose=Purpose.UPLOADING,
|
||||||
)
|
)
|
||||||
assert result == ["MQTTIP", "test.local"]
|
assert result == ["MQTTIP"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("mock_serial_ports")
|
@pytest.mark.usefixtures("mock_serial_ports")
|
||||||
@@ -794,7 +794,7 @@ def test_choose_upload_log_host_ota_local_all_options_logging() -> None:
|
|||||||
check_default=None,
|
check_default=None,
|
||||||
purpose=Purpose.LOGGING,
|
purpose=Purpose.LOGGING,
|
||||||
)
|
)
|
||||||
assert result == ["MQTTIP", "MQTT", "test.local"]
|
assert result == ["MQTTIP", "MQTT"]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("mock_no_mqtt_logging")
|
@pytest.mark.usefixtures("mock_no_mqtt_logging")
|
||||||
@@ -1564,7 +1564,7 @@ def test_has_resolvable_address() -> None:
|
|||||||
setup_core(
|
setup_core(
|
||||||
config={CONF_MDNS: {CONF_DISABLED: True}}, address="esphome-device.local"
|
config={CONF_MDNS: {CONF_DISABLED: True}}, address="esphome-device.local"
|
||||||
)
|
)
|
||||||
assert has_resolvable_address() is True
|
assert has_resolvable_address() is False
|
||||||
|
|
||||||
# Test with mDNS disabled and regular DNS hostname (resolvable)
|
# Test with mDNS disabled and regular DNS hostname (resolvable)
|
||||||
setup_core(config={CONF_MDNS: {CONF_DISABLED: True}}, address="device.example.com")
|
setup_core(config={CONF_MDNS: {CONF_DISABLED: True}}, address="device.example.com")
|
||||||
|
|||||||
Reference in New Issue
Block a user