mirror of
https://github.com/esphome/esphome.git
synced 2026-10-15 02:32:49 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f9d7406912 | ||
|
|
c9e3976446 | ||
|
|
4dccc1ea89 | ||
|
|
3a8a83d9fb | ||
|
|
eb6af50a89 | ||
|
|
fa070bf340 | ||
|
|
a31ce9bd9e | ||
|
|
26bede7a48 | ||
|
|
fd7fcbad0f | ||
|
|
5860a392bd | ||
|
|
04c2bf1286 | ||
|
|
55487971c3 | ||
|
|
82c535e0a7 | ||
|
|
de6991144e | ||
|
|
af1285f006 | ||
|
|
549761a574 | ||
|
|
2fa7775fe7 | ||
|
|
926f2561b4 | ||
|
|
c4544e6a22 | ||
|
|
f24dba9de8 | ||
|
|
82c3e0db96 | ||
|
|
e207138557 | ||
|
|
11af5a1e78 | ||
|
|
a04dca7823 | ||
|
|
edeaded161 | ||
|
|
09a3b1a3d1 | ||
|
|
10d232dc40 | ||
|
|
663f462877 |
@@ -183,7 +183,6 @@ esphome/components/es7243e/* @kbx81
|
||||
esphome/components/es8156/* @kbx81
|
||||
esphome/components/es8311/* @kahrendt @kroimon
|
||||
esphome/components/es8388/* @P4uLT
|
||||
esphome/components/es9038q2m_katana/* @GioMez
|
||||
esphome/components/esp32/* @esphome/core
|
||||
esphome/components/esp32_ble/* @bdraco @jesserockz @Rapsssito
|
||||
esphome/components/esp32_ble_client/* @bdraco @jesserockz
|
||||
|
||||
@@ -10,7 +10,7 @@ void AbsoluteHumidityComponent::setup() {
|
||||
this->temperature_ = state;
|
||||
this->enable_loop();
|
||||
});
|
||||
ESP_LOGD(TAG, " Added callback for temperature '%s'", LOG_STR_ARG(this->temperature_sensor_->get_log_name()));
|
||||
ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str());
|
||||
// Get initial value
|
||||
if (this->temperature_sensor_->has_state()) {
|
||||
this->temperature_ = this->temperature_sensor_->get_state();
|
||||
@@ -20,7 +20,7 @@ void AbsoluteHumidityComponent::setup() {
|
||||
this->humidity_ = state;
|
||||
this->enable_loop();
|
||||
});
|
||||
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str());
|
||||
// Get initial value
|
||||
if (this->humidity_sensor_->has_state()) {
|
||||
this->humidity_ = this->humidity_sensor_->get_state();
|
||||
@@ -49,8 +49,7 @@ void AbsoluteHumidityComponent::dump_config() {
|
||||
"Sources\n"
|
||||
" Temperature: '%s'\n"
|
||||
" Relative Humidity: '%s'",
|
||||
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
|
||||
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
|
||||
}
|
||||
|
||||
void AbsoluteHumidityComponent::loop() {
|
||||
|
||||
@@ -66,7 +66,7 @@ template class Aggregator<uint32_t>;
|
||||
|
||||
void ADCSensor::update() {
|
||||
float value_v = this->sample();
|
||||
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", LOG_STR_ARG(this->get_log_name()), value_v);
|
||||
ESP_LOGV(TAG, "'%s': Voltage=%.4fV", this->get_name().c_str(), value_v);
|
||||
this->publish_state(value_v);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ float ADS1115Sensor::sample() {
|
||||
void ADS1115Sensor::update() {
|
||||
float v = this->sample();
|
||||
if (!std::isnan(v)) {
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
|
||||
this->publish_state(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ float ADS1118Sensor::sample() {
|
||||
void ADS1118Sensor::update() {
|
||||
float v = this->sample();
|
||||
if (!std::isnan(v)) {
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", LOG_STR_ARG(this->get_log_name()), v);
|
||||
ESP_LOGD(TAG, "'%s': Got Voltage=%fV", this->get_name().c_str(), v);
|
||||
this->publish_state(v);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
|
||||
this->last_update_ = millis();
|
||||
if (state != this->current_state_) {
|
||||
auto prev_state = this->current_state_;
|
||||
ESP_LOGV(TAG, "'%s' >> %s (was %s)", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGV(TAG, "'%s' >> %s (was %s)", this->get_name().c_str(),
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(state)),
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
|
||||
this->current_state_ = state;
|
||||
|
||||
@@ -30,9 +30,9 @@ void Am43Component::loop() {
|
||||
auto status =
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
ESP_LOGI(TAG, "[%s] Logging into AM43", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
|
||||
} else {
|
||||
this->logged_in_ = true;
|
||||
}
|
||||
@@ -50,7 +50,7 @@ CoverTraits Am43Component::get_traits() {
|
||||
|
||||
void Am43Component::control(const CoverCall &call) {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot send cover control, not connected", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
if (call.get_stop()) {
|
||||
@@ -59,7 +59,7 @@ void Am43Component::control(const CoverCall &call) {
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
|
||||
}
|
||||
}
|
||||
auto opt_pos = call.get_position();
|
||||
@@ -73,8 +73,7 @@ void Am43Component::control(const CoverCall &call) {
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
|
||||
packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,9 +89,9 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
|
||||
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
|
||||
} else {
|
||||
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGE(TAG, "[%s] No control service found at device, not an AM43..?", this->get_name().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -101,8 +100,7 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
|
||||
chr->handle);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -128,26 +126,25 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
|
||||
if (this->decoder_->has_pin_response()) {
|
||||
if (this->decoder_->pin_ok_) {
|
||||
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
|
||||
auto *packet = this->encoder_->get_position_request();
|
||||
auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
|
||||
this->char_handle_, packet->length, packet->data,
|
||||
ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
|
||||
}
|
||||
|
||||
if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -67,9 +67,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
case ESP_GATTC_SEARCH_CMPL_EVT: {
|
||||
auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
|
||||
if (chr == nullptr) {
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
|
||||
ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
this->char_handle_ = chr->handle;
|
||||
@@ -77,8 +76,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
|
||||
auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
|
||||
chr->handle);
|
||||
if (status) {
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", LOG_STR_ARG(this->get_log_name()),
|
||||
status);
|
||||
ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -251,6 +251,9 @@ def _validate_supports_response(value: Any) -> str:
|
||||
return cv.enum(SUPPORTS_RESPONSE_OPTIONS, lower=True)(value)
|
||||
|
||||
|
||||
# ESP8266 copies every string of an action into a stack buffer sized by codegen; keep it small
|
||||
ESP8266_ACTION_STRINGS_MAX_TOTAL = 384
|
||||
|
||||
VARIABLE_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_TYPE): cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True),
|
||||
@@ -481,6 +484,29 @@ def _action_strings(conf: ConfigType, has_metadata: bool) -> list[str | None]:
|
||||
return strings
|
||||
|
||||
|
||||
def _action_strings_size(strings: list[str | None]) -> int:
|
||||
"""Bytes needed to copy every string out of flash, each with its terminator."""
|
||||
return sum(
|
||||
len(string.encode("utf-8")) + 1 for string in strings if string is not None
|
||||
)
|
||||
|
||||
|
||||
def _validate_esp8266_action_strings(config: ConfigType) -> ConfigType:
|
||||
if not CORE.is_esp8266:
|
||||
return config
|
||||
actions = config.get(CONF_ACTIONS, [])
|
||||
has_metadata = _has_action_metadata(actions)
|
||||
for conf in actions:
|
||||
size = _action_strings_size(_action_strings(conf, has_metadata))
|
||||
if size > ESP8266_ACTION_STRINGS_MAX_TOTAL:
|
||||
raise cv.Invalid(
|
||||
f"Action '{conf[CONF_ACTION]}' has {size} bytes of name, variable name, "
|
||||
f"description and example text; ESP8266 allows at most "
|
||||
f"{ESP8266_ACTION_STRINGS_MAX_TOTAL} bytes per action"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
def _validate_outgoing_host_ipv6(config: ConfigType) -> ConfigType:
|
||||
"""An IPv6 host can never be parsed, so never dialed, without IPv6."""
|
||||
if (
|
||||
@@ -505,6 +531,7 @@ def _validate_wizard(config: ConfigType) -> ConfigType:
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = cv.All(
|
||||
_validate_esp8266_action_strings,
|
||||
_validate_outgoing_host_ipv6,
|
||||
_validate_wizard,
|
||||
)
|
||||
@@ -560,6 +587,7 @@ async def to_code(config: ConfigType) -> None:
|
||||
if config[CONF_HOMEASSISTANT_STATES]:
|
||||
cg.add_define("USE_API_HOMEASSISTANT_STATES")
|
||||
|
||||
scratch_size = 0
|
||||
if actions:
|
||||
# Metadata is compiled in for every action once any action declares it, because the
|
||||
# string table layout is fixed by the define rather than per action
|
||||
@@ -611,6 +639,8 @@ async def to_code(config: ConfigType) -> None:
|
||||
func_args.append((native, name))
|
||||
strings = _action_strings(conf, has_metadata)
|
||||
table = _add_action_strings(index, strings)
|
||||
if CORE.is_esp8266:
|
||||
scratch_size = max(scratch_size, _action_strings_size(strings))
|
||||
# Template args: supports_response mode, then user service arg types
|
||||
templ = cg.TemplateArguments(supports_response, *service_template_args)
|
||||
# Key is hashed here because the name is not readable at runtime on ESP8266
|
||||
@@ -637,6 +667,9 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add(auto.add_action(unregister_action))
|
||||
# Register all services at once - single allocation, no reallocations
|
||||
cg.add(var.initialize_user_services(triggers))
|
||||
if CORE.is_esp8266 and has_user_actions:
|
||||
# Stack buffer that list-entities copies PROGMEM strings into, sized for the largest action
|
||||
cg.add_define("API_USER_ACTION_STRINGS_SCRATCH_SIZE", max(scratch_size, 1))
|
||||
|
||||
if (wizard_config := config.get(wizard.CONF_WIZARD)) is not None:
|
||||
await wizard.to_code(wizard_config)
|
||||
|
||||
@@ -403,9 +403,6 @@ message WizardCapabilities {
|
||||
message SendspinCapabilities {
|
||||
// Bitmask of the Sendspin features this device supports
|
||||
uint32 feature_flags = 1;
|
||||
// The Sendspin client_id: base64url of the client's static public key, 43 characters.
|
||||
// Empty until the Sendspin client has started once since boot.
|
||||
string client_id = 2 [(max_data_length) = 43];
|
||||
}
|
||||
|
||||
message DeviceCapabilitiesResponse {
|
||||
@@ -555,7 +552,7 @@ message ListEntitiesBinarySensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string device_class = 5 [(max_data_length) = 47];
|
||||
@@ -589,7 +586,7 @@ message ListEntitiesCoverResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool assumed_state = 5;
|
||||
@@ -673,7 +670,7 @@ message ListEntitiesFanResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_oscillation = 5;
|
||||
@@ -761,7 +758,7 @@ message ListEntitiesLightResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
repeated ColorMode supported_color_modes = 12 [(container_pointer_no_template) = "light::ColorModeMask"];
|
||||
@@ -866,7 +863,7 @@ message ListEntitiesSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -907,7 +904,7 @@ message ListEntitiesSwitchResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -952,7 +949,7 @@ message ListEntitiesTextSensorResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1029,8 +1026,8 @@ message SubscribeHomeassistantServicesRequest {
|
||||
}
|
||||
|
||||
message HomeassistantServiceMap {
|
||||
string key = 1 [(progmem) = true];
|
||||
string value = 2 [(progmem) = true];
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
message HomeassistantActionRequest {
|
||||
@@ -1039,7 +1036,7 @@ message HomeassistantActionRequest {
|
||||
option (no_delay) = true;
|
||||
option (ifdef) = "USE_API_HOMEASSISTANT_SERVICES";
|
||||
|
||||
string service = 1 [(progmem) = true];
|
||||
string service = 1;
|
||||
repeated HomeassistantServiceMap data = 2 [(fixed_vector) = true];
|
||||
repeated HomeassistantServiceMap data_template = 3 [(fixed_vector) = true];
|
||||
repeated HomeassistantServiceMap variables = 4 [(fixed_vector) = true];
|
||||
@@ -1160,21 +1157,21 @@ enum SupportsResponseType {
|
||||
}
|
||||
message ListEntitiesServicesArgument {
|
||||
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
|
||||
string name = 1 [(progmem) = true];
|
||||
string name = 1;
|
||||
ServiceArgType type = 2;
|
||||
string description = 3 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
|
||||
string example = 4 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
|
||||
string description = 3 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
|
||||
string example = 4 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
|
||||
}
|
||||
message ListEntitiesServicesResponse {
|
||||
option (id) = 41;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
|
||||
|
||||
string name = 1 [(progmem) = true];
|
||||
string name = 1;
|
||||
fixed32 key = 2 [(force) = true];
|
||||
repeated ListEntitiesServicesArgument args = 3 [(fixed_vector) = true];
|
||||
SupportsResponseType supports_response = 4;
|
||||
string description = 5 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA", (progmem) = true];
|
||||
string description = 5 [(field_ifdef) = "USE_API_USER_DEFINED_ACTION_METADATA"];
|
||||
}
|
||||
message ExecuteServiceArgument {
|
||||
option (ifdef) = "USE_API_USER_DEFINED_ACTIONS";
|
||||
@@ -1223,7 +1220,7 @@ message ListEntitiesCameraResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
bool disabled_by_default = 5;
|
||||
string icon = 6 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1315,7 +1312,7 @@ message ListEntitiesClimateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
bool supports_current_temperature = 5; // Deprecated: use feature_flags
|
||||
@@ -1430,7 +1427,7 @@ message ListEntitiesWaterHeaterResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -1510,7 +1507,7 @@ message ListEntitiesNumberResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1559,7 +1556,7 @@ message ListEntitiesSelectResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1603,7 +1600,7 @@ message ListEntitiesSirenResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1668,7 +1665,7 @@ message ListEntitiesLockResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1717,7 +1714,7 @@ message ListEntitiesButtonResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -1784,7 +1781,7 @@ message ListEntitiesMediaPlayerResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2376,7 +2373,7 @@ message ListEntitiesAlarmControlPanelResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2423,7 +2420,7 @@ message ListEntitiesTextResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 6;
|
||||
@@ -2471,7 +2468,7 @@ message ListEntitiesDateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2518,7 +2515,7 @@ message ListEntitiesTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2565,7 +2562,7 @@ message ListEntitiesEventResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2596,7 +2593,7 @@ message ListEntitiesValveResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2651,7 +2648,7 @@ message ListEntitiesDateTimeResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2694,7 +2691,7 @@ message ListEntitiesUpdateResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
reserved 4; // Deprecated: was string unique_id
|
||||
|
||||
string icon = 5 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
@@ -2794,7 +2791,7 @@ message ListEntitiesInfraredResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -2863,7 +2860,7 @@ message ListEntitiesRadioFrequencyResponse {
|
||||
|
||||
string object_id = 1 [(max_data_length) = 120, (force) = true];
|
||||
fixed32 key = 2 [(force) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true, (progmem) = true];
|
||||
string name = 3 [(max_data_length) = 120, (force) = true];
|
||||
string icon = 4 [(field_ifdef) = "USE_ENTITY_ICON", (max_data_length) = 63];
|
||||
bool disabled_by_default = 5;
|
||||
EntityCategory entity_category = 6;
|
||||
@@ -3046,15 +3043,12 @@ enum SerialProxyIdentityFlag {
|
||||
// IDs below are empty
|
||||
}
|
||||
|
||||
// The descriptor fields of a USB device as seen by the host stack, and the port's index
|
||||
// among those a vendor driver exposes on the interface
|
||||
// The descriptor fields of a USB device as seen by the host stack
|
||||
message UsbDeviceDescriptor {
|
||||
uint32 vendor_id = 1;
|
||||
uint32 product_id = 2;
|
||||
uint32 bcd_device = 3;
|
||||
uint32 interface_number = 4; // bInterfaceNumber the port is bound through
|
||||
uint32 interface_class = 5; // bInterfaceClass of that interface
|
||||
uint32 port_number = 6;
|
||||
uint32 interface_number = 4; // bInterfaceNumber the host driver binds to
|
||||
}
|
||||
|
||||
// The identity of the device behind a port. Identifies one physical device among others of
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
#include "api_connection.h"
|
||||
#if defined(USE_LOGGER) && defined(USE_CRASH_HANDLER)
|
||||
#include "esphome/components/logger/logger.h"
|
||||
#endif
|
||||
#ifdef USE_API
|
||||
#include "api_connection_buffer.h" // for the APIServer-dependent APIConnection inlines
|
||||
#ifdef USE_API_NOISE
|
||||
@@ -454,15 +451,6 @@ bool APIConnection::send_disconnect_response_() {
|
||||
DisconnectResponse resp;
|
||||
return this->send_message(resp);
|
||||
}
|
||||
void APIConnection::on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
|
||||
this->flags_.log_subscription = msg.level;
|
||||
if (msg.dump_config)
|
||||
App.schedule_dump_config();
|
||||
#if defined(USE_LOGGER) && defined(USE_CRASH_HANDLER)
|
||||
logger::log_crash_to_client();
|
||||
#endif
|
||||
}
|
||||
|
||||
void APIConnection::on_disconnect_response() {
|
||||
// Don't close socket here, let APIServer::loop() do it
|
||||
// so getpeername() still works for the disconnect trigger
|
||||
@@ -486,7 +474,7 @@ uint16_t APIConnection::fill_and_encode_entity_info(EntityBase *entity, InfoResp
|
||||
msg.key = entity->get_object_id_hash();
|
||||
|
||||
if (entity->has_own_name()) {
|
||||
msg.name = entity->get_name_progmem();
|
||||
msg.name = entity->get_name();
|
||||
}
|
||||
|
||||
// Set common EntityBase properties
|
||||
@@ -2131,7 +2119,6 @@ bool APIConnection::send_device_capabilities_response_() {
|
||||
#endif
|
||||
#if defined(USE_SENDSPIN) && defined(USE_ESP_IDF)
|
||||
resp.sendspin.feature_flags = sendspin_::global_sendspin_hub->get_feature_flags();
|
||||
resp.sendspin.client_id = sendspin_::global_sendspin_hub->get_client_id();
|
||||
#endif
|
||||
return this->send_message(resp);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
#include "subscribe_state.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/component.h"
|
||||
#ifdef USE_ESP32_CRASH_HANDLER
|
||||
#include "esphome/components/esp32/crash_handler.h"
|
||||
#endif
|
||||
#ifdef USE_RP2_CRASH_HANDLER
|
||||
#include "esphome/components/rp2/crash_handler.h"
|
||||
#endif
|
||||
#ifdef USE_ESP8266_CRASH_HANDLER
|
||||
#include "esphome/components/esp8266/crash_handler.h"
|
||||
#endif
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
@@ -289,7 +298,21 @@ class APIConnection final : public APIServerConnectionBase {
|
||||
this->begin_iterator_(ActiveIterator::INITIAL_STATE);
|
||||
}
|
||||
}
|
||||
void on_subscribe_logs_request(const SubscribeLogsRequest &msg);
|
||||
void on_subscribe_logs_request(const SubscribeLogsRequest &msg) {
|
||||
this->flags_.log_subscription = msg.level;
|
||||
if (msg.dump_config)
|
||||
App.schedule_dump_config();
|
||||
#ifdef USE_ESP32_CRASH_HANDLER
|
||||
esp32::crash_handler_log();
|
||||
esp32::crash_handler_clear();
|
||||
#endif
|
||||
#ifdef USE_RP2_CRASH_HANDLER
|
||||
rp2::crash_handler_log();
|
||||
#endif
|
||||
#ifdef USE_ESP8266_CRASH_HANDLER
|
||||
esp8266::crash_handler_log();
|
||||
#endif
|
||||
}
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
void on_subscribe_homeassistant_services_request() { this->flags_.service_call_subscription = true; }
|
||||
#endif
|
||||
|
||||
@@ -123,7 +123,7 @@ extend google.protobuf.FieldOptions {
|
||||
// from an absent one (e.g. a UTC ParsedTimezone, which is all zeros).
|
||||
optional bool track_presence = 50020 [default=false];
|
||||
|
||||
// progmem: The string field, or pointer_to_buffer bytes field, points into flash (PROGMEM).
|
||||
// progmem: The pointer_to_buffer bytes field points into flash (PROGMEM).
|
||||
// The generated encode and dump copy it with progmem_memcpy, as ESP8266
|
||||
// cannot read flash with ordinary loads.
|
||||
optional bool progmem = 50021 [default=false];
|
||||
|
||||
@@ -310,14 +310,12 @@ uint32_t WizardCapabilities::calc_size_msg(const void *self) {
|
||||
uint8_t *SendspinCapabilities::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.feature_flags);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.client_id);
|
||||
return pos;
|
||||
}
|
||||
uint32_t SendspinCapabilities::calc_size_msg(const void *self) {
|
||||
const auto &msg = *static_cast<const SendspinCapabilities *>(self);
|
||||
uint32_t size = 0;
|
||||
size += ProtoSize::calc_uint32(1, msg.feature_flags);
|
||||
size += !msg.client_id.empty() ? 2 + msg.client_id.size() : 0;
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
@@ -403,7 +401,7 @@ uint8_t *ListEntitiesBinarySensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesBinarySensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.device_class);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.is_status_binary_sensor);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.disabled_by_default);
|
||||
@@ -461,7 +459,7 @@ uint8_t *ListEntitiesCoverResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesCoverResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.assumed_state);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_position);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_tilt);
|
||||
@@ -560,7 +558,7 @@ uint8_t *ListEntitiesFanResponse::encode_msg(const void *self, uint8_t *__restri
|
||||
const auto &msg = *static_cast<const ListEntitiesFanResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_oscillation);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_speed);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, msg.supports_direction);
|
||||
@@ -680,7 +678,7 @@ uint8_t *ListEntitiesLightResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesLightResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
for (const auto &it : *msg.supported_color_modes) {
|
||||
pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast<uint32_t>(it));
|
||||
}
|
||||
@@ -886,7 +884,7 @@ uint8_t *ListEntitiesSensorResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -956,7 +954,7 @@ uint8_t *ListEntitiesSwitchResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSwitchResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1032,7 +1030,7 @@ uint8_t *ListEntitiesTextSensorResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesTextSensorResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -1142,8 +1140,8 @@ uint32_t NoiseEncryptionSetKeyResponse::calc_size_msg(const void *self) {
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
uint8_t *HomeassistantServiceMap::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const HomeassistantServiceMap *>(self);
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.key);
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.value);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.key);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.value);
|
||||
return pos;
|
||||
}
|
||||
uint32_t HomeassistantServiceMap::calc_size_msg(const void *self) {
|
||||
@@ -1155,7 +1153,7 @@ uint32_t HomeassistantServiceMap::calc_size_msg(const void *self) {
|
||||
}
|
||||
uint8_t *HomeassistantActionRequest::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const HomeassistantActionRequest *>(self);
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.service);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.service);
|
||||
for (auto &it : msg.data) {
|
||||
pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 2, it);
|
||||
}
|
||||
@@ -1326,13 +1324,13 @@ void GetTimeResponse::decode_field(void *self, uint32_t tag, const uint8_t *data
|
||||
uint8_t *ListEntitiesServicesArgument::encode_msg(const void *self,
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const ListEntitiesServicesArgument *>(self);
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast<uint32_t>(msg.type));
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.description);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.description);
|
||||
#endif
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.example);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.example);
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
@@ -1352,14 +1350,14 @@ uint32_t ListEntitiesServicesArgument::calc_size_msg(const void *self) {
|
||||
uint8_t *ListEntitiesServicesResponse::encode_msg(const void *self,
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
const auto &msg = *static_cast<const ListEntitiesServicesResponse *>(self);
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, msg.name);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
for (auto &it : msg.args) {
|
||||
pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, 3, it);
|
||||
}
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast<uint32_t>(msg.supports_response));
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
pos = ProtoEncode::encode_progmem_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.description);
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.description);
|
||||
#endif
|
||||
return pos;
|
||||
}
|
||||
@@ -1480,7 +1478,7 @@ uint8_t *ListEntitiesCameraResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesCameraResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.icon);
|
||||
@@ -1546,7 +1544,7 @@ uint8_t *ListEntitiesClimateResponse::encode_msg(const void *self, uint8_t *__re
|
||||
const auto &msg = *static_cast<const ListEntitiesClimateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.supports_current_temperature);
|
||||
pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.supports_two_point_target_temperature);
|
||||
for (const auto &it : *msg.supported_modes) {
|
||||
@@ -1783,7 +1781,7 @@ uint8_t *ListEntitiesWaterHeaterResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesWaterHeaterResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -1910,7 +1908,7 @@ uint8_t *ListEntitiesNumberResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesNumberResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2001,7 +1999,7 @@ uint8_t *ListEntitiesSelectResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesSelectResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2080,7 +2078,7 @@ uint8_t *ListEntitiesSirenResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesSirenResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2182,7 +2180,7 @@ uint8_t *ListEntitiesLockResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesLockResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2265,7 +2263,7 @@ uint8_t *ListEntitiesButtonResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesButtonResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -2334,7 +2332,7 @@ uint8_t *ListEntitiesMediaPlayerResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesMediaPlayerResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3180,7 +3178,7 @@ uint8_t *ListEntitiesAlarmControlPanelResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesAlarmControlPanelResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3260,7 +3258,7 @@ uint8_t *ListEntitiesTextResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTextResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3339,7 +3337,7 @@ uint8_t *ListEntitiesDateResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesDateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3420,7 +3418,7 @@ uint8_t *ListEntitiesTimeResponse::encode_msg(const void *self, uint8_t *__restr
|
||||
const auto &msg = *static_cast<const ListEntitiesTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3501,7 +3499,7 @@ uint8_t *ListEntitiesEventResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesEventResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3563,7 +3561,7 @@ uint8_t *ListEntitiesValveResponse::encode_msg(const void *self, uint8_t *__rest
|
||||
const auto &msg = *static_cast<const ListEntitiesValveResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3651,7 +3649,7 @@ uint8_t *ListEntitiesDateTimeResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesDateTimeResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3724,7 +3722,7 @@ uint8_t *ListEntitiesUpdateResponse::encode_msg(const void *self, uint8_t *__res
|
||||
const auto &msg = *static_cast<const ListEntitiesUpdateResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.icon);
|
||||
#endif
|
||||
@@ -3880,7 +3878,7 @@ uint8_t *ListEntitiesInfraredResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesInfraredResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -3998,7 +3996,7 @@ uint8_t *ListEntitiesRadioFrequencyResponse::encode_msg(const void *self,
|
||||
const auto &msg = *static_cast<const ListEntitiesRadioFrequencyResponse *>(self);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, msg.object_id);
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, msg.key);
|
||||
pos = ProtoEncode::encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, msg.name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.icon);
|
||||
#endif
|
||||
@@ -4177,8 +4175,6 @@ uint8_t *UsbDeviceDescriptor::encode_msg(const void *self, uint8_t *__restrict__
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, msg.product_id);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, msg.bcd_device);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, msg.interface_number);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, msg.interface_class);
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, msg.port_number);
|
||||
return pos;
|
||||
}
|
||||
uint32_t UsbDeviceDescriptor::calc_size_msg(const void *self) {
|
||||
@@ -4188,8 +4184,6 @@ uint32_t UsbDeviceDescriptor::calc_size_msg(const void *self) {
|
||||
size += ProtoSize::calc_uint32(1, msg.product_id);
|
||||
size += ProtoSize::calc_uint32(1, msg.bcd_device);
|
||||
size += ProtoSize::calc_uint32(1, msg.interface_number);
|
||||
size += ProtoSize::calc_uint32(1, msg.interface_class);
|
||||
size += ProtoSize::calc_uint32(1, msg.port_number);
|
||||
return size;
|
||||
}
|
||||
uint8_t *SerialProxyIdentity::encode_msg(const void *self, uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) {
|
||||
|
||||
@@ -399,7 +399,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
|
||||
public:
|
||||
StringRef object_id{};
|
||||
uint32_t key{0};
|
||||
ProgmemStringRef name{};
|
||||
StringRef name{};
|
||||
bool disabled_by_default{false};
|
||||
#ifdef USE_ENTITY_ICON
|
||||
StringRef icon{nullptr, 0}; // null until set, encode only
|
||||
@@ -750,7 +750,6 @@ class WizardCapabilities final : public ProtoMessage {
|
||||
class SendspinCapabilities final : public ProtoMessage {
|
||||
public:
|
||||
uint32_t feature_flags{0};
|
||||
StringRef client_id{nullptr, 0}; // null until set, encode only
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
|
||||
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
|
||||
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
|
||||
@@ -1389,8 +1388,8 @@ class NoiseEncryptionSetKeyResponse final : public ProtoMessage {
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
class HomeassistantServiceMap final : public ProtoMessage {
|
||||
public:
|
||||
ProgmemStringRef key{};
|
||||
ProgmemStringRef value{};
|
||||
StringRef key{nullptr, 0}; // null until set, encode only
|
||||
StringRef value{nullptr, 0}; // null until set, encode only
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
|
||||
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
|
||||
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
|
||||
@@ -1410,7 +1409,7 @@ class HomeassistantActionRequest final : public ProtoMessage {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const LogString *message_name() const override { return LOG_STR("homeassistant_action_request"); }
|
||||
#endif
|
||||
ProgmemStringRef service{};
|
||||
StringRef service{nullptr, 0}; // null until set, encode only
|
||||
FixedVector<HomeassistantServiceMap> data{};
|
||||
FixedVector<HomeassistantServiceMap> data_template{};
|
||||
FixedVector<HomeassistantServiceMap> variables{};
|
||||
@@ -1577,13 +1576,13 @@ class GetTimeResponse final : public ProtoDecodableMessage {
|
||||
#ifdef USE_API_USER_DEFINED_ACTIONS
|
||||
class ListEntitiesServicesArgument final : public ProtoMessage {
|
||||
public:
|
||||
ProgmemStringRef name{};
|
||||
StringRef name{nullptr, 0}; // null until set, encode only
|
||||
enums::ServiceArgType type{};
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
ProgmemStringRef description{};
|
||||
StringRef description{nullptr, 0}; // null until set, encode only
|
||||
#endif
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
ProgmemStringRef example{};
|
||||
StringRef example{nullptr, 0}; // null until set, encode only
|
||||
#endif
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
|
||||
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
|
||||
@@ -1604,12 +1603,12 @@ class ListEntitiesServicesResponse final : public ProtoMessage {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const LogString *message_name() const override { return LOG_STR("list_entities_services_response"); }
|
||||
#endif
|
||||
ProgmemStringRef name{};
|
||||
StringRef name{nullptr, 0}; // null until set, encode only
|
||||
uint32_t key{0};
|
||||
FixedVector<ListEntitiesServicesArgument> args{};
|
||||
enums::SupportsResponseType supports_response{};
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
ProgmemStringRef description{};
|
||||
StringRef description{nullptr, 0}; // null until set, encode only
|
||||
#endif
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
|
||||
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
|
||||
@@ -4084,8 +4083,6 @@ class UsbDeviceDescriptor final : public ProtoMessage {
|
||||
uint32_t product_id{0};
|
||||
uint32_t bcd_device{0};
|
||||
uint32_t interface_number{0};
|
||||
uint32_t interface_class{0};
|
||||
uint32_t port_number{0};
|
||||
static uint8_t *encode_msg(const void *self, uint8_t *pos PROTO_ENCODE_DEBUG_PARAM);
|
||||
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
|
||||
return encode_msg(this, buffer.get_pos() PROTO_ENCODE_DEBUG_ARG);
|
||||
|
||||
@@ -12,9 +12,8 @@ namespace esphome::api {
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
// Out-of-line to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void DumpBuffer::append_p_esp8266(const char *str) { this->append_p_esp8266(str, strlen_P(str)); }
|
||||
|
||||
void DumpBuffer::append_p_esp8266(const char *str, size_t len) {
|
||||
void DumpBuffer::append_p_esp8266(const char *str) {
|
||||
size_t len = strlen_P(str);
|
||||
size_t space = CAPACITY - 1 - pos_;
|
||||
if (len > space)
|
||||
len = space;
|
||||
@@ -135,13 +134,6 @@ static void dump_progmem_bytes_field(DumpBuffer &out, const char *field_name, co
|
||||
progmem_memcpy(data_buf, data, len);
|
||||
dump_bytes_field(out, field_name, data_buf, len, indent);
|
||||
}
|
||||
|
||||
// Helper for string fields in flash
|
||||
static void dump_progmem_string_field(DumpBuffer &out, const char *field_name, const ProgmemStringRef &value,
|
||||
int indent = 2) {
|
||||
append_field_prefix(out, field_name, indent);
|
||||
out.append("'").append_p(value.progmem_ptr(), value.size()).append("'\n");
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template<> const char *proto_enum_to_string<enums::DisconnectReason>(enums::DisconnectReason value) {
|
||||
@@ -1127,7 +1119,6 @@ const char *WizardCapabilities::dump_to(DumpBuffer &out) const {
|
||||
const char *SendspinCapabilities::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("SendspinCapabilities"));
|
||||
dump_field(out, ESPHOME_PSTR("feature_flags"), this->feature_flags);
|
||||
dump_field(out, ESPHOME_PSTR("client_id"), this->client_id);
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
@@ -1191,7 +1182,7 @@ const char *ListEntitiesBinarySensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesBinarySensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("device_class"), this->device_class);
|
||||
dump_field(out, ESPHOME_PSTR("is_status_binary_sensor"), this->is_status_binary_sensor);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
@@ -1220,7 +1211,7 @@ const char *ListEntitiesCoverResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCoverResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("assumed_state"), this->assumed_state);
|
||||
dump_field(out, ESPHOME_PSTR("supports_position"), this->supports_position);
|
||||
dump_field(out, ESPHOME_PSTR("supports_tilt"), this->supports_tilt);
|
||||
@@ -1266,7 +1257,7 @@ const char *ListEntitiesFanResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesFanResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_oscillation"), this->supports_oscillation);
|
||||
dump_field(out, ESPHOME_PSTR("supports_speed"), this->supports_speed);
|
||||
dump_field(out, ESPHOME_PSTR("supports_direction"), this->supports_direction);
|
||||
@@ -1321,7 +1312,7 @@ const char *ListEntitiesLightResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLightResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
for (const auto &it : *this->supported_color_modes) {
|
||||
dump_field(out, ESPHOME_PSTR("supported_color_modes"), static_cast<enums::ColorMode>(it), 4);
|
||||
}
|
||||
@@ -1400,7 +1391,7 @@ const char *ListEntitiesSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1432,7 +1423,7 @@ const char *ListEntitiesSwitchResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSwitchResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1470,7 +1461,7 @@ const char *ListEntitiesTextSensorResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextSensorResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1520,13 +1511,13 @@ const char *NoiseEncryptionSetKeyResponse::dump_to(DumpBuffer &out) const {
|
||||
#ifdef USE_API_HOMEASSISTANT_SERVICES
|
||||
const char *HomeassistantServiceMap::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantServiceMap"));
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("value"), this->value);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_field(out, ESPHOME_PSTR("value"), this->value);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *HomeassistantActionRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("HomeassistantActionRequest"));
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("service"), this->service);
|
||||
dump_field(out, ESPHOME_PSTR("service"), this->service);
|
||||
for (const auto &it : this->data) {
|
||||
out.append(4, ' ').append_p(ESPHOME_PSTR("data")).append(": ");
|
||||
it.dump_to(out);
|
||||
@@ -1621,19 +1612,19 @@ const char *GetTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
#ifdef USE_API_USER_DEFINED_ACTIONS
|
||||
const char *ListEntitiesServicesArgument::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesArgument"));
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("type"), static_cast<enums::ServiceArgType>(this->type));
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("description"), this->description);
|
||||
dump_field(out, ESPHOME_PSTR("description"), this->description);
|
||||
#endif
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("example"), this->example);
|
||||
dump_field(out, ESPHOME_PSTR("example"), this->example);
|
||||
#endif
|
||||
return out.c_str();
|
||||
}
|
||||
const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesServicesResponse"));
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
for (const auto &it : this->args) {
|
||||
out.append(4, ' ').append_p(ESPHOME_PSTR("args")).append(": ");
|
||||
@@ -1642,7 +1633,7 @@ const char *ListEntitiesServicesResponse::dump_to(DumpBuffer &out) const {
|
||||
}
|
||||
dump_field(out, ESPHOME_PSTR("supports_response"), static_cast<enums::SupportsResponseType>(this->supports_response));
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("description"), this->description);
|
||||
dump_field(out, ESPHOME_PSTR("description"), this->description);
|
||||
#endif
|
||||
return out.c_str();
|
||||
}
|
||||
@@ -1701,7 +1692,7 @@ const char *ListEntitiesCameraResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesCameraResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("disabled_by_default"), this->disabled_by_default);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
@@ -1734,7 +1725,7 @@ const char *ListEntitiesClimateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesClimateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("supports_current_temperature"), this->supports_current_temperature);
|
||||
dump_field(out, ESPHOME_PSTR("supports_two_point_target_temperature"), this->supports_two_point_target_temperature);
|
||||
for (const auto &it : *this->supported_modes) {
|
||||
@@ -1832,7 +1823,7 @@ const char *ListEntitiesWaterHeaterResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesWaterHeaterResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1886,7 +1877,7 @@ const char *ListEntitiesNumberResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesNumberResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1928,7 +1919,7 @@ const char *ListEntitiesSelectResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSelectResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -1967,7 +1958,7 @@ const char *ListEntitiesSirenResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesSirenResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2014,7 +2005,7 @@ const char *ListEntitiesLockResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesLockResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2055,7 +2046,7 @@ const char *ListEntitiesButtonResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesButtonResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2090,7 +2081,7 @@ const char *ListEntitiesMediaPlayerResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesMediaPlayerResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2480,7 +2471,7 @@ const char *ListEntitiesAlarmControlPanelResponse::dump_to(DumpBuffer &out) cons
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesAlarmControlPanelResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2519,7 +2510,7 @@ const char *ListEntitiesTextResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTextResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2559,7 +2550,7 @@ const char *ListEntitiesDateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2599,7 +2590,7 @@ const char *ListEntitiesTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2639,7 +2630,7 @@ const char *ListEntitiesEventResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesEventResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2669,7 +2660,7 @@ const char *ListEntitiesValveResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesValveResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2711,7 +2702,7 @@ const char *ListEntitiesDateTimeResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesDateTimeResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2747,7 +2738,7 @@ const char *ListEntitiesUpdateResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesUpdateResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2810,7 +2801,7 @@ const char *ListEntitiesInfraredResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesInfraredResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2868,7 +2859,7 @@ const char *ListEntitiesRadioFrequencyResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, ESPHOME_PSTR("ListEntitiesRadioFrequencyResponse"));
|
||||
dump_field(out, ESPHOME_PSTR("object_id"), this->object_id);
|
||||
dump_field(out, ESPHOME_PSTR("key"), this->key);
|
||||
dump_progmem_string_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
dump_field(out, ESPHOME_PSTR("name"), this->name);
|
||||
#ifdef USE_ENTITY_ICON
|
||||
dump_field(out, ESPHOME_PSTR("icon"), this->icon);
|
||||
#endif
|
||||
@@ -2951,8 +2942,6 @@ const char *UsbDeviceDescriptor::dump_to(DumpBuffer &out) const {
|
||||
dump_field(out, ESPHOME_PSTR("product_id"), this->product_id);
|
||||
dump_field(out, ESPHOME_PSTR("bcd_device"), this->bcd_device);
|
||||
dump_field(out, ESPHOME_PSTR("interface_number"), this->interface_number);
|
||||
dump_field(out, ESPHOME_PSTR("interface_class"), this->interface_class);
|
||||
dump_field(out, ESPHOME_PSTR("port_number"), this->port_number);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyIdentity::dump_to(DumpBuffer &out) const {
|
||||
|
||||
@@ -547,7 +547,7 @@ void APIServer::send_homeassistant_action(const HomeassistantActionRequest &call
|
||||
// arrive before the subscription and are lost - warn instead of failing silently.
|
||||
ESP_LOGW(TAG, "Home Assistant %s '%.*s' dropped; %s",
|
||||
call.is_event ? LOG_STR_LITERAL("event") : LOG_STR_LITERAL("action"),
|
||||
static_cast<int>(call.service.size()), call.service.empty() ? "" : call.service.progmem_ptr(),
|
||||
static_cast<int>(call.service.size()), call.service.empty() ? "" : call.service.c_str(),
|
||||
this->is_connected() ? LOG_STR_LITERAL("client has not subscribed to actions (yet)")
|
||||
: LOG_STR_LITERAL("no client connected"));
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ class CustomAPIDevice {
|
||||
*/
|
||||
void call_homeassistant_service(const std::string &service_name) {
|
||||
HomeassistantActionRequest resp;
|
||||
resp.service = ProgmemStringRef(StringRef(service_name));
|
||||
resp.service = StringRef(service_name);
|
||||
global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -267,12 +267,12 @@ class CustomAPIDevice {
|
||||
*/
|
||||
void call_homeassistant_service(const std::string &service_name, const std::map<std::string, std::string> &data) {
|
||||
HomeassistantActionRequest resp;
|
||||
resp.service = ProgmemStringRef(StringRef(service_name));
|
||||
resp.service = StringRef(service_name);
|
||||
resp.data.init(data.size());
|
||||
for (auto &it : data) {
|
||||
auto &kv = resp.data.emplace_back();
|
||||
kv.key = ProgmemStringRef(StringRef(it.first));
|
||||
kv.value = ProgmemStringRef(StringRef(it.second)); // data map lives until send completes
|
||||
kv.key = StringRef(it.first);
|
||||
kv.value = StringRef(it.second); // data map lives until send completes
|
||||
}
|
||||
global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
@@ -289,7 +289,7 @@ class CustomAPIDevice {
|
||||
*/
|
||||
void fire_homeassistant_event(const std::string &event_name) {
|
||||
HomeassistantActionRequest resp;
|
||||
resp.service = ProgmemStringRef(StringRef(event_name));
|
||||
resp.service = StringRef(event_name);
|
||||
resp.is_event = true;
|
||||
global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
@@ -309,13 +309,13 @@ class CustomAPIDevice {
|
||||
*/
|
||||
void fire_homeassistant_event(const std::string &service_name, const std::map<std::string, std::string> &data) {
|
||||
HomeassistantActionRequest resp;
|
||||
resp.service = ProgmemStringRef(StringRef(service_name));
|
||||
resp.service = StringRef(service_name);
|
||||
resp.is_event = true;
|
||||
resp.data.init(data.size());
|
||||
for (auto &it : data) {
|
||||
auto &kv = resp.data.emplace_back();
|
||||
kv.key = ProgmemStringRef(StringRef(it.first));
|
||||
kv.value = ProgmemStringRef(StringRef(it.second)); // data map lives until send completes
|
||||
kv.key = StringRef(it.first);
|
||||
kv.value = StringRef(it.second); // data map lives until send completes
|
||||
}
|
||||
global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -116,18 +116,42 @@ template<typename... Ts> class HomeAssistantServiceCallAction final : public Act
|
||||
const Field *fields = this->fields_;
|
||||
const size_t total = 1 + this->data_count_ + this->data_template_count_ + this->variables_count_;
|
||||
|
||||
// Lambda results must live until the send; the constant strings are encoded from flash where they are
|
||||
// Lambda results, and on ESP8266 the RAM copies of the flash strings, must live until the send
|
||||
size_t lambda_count = 0;
|
||||
for (size_t i = 0; i < total; i++)
|
||||
#ifdef USE_ESP8266
|
||||
size_t flash_len = 0;
|
||||
#endif
|
||||
for (size_t i = 0; i < total; i++) {
|
||||
lambda_count += fields[i].fn != nullptr;
|
||||
#ifdef USE_ESP8266
|
||||
if (fields[i].fn == nullptr)
|
||||
flash_len += ESPHOME_strlen_P(fields[i].value);
|
||||
if (fields[i].key != nullptr)
|
||||
flash_len += ESPHOME_strlen_P(fields[i].key);
|
||||
#endif
|
||||
}
|
||||
FixedVector<std::string> results;
|
||||
results.init(lambda_count);
|
||||
auto string_ref = [](const char *str) { return ProgmemStringRef(str, ESPHOME_strlen_P(str)); };
|
||||
#ifdef USE_ESP8266
|
||||
SmallBufferWithHeapFallback<128, char> flash_copy(flash_len);
|
||||
char *cursor = flash_copy.get();
|
||||
#endif
|
||||
auto string_ref = [&](const char *str) {
|
||||
#ifdef USE_ESP8266
|
||||
size_t len = ESPHOME_strlen_P(str);
|
||||
memcpy_P(cursor, str, len);
|
||||
StringRef ref(cursor, len);
|
||||
cursor += len;
|
||||
return ref;
|
||||
#else
|
||||
return StringRef(str);
|
||||
#endif
|
||||
};
|
||||
auto value_ref = [&](const Field &field) {
|
||||
if (field.fn == nullptr)
|
||||
return string_ref(field.value);
|
||||
results.push_back(field.fn(x...));
|
||||
return ProgmemStringRef(StringRef(results.back()));
|
||||
return StringRef(results.back());
|
||||
};
|
||||
auto fill = [&](FixedVector<HomeassistantServiceMap> &dest, uint8_t count) {
|
||||
dest.init(count);
|
||||
|
||||
@@ -99,7 +99,8 @@ ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(clie
|
||||
static constexpr uint8_t SERVICE_YIELD_INTERVAL = 3;
|
||||
|
||||
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
|
||||
auto resp = service->encode_list_service_response();
|
||||
UserActionScratch scratch;
|
||||
auto resp = service->encode_list_service_response(scratch);
|
||||
if (!this->client_->send_message(resp))
|
||||
return false;
|
||||
// at_ is this service's index
|
||||
|
||||
@@ -409,10 +409,6 @@ class ProtoEncode {
|
||||
/// Tag must be a single-byte varint (< 128). Always encodes (no zero check).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint8_t tag, const StringRef &ref) {
|
||||
#ifdef USE_ESP8266
|
||||
// memcpy_P reads RAM too, and sharing the progmem copy is smaller than an inline memcpy
|
||||
return encode_short_progmem_string_force(pos PROTO_ENCODE_DEBUG_ARG, tag, ProgmemStringRef(ref));
|
||||
#else
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
@@ -421,19 +417,6 @@ class ProtoEncode {
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
std::memcpy(pos + 2, ref.c_str(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
#endif
|
||||
}
|
||||
/// encode_short_string_force for a string that may be in flash (PROGMEM).
|
||||
[[nodiscard]] static inline uint8_t *encode_short_progmem_string_force(
|
||||
uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, const ProgmemStringRef &ref) {
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(ref.size() < 128 && "encode_short_progmem_string_force: string exceeds max_data_length < 128");
|
||||
#endif
|
||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 2 + ref.size());
|
||||
pos[0] = tag;
|
||||
pos[1] = static_cast<uint8_t>(ref.size());
|
||||
progmem_memcpy(pos + 2, ref.progmem_ptr(), ref.size());
|
||||
return pos + 2 + ref.size();
|
||||
}
|
||||
/// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field.
|
||||
[[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32(
|
||||
@@ -498,17 +481,6 @@ class ProtoEncode {
|
||||
progmem_memcpy(pos, data, len);
|
||||
return pos + len;
|
||||
}
|
||||
/// encode_progmem_bytes for a string field that may be in flash.
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_progmem_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, const ProgmemStringRef &ref) {
|
||||
return encode_progmem_bytes_force(pos PROTO_ENCODE_DEBUG_ARG, field_id,
|
||||
reinterpret_cast<const uint8_t *>(ref.progmem_ptr()), ref.size());
|
||||
}
|
||||
[[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM,
|
||||
uint32_t field_id, uint32_t value) {
|
||||
pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0);
|
||||
@@ -708,20 +680,9 @@ class DumpBuffer {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Append len bytes of a PROGMEM string
|
||||
DumpBuffer &append_p(const char *str, size_t len) {
|
||||
#ifdef USE_ESP8266
|
||||
append_p_esp8266(str, len);
|
||||
#else
|
||||
append_impl_(str, len);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
/// Out-of-line ESP8266 PROGMEM append to avoid inlining strlen_P/memcpy_P at every call site
|
||||
void append_p_esp8266(const char *str);
|
||||
void append_p_esp8266(const char *str, size_t len);
|
||||
#endif
|
||||
|
||||
const char *c_str() const { return buf_; }
|
||||
|
||||
@@ -1,36 +1,47 @@
|
||||
#include "user_services.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::api {
|
||||
|
||||
ProgmemStringRef UserServiceStatic::str_(size_t idx) const {
|
||||
StringRef UserServiceStatic::str_(size_t idx, std::span<char> &scratch) const {
|
||||
const char *s = progmem_read_ptr(&this->strings_[idx]);
|
||||
if (s == nullptr)
|
||||
return {};
|
||||
return ProgmemStringRef(s, ESPHOME_strlen_P(s));
|
||||
#ifdef USE_ESP8266
|
||||
// Codegen sizes the scratch buffer for the largest service; the bound only guards other callers
|
||||
if (scratch.empty())
|
||||
return {};
|
||||
size_t len = strnlen_P(s, scratch.size() - 1);
|
||||
progmem_memcpy(scratch.data(), s, len);
|
||||
scratch[len] = '\0';
|
||||
StringRef ref(scratch.data(), len);
|
||||
scratch = scratch.subspan(len + 1);
|
||||
return ref;
|
||||
#else
|
||||
return StringRef(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
ListEntitiesServicesResponse UserServiceStatic::encode_list_service_response_(
|
||||
std::span<const enums::ServiceArgType> arg_types) const {
|
||||
std::span<const enums::ServiceArgType> arg_types, std::span<char> scratch) const {
|
||||
ListEntitiesServicesResponse msg;
|
||||
msg.name = this->str_(0);
|
||||
msg.name = this->str_(0, scratch);
|
||||
msg.key = this->key_;
|
||||
msg.supports_response = this->supports_response_;
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
msg.description = this->str_(1);
|
||||
msg.description = this->str_(1, scratch);
|
||||
#endif
|
||||
msg.args.init(arg_types.size());
|
||||
for (size_t i = 0; i < arg_types.size(); i++) {
|
||||
size_t base = USER_ACTION_HEADER_STRINGS + i * USER_ACTION_ARG_STRINGS;
|
||||
auto &arg = msg.args.emplace_back();
|
||||
arg.type = arg_types[i];
|
||||
arg.name = this->str_(base);
|
||||
arg.name = this->str_(base, scratch);
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_METADATA
|
||||
arg.description = this->str_(base + 1);
|
||||
arg.example = this->str_(base + 2);
|
||||
arg.description = this->str_(base + 1, scratch);
|
||||
arg.example = this->str_(base + 2, scratch);
|
||||
#endif
|
||||
}
|
||||
return msg;
|
||||
|
||||
@@ -20,8 +20,9 @@ class APIServer;
|
||||
|
||||
class UserServiceDescriptor {
|
||||
public:
|
||||
/// Build the list-entities message; its strings may point into flash (PROGMEM).
|
||||
virtual ListEntitiesServicesResponse encode_list_service_response() = 0;
|
||||
/// Build the list-entities message. On ESP8266 the strings live in PROGMEM and are copied into
|
||||
/// `scratch`, so the returned message is only valid while `scratch` is; other platforms ignore it.
|
||||
virtual ListEntitiesServicesResponse encode_list_service_response(std::span<char> scratch) = 0;
|
||||
|
||||
virtual bool execute_service(const ExecuteServiceRequest &req) = 0;
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
|
||||
@@ -36,6 +37,13 @@ template<typename T> T get_execute_arg_value(const ExecuteServiceArgument &arg);
|
||||
|
||||
template<typename T> enums::ServiceArgType to_service_arg_type();
|
||||
|
||||
// Scratch buffer list-entities hands to encode_list_service_response(); only ESP8266 copies into it
|
||||
#ifdef USE_ESP8266
|
||||
using UserActionScratch = std::array<char, API_USER_ACTION_STRINGS_SCRATCH_SIZE>;
|
||||
#else
|
||||
using UserActionScratch = std::array<char, 0>;
|
||||
#endif
|
||||
|
||||
// Non-template base for YAML-defined services so the list-entities encoder is compiled once.
|
||||
// All strings live in one PROGMEM pointer table emitted by codegen (see _action_strings in
|
||||
// __init__.py), so each service costs a single pointer of RAM. Layout: the action name, then
|
||||
@@ -55,9 +63,12 @@ class UserServiceStatic : public UserServiceDescriptor {
|
||||
: strings_(strings), key_(key), supports_response_(supports_response) {}
|
||||
|
||||
protected:
|
||||
ListEntitiesServicesResponse encode_list_service_response_(std::span<const enums::ServiceArgType> arg_types) const;
|
||||
/// Table entry `idx` as it sits in flash; nullptr gives an empty string.
|
||||
ProgmemStringRef str_(size_t idx) const;
|
||||
ListEntitiesServicesResponse encode_list_service_response_(std::span<const enums::ServiceArgType> arg_types,
|
||||
std::span<char> scratch) const;
|
||||
/// Reference table entry `idx`; nullptr gives an empty StringRef.
|
||||
/// On ESP8266 the bytes are copied out of PROGMEM into `scratch` with a terminator, and the span
|
||||
/// is advanced past the copy.
|
||||
StringRef str_(size_t idx, std::span<char> &scratch) const;
|
||||
|
||||
const char *const *strings_; // PROGMEM pointer table, read with progmem_read_ptr()
|
||||
uint32_t key_;
|
||||
@@ -68,9 +79,9 @@ template<typename... Ts> class UserServiceBase : public UserServiceStatic {
|
||||
public:
|
||||
using UserServiceStatic::UserServiceStatic;
|
||||
|
||||
ListEntitiesServicesResponse encode_list_service_response() override {
|
||||
ListEntitiesServicesResponse encode_list_service_response(std::span<char> scratch) override {
|
||||
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
|
||||
return this->encode_list_service_response_(arg_types);
|
||||
return this->encode_list_service_response_(arg_types, scratch);
|
||||
}
|
||||
|
||||
bool execute_service(const ExecuteServiceRequest &req) override {
|
||||
@@ -114,9 +125,9 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
|
||||
this->key_ = fnv1_hash(this->name_.c_str());
|
||||
}
|
||||
|
||||
ListEntitiesServicesResponse encode_list_service_response() override {
|
||||
ListEntitiesServicesResponse encode_list_service_response(std::span<char> /*scratch*/) override {
|
||||
ListEntitiesServicesResponse msg;
|
||||
msg.name = ProgmemStringRef(StringRef(this->name_));
|
||||
msg.name = StringRef(this->name_);
|
||||
msg.key = this->key_;
|
||||
msg.supports_response = enums::SUPPORTS_RESPONSE_NONE; // Dynamic services don't support responses yet
|
||||
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
|
||||
@@ -124,7 +135,7 @@ template<typename... Ts> class UserServiceDynamic : public UserServiceDescriptor
|
||||
for (size_t i = 0; i < sizeof...(Ts); i++) {
|
||||
auto &arg = msg.args.emplace_back();
|
||||
arg.type = arg_types[i];
|
||||
arg.name = ProgmemStringRef(StringRef(this->arg_names_[i]));
|
||||
arg.name = StringRef(this->arg_names_[i]);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ void AQISensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Extended Range: %s",
|
||||
this->extended_range_ ? LOG_STR_LITERAL("enabled") : LOG_STR_LITERAL("disabled"));
|
||||
if (this->pm_2_5_sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", LOG_STR_ARG(this->pm_2_5_sensor_->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, " PM2.5 Sensor: '%s'", this->pm_2_5_sensor_->get_name().c_str());
|
||||
}
|
||||
if (this->pm_10_0_sensor_ != nullptr) {
|
||||
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", LOG_STR_ARG(this->pm_10_0_sensor_->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, " PM10 Sensor: '%s'", this->pm_10_0_sensor_->get_name().c_str());
|
||||
}
|
||||
LOG_SENSOR(" ", "AQI", this);
|
||||
}
|
||||
|
||||
@@ -1289,7 +1289,7 @@ void ATM90E32Component::check_phase_status() {
|
||||
if (!status.empty()) {
|
||||
status.pop_back(); // remove space
|
||||
status.pop_back(); // remove semicolon
|
||||
ESP_LOGW(TAG, "%s: %s", LOG_STR_ARG(sensor->get_log_name()), status.c_str());
|
||||
ESP_LOGW(TAG, "%s: %s", sensor->get_name().c_str(), status.c_str());
|
||||
sensor->publish_state(status);
|
||||
} else {
|
||||
sensor->publish_state("Okay");
|
||||
|
||||
@@ -8,12 +8,11 @@ ESPHOME_LOG_TAG(TAG, "atm90e32.button");
|
||||
|
||||
void ATM90E32GainCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Gain Calibration button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG,
|
||||
"[CALIBRATION] Use gain_ct: & gain_voltage: under each phase_x: in your config file to save these values");
|
||||
this->parent_->run_gain_calibrations();
|
||||
@@ -21,22 +20,21 @@ void ATM90E32GainCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearGainCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Gain button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
this->parent_->clear_gain_calibrations();
|
||||
}
|
||||
|
||||
void ATM90E32OffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Offset Calibration button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs and ACVs must be 0 during this process. USB power only**");
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Use offset_voltage: & offset_current: under each phase_x: in your config file to save "
|
||||
"these values");
|
||||
@@ -45,22 +43,21 @@ void ATM90E32OffsetCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Offset button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
this->parent_->clear_offset_calibrations();
|
||||
}
|
||||
|
||||
void ATM90E32PowerOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Power Calibration button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
ESP_LOGI(TAG, "[CALIBRATION] **NOTE: CTs must be 0 during this process. Voltage reference should be present**");
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Use offset_active_power: & offset_reactive_power: under each phase_x: in your config "
|
||||
"file to save these values");
|
||||
@@ -69,11 +66,11 @@ void ATM90E32PowerOffsetCalibrationButton::press_action() {
|
||||
|
||||
void ATM90E32ClearPowerOffsetCalibrationButton::press_action() {
|
||||
if (this->parent_ == nullptr) {
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[CALIBRATION] No meters assigned to Clear Power button [%s]", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%s", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "%s", this->get_name().c_str());
|
||||
this->parent_->clear_power_offset_calibrations();
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
} else if (fan_mode == CLIMATE_FAN_HIGH) {
|
||||
result = this->parent_->set_fan_speed(75);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGW(TAG, "[%s] Unsupported fan mode: %s", this->get_name().c_str(),
|
||||
LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
|
||||
return;
|
||||
}
|
||||
@@ -223,7 +223,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
auto fan_mode = call.get_custom_fan_mode();
|
||||
auto fan_index = bedjet_fan_speed_to_step(fan_mode.c_str());
|
||||
if (fan_index <= 19) {
|
||||
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGV(TAG, "[%s] Converted fan mode %.*s to bedjet fan step %d", this->get_name().c_str(),
|
||||
(int) fan_mode.size(), fan_mode.c_str(), fan_index);
|
||||
bool result = this->parent_->set_fan_index(fan_index);
|
||||
if (result) {
|
||||
@@ -236,7 +236,7 @@ void BedJetClimate::control(const ClimateCall &call) {
|
||||
void BedJetClimate::on_bedjet_state(bool is_ready) {}
|
||||
|
||||
void BedJetClimate::on_status(const BedjetStatusPacket *data) {
|
||||
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
|
||||
ESP_LOGV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
|
||||
|
||||
auto converted_temp = bedjet_temp_to_c(data->target_temp_step);
|
||||
if (converted_temp > 0)
|
||||
@@ -310,11 +310,11 @@ void BedJetClimate::on_status(const BedjetStatusPacket *data) {
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", LOG_STR_ARG(this->get_log_name()), data->mode);
|
||||
ESP_LOGW(TAG, "[%s] Unexpected mode: 0x%02X", this->get_name().c_str(), data->mode);
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGV(TAG, "[%s] After on_status, new mode=%s", this->get_name().c_str(),
|
||||
LOG_STR_ARG(climate_mode_to_string(this->mode)));
|
||||
// FIXME: compare new state to previous state.
|
||||
this->publish_state();
|
||||
@@ -351,11 +351,11 @@ bool BedJetClimate::update_status_() {
|
||||
}
|
||||
|
||||
void BedJetClimate::update() {
|
||||
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
|
||||
// TODO: if the hub component is already polling, do we also need to include polling?
|
||||
// We're already going to get on_status() at the hub's polling interval.
|
||||
auto result = this->update_status_();
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
|
||||
}
|
||||
|
||||
} // namespace esphome::bedjet
|
||||
|
||||
@@ -53,7 +53,7 @@ void BedJetFan::control(const fan::FanCall &call) {
|
||||
}
|
||||
|
||||
void BedJetFan::on_status(const BedjetStatusPacket *data) {
|
||||
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", LOG_STR_ARG(this->get_log_name()), (void *) data);
|
||||
ESP_LOGVV(TAG, "[%s] Handling on_status with data=%p", this->get_name().c_str(), (void *) data);
|
||||
bool did_change = false;
|
||||
bool new_state = data->mode != MODE_STANDBY && data->mode != MODE_WAIT;
|
||||
|
||||
@@ -96,11 +96,11 @@ bool BedJetFan::update_status_() {
|
||||
}
|
||||
|
||||
void BedJetFan::update() {
|
||||
ESP_LOGD(TAG, "[%s] update()", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "[%s] update()", this->get_name().c_str());
|
||||
// TODO: if the hub component is already polling, do we also need to include polling?
|
||||
// We're already going to get on_status() at the hub's polling interval.
|
||||
auto result = this->update_status_();
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", LOG_STR_ARG(this->get_log_name()), result ? "true" : "false");
|
||||
ESP_LOGD(TAG, "[%s] update_status result=%s", this->get_name().c_str(), result ? "true" : "false");
|
||||
}
|
||||
|
||||
/** Resets states to defaults. */
|
||||
|
||||
@@ -75,7 +75,7 @@ void BH1750Sensor::dump_config() {
|
||||
LOG_SENSOR("", "BH1750", this);
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
|
||||
}
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
@@ -154,7 +154,7 @@ void BH1750Sensor::loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", LOG_STR_ARG(this->get_log_name()), lx);
|
||||
ESP_LOGV(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), lx);
|
||||
this->status_clear_warning();
|
||||
this->publish_state(lx);
|
||||
this->state_ = IDLE;
|
||||
|
||||
@@ -3,7 +3,6 @@ from logging import getLogger
|
||||
from esphome import automation, core
|
||||
from esphome.automation import maybe_simple_id
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import mqtt, web_server, zigbee
|
||||
from esphome.components.const import CONF_ON_STATE_CHANGE
|
||||
from esphome.config_helpers import filter_source_files_from_defines
|
||||
import esphome.config_validation as cv
|
||||
@@ -29,7 +28,6 @@ from esphome.const import (
|
||||
CONF_STATE,
|
||||
CONF_TIMING,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_WEB_SERVER,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_BATTERY_CHARGING,
|
||||
DEVICE_CLASS_CARBON_MONOXIDE,
|
||||
@@ -61,10 +59,12 @@ from esphome.const import (
|
||||
DEVICE_CLASS_VIBRATION,
|
||||
DEVICE_CLASS_WINDOW,
|
||||
)
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority
|
||||
from esphome.core import CORE, ID, CoroPriority, coroutine_with_priority, entity_helpers
|
||||
from esphome.core.entity_helpers import (
|
||||
SubEntities,
|
||||
entity_duplicate_validator,
|
||||
lazy_load_validator,
|
||||
mqtt_component_class,
|
||||
queue_entity_register,
|
||||
setup_device_class,
|
||||
setup_entity,
|
||||
@@ -433,14 +433,14 @@ def validate_publish_initial_state(value):
|
||||
|
||||
|
||||
_BINARY_SENSOR_SCHEMA = (
|
||||
cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA)
|
||||
cv.ENTITY_BASE_SCHEMA.extend(entity_helpers.WEBSERVER_SORTING_SCHEMA)
|
||||
.extend(cv.MQTT_COMPONENT_SCHEMA)
|
||||
.extend(zigbee.BINARY_SENSOR_SCHEMA)
|
||||
.extend(entity_helpers.ZIGBEE_BINARY_SENSOR_SCHEMA)
|
||||
.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(BinarySensor),
|
||||
cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(
|
||||
mqtt.MQTTBinarySensorComponent
|
||||
mqtt_component_class("MQTTBinarySensorComponent")
|
||||
),
|
||||
cv.Exclusive(
|
||||
CONF_PUBLISH_INITIAL_STATE, CONF_TRIGGER_ON_INITIAL_STATE
|
||||
@@ -508,7 +508,7 @@ _BINARY_SENSOR_SCHEMA = (
|
||||
|
||||
|
||||
_BINARY_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("binary_sensor"))
|
||||
_BINARY_SENSOR_SCHEMA.add_extra(zigbee.validate_binary_sensor)
|
||||
_BINARY_SENSOR_SCHEMA.add_extra(lazy_load_validator("zigbee", "validate_binary_sensor"))
|
||||
|
||||
|
||||
def binary_sensor_schema(
|
||||
@@ -619,14 +619,12 @@ async def setup_binary_sensor_core_(var, config):
|
||||
|
||||
CORE.add_job(_build_binary_sensor_automations, var, config)
|
||||
|
||||
if mqtt_id := config.get(CONF_MQTT_ID):
|
||||
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||
await mqtt.register_mqtt_component(mqtt_, config)
|
||||
await entity_helpers.setup_entity_integrations(var, config)
|
||||
|
||||
if web_server_config := config.get(CONF_WEB_SERVER):
|
||||
await web_server.add_entity_config(var, web_server_config)
|
||||
if "zigbee" in CORE.loaded_integrations:
|
||||
from esphome.components import zigbee
|
||||
|
||||
await zigbee.setup_binary_sensor(var, config)
|
||||
await zigbee.setup_binary_sensor(var, config)
|
||||
|
||||
|
||||
async def register_binary_sensor(var, config):
|
||||
|
||||
@@ -13,7 +13,7 @@ void log_binary_sensor(const char *tag, const char *prefix, const char *type, Bi
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
|
||||
LOG_ENTITY_DEVICE_CLASS(tag, prefix, *obj);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ bool BinarySensor::set_new_state(const optional<bool> &new_state) {
|
||||
#if defined(USE_BINARY_SENSOR) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_binary_sensor_update(this);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "'%s' >> %s", LOG_STR_ARG(this->get_log_name()), ONOFFMAYBE(new_state));
|
||||
ESP_LOGV(TAG, "'%s' >> %s", this->get_name().c_str(), ONOFFMAYBE(new_state));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -47,7 +47,7 @@ void BinarySensorMap::process_group_() {
|
||||
}
|
||||
} else if (this->last_mask_ != 0ULL) {
|
||||
// no buttons are pressed and the states have changed since last run, so publish NAN
|
||||
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - No binary sensor active, publishing NAN", this->name_.c_str());
|
||||
this->publish_state(NAN);
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ float BL0940::update_temp_(sensor::Sensor *sensor, uint16_le_t temperature) cons
|
||||
if (sensor != nullptr) {
|
||||
if (sensor->has_state() && std::abs(converted_temp - sensor->get_state()) > max_temperature_diff_) {
|
||||
ESP_LOGD(TAG, "Invalid temperature change. Sensor: '%s', Old temperature: %f, New temperature: %f",
|
||||
LOG_STR_ARG(sensor->get_log_name()), sensor->get_state(), converted_temp);
|
||||
sensor->get_name().c_str(), sensor->get_state(), converted_temp);
|
||||
return 0.0f;
|
||||
}
|
||||
sensor->publish_state(converted_temp);
|
||||
|
||||
@@ -63,7 +63,7 @@ void BLEClientRSSISensor::gap_event_handler(esp_gap_ble_cb_event_t event, esp_bl
|
||||
|
||||
void BLEClientRSSISensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
this->should_update_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
|
||||
switch (event) {
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
if (param->open.status == ESP_GATT_OK) {
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_CLOSE_EVT: {
|
||||
ESP_LOGW(TAG, "[%s] Disconnected!", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Disconnected!", this->get_name().c_str());
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
break;
|
||||
@@ -102,10 +102,10 @@ void BLESensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t ga
|
||||
}
|
||||
case ESP_GATTC_NOTIFY_EVT: {
|
||||
if (param->notify.value_len == 0) {
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
|
||||
param->notify.handle, param->notify.value[0]);
|
||||
if (param->notify.handle != this->handle)
|
||||
break;
|
||||
@@ -143,11 +143,11 @@ float BLESensor::parse_data_(uint8_t *value, uint16_t value_len) {
|
||||
|
||||
void BLESensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
if (this->handle == 0) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ void BLESensor::update() {
|
||||
if (status) {
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
switch (event) {
|
||||
case ESP_GATTC_OPEN_EVT: {
|
||||
if (param->open.status == ESP_GATT_OK) {
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGI(TAG, "[%s] Connected successfully!", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -104,10 +104,10 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
if (param->notify.handle != this->handle)
|
||||
break;
|
||||
if (param->notify.value_len == 0) {
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: empty value", this->get_name().c_str());
|
||||
break;
|
||||
}
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGV(TAG, "[%s] ESP_GATTC_NOTIFY_EVT: handle=0x%x, value=0x%x", this->get_name().c_str(),
|
||||
param->notify.handle, param->notify.value[0]);
|
||||
this->publish_state(reinterpret_cast<const char *>(param->notify.value), param->notify.value_len);
|
||||
break;
|
||||
@@ -124,11 +124,11 @@ void BLETextSensor::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
|
||||
|
||||
void BLETextSensor::update() {
|
||||
if (this->node_state != espbt::ClientState::ESTABLISHED) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, not connected", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
if (this->handle == 0) {
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "[%s] Cannot poll, no service or characteristic found", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ void BLETextSensor::update() {
|
||||
if (status) {
|
||||
this->status_set_warning();
|
||||
this->publish_state("");
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", LOG_STR_ARG(this->get_log_name()), status);
|
||||
ESP_LOGW(TAG, "[%s] Error sending read request for sensor, status=%d", this->get_name().c_str(), status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -382,7 +382,7 @@ void BluedroidGattClient::set_disconnecting_() {
|
||||
|
||||
esp_err_t BluedroidGattClient::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
|
||||
uint16_t timeout, const char *param_type) {
|
||||
esp_ble_conn_update_params_t conn_params = {};
|
||||
esp_ble_conn_update_params_t conn_params = {{0}};
|
||||
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
|
||||
conn_params.min_int = min_interval;
|
||||
conn_params.max_int = max_interval;
|
||||
|
||||
@@ -11,12 +11,12 @@ void log_button(const char *tag, const char *prefix, const char *type, Button *o
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, LOG_STR_ARG(obj->get_log_name()));
|
||||
ESP_LOGCONFIG(tag, "%s%s '%s'", prefix, type, obj->get_name().c_str());
|
||||
LOG_ENTITY_ICON(tag, prefix, *obj);
|
||||
}
|
||||
|
||||
void Button::press() {
|
||||
ESP_LOGV(TAG, "'%s' Pressed.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' Pressed.", this->get_name().c_str());
|
||||
this->press_action();
|
||||
this->press_callback_.call();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = {
|
||||
|
||||
void ClimateCall::perform() {
|
||||
this->parent_->control_callback_.call(*this);
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
this->validate_();
|
||||
if (this->mode_.has_value()) {
|
||||
const LogString *mode_s = climate_mode_to_string(*this->mode_);
|
||||
@@ -183,7 +183,7 @@ ClimateCall &ClimateCall::set_mode(const char *mode, size_t len) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len, mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized mode %.*s", this->parent_->get_name().c_str(), (int) len, mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -214,8 +214,7 @@ ClimateCall &ClimateCall::set_fan_mode(const char *custom_fan_mode, size_t len)
|
||||
this->fan_mode_.reset();
|
||||
return *this;
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
custom_fan_mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %.*s", this->parent_->get_name().c_str(), (int) len, custom_fan_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -253,8 +252,7 @@ ClimateCall &ClimateCall::set_preset(const char *custom_preset, size_t len) {
|
||||
this->preset_.reset();
|
||||
return *this;
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
custom_preset);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized preset %.*s", this->parent_->get_name().c_str(), (int) len, custom_preset);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -282,8 +280,7 @@ ClimateCall &ClimateCall::set_swing_mode(const char *swing_mode, size_t len) {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", LOG_STR_ARG(this->parent_->get_log_name()), (int) len,
|
||||
swing_mode);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %.*s", this->parent_->get_name().c_str(), (int) len, swing_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -431,7 +428,7 @@ void Climate::save_state_(const ClimateTraits &traits) {
|
||||
|
||||
void Climate::publish_state() {
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
|
||||
auto traits = this->get_traits();
|
||||
|
||||
ESP_LOGV(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
|
||||
@@ -552,7 +549,7 @@ void ClimateDeviceRestoreState::apply(Climate *climate) {
|
||||
if (traits.supports_mode(this->mode)) {
|
||||
climate->mode = this->mode;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", LOG_STR_ARG(climate->get_log_name()),
|
||||
ESP_LOGW(TAG, "'%s' - Saved mode %s is no longer supported, keeping %s", climate->get_name().c_str(),
|
||||
LOG_STR_ARG(climate_mode_to_string(this->mode)), LOG_STR_ARG(climate_mode_to_string(climate->mode)));
|
||||
}
|
||||
if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::climate {
|
||||
|
||||
#define LOG_CLIMATE(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
}
|
||||
|
||||
class Climate;
|
||||
|
||||
@@ -30,14 +30,14 @@ void CombinationOneParameterComponent::add_source(Sensor *sensor, float value) {
|
||||
void CombinationNoParameterComponent::log_source_sensors() {
|
||||
ESP_LOGCONFIG(TAG, " Source Sensors:");
|
||||
for (const auto &sensor : this->sensors_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(sensor->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, " - %s", sensor->get_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CombinationOneParameterComponent::log_source_sensors() {
|
||||
ESP_LOGCONFIG(TAG, " Source Sensors:");
|
||||
for (const auto &source : this->sensor_sources_) {
|
||||
ESP_LOGCONFIG(TAG, " - %s", LOG_STR_ARG(source.sensor->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, " - %s", source.sensor->get_name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ CoverCall &CoverCall::set_command(const char *command) {
|
||||
} else if (ESPHOME_strcasecmp_P(command, ESPHOME_PSTR("TOGGLE")) == 0) {
|
||||
this->set_command_toggle();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", LOG_STR_ARG(this->parent_->get_log_name()), command);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ CoverCall &CoverCall::set_tilt(float tilt) {
|
||||
return *this;
|
||||
}
|
||||
void CoverCall::perform() {
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
auto traits = this->parent_->get_traits();
|
||||
this->validate_();
|
||||
if (this->stop_) {
|
||||
@@ -94,7 +94,7 @@ const optional<float> &CoverCall::get_tilt() const { return this->tilt_; }
|
||||
const optional<bool> &CoverCall::get_toggle() const { return this->toggle_; }
|
||||
void CoverCall::validate_() {
|
||||
auto traits = this->parent_->get_traits();
|
||||
const char *name = LOG_STR_ARG(this->parent_->get_log_name());
|
||||
const char *name = this->parent_->get_name().c_str();
|
||||
|
||||
if (this->position_.has_value()) {
|
||||
auto pos = *this->position_;
|
||||
@@ -139,7 +139,7 @@ void Cover::publish_state(bool save) {
|
||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
||||
|
||||
ESP_LOGV(TAG, "'%s' >>", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' >>", this->name_.c_str());
|
||||
auto traits = this->get_traits();
|
||||
if (traits.get_supports_position()) {
|
||||
ESP_LOGV(TAG, " Position: %.0f%%", this->position * 100.0f);
|
||||
|
||||
@@ -15,7 +15,7 @@ static constexpr float COVER_CLOSED = 0.0f;
|
||||
|
||||
#define LOG_COVER(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
auto traits_ = (obj)->get_traits(); \
|
||||
if (traits_.get_is_assumed_state()) { \
|
||||
ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
|
||||
|
||||
@@ -40,8 +40,7 @@ void CTClampSensor::update() {
|
||||
if (rms_ac_squared > 0)
|
||||
rms_ac = std::sqrt(rms_ac_squared);
|
||||
ESP_LOGD(TAG, "'%s' - Raw AC Value: %.3fA after %" PRIu32 " different samples (%" PRIu32 " SPS)",
|
||||
LOG_STR_ARG(this->get_log_name()), rms_ac, this->num_samples_,
|
||||
1000 * this->num_samples_ / this->sample_duration_);
|
||||
this->name_.c_str(), rms_ac, this->num_samples_, 1000 * this->num_samples_ / this->sample_duration_);
|
||||
this->publish_state(rms_ac);
|
||||
});
|
||||
|
||||
|
||||
@@ -70,20 +70,20 @@ void CurrentBasedCover::loop() {
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
this->name_.c_str());
|
||||
} else if (this->is_opening_blocked_()) { // Blocked
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during opening.", this->name_.c_str());
|
||||
this->direction_idle_();
|
||||
if (this->obstacle_rollback_ != 0) {
|
||||
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
|
||||
this->target_position_ = clamp(this->position - this->obstacle_rollback_, 0.0F, 1.0F);
|
||||
this->start_direction_(COVER_OPERATION_CLOSING);
|
||||
});
|
||||
}
|
||||
} else if (this->is_initial_delay_finished_() && !this->is_opening_()) { // End reached
|
||||
auto dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Open position reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
this->direction_idle_(COVER_OPEN);
|
||||
}
|
||||
} else if (this->current_operation == COVER_OPERATION_CLOSING) {
|
||||
@@ -91,25 +91,25 @@ void CurrentBasedCover::loop() {
|
||||
this->direction_idle_();
|
||||
this->malfunction_trigger_.trigger();
|
||||
ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit",
|
||||
LOG_STR_ARG(this->get_log_name()));
|
||||
this->name_.c_str());
|
||||
} else if (this->is_closing_blocked_()) { // Blocked
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Obstacle detected during closing.", this->name_.c_str());
|
||||
this->direction_idle_();
|
||||
if (this->obstacle_rollback_ != 0) {
|
||||
this->set_timeout(ROLLBACK_TIMEOUT_ID, 300, [this]() {
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Rollback.", this->name_.c_str());
|
||||
this->target_position_ = clamp(this->position + this->obstacle_rollback_, 0.0F, 1.0F);
|
||||
this->start_direction_(COVER_OPERATION_OPENING);
|
||||
});
|
||||
}
|
||||
} else if (this->is_initial_delay_finished_() && !this->is_closing_()) { // End reached
|
||||
auto dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Close position reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
this->direction_idle_(COVER_CLOSED);
|
||||
}
|
||||
}
|
||||
if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
this->direction_idle_();
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ void DallasTemperatureSensor::update() {
|
||||
}
|
||||
|
||||
float tempc = this->get_temp_c_();
|
||||
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", LOG_STR_ARG(this->get_log_name()), tempc);
|
||||
ESP_LOGD(TAG, "'%s': Got Temperature=%f°C", this->get_name().c_str(), tempc);
|
||||
this->publish_state(tempc);
|
||||
});
|
||||
}
|
||||
@@ -65,7 +65,7 @@ bool DallasTemperatureSensor::read_scratch_pad_() {
|
||||
i = this->bus_->read8();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s' - reading scratch pad failed bus reset", this->get_name().c_str());
|
||||
this->status_set_warning(LOG_STR("bus reset failed"));
|
||||
}
|
||||
return success;
|
||||
|
||||
@@ -30,7 +30,7 @@ void DateEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_, this->day_);
|
||||
ESP_LOGV(TAG, "'%s' >> %d-%d-%d", this->get_name().c_str(), this->year_, this->month_, this->day_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_DATE) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_date_update(this);
|
||||
@@ -81,7 +81,7 @@ void DateCall::validate_() {
|
||||
|
||||
void DateCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
|
||||
if (this->year_.has_value()) {
|
||||
ESP_LOGV(TAG, " Year: %d", *this->year_);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_DATE(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ void DateTimeEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->year_, this->month_,
|
||||
ESP_LOGV(TAG, "'%s' >> %04u-%02u-%02u %02d:%02d:%02d", this->get_name().c_str(), this->year_, this->month_,
|
||||
this->day_, this->hour_, this->minute_, this->second_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_DATETIME) && defined(USE_CONTROLLER_REGISTRY)
|
||||
@@ -125,7 +125,7 @@ void DateTimeCall::validate_() {
|
||||
|
||||
void DateTimeCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
|
||||
if (this->year_.has_value()) {
|
||||
ESP_LOGV(TAG, " Year: %d", *this->year_);
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_DATETIME(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void TimeEntity::publish_state() {
|
||||
return;
|
||||
}
|
||||
this->set_has_state(true);
|
||||
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", LOG_STR_ARG(this->get_log_name()), this->hour_, this->minute_, this->second_);
|
||||
ESP_LOGV(TAG, "'%s' >> %02d:%02d:%02d", this->get_name().c_str(), this->hour_, this->minute_, this->second_);
|
||||
this->state_callback_.call();
|
||||
#if defined(USE_DATETIME_TIME) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_time_update(this);
|
||||
@@ -50,7 +50,7 @@ void TimeCall::validate_() {
|
||||
|
||||
void TimeCall::perform() {
|
||||
this->validate_();
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
if (this->hour_.has_value()) {
|
||||
ESP_LOGV(TAG, " Hour: %d", *this->hour_);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace esphome::datetime {
|
||||
|
||||
#define LOG_DATETIME_TIME(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ void DewPointComponent::dump_config() {
|
||||
"Sources\n"
|
||||
" Temperature: '%s'\n"
|
||||
" Humidity: '%s'",
|
||||
LOG_STR_ARG(this->temperature_sensor_->get_log_name()),
|
||||
LOG_STR_ARG(this->humidity_sensor_->get_log_name()));
|
||||
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
|
||||
}
|
||||
|
||||
float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; }
|
||||
@@ -76,8 +75,8 @@ void DewPointComponent::loop() {
|
||||
// Publish the calculated dew point
|
||||
this->publish_state(dew_point);
|
||||
|
||||
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", LOG_STR_ARG(this->get_log_name()), dew_point,
|
||||
this->temperature_value_, this->humidity_value_);
|
||||
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_,
|
||||
this->humidity_value_);
|
||||
}
|
||||
|
||||
} // namespace esphome::dew_point
|
||||
|
||||
@@ -36,7 +36,7 @@ void DutyCycleSensor::update() {
|
||||
const float total_time = float(now - this->last_update_);
|
||||
|
||||
const float value = (on_time * 100.0f) / total_time;
|
||||
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", LOG_STR_ARG(this->get_log_name()), value);
|
||||
ESP_LOGD(TAG, "'%s' Got duty cycle=%.1f%%", this->get_name().c_str(), value);
|
||||
this->publish_state(value);
|
||||
}
|
||||
this->last_update_ = now;
|
||||
|
||||
@@ -118,8 +118,13 @@ void Ecocomfort2Fan::on_status() {
|
||||
|
||||
int new_speed = this->speed;
|
||||
uint8_t base_speed = raw_speed & SPEED_MASK;
|
||||
if (base_speed >= SPEED_SLEEP && base_speed <= SPEED_VEL3)
|
||||
if (raw_speed & FLAG_BOOST) {
|
||||
new_speed = SPEED_COUNT;
|
||||
} else if (raw_speed & FLAG_NIGHT) {
|
||||
new_speed = SPEED_SLEEP;
|
||||
} else if (base_speed >= SPEED_SLEEP && base_speed <= SPEED_VEL3) {
|
||||
new_speed = base_speed;
|
||||
}
|
||||
const Preset *preset = find_preset(mode, (raw_speed & FLAG_AUTO) != 0);
|
||||
const char *new_preset = preset != nullptr ? preset->name : nullptr;
|
||||
bool same_preset = new_preset == nullptr ? !this->has_preset_mode() : this->get_preset_mode().c_str() == new_preset;
|
||||
|
||||
@@ -205,10 +205,6 @@ void Ecocomfort2Hub::publish_unknown_() {
|
||||
sensor->publish_state(NAN);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->boost_binary_sensor_ != nullptr)
|
||||
this->boost_binary_sensor_->invalidate_state();
|
||||
#endif
|
||||
}
|
||||
|
||||
// C_OPER: mode byte, speed/flags byte
|
||||
@@ -220,6 +216,10 @@ void Ecocomfort2Hub::on_oper_(const uint8_t *data, uint16_t len) {
|
||||
this->mode_ = data[0];
|
||||
this->speed_ = data[1];
|
||||
ESP_LOGD(TAG, "[%s] C_OPER: mode=0x%02x, speed=0x%02x", this->parent_->address_str(), this->mode_, this->speed_);
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->boost_binary_sensor_ != nullptr)
|
||||
this->boost_binary_sensor_->publish_state((this->speed_ & FLAG_BOOST) != 0);
|
||||
#endif
|
||||
#ifdef ECOCOMFORT2_CHILD_COUNT
|
||||
for (auto *child : this->children_) {
|
||||
child->on_status();
|
||||
@@ -227,9 +227,7 @@ void Ecocomfort2Hub::on_oper_(const uint8_t *data, uint16_t len) {
|
||||
#endif
|
||||
}
|
||||
|
||||
// C_STATE: bytes 0-1 the mode and speed the unit runs; byte 1 also has the boost flag (0x40) and the advanced
|
||||
// control step (0x20). Byte 2 the air flow direction, bytes 3-4 temperature and 5-6 humidity in hundredths,
|
||||
// 7-8 VOC in ppb
|
||||
// C_STATE: bytes 3-4 temperature and 5-6 humidity in hundredths, 7-8 VOC in ppb, byte 2 the air flow direction
|
||||
void Ecocomfort2Hub::on_state_(const uint8_t *data, uint16_t len) {
|
||||
if (len < 9) {
|
||||
ESP_LOGW(TAG, "[%s] C_STATE too short: %u bytes", this->parent_->address_str(), len);
|
||||
@@ -238,12 +236,8 @@ void Ecocomfort2Hub::on_state_(const uint8_t *data, uint16_t len) {
|
||||
const float temperature = static_cast<int16_t>(encode_uint16(data[3], data[4])) / 100.0f;
|
||||
const float humidity = encode_uint16(data[5], data[6]) / 100.0f;
|
||||
const uint16_t voc = encode_uint16(data[7], data[8]);
|
||||
ESP_LOGD(TAG, "[%s] C_STATE: mode=0x%02x, speed=0x%02x, %.2f °C, %.2f %%, %u ppb, direction=%u",
|
||||
this->parent_->address_str(), data[0], data[1], temperature, humidity, voc, data[2]);
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->boost_binary_sensor_ != nullptr)
|
||||
this->boost_binary_sensor_->publish_state((data[1] & FLAG_BOOST) != 0);
|
||||
#endif
|
||||
ESP_LOGD(TAG, "[%s] C_STATE: %.2f °C, %.2f %%, %u ppb, direction=%u", this->parent_->address_str(), temperature,
|
||||
humidity, voc, data[2]);
|
||||
#ifdef USE_SENSOR
|
||||
if (this->temperature_sensor_ != nullptr)
|
||||
this->temperature_sensor_->publish_state(temperature);
|
||||
@@ -273,7 +267,7 @@ void Ecocomfort2Hub::on_info_(const uint8_t *data, uint16_t len) {
|
||||
}
|
||||
|
||||
#ifdef USE_TIME
|
||||
// C_CLOCK: two-digit year, month, day, weekday with Monday as 0, hour, minute, second, automatic DST flag
|
||||
// C_CLOCK: hour, minute, second, weekday with Monday as 0, day, month, year as two bytes
|
||||
void Ecocomfort2Hub::sync_clock_() {
|
||||
if (!this->is_ready() || this->char_handle_clock_ == 0)
|
||||
return;
|
||||
@@ -282,11 +276,15 @@ void Ecocomfort2Hub::sync_clock_() {
|
||||
return;
|
||||
// ESPTime counts Sunday=1 .. Saturday=7, the unit Monday=0 .. Sunday=6
|
||||
const uint8_t weekday = (now.day_of_week + 5) % 7;
|
||||
// The time source already applies DST and every sync rewrites the clock, so the unit must not shift it again
|
||||
uint8_t data[8]{
|
||||
static_cast<uint8_t>(now.year % 100), now.month, now.day_of_month, weekday, now.hour, now.minute, now.second, 0};
|
||||
ESP_LOGD(TAG, "[%s] Syncing clock to %04u-%02u-%02u %02u:%02u:%02u", this->parent_->address_str(), now.year,
|
||||
now.month, now.day_of_month, now.hour, now.minute, now.second);
|
||||
uint8_t data[8]{now.hour,
|
||||
now.minute,
|
||||
now.second,
|
||||
weekday,
|
||||
now.day_of_month,
|
||||
now.month,
|
||||
static_cast<uint8_t>(now.year >> 8),
|
||||
static_cast<uint8_t>(now.year)};
|
||||
ESP_LOGD(TAG, "[%s] Syncing clock to %02u:%02u:%02u", this->parent_->address_str(), now.hour, now.minute, now.second);
|
||||
auto status =
|
||||
esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_clock_,
|
||||
sizeof(data), data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
|
||||
|
||||
@@ -32,8 +32,7 @@ static constexpr uint8_t OPER_OUT = 0x02;
|
||||
static constexpr uint8_t OPER_IN_OUT = 0x03;
|
||||
static constexpr uint8_t OPER_SENSOR_OR_AUTO = 0x04;
|
||||
|
||||
// Speed byte: speed in the low nibble, flags in the high nibble.
|
||||
// C_OPER carries FLAG_AUTO; the unit reports FLAG_BOOST in byte 1 of C_STATE.
|
||||
// C_OPER byte 1: speed in the low nibble, flags in the high nibble
|
||||
static constexpr uint8_t SPEED_OFF = 0x00;
|
||||
static constexpr uint8_t SPEED_SLEEP = 0x01;
|
||||
static constexpr uint8_t SPEED_VEL1 = 0x02;
|
||||
@@ -42,6 +41,7 @@ static constexpr uint8_t SPEED_VEL3 = 0x04;
|
||||
static constexpr uint8_t SPEED_MASK = 0x0F;
|
||||
static constexpr uint8_t FLAG_AUTO = 0x10;
|
||||
static constexpr uint8_t FLAG_BOOST = 0x40;
|
||||
static constexpr uint8_t FLAG_NIGHT = 0x80;
|
||||
|
||||
/** Hub component for Ecocomfort 2.0 VMC via BLE. */
|
||||
class Ecocomfort2Hub : public esphome::ble_client::BLEClientNode, public PollingComponent {
|
||||
|
||||
@@ -70,20 +70,20 @@ void EndstopCover::loop() {
|
||||
|
||||
if (this->current_operation == COVER_OPERATION_OPENING && this->is_open_()) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Open endstop reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->position = COVER_OPEN;
|
||||
this->publish_state();
|
||||
} else if (this->current_operation == COVER_OPERATION_CLOSING && this->is_closed_()) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()), dur);
|
||||
ESP_LOGD(TAG, "'%s' - Close endstop reached. Took %.1fs.", this->name_.c_str(), dur);
|
||||
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->position = COVER_CLOSED;
|
||||
this->publish_state();
|
||||
} else if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
CODEOWNERS = ["@GioMez"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
DOMAIN = "es9038q2m_katana"
|
||||
@@ -1,92 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import audio_dac, i2c
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_BITS_PER_SAMPLE, CONF_ID, CONF_SAMPLE_RATE
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CONF_DEEMPHASIS = "deemphasis"
|
||||
CONF_DOP = "dop"
|
||||
CONF_FILTER_SHAPE = "filter_shape"
|
||||
|
||||
# Fields of the Katana format register: channel layout, word length and rate code.
|
||||
FORMAT_STEREO = 0x80
|
||||
BITS_PER_SAMPLE_CODES = {16: 0x10, 24: 0x20, 32: 0x30}
|
||||
SAMPLE_RATE_CODES = {
|
||||
44100: 0x04,
|
||||
48000: 0x05,
|
||||
88200: 0x06,
|
||||
96000: 0x07,
|
||||
176400: 0x08,
|
||||
192000: 0x09,
|
||||
352800: 0x0A,
|
||||
384000: 0x0B,
|
||||
}
|
||||
|
||||
es9038q2m_katana_ns = cg.esphome_ns.namespace("es9038q2m_katana")
|
||||
ES9038Q2MKatana = es9038q2m_katana_ns.class_(
|
||||
"ES9038Q2MKatana",
|
||||
audio_dac.AudioDac,
|
||||
cg.Component,
|
||||
i2c.I2CDevice,
|
||||
)
|
||||
|
||||
FilterShape = es9038q2m_katana_ns.enum("FilterShape")
|
||||
FILTER_SHAPES = {
|
||||
"linear_phase_fast": FilterShape.FILTER_SHAPE_LINEAR_PHASE_FAST,
|
||||
"linear_phase_slow": FilterShape.FILTER_SHAPE_LINEAR_PHASE_SLOW,
|
||||
"minimum_phase_fast": FilterShape.FILTER_SHAPE_MIN_PHASE_FAST,
|
||||
"minimum_phase_slow": FilterShape.FILTER_SHAPE_MIN_PHASE_SLOW,
|
||||
"apodizing": FilterShape.FILTER_SHAPE_APODIZING,
|
||||
"hybrid": FilterShape.FILTER_SHAPE_HYBRID,
|
||||
"brick_wall": FilterShape.FILTER_SHAPE_BRICK_WALL,
|
||||
}
|
||||
|
||||
DeemphasisMode = es9038q2m_katana_ns.enum("DeemphasisMode")
|
||||
DEEMPHASIS_MODES = {
|
||||
"bypass": DeemphasisMode.DEEMPHASIS_BYPASS,
|
||||
"32khz": DeemphasisMode.DEEMPHASIS_32KHZ,
|
||||
"44_1khz": DeemphasisMode.DEEMPHASIS_44_1KHZ,
|
||||
"48khz": DeemphasisMode.DEEMPHASIS_48KHZ,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ES9038Q2MKatana),
|
||||
cv.Optional(CONF_FILTER_SHAPE, default="apodizing"): cv.enum(
|
||||
FILTER_SHAPES, lower=True
|
||||
),
|
||||
cv.Optional(CONF_BITS_PER_SAMPLE, default="16bit"): cv.All(
|
||||
cv.float_with_unit("bits", "bit"),
|
||||
cv.one_of(*BITS_PER_SAMPLE_CODES, int=True),
|
||||
),
|
||||
cv.Optional(CONF_SAMPLE_RATE, default=48000): cv.one_of(
|
||||
*SAMPLE_RATE_CODES, int=True
|
||||
),
|
||||
cv.Optional(CONF_DEEMPHASIS, default="bypass"): cv.enum(
|
||||
DEEMPHASIS_MODES, lower=True
|
||||
),
|
||||
# Only switches the control logic; the source must already send DoP frames.
|
||||
cv.Optional(CONF_DOP, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x30))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
cg.add(var.set_filter_shape(config[CONF_FILTER_SHAPE]))
|
||||
cg.add(
|
||||
var.set_format(
|
||||
FORMAT_STEREO
|
||||
| BITS_PER_SAMPLE_CODES[config[CONF_BITS_PER_SAMPLE]]
|
||||
| SAMPLE_RATE_CODES[config[CONF_SAMPLE_RATE]]
|
||||
)
|
||||
)
|
||||
cg.add(var.set_deemphasis_mode(config[CONF_DEEMPHASIS]))
|
||||
cg.add(var.set_dop_enabled(config[CONF_DOP]))
|
||||
@@ -1,176 +0,0 @@
|
||||
#include "es9038q2m_katana.h"
|
||||
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace esphome::es9038q2m_katana {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "es9038q2m_katana");
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint8_t KATANA_CHIP_ID = 0x30;
|
||||
|
||||
constexpr uint8_t KATANA_REG_CHIP_ID = 0x00;
|
||||
constexpr uint8_t KATANA_REG_RESET = 0x01;
|
||||
constexpr uint8_t KATANA_REG_VOLUME_1 = 0x02;
|
||||
constexpr uint8_t KATANA_REG_VOLUME_2 = 0x03;
|
||||
constexpr uint8_t KATANA_REG_MUTE = 0x04;
|
||||
constexpr uint8_t KATANA_REG_DSP_PROGRAM = 0x05;
|
||||
constexpr uint8_t KATANA_REG_DEEMPHASIS = 0x06;
|
||||
constexpr uint8_t KATANA_REG_DOP = 0x07;
|
||||
constexpr uint8_t KATANA_REG_FORMAT = 0x08;
|
||||
constexpr uint8_t KATANA_REG_COMMAND = 0x09;
|
||||
constexpr uint8_t KATANA_REG_MUTE_STREAM = 0x0A;
|
||||
|
||||
constexpr float KATANA_VOLUME_MIDPOINT = 0.5f;
|
||||
constexpr float KATANA_VOLUME_MIDPOINT_STEPS = 50.0f; // -25 dB at 50% volume.
|
||||
// Cubic amplitude gain: -20 * log10(volume^3) / 0.5 attenuation steps.
|
||||
constexpr float KATANA_VOLUME_CUBIC_SCALE = 120.0f;
|
||||
constexpr uint8_t KATANA_VOLUME_FULL_ATTENUATION = 255;
|
||||
|
||||
// The control logic ignores writes for this long after a reset.
|
||||
constexpr uint32_t RESET_SETTLE_DELAY_MS = 10;
|
||||
|
||||
const LogString *filter_shape_to_str(FilterShape shape) {
|
||||
switch (shape) {
|
||||
case FILTER_SHAPE_LINEAR_PHASE_FAST:
|
||||
return LOG_STR("linear_phase_fast");
|
||||
case FILTER_SHAPE_LINEAR_PHASE_SLOW:
|
||||
return LOG_STR("linear_phase_slow");
|
||||
case FILTER_SHAPE_MIN_PHASE_FAST:
|
||||
return LOG_STR("minimum_phase_fast");
|
||||
case FILTER_SHAPE_MIN_PHASE_SLOW:
|
||||
return LOG_STR("minimum_phase_slow");
|
||||
case FILTER_SHAPE_APODIZING:
|
||||
return LOG_STR("apodizing");
|
||||
case FILTER_SHAPE_HYBRID:
|
||||
return LOG_STR("hybrid");
|
||||
default:
|
||||
return LOG_STR("brick_wall");
|
||||
}
|
||||
}
|
||||
|
||||
const LogString *deemphasis_to_str(DeemphasisMode mode) {
|
||||
switch (mode) {
|
||||
case DEEMPHASIS_32KHZ:
|
||||
return LOG_STR("32khz");
|
||||
case DEEMPHASIS_44_1KHZ:
|
||||
return LOG_STR("44_1khz");
|
||||
case DEEMPHASIS_48KHZ:
|
||||
return LOG_STR("48khz");
|
||||
default:
|
||||
return LOG_STR("bypass");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ES9038Q2MKatana::setup() {
|
||||
uint8_t chip_id = 0;
|
||||
if (!this->read_byte(KATANA_REG_CHIP_ID, &chip_id)) {
|
||||
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
return;
|
||||
}
|
||||
if (chip_id != KATANA_CHIP_ID) {
|
||||
ESP_LOGE(TAG, "Unexpected chip ID 0x%02X", chip_id);
|
||||
this->mark_failed(LOG_STR("Unexpected chip ID"));
|
||||
return;
|
||||
}
|
||||
if (!this->write_byte(KATANA_REG_RESET, 0x01)) {
|
||||
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
return;
|
||||
}
|
||||
delay(RESET_SETTLE_DELAY_MS);
|
||||
|
||||
// MUTE_STREAM is the gate the Linux driver closes between streams; ESPHome has no such
|
||||
// notion, so it stays open and mute is only ever driven through MUTE.
|
||||
if (!this->write_byte(KATANA_REG_FORMAT, this->format_) || !this->write_byte(KATANA_REG_COMMAND, 0x00) ||
|
||||
!this->write_byte(KATANA_REG_DSP_PROGRAM, this->filter_shape_) ||
|
||||
!this->write_byte(KATANA_REG_DEEMPHASIS, this->deemphasis_mode_) ||
|
||||
!this->write_byte(KATANA_REG_DOP, this->dop_enabled_ ? 1 : 0) || !this->write_volume_() ||
|
||||
!this->write_byte(KATANA_REG_MUTE, this->is_muted_ ? 1 : 0) || !this->write_byte(KATANA_REG_MUTE_STREAM, 0x00)) {
|
||||
this->mark_failed(LOG_STR("Failed to configure the control logic"));
|
||||
}
|
||||
}
|
||||
|
||||
void ES9038Q2MKatana::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"ES9038Q2M Katana:\n"
|
||||
" Filter shape: %s\n"
|
||||
" De-emphasis: %s\n"
|
||||
" Format register: 0x%02X\n"
|
||||
" DoP: %s",
|
||||
LOG_STR_ARG(filter_shape_to_str(this->filter_shape_)),
|
||||
LOG_STR_ARG(deemphasis_to_str(this->deemphasis_mode_)), this->format_, ONOFF(this->dop_enabled_));
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed())
|
||||
return;
|
||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||
for (uint8_t reg = KATANA_REG_CHIP_ID; reg <= KATANA_REG_MUTE_STREAM; reg++) {
|
||||
uint8_t value = 0;
|
||||
if (this->read_byte(reg, &value)) {
|
||||
ESP_LOGV(TAG, " Register 0x%02X: 0x%02X", reg, value);
|
||||
} else {
|
||||
ESP_LOGV(TAG, " Register 0x%02X: read failed", reg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Both channel registers follow ESPHome's single master volume.
|
||||
bool ES9038Q2MKatana::write_volume_() {
|
||||
return this->write_byte(KATANA_REG_VOLUME_1, this->volume_reg_) &&
|
||||
this->write_byte(KATANA_REG_VOLUME_2, this->volume_reg_);
|
||||
}
|
||||
|
||||
// Records the outcome of a runtime write; the cached state only changes on success.
|
||||
bool ES9038Q2MKatana::check_write_(bool ok) {
|
||||
if (ok) {
|
||||
this->status_clear_warning();
|
||||
} else {
|
||||
this->status_set_warning(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool ES9038Q2MKatana::set_volume(float volume) {
|
||||
if (this->is_failed())
|
||||
return false;
|
||||
volume = clamp(volume, 0.0f, 1.0f);
|
||||
const uint8_t previous = this->volume_reg_;
|
||||
float attenuation = KATANA_VOLUME_FULL_ATTENUATION;
|
||||
if (volume >= KATANA_VOLUME_MIDPOINT) {
|
||||
attenuation = KATANA_VOLUME_MIDPOINT_STEPS * (1.0f - volume) / (1.0f - KATANA_VOLUME_MIDPOINT);
|
||||
} else if (volume > 0.0f) {
|
||||
attenuation = KATANA_VOLUME_MIDPOINT_STEPS - KATANA_VOLUME_CUBIC_SCALE * log10f(volume / KATANA_VOLUME_MIDPOINT);
|
||||
}
|
||||
this->volume_reg_ =
|
||||
static_cast<uint8_t>(lroundf(clamp(attenuation, 0.0f, static_cast<float>(KATANA_VOLUME_FULL_ATTENUATION))));
|
||||
if (this->check_write_(this->write_volume_()))
|
||||
return true;
|
||||
this->volume_reg_ = previous;
|
||||
return false;
|
||||
}
|
||||
|
||||
float ES9038Q2MKatana::volume() {
|
||||
if (this->volume_reg_ == KATANA_VOLUME_FULL_ATTENUATION)
|
||||
return 0.0f;
|
||||
if (this->volume_reg_ <= KATANA_VOLUME_MIDPOINT_STEPS)
|
||||
return 1.0f - this->volume_reg_ * (1.0f - KATANA_VOLUME_MIDPOINT) / KATANA_VOLUME_MIDPOINT_STEPS;
|
||||
return KATANA_VOLUME_MIDPOINT *
|
||||
powf(10.0f, (KATANA_VOLUME_MIDPOINT_STEPS - this->volume_reg_) / KATANA_VOLUME_CUBIC_SCALE);
|
||||
}
|
||||
|
||||
bool ES9038Q2MKatana::set_mute_state_(bool mute_state) {
|
||||
if (this->is_failed())
|
||||
return false;
|
||||
if (!this->check_write_(this->write_byte(KATANA_REG_MUTE, mute_state ? 1 : 0)))
|
||||
return false;
|
||||
this->is_muted_ = mute_state;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace esphome::es9038q2m_katana
|
||||
@@ -1,62 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/components/audio_dac/audio_dac.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome::es9038q2m_katana {
|
||||
|
||||
// DSP program numbers of the Katana control interface; there is no program 5.
|
||||
enum FilterShape : uint8_t {
|
||||
FILTER_SHAPE_LINEAR_PHASE_FAST = 0,
|
||||
FILTER_SHAPE_LINEAR_PHASE_SLOW = 1,
|
||||
FILTER_SHAPE_MIN_PHASE_FAST = 2,
|
||||
FILTER_SHAPE_MIN_PHASE_SLOW = 3,
|
||||
FILTER_SHAPE_APODIZING = 4,
|
||||
FILTER_SHAPE_HYBRID = 6,
|
||||
FILTER_SHAPE_BRICK_WALL = 7,
|
||||
};
|
||||
|
||||
enum DeemphasisMode : uint8_t {
|
||||
DEEMPHASIS_BYPASS = 0,
|
||||
DEEMPHASIS_32KHZ = 1,
|
||||
DEEMPHASIS_44_1KHZ = 2,
|
||||
DEEMPHASIS_48KHZ = 3,
|
||||
};
|
||||
|
||||
// Boards that expose an ES9038Q2M through the Allo Katana control logic at I2C address 0x30.
|
||||
// Ported from the Linux driver sound/soc/bcm/allo-katana-codec.c; the DAC's own registers
|
||||
// are never written, the control logic applies the configuration itself.
|
||||
class ES9038Q2MKatana : public audio_dac::AudioDac, public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
// Cubic below 50%, then 0.5 dB per 1% above, meeting at -25 dB.
|
||||
// Zero selects full attenuation (-127.5 dB).
|
||||
bool set_volume(float volume) override;
|
||||
float volume() override;
|
||||
bool set_mute_off() override { return this->set_mute_state_(false); }
|
||||
bool set_mute_on() override { return this->set_mute_state_(true); }
|
||||
bool is_muted() override { return this->is_muted_; }
|
||||
|
||||
void set_filter_shape(FilterShape shape) { this->filter_shape_ = shape; }
|
||||
void set_format(uint8_t format) { this->format_ = format; }
|
||||
void set_deemphasis_mode(DeemphasisMode mode) { this->deemphasis_mode_ = mode; }
|
||||
void set_dop_enabled(bool enabled) { this->dop_enabled_ = enabled; }
|
||||
|
||||
protected:
|
||||
bool set_mute_state_(bool mute_state);
|
||||
bool write_volume_();
|
||||
bool check_write_(bool ok);
|
||||
|
||||
FilterShape filter_shape_{FILTER_SHAPE_APODIZING};
|
||||
DeemphasisMode deemphasis_mode_{DEEMPHASIS_BYPASS};
|
||||
uint8_t format_{0};
|
||||
// Attenuation in 0.5 dB steps: 0 is loudest, 255 quietest. Starts 20 dB down.
|
||||
uint8_t volume_reg_{0x28};
|
||||
bool dop_enabled_{false};
|
||||
};
|
||||
|
||||
} // namespace esphome::es9038q2m_katana
|
||||
@@ -2920,7 +2920,6 @@ async def _finalize_arduino_aware_flags():
|
||||
if not arduino_linked:
|
||||
cg.add_build_flag("-Wl,--wrap=esp_panic_handler")
|
||||
cg.add_define("USE_ESP32_CRASH_HANDLER")
|
||||
cg.add_define("USE_CRASH_HANDLER")
|
||||
elif not CORE.using_arduino:
|
||||
cg.add_build_flag("-DUSE_ARDUINO")
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ static bool s_crash_data_valid = false; // NOLINT(cppcoreguidelines-avoid-non-c
|
||||
|
||||
namespace esphome::esp32 {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, CRASH_LOG_TAG);
|
||||
ESPHOME_LOG_TAG(TAG, "esp32.crash");
|
||||
|
||||
// RAM copy of the build timestamp. The generated constant lives in flash,
|
||||
// which the panic handler must not read (cache may be disabled during
|
||||
@@ -175,8 +175,7 @@ static uint32_t s_current_build_time = static_cast<uint32_t>(ESPHOME_BUILD_TIME)
|
||||
|
||||
// Validate the NOINIT record. Runs on every has_data() call; re-running is
|
||||
// harmless and the magic is left alone so the record survives an OTA
|
||||
// rollback reboot, crash_handler_clear() drops it once a log client has it
|
||||
// (logger::log_crash_to_client(), for the API and MQTT).
|
||||
// rollback reboot, crash_handler_clear() drops it once an API client has it.
|
||||
static void read_crash_data() {
|
||||
if (s_raw_crash_data.magic == CRASH_MAGIC && s_raw_crash_data.version == CRASH_DATA_VERSION) {
|
||||
s_crash_data_valid = true;
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
|
||||
namespace esphome::esp32 {
|
||||
|
||||
/// The tag the crash record is logged under, so a client can check the level in force for it
|
||||
inline constexpr const char *CRASH_LOG_TAG = "esp32.crash";
|
||||
|
||||
/// Log crash data if a crash was detected on previous boot.
|
||||
void crash_handler_log();
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ void BLEClientBase::log_warning_(const char *message) {
|
||||
|
||||
esp_err_t BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
|
||||
uint16_t timeout, const char *param_type) {
|
||||
esp_ble_conn_update_params_t conn_params = {};
|
||||
esp_ble_conn_update_params_t conn_params = {{0}};
|
||||
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
|
||||
conn_params.min_int = min_interval;
|
||||
conn_params.max_int = max_interval;
|
||||
|
||||
@@ -132,9 +132,9 @@ void ESP32Camera::dump_config() {
|
||||
" External Clock: Pin:%d Frequency:%u\n"
|
||||
" I2C Pins: SDA:%d SCL:%d\n"
|
||||
" Reset Pin: %d",
|
||||
LOG_STR_ARG(this->get_log_name()), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2,
|
||||
conf.pin_d3, conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href,
|
||||
conf.pin_pclk, conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
|
||||
this->name_.c_str(), YESNO(this->is_internal()), conf.pin_d0, conf.pin_d1, conf.pin_d2, conf.pin_d3,
|
||||
conf.pin_d4, conf.pin_d5, conf.pin_d6, conf.pin_d7, conf.pin_vsync, conf.pin_href, conf.pin_pclk,
|
||||
conf.pin_xclk, conf.xclk_freq_hz, conf.pin_sccb_sda, conf.pin_sccb_scl, conf.pin_reset);
|
||||
|
||||
ESP_LOGCONFIG(TAG, " Resolution: %s", frame_size_to_str(this->config_.frame_size));
|
||||
ESP_LOGCONFIG(TAG, " Pixel Format: %s", pixel_format_to_str(this->config_.pixel_format));
|
||||
|
||||
@@ -346,13 +346,13 @@ void ESP32TouchComponent::loop() {
|
||||
child->publish_state(new_state);
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: %s (value: %" PRIu32 ", threshold: %" PRIu32 ")",
|
||||
LOG_STR_ARG(child->get_log_name()), ONOFF(new_state), value, child->get_threshold());
|
||||
child->get_name().c_str(), ONOFF(new_state), value, child->get_threshold());
|
||||
#else
|
||||
if (new_state) {
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: ON (value: %" PRIu32 ", benchmark: %" PRIu32 ", threshold: %" PRIu32 ")",
|
||||
LOG_STR_ARG(child->get_log_name()), value, benchmark, child->get_threshold());
|
||||
child->get_name().c_str(), value, benchmark, child->get_threshold());
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", LOG_STR_ARG(child->get_log_name()));
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF", child->get_name().c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -475,8 +475,7 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
|
||||
child->value_ = smooth_value;
|
||||
|
||||
#ifdef USE_ESP32_VARIANT_ESP32
|
||||
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, LOG_STR_ARG(child->get_log_name()), child->channel_id_,
|
||||
smooth_value);
|
||||
ESP_LOGD(TAG, "Touch Pad '%s' (Ch%d): %" PRIu32, child->get_name().c_str(), child->channel_id_, smooth_value);
|
||||
#else
|
||||
uint32_t benchmark = 0;
|
||||
touch_channel_read_data(child->chan_handle_, TOUCH_CHAN_DATA_TYPE_BENCHMARK, &benchmark);
|
||||
@@ -485,7 +484,7 @@ void ESP32TouchComponent::process_setup_mode_logging_(uint32_t now) {
|
||||
ESP_LOGD(TAG,
|
||||
"Touch Pad '%s' (Ch%d): value=%" PRIu32 ", benchmark=%" PRIu32 ", difference=%" PRId32
|
||||
" (set threshold < %" PRId32 " to detect touch)",
|
||||
LOG_STR_ARG(child->get_log_name()), child->channel_id_, smooth_value, benchmark, difference, difference);
|
||||
child->get_name().c_str(), child->channel_id_, smooth_value, benchmark, difference, difference);
|
||||
#endif
|
||||
}
|
||||
this->setup_mode_last_log_print_ = now;
|
||||
@@ -497,7 +496,7 @@ void ESP32TouchComponent::publish_initial_state_if_needed_(ESP32TouchBinarySenso
|
||||
if (now > INITIAL_STATE_DELAY_MS) {
|
||||
child->publish_initial_state(false);
|
||||
child->initial_state_published_ = true;
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", LOG_STR_ARG(child->get_log_name()));
|
||||
ESP_LOGV(TAG, "Touch Pad '%s' state: OFF (initial)", child->get_name().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,7 +420,6 @@ async def to_code(config: ConfigType) -> None:
|
||||
cg.add_define("ESPHOME_VARIANT", "ESP8266")
|
||||
cg.add_define(ThreadModel.SINGLE)
|
||||
cg.add_define("USE_ESP8266_CRASH_HANDLER")
|
||||
cg.add_define("USE_CRASH_HANDLER")
|
||||
|
||||
enable_scanf_float = config.get(CONF_ENABLE_SCANF_FLOAT)
|
||||
if enable_scanf_float is None and lambdas_use_scanf_float(CORE.config):
|
||||
|
||||
@@ -17,11 +17,11 @@ void Event::trigger(const char *event_type) {
|
||||
}
|
||||
}
|
||||
if (found == nullptr) {
|
||||
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", LOG_STR_ARG(this->get_log_name()), event_type);
|
||||
ESP_LOGE(TAG, "'%s': invalid event type for trigger(): %s", this->get_name().c_str(), event_type);
|
||||
return;
|
||||
}
|
||||
this->last_event_type_ = found;
|
||||
ESP_LOGV(TAG, "'%s' >> '%s'", LOG_STR_ARG(this->get_log_name()), this->last_event_type_);
|
||||
ESP_LOGV(TAG, "'%s' >> '%s'", this->get_name().c_str(), this->last_event_type_);
|
||||
this->event_callback_.call(StringRef(found));
|
||||
#if defined(USE_EVENT) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_event(this);
|
||||
|
||||
@@ -16,7 +16,7 @@ using EventTypes = ConstVector<const char *, true>;
|
||||
|
||||
#define LOG_EVENT(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
LOG_ENTITY_DEVICE_CLASS(TAG, prefix, *(obj)); \
|
||||
}
|
||||
|
||||
@@ -52,15 +52,14 @@ FanCall &FanCall::set_preset_mode(const char *preset_mode, size_t len) {
|
||||
this->preset_mode_ = validated_mode; // Store pointer from traits
|
||||
} else {
|
||||
// Preset mode not found in traits - log warning and don't set
|
||||
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", LOG_STR_ARG(this->parent_.get_log_name()), (int) len,
|
||||
preset_mode);
|
||||
ESP_LOGW(TAG, "%s: Preset mode '%.*s' not supported", this->parent_.get_name().c_str(), (int) len, preset_mode);
|
||||
this->preset_mode_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void FanCall::perform() {
|
||||
ESP_LOGV(TAG, "'%s' - Setting:", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting:", this->parent_.get_name().c_str());
|
||||
this->validate_();
|
||||
if (this->binary_state_.has_value()) {
|
||||
ESP_LOGV(TAG, " State: %s", ONOFF(*this->binary_state_));
|
||||
@@ -104,17 +103,17 @@ void FanCall::validate_() {
|
||||
}
|
||||
|
||||
if (this->oscillating_.has_value() && !traits.supports_oscillation()) {
|
||||
ESP_LOGW(TAG, "%s: Oscillation not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
ESP_LOGW(TAG, "%s: Oscillation not supported", this->parent_.get_name().c_str());
|
||||
this->oscillating_.reset();
|
||||
}
|
||||
|
||||
if (this->speed_.has_value() && !traits.supports_speed()) {
|
||||
ESP_LOGW(TAG, "%s: Speed control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
ESP_LOGW(TAG, "%s: Speed control not supported", this->parent_.get_name().c_str());
|
||||
this->speed_.reset();
|
||||
}
|
||||
|
||||
if (this->direction_.has_value() && !traits.supports_direction()) {
|
||||
ESP_LOGW(TAG, "%s: Direction control not supported", LOG_STR_ARG(this->parent_.get_log_name()));
|
||||
ESP_LOGW(TAG, "%s: Direction control not supported", this->parent_.get_name().c_str());
|
||||
this->direction_.reset();
|
||||
}
|
||||
}
|
||||
@@ -222,7 +221,7 @@ void Fan::publish_state() {
|
||||
ESP_LOGV(TAG,
|
||||
"'%s' >>\n"
|
||||
" State: %s",
|
||||
LOG_STR_ARG(this->get_log_name()), ONOFF(this->state));
|
||||
this->name_.c_str(), ONOFF(this->state));
|
||||
if (traits.supports_speed()) {
|
||||
ESP_LOGV(TAG, " Speed: %d", this->speed);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace esphome::fan {
|
||||
|
||||
#define LOG_FAN(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
(obj)->dump_traits_(TAG, prefix); \
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ void FeedbackCover::set_open_sensor(binary_sensor::BinarySensor *open_feedback)
|
||||
|
||||
// setup callbacks to react to sensor changes
|
||||
open_feedback->add_on_state_callback([this](bool state) {
|
||||
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - Open feedback '%s'.", this->name_.c_str(),
|
||||
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
|
||||
this->recompute_position_();
|
||||
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_OPENING) {
|
||||
@@ -112,7 +112,7 @@ void FeedbackCover::set_close_sensor(binary_sensor::BinarySensor *close_feedback
|
||||
this->close_feedback_ = close_feedback;
|
||||
|
||||
close_feedback->add_on_state_callback([this](bool state) {
|
||||
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - Close feedback '%s'.", this->name_.c_str(),
|
||||
state ? LOG_STR_LITERAL("STARTED") : LOG_STR_LITERAL("ENDED"));
|
||||
this->recompute_position_();
|
||||
if (!state && this->infer_endstop_ && this->current_trigger_operation_ == COVER_OPERATION_CLOSING) {
|
||||
@@ -151,7 +151,7 @@ void FeedbackCover::endstop_reached_(bool open_endstop) {
|
||||
// from a position slightly past the endpoint
|
||||
if (this->current_trigger_operation_ == (open_endstop ? COVER_OPERATION_OPENING : COVER_OPERATION_CLOSING)) {
|
||||
float dur = (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(),
|
||||
open_endstop ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"), dur);
|
||||
|
||||
// if there is no external mechanism, stop the cover
|
||||
@@ -198,7 +198,7 @@ void FeedbackCover::set_close_obstacle_sensor(binary_sensor::BinarySensor *close
|
||||
close_obstacle->add_on_state_callback([this](bool state) {
|
||||
if (state && (this->current_operation == COVER_OPERATION_CLOSING ||
|
||||
this->current_trigger_operation_ == COVER_OPERATION_CLOSING)) {
|
||||
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Close obstacle detected.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
|
||||
if (this->obstacle_rollback_) {
|
||||
@@ -215,7 +215,7 @@ void FeedbackCover::set_open_obstacle_sensor(binary_sensor::BinarySensor *open_o
|
||||
open_obstacle->add_on_state_callback([this](bool state) {
|
||||
if (state && (this->current_operation == COVER_OPERATION_OPENING ||
|
||||
this->current_trigger_operation_ == COVER_OPERATION_OPENING)) {
|
||||
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Open obstacle detected.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
|
||||
if (this->obstacle_rollback_) {
|
||||
@@ -251,7 +251,7 @@ void FeedbackCover::loop() {
|
||||
this->start_overshoot_time_ = now;
|
||||
} else if (now - this->start_overshoot_time_ > this->overshoot_duration_ ||
|
||||
now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Overshoot duration reached. Stopping cover.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
#endif
|
||||
@@ -259,7 +259,7 @@ void FeedbackCover::loop() {
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
} else if (now - this->start_dir_time_ > this->max_duration_) {
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
}
|
||||
}
|
||||
@@ -390,7 +390,7 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
|
||||
// check if there is an obstacle to start the new operation -> abort without any change
|
||||
// the case when an obstacle appears while moving is handled in the callback
|
||||
if (obstacle != nullptr && obstacle->state) {
|
||||
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - %s obstacle detected. Action not started.", this->name_.c_str(),
|
||||
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"));
|
||||
return;
|
||||
}
|
||||
@@ -401,13 +401,13 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
|
||||
if (this->direction_change_waittime_.has_value() && dir != COVER_OPERATION_IDLE &&
|
||||
this->current_operation != COVER_OPERATION_IDLE && dir != this->current_operation) {
|
||||
const uint32_t waittime = *this->direction_change_waittime_;
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", this->name_.c_str());
|
||||
this->start_direction_(COVER_OPERATION_IDLE);
|
||||
this->set_timeout(DIRECTION_CHANGE_TIMEOUT_ID, waittime, [this, dir]() { this->start_direction_(dir); });
|
||||
} else {
|
||||
this->set_current_operation_(dir, true);
|
||||
this->prev_command_trigger_ = trig;
|
||||
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - Firing '%s' trigger.", this->name_.c_str(),
|
||||
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("OPEN")
|
||||
: dir == COVER_OPERATION_CLOSING ? LOG_STR_LITERAL("CLOSE")
|
||||
: LOG_STR_LITERAL("STOP"));
|
||||
|
||||
@@ -1,40 +1,2 @@
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID, CONF_INTERRUPT_PIN
|
||||
from esphome.types import ConfigType
|
||||
|
||||
CODEOWNERS = ["@remcom"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
DOMAIN = "fusb302b"
|
||||
|
||||
CONF_REQUEST_VOLTAGE = "request_voltage"
|
||||
|
||||
fusb302b_ns = cg.esphome_ns.namespace("fusb302b")
|
||||
FUSB302B = fusb302b_ns.class_("FUSB302B", cg.Component, i2c.I2CDevice)
|
||||
|
||||
# USB PD fixed supply voltages are 5, 9, 12, 15 and 20 V; the highest one that does not exceed the
|
||||
# requested voltage is chosen.
|
||||
validate_voltage = cv.int_range(min=5, max=20)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(FUSB302B),
|
||||
cv.Required(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pullup_pin_schema,
|
||||
cv.Required(CONF_REQUEST_VOLTAGE): validate_voltage,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0x22)),
|
||||
cv.only_on_esp32,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
interrupt_pin = await cg.gpio_pin_expression(config[CONF_INTERRUPT_PIN])
|
||||
var = cg.new_Pvariable(config[CONF_ID], interrupt_pin)
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
cg.add(var.set_request_voltage(config[CONF_REQUEST_VOLTAGE]))
|
||||
|
||||
@@ -1,415 +0,0 @@
|
||||
#include "fusb302b.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include "fusb302b_registers.h"
|
||||
|
||||
namespace esphome::fusb302b {
|
||||
|
||||
ESPHOME_LOG_TAG(TAG, "fusb302b");
|
||||
|
||||
// Task notification bits
|
||||
static constexpr uint32_t NOTIFY_IRQ = 1 << 0;
|
||||
static constexpr uint32_t NOTIFY_STOP = 1 << 1;
|
||||
|
||||
static constexpr uint32_t TASK_STACK_SIZE = 4096;
|
||||
static constexpr UBaseType_t TASK_PRIORITY = 18;
|
||||
|
||||
static constexpr uint32_t STARTUP_DELAY_MS = 2000;
|
||||
static constexpr uint32_t CC_SETTLE_MS = 5;
|
||||
static constexpr uint32_t CC_POLL_INTERVAL_MS = 500;
|
||||
static constexpr uint32_t PD_POLL_INTERVAL_MS = 100;
|
||||
// Safety net in case an interrupt edge is missed while attached and idle
|
||||
static constexpr uint32_t IDLE_POLL_INTERVAL_MS = 1000;
|
||||
// Time to wait for the source to send its capabilities on its own after attach
|
||||
static constexpr uint32_t SOURCE_CAP_WAIT_MS = 5000;
|
||||
// Time to wait after each GET_SOURCE_CAP / soft reset before the next recovery step
|
||||
static constexpr uint32_t SOURCE_CAP_RETRY_MS = 2500;
|
||||
// Upper bound on back-to-back interrupt handling while INT_N stays asserted
|
||||
static constexpr uint8_t MAX_IRQ_ROUNDS = 8;
|
||||
// BC_LVL is read this many extra times to confirm a stable measurement
|
||||
static constexpr uint8_t CC_STABLE_READS = 5;
|
||||
static constexpr uint8_t CC_LEVEL_UNSTABLE = 0xFF;
|
||||
|
||||
void IRAM_ATTR FUSB302B::gpio_intr(FUSB302B *arg) {
|
||||
TaskHandle_t handle = arg->task_.get_handle();
|
||||
if (handle == nullptr)
|
||||
return;
|
||||
BaseType_t woken = pdFALSE;
|
||||
xTaskNotifyFromISR(handle, NOTIFY_IRQ, eSetBits, &woken);
|
||||
portYIELD_FROM_ISR(woken);
|
||||
}
|
||||
|
||||
void FUSB302B::task_func(void *arg) { static_cast<FUSB302B *>(arg)->run_task_(); }
|
||||
|
||||
void FUSB302B::setup() {
|
||||
uint8_t device_id = 0;
|
||||
if (!this->read_byte(FUSB_DEVICE_ID, &device_id)) {
|
||||
this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
|
||||
return;
|
||||
}
|
||||
const uint8_t version = device_id & FUSB_DEVICE_ID_VERSION_MASK;
|
||||
if (version != FUSB_DEVICE_ID_VERSION_A && version != FUSB_DEVICE_ID_VERSION_B) {
|
||||
ESP_LOGE(TAG, "Unknown device ID 0x%02X", device_id);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "Device ID 0x%02X (product %u, revision %u)", device_id, (device_id >> 2) & 0x3, device_id & 0x3);
|
||||
if (!this->init_chip_()) {
|
||||
this->mark_failed(LOG_STR("Initialization failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
this->interrupt_pin_->setup();
|
||||
// The task must exist before the interrupt is attached, since the ISR notifies it
|
||||
if (!this->task_.create(FUSB302B::task_func, "fusb302b", TASK_STACK_SIZE, this, TASK_PRIORITY, false)) {
|
||||
this->mark_failed(LOG_STR("Failed to create task"));
|
||||
return;
|
||||
}
|
||||
this->interrupt_pin_->attach_interrupt(&FUSB302B::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE);
|
||||
}
|
||||
|
||||
void FUSB302B::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"FUSB302B:\n"
|
||||
" Request Voltage: %u V",
|
||||
this->get_request_voltage());
|
||||
LOG_I2C_DEVICE(this);
|
||||
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||
}
|
||||
|
||||
void FUSB302B::on_shutdown() {
|
||||
this->interrupt_pin_->detach_interrupt();
|
||||
// The task parks itself instead of being deleted, so it can never be stopped in the middle of an I2C transfer
|
||||
if (this->task_.is_created())
|
||||
xTaskNotify(this->task_.get_handle(), NOTIFY_STOP, eSetBits);
|
||||
}
|
||||
|
||||
void FUSB302B::run_task_() {
|
||||
// Give the source time to settle after power-up before the first CC measurement
|
||||
vTaskDelay(pdMS_TO_TICKS(STARTUP_DELAY_MS));
|
||||
|
||||
while (true) {
|
||||
uint32_t wait_ms = CC_POLL_INTERVAL_MS;
|
||||
if (this->attached_) {
|
||||
const bool busy = this->waiting_for_source_caps_ || this->retry_request_pending_ || this->check_ams_();
|
||||
wait_ms = busy ? PD_POLL_INTERVAL_MS : IDLE_POLL_INTERVAL_MS;
|
||||
}
|
||||
uint32_t bits = 0;
|
||||
xTaskNotifyWait(0, UINT32_MAX, &bits, pdMS_TO_TICKS(wait_ms));
|
||||
|
||||
if (bits & NOTIFY_STOP) {
|
||||
while (true)
|
||||
vTaskSuspend(nullptr);
|
||||
}
|
||||
|
||||
// INT_N is held low until the interrupt registers are read, so a new event that arrives while it is
|
||||
// already low has no falling edge: keep servicing while the pin stays asserted.
|
||||
if (bits & NOTIFY_IRQ)
|
||||
this->handle_interrupt_();
|
||||
for (uint8_t i = 0; i < MAX_IRQ_ROUNDS && !this->interrupt_pin_->digital_read(); i++)
|
||||
this->handle_interrupt_();
|
||||
|
||||
if (!this->attached_) {
|
||||
this->try_attach_();
|
||||
continue;
|
||||
}
|
||||
this->check_transition_timeout_();
|
||||
this->check_request_retry_();
|
||||
this->check_source_caps_();
|
||||
}
|
||||
}
|
||||
|
||||
bool FUSB302B::init_chip_() {
|
||||
// Software reset restores all registers to their defaults
|
||||
if (!this->write_byte(FUSB_RESET, FUSB_RESET_SW_RES))
|
||||
return false;
|
||||
if (!this->reset_pd_())
|
||||
return false;
|
||||
|
||||
// Unmask the interrupts used for PD messaging and VBUS changes
|
||||
if (!this->write_byte(FUSB_MASK1, FUSB_MASK1_DEFAULT) || !this->write_byte(FUSB_MASKA, 0) ||
|
||||
!this->write_byte(FUSB_MASKB, 0))
|
||||
return false;
|
||||
|
||||
// Let the chip retransmit unacknowledged messages up to 3 times
|
||||
uint8_t control3 = 0;
|
||||
if (!this->read_byte(FUSB_CONTROL3, &control3))
|
||||
return false;
|
||||
control3 =
|
||||
(control3 & ~FUSB_CONTROL3_N_RETRIES_MASK) | (3 << FUSB_CONTROL3_N_RETRIES_SHIFT) | FUSB_CONTROL3_AUTO_RETRY;
|
||||
if (!this->write_byte(FUSB_CONTROL3, control3))
|
||||
return false;
|
||||
|
||||
if (!this->write_byte(FUSB_POWER, FUSB_POWER_ALL))
|
||||
return false;
|
||||
return this->reset_pd_();
|
||||
}
|
||||
|
||||
bool FUSB302B::reset_pd_() {
|
||||
this->reset_protocol_();
|
||||
// Writing CONTROL0 as a whole byte also clears INT_MASK, which is what enables the INT_N pin
|
||||
return this->write_byte(FUSB_CONTROL0, FUSB_CONTROL0_TX_FLUSH) &&
|
||||
this->write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH) && this->write_byte(FUSB_RESET, FUSB_RESET_PD_RESET);
|
||||
}
|
||||
|
||||
bool FUSB302B::enable_auto_crc_() {
|
||||
uint8_t switches1 = 0;
|
||||
return this->read_byte(FUSB_SWITCHES1, &switches1) &&
|
||||
this->write_byte(FUSB_SWITCHES1, switches1 | FUSB_SWITCHES1_AUTO_CRC);
|
||||
}
|
||||
|
||||
void FUSB302B::handle_interrupt_() {
|
||||
// STATUS0A, STATUS1A, INTERRUPTA, INTERRUPTB, STATUS0, STATUS1, INTERRUPT; reading clears the interrupts
|
||||
uint8_t regs[7];
|
||||
if (this->read_register(FUSB_STATUS0A, regs, sizeof(regs)) != i2c::ERROR_OK) {
|
||||
this->enter_error_();
|
||||
return;
|
||||
}
|
||||
const uint8_t interrupta = regs[2];
|
||||
const uint8_t status0 = regs[4];
|
||||
uint8_t status1 = regs[5];
|
||||
const uint8_t interrupt = regs[6];
|
||||
|
||||
if ((interrupt & FUSB_INTERRUPT_I_VBUSOK) && !(status0 & FUSB_STATUS0_VBUSOK)) {
|
||||
if (this->attached_)
|
||||
this->detach_();
|
||||
return;
|
||||
}
|
||||
if (interrupta & FUSB_INTERRUPTA_I_HARDRST) {
|
||||
if (this->attached_)
|
||||
this->handle_hard_reset_();
|
||||
return;
|
||||
}
|
||||
if (interrupta & FUSB_INTERRUPTA_I_SOFTRST) {
|
||||
ESP_LOGV(TAG, "Soft reset received");
|
||||
}
|
||||
if ((interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) && this->attached_)
|
||||
this->handle_transmit_failed_();
|
||||
|
||||
if (!this->attached_)
|
||||
return;
|
||||
PdMsg msg;
|
||||
while (!(status1 & FUSB_STATUS1_RX_EMPTY)) {
|
||||
bool is_sop = false;
|
||||
if (!this->read_message_(msg, is_sop)) {
|
||||
ESP_LOGW(TAG, "Reading message failed");
|
||||
// A partial read leaves the FIFO misaligned
|
||||
this->write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
|
||||
return;
|
||||
}
|
||||
// Only SOP packets are addressed to a sink; SOP'/SOP'' are for cable plugs
|
||||
if (is_sop)
|
||||
this->handle_message_(msg);
|
||||
if (!this->read_byte(FUSB_STATUS1, &status1))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool FUSB302B::read_message_(PdMsg &msg, bool &is_sop) {
|
||||
uint8_t token = 0;
|
||||
uint8_t header[2];
|
||||
if (!this->read_byte(FUSB_FIFOS, &token) || this->read_register(FUSB_FIFOS, header, 2) != i2c::ERROR_OK)
|
||||
return false;
|
||||
msg.set_header(encode_uint16(header[1], header[0]));
|
||||
|
||||
// Data objects, followed by the CRC32 that the chip already checked
|
||||
uint8_t buf[PD_MAX_NUM_DATA_OBJECTS * 4 + 4];
|
||||
if (this->read_register(FUSB_FIFOS, buf, msg.num_of_obj * 4 + 4) != i2c::ERROR_OK)
|
||||
return false;
|
||||
for (uint8_t i = 0; i < msg.num_of_obj; i++) {
|
||||
const uint8_t *obj = &buf[i * 4];
|
||||
msg.data_objects[i] = encode_uint32(obj[3], obj[2], obj[1], obj[0]);
|
||||
}
|
||||
is_sop = (token & FUSB_FIFO_RX_TOKEN_BITS) == FUSB_FIFO_RX_SOP;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FUSB302B::send_message(const PdMsg &msg) {
|
||||
// Register address, then the TX tokens; written in one transfer without the copy write_register() makes
|
||||
uint8_t buf[1 + 4 + 1 + 2 + PD_MAX_NUM_DATA_OBJECTS * 4 + 4];
|
||||
size_t len = 0;
|
||||
const uint16_t header = msg.get_coded_header();
|
||||
|
||||
buf[len++] = FUSB_FIFOS;
|
||||
buf[len++] = FUSB_TX_TOKEN_SYNC1;
|
||||
buf[len++] = FUSB_TX_TOKEN_SYNC1;
|
||||
buf[len++] = FUSB_TX_TOKEN_SYNC1;
|
||||
buf[len++] = FUSB_TX_TOKEN_SYNC2;
|
||||
buf[len++] = FUSB_TX_TOKEN_PACKSYM | (msg.num_of_obj * 4 + 2);
|
||||
buf[len++] = header & 0xFF;
|
||||
buf[len++] = header >> 8;
|
||||
for (uint8_t i = 0; i < msg.num_of_obj; i++) {
|
||||
const uint32_t obj = msg.data_objects[i];
|
||||
buf[len++] = obj & 0xFF;
|
||||
buf[len++] = (obj >> 8) & 0xFF;
|
||||
buf[len++] = (obj >> 16) & 0xFF;
|
||||
buf[len++] = obj >> 24;
|
||||
}
|
||||
buf[len++] = FUSB_TX_TOKEN_JAM_CRC;
|
||||
buf[len++] = FUSB_TX_TOKEN_EOP;
|
||||
buf[len++] = FUSB_TX_TOKEN_TXOFF;
|
||||
buf[len++] = FUSB_TX_TOKEN_TXON;
|
||||
|
||||
i2c::ErrorCode err = this->write(buf, len);
|
||||
if (err != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Sending message type %u failed (error %d)", msg.type, static_cast<int>(err));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FUSB302B::measure_cc_(uint8_t meas_switch, uint8_t &level) {
|
||||
if (!this->write_byte(FUSB_SWITCHES0, FUSB_SWITCHES0_PDWN_1 | FUSB_SWITCHES0_PDWN_2 | meas_switch))
|
||||
return false;
|
||||
vTaskDelay(pdMS_TO_TICKS(CC_SETTLE_MS));
|
||||
uint8_t status0 = 0;
|
||||
if (!this->read_byte(FUSB_STATUS0, &status0))
|
||||
return false;
|
||||
level = status0 & FUSB_STATUS0_BC_LVL;
|
||||
for (uint8_t i = 0; i < CC_STABLE_READS; i++) {
|
||||
if (!this->read_byte(FUSB_STATUS0, &status0))
|
||||
return false;
|
||||
if ((status0 & FUSB_STATUS0_BC_LVL) != level) {
|
||||
level = CC_LEVEL_UNSTABLE;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FUSB302B::try_attach_() {
|
||||
if (this->state_ == PdState::PD_STATE_ERROR) {
|
||||
if (!this->init_chip_())
|
||||
return;
|
||||
ESP_LOGI(TAG, "Communication restored");
|
||||
this->set_state_(PdState::PD_STATE_DISCONNECTED);
|
||||
}
|
||||
|
||||
uint8_t status0 = 0;
|
||||
if (!this->write_byte(FUSB_POWER, FUSB_POWER_ALL) || !this->read_byte(FUSB_STATUS0, &status0)) {
|
||||
this->enter_error_();
|
||||
return;
|
||||
}
|
||||
// A source may present its CC pull-up before VBUS is on; detach is only detected when VBUS drops
|
||||
if (!(status0 & FUSB_STATUS0_VBUSOK)) {
|
||||
this->cc_ambiguous_logged_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t cc1 = 0;
|
||||
uint8_t cc2 = 0;
|
||||
if (!this->write_byte(FUSB_SWITCHES1, FUSB_SWITCHES1_SPECREV_REV2) ||
|
||||
!this->write_byte(FUSB_MEASURE, FUSB_MEASURE_MDAC_CC) || !this->measure_cc_(FUSB_SWITCHES0_MEAS_CC1, cc1) ||
|
||||
!this->measure_cc_(FUSB_SWITCHES0_MEAS_CC2, cc2)) {
|
||||
this->enter_error_();
|
||||
return;
|
||||
}
|
||||
// Exactly one CC line carries the source pull-up; the other one is open
|
||||
uint8_t meas_switch;
|
||||
uint8_t tx_switch;
|
||||
if (cc1 != CC_LEVEL_UNSTABLE && cc1 > 0 && cc2 == 0) {
|
||||
meas_switch = FUSB_SWITCHES0_MEAS_CC1;
|
||||
tx_switch = FUSB_SWITCHES1_TXCC1;
|
||||
} else if (cc2 != CC_LEVEL_UNSTABLE && cc2 > 0 && cc1 == 0) {
|
||||
meas_switch = FUSB_SWITCHES0_MEAS_CC2;
|
||||
tx_switch = FUSB_SWITCHES1_TXCC2;
|
||||
} else {
|
||||
if (!this->cc_ambiguous_logged_) {
|
||||
ESP_LOGD(TAG, "VBUS present but no single CC line with a source pull-up (CC1 %u, CC2 %u)", cc1, cc2);
|
||||
this->cc_ambiguous_logged_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->write_byte(FUSB_SWITCHES0, FUSB_SWITCHES0_PDWN_1 | FUSB_SWITCHES0_PDWN_2 | meas_switch) ||
|
||||
!this->write_byte(FUSB_SWITCHES1, tx_switch | FUSB_SWITCHES1_SPECREV_REV2) || !this->enable_auto_crc_() ||
|
||||
!this->reset_pd_()) {
|
||||
this->enter_error_();
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "Attached on CC%u", meas_switch == FUSB_SWITCHES0_MEAS_CC1 ? 1 : 2);
|
||||
this->attached_ = true;
|
||||
this->cc_ambiguous_logged_ = false;
|
||||
this->start_source_cap_wait_(SourceCapStep::SOURCE_CAP_STEP_WAIT);
|
||||
this->set_state_and_contract_(PdState::PD_STATE_DEFAULT_CONTRACT, DEFAULT_CONTRACT);
|
||||
}
|
||||
|
||||
void FUSB302B::detach_() {
|
||||
ESP_LOGD(TAG, "Detached (VBUS lost)");
|
||||
this->attached_ = false;
|
||||
this->waiting_for_source_caps_ = false;
|
||||
this->reset_pd_();
|
||||
this->clear_contract_();
|
||||
this->set_state_(PdState::PD_STATE_DISCONNECTED);
|
||||
}
|
||||
|
||||
void FUSB302B::handle_hard_reset_() {
|
||||
ESP_LOGD(TAG, "Hard reset received");
|
||||
// The source returns to Type-C default power and sends its capabilities again
|
||||
// Also flushes the RX FIFO, so the caller has nothing left to read
|
||||
if (!this->reset_pd_()) {
|
||||
this->enter_error_();
|
||||
return;
|
||||
}
|
||||
this->set_state_and_contract_(PdState::PD_STATE_DEFAULT_CONTRACT, DEFAULT_CONTRACT);
|
||||
this->start_source_cap_wait_(SourceCapStep::SOURCE_CAP_STEP_WAIT);
|
||||
}
|
||||
|
||||
void FUSB302B::enter_error_() {
|
||||
if (this->state_ == PdState::PD_STATE_ERROR)
|
||||
return;
|
||||
ESP_LOGW(TAG, "Communication with the chip failed");
|
||||
this->attached_ = false;
|
||||
this->waiting_for_source_caps_ = false;
|
||||
this->clear_contract_();
|
||||
this->set_state_(PdState::PD_STATE_ERROR);
|
||||
}
|
||||
|
||||
void FUSB302B::send_soft_reset_() {
|
||||
this->reset_pd_();
|
||||
this->send_message(this->make_control_msg_(PD_CNTRL_SOFT_RESET));
|
||||
// The source answers a soft reset with new source capabilities
|
||||
this->start_source_cap_wait_(SourceCapStep::SOURCE_CAP_STEP_SOFT_RESET_SENT);
|
||||
}
|
||||
|
||||
void FUSB302B::start_source_cap_wait_(SourceCapStep step) {
|
||||
this->waiting_for_source_caps_ = true;
|
||||
this->source_cap_step_ = step;
|
||||
this->source_cap_step_start_ = millis();
|
||||
}
|
||||
|
||||
void FUSB302B::check_source_caps_() {
|
||||
if (!this->waiting_for_source_caps_ || this->check_ams_())
|
||||
return;
|
||||
const uint32_t elapsed = millis() - this->source_cap_step_start_;
|
||||
switch (this->source_cap_step_) {
|
||||
case SourceCapStep::SOURCE_CAP_STEP_WAIT:
|
||||
if (elapsed < SOURCE_CAP_WAIT_MS)
|
||||
return;
|
||||
ESP_LOGD(TAG, "No source capabilities received, requesting them");
|
||||
this->send_message(this->make_control_msg_(PD_CNTRL_GET_SOURCE_CAP));
|
||||
this->source_cap_step_ = SourceCapStep::SOURCE_CAP_STEP_GET_SENT;
|
||||
break;
|
||||
case SourceCapStep::SOURCE_CAP_STEP_GET_SENT:
|
||||
if (elapsed < SOURCE_CAP_RETRY_MS)
|
||||
return;
|
||||
ESP_LOGD(TAG, "No source capabilities received, sending soft reset");
|
||||
this->send_soft_reset_();
|
||||
return;
|
||||
case SourceCapStep::SOURCE_CAP_STEP_SOFT_RESET_SENT:
|
||||
if (elapsed < SOURCE_CAP_RETRY_MS)
|
||||
return;
|
||||
ESP_LOGW(TAG, "PD negotiation failed, staying at 5 V");
|
||||
this->waiting_for_source_caps_ = false;
|
||||
this->set_state_(PdState::PD_STATE_PD_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
this->source_cap_step_start_ = millis();
|
||||
}
|
||||
|
||||
} // namespace esphome::fusb302b
|
||||
|
||||
#endif // USE_ESP32
|
||||
@@ -1,74 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/static_task.h"
|
||||
|
||||
#include "pd.h"
|
||||
|
||||
namespace esphome::fusb302b {
|
||||
|
||||
/// FUSB302B USB Type-C / Power Delivery sink controller.
|
||||
///
|
||||
/// A dedicated task owns all I2C traffic to the chip so that PD replies meet the protocol timing
|
||||
/// even while the main loop is busy.
|
||||
class FUSB302B : public PowerDelivery, public Component, public i2c::I2CDevice {
|
||||
public:
|
||||
explicit FUSB302B(InternalGPIOPin *interrupt_pin) : interrupt_pin_(interrupt_pin) {}
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void on_shutdown() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
protected:
|
||||
enum class SourceCapStep : uint8_t {
|
||||
SOURCE_CAP_STEP_WAIT,
|
||||
SOURCE_CAP_STEP_GET_SENT,
|
||||
SOURCE_CAP_STEP_SOFT_RESET_SENT,
|
||||
};
|
||||
|
||||
static void gpio_intr(FUSB302B *arg);
|
||||
static void task_func(void *arg);
|
||||
|
||||
bool send_message(const PdMsg &msg) override;
|
||||
void on_state_changed() override {}
|
||||
void on_soft_reset_received() override { this->start_source_cap_wait_(SourceCapStep::SOURCE_CAP_STEP_WAIT); }
|
||||
void on_source_caps_received() override { this->waiting_for_source_caps_ = false; }
|
||||
void on_transition_timeout() override { this->send_soft_reset_(); }
|
||||
|
||||
// PHY task only
|
||||
[[noreturn]] void run_task_();
|
||||
bool init_chip_();
|
||||
bool reset_pd_();
|
||||
bool enable_auto_crc_();
|
||||
void handle_interrupt_();
|
||||
bool read_message_(PdMsg &msg, bool &is_sop);
|
||||
void try_attach_();
|
||||
bool measure_cc_(uint8_t meas_switch, uint8_t &level);
|
||||
void detach_();
|
||||
void handle_hard_reset_();
|
||||
void start_source_cap_wait_(SourceCapStep step);
|
||||
void send_soft_reset_();
|
||||
void check_source_caps_();
|
||||
void enter_error_();
|
||||
|
||||
InternalGPIOPin *interrupt_pin_;
|
||||
StaticTask task_;
|
||||
|
||||
// PHY task only
|
||||
uint32_t source_cap_step_start_{0};
|
||||
SourceCapStep source_cap_step_{SourceCapStep::SOURCE_CAP_STEP_WAIT};
|
||||
bool attached_{false};
|
||||
bool waiting_for_source_caps_{false};
|
||||
bool cc_ambiguous_logged_{false};
|
||||
};
|
||||
|
||||
} // namespace esphome::fusb302b
|
||||
|
||||
#endif // USE_ESP32
|
||||
@@ -1,94 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace esphome::fusb302b {
|
||||
|
||||
// Register addresses
|
||||
static constexpr uint8_t FUSB_DEVICE_ID = 0x01;
|
||||
static constexpr uint8_t FUSB_SWITCHES0 = 0x02;
|
||||
static constexpr uint8_t FUSB_SWITCHES1 = 0x03;
|
||||
static constexpr uint8_t FUSB_MEASURE = 0x04;
|
||||
static constexpr uint8_t FUSB_CONTROL0 = 0x06;
|
||||
static constexpr uint8_t FUSB_CONTROL1 = 0x07;
|
||||
static constexpr uint8_t FUSB_CONTROL3 = 0x09;
|
||||
static constexpr uint8_t FUSB_MASK1 = 0x0A;
|
||||
static constexpr uint8_t FUSB_POWER = 0x0B;
|
||||
static constexpr uint8_t FUSB_RESET = 0x0C;
|
||||
static constexpr uint8_t FUSB_MASKA = 0x0E;
|
||||
static constexpr uint8_t FUSB_MASKB = 0x0F;
|
||||
static constexpr uint8_t FUSB_STATUS0A = 0x3C;
|
||||
static constexpr uint8_t FUSB_STATUS0 = 0x40;
|
||||
static constexpr uint8_t FUSB_STATUS1 = 0x41;
|
||||
static constexpr uint8_t FUSB_FIFOS = 0x43;
|
||||
|
||||
// DEVICE_ID: version in bits 7:4, product variant (I2C address 0x22-0x25) in bits 3:2, silicon revision in bits 1:0
|
||||
static constexpr uint8_t FUSB_DEVICE_ID_VERSION_MASK = 0xF0;
|
||||
static constexpr uint8_t FUSB_DEVICE_ID_VERSION_A = 0x80;
|
||||
static constexpr uint8_t FUSB_DEVICE_ID_VERSION_B = 0x90;
|
||||
|
||||
// SWITCHES0 bits
|
||||
static constexpr uint8_t FUSB_SWITCHES0_MEAS_CC2 = 1 << 3;
|
||||
static constexpr uint8_t FUSB_SWITCHES0_MEAS_CC1 = 1 << 2;
|
||||
static constexpr uint8_t FUSB_SWITCHES0_PDWN_2 = 1 << 1;
|
||||
static constexpr uint8_t FUSB_SWITCHES0_PDWN_1 = 1 << 0;
|
||||
|
||||
// SWITCHES1 bits
|
||||
static constexpr uint8_t FUSB_SWITCHES1_SPECREV_REV2 = 0x01 << 5;
|
||||
static constexpr uint8_t FUSB_SWITCHES1_AUTO_CRC = 1 << 2;
|
||||
static constexpr uint8_t FUSB_SWITCHES1_TXCC2 = 1 << 1;
|
||||
static constexpr uint8_t FUSB_SWITCHES1_TXCC1 = 1 << 0;
|
||||
|
||||
// MEASURE value used for CC detection
|
||||
static constexpr uint8_t FUSB_MEASURE_MDAC_CC = 49;
|
||||
|
||||
// CONTROL0 bits
|
||||
static constexpr uint8_t FUSB_CONTROL0_TX_FLUSH = 1 << 6;
|
||||
|
||||
// CONTROL1 bits
|
||||
static constexpr uint8_t FUSB_CONTROL1_RX_FLUSH = 1 << 2;
|
||||
|
||||
// CONTROL3 bits
|
||||
static constexpr uint8_t FUSB_CONTROL3_N_RETRIES_SHIFT = 1;
|
||||
static constexpr uint8_t FUSB_CONTROL3_N_RETRIES_MASK = 0x3 << FUSB_CONTROL3_N_RETRIES_SHIFT;
|
||||
static constexpr uint8_t FUSB_CONTROL3_AUTO_RETRY = 1 << 0;
|
||||
|
||||
// MASK1: mask the ACTIVITY, CRC_CHK and BC_LVL interrupts
|
||||
static constexpr uint8_t FUSB_MASK1_DEFAULT = 0x51;
|
||||
|
||||
// POWER bits
|
||||
static constexpr uint8_t FUSB_POWER_ALL = 0x0F;
|
||||
|
||||
// RESET bits
|
||||
static constexpr uint8_t FUSB_RESET_PD_RESET = 1 << 1;
|
||||
static constexpr uint8_t FUSB_RESET_SW_RES = 1 << 0;
|
||||
|
||||
// INTERRUPTA bits
|
||||
static constexpr uint8_t FUSB_INTERRUPTA_I_RETRYFAIL = 1 << 4;
|
||||
static constexpr uint8_t FUSB_INTERRUPTA_I_SOFTRST = 1 << 1;
|
||||
static constexpr uint8_t FUSB_INTERRUPTA_I_HARDRST = 1 << 0;
|
||||
|
||||
// INTERRUPT bits
|
||||
static constexpr uint8_t FUSB_INTERRUPT_I_VBUSOK = 1 << 7;
|
||||
|
||||
// STATUS0 bits
|
||||
static constexpr uint8_t FUSB_STATUS0_VBUSOK = 1 << 7;
|
||||
static constexpr uint8_t FUSB_STATUS0_BC_LVL = 0x03;
|
||||
|
||||
// STATUS1 bits
|
||||
static constexpr uint8_t FUSB_STATUS1_RX_EMPTY = 1 << 5;
|
||||
|
||||
// RX FIFO token
|
||||
static constexpr uint8_t FUSB_FIFO_RX_TOKEN_BITS = 0xE0;
|
||||
static constexpr uint8_t FUSB_FIFO_RX_SOP = 0xE0;
|
||||
|
||||
// TX FIFO tokens
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_TXON = 0xA1;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_SYNC1 = 0x12;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_SYNC2 = 0x13;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_PACKSYM = 0x80;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_JAM_CRC = 0xFF;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_EOP = 0x14;
|
||||
static constexpr uint8_t FUSB_TX_TOKEN_TXOFF = 0xFE;
|
||||
|
||||
} // namespace esphome::fusb302b
|
||||
@@ -30,7 +30,6 @@ enum PdControlMsgType : uint8_t {
|
||||
PD_CNTRL_REJECT = 0x04,
|
||||
PD_CNTRL_PING = 0x05,
|
||||
PD_CNTRL_PS_RDY = 0x06,
|
||||
PD_CNTRL_GET_SOURCE_CAP = 0x07,
|
||||
PD_CNTRL_GET_SINK_CAP = 0x08,
|
||||
PD_CNTRL_WAIT = 0x0C,
|
||||
PD_CNTRL_SOFT_RESET = 0x0D,
|
||||
|
||||
@@ -28,7 +28,7 @@ void GPIOSwitch::dump_config() {
|
||||
for (auto *lock : this->interlock_) {
|
||||
if (lock == this)
|
||||
continue;
|
||||
ESP_LOGCONFIG(TAG, " %s", LOG_STR_ARG(lock->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, " %s", lock->get_name().c_str());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -58,7 +58,7 @@ void HE60rCover::endstop_reached_(CoverOperation operation) {
|
||||
this->current_operation = COVER_OPERATION_IDLE;
|
||||
if (this->last_command_ == operation) {
|
||||
float dur = (float) (now - this->start_dir_time_) / 1e3f;
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(),
|
||||
operation == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("Open") : LOG_STR_LITERAL("Close"), dur);
|
||||
}
|
||||
this->publish_state();
|
||||
@@ -213,7 +213,7 @@ void HE60rCover::start_direction_(CoverOperation dir) {
|
||||
this->last_command_ = dir;
|
||||
if (this->current_operation == dir)
|
||||
return;
|
||||
ESP_LOGD(TAG, "'%s' - Direction '%s' requested.", LOG_STR_ARG(this->get_log_name()),
|
||||
ESP_LOGD(TAG, "'%s' - Direction '%s' requested.", this->name_.c_str(),
|
||||
dir == COVER_OPERATION_OPENING ? LOG_STR_LITERAL("OPEN")
|
||||
: dir == COVER_OPERATION_CLOSING ? LOG_STR_LITERAL("CLOSE")
|
||||
: LOG_STR_LITERAL("STOP"));
|
||||
@@ -229,7 +229,7 @@ void HE60rCover::start_direction_(CoverOperation dir) {
|
||||
// just stop and reverse
|
||||
this->toggles_needed_ = 2;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' - Reversing direction.", this->name_.c_str());
|
||||
}
|
||||
this->start_dir_time_ = millis();
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "esphome/components/api/api_pb2.h"
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::homeassistant {
|
||||
@@ -27,26 +26,27 @@ void HomeassistantButton::press_action() {
|
||||
|
||||
#ifdef USE_API_WIZARD_LINKED_INPUTS
|
||||
if (this->entity_id_[0] == '\0') {
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// In flash on the ESP8266 and encoded from there
|
||||
static const char SERVICE_BUTTON[] PROGMEM = "button.press";
|
||||
static const char SERVICE_INPUT_BUTTON[] PROGMEM = "input_button.press";
|
||||
static const char ENTITY_ID_KEY[] PROGMEM = "entity_id";
|
||||
static constexpr auto SERVICE_BUTTON = StringRef::from_lit("button.press");
|
||||
static constexpr auto SERVICE_INPUT_BUTTON = StringRef::from_lit("input_button.press");
|
||||
static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
|
||||
static constexpr char INPUT_PREFIX[] = "input_";
|
||||
|
||||
api::HomeassistantActionRequest resp;
|
||||
// An input helper entity id starts with the "input_" its action name starts with
|
||||
const bool input_helper = ESPHOME_strncmp_P(this->entity_id_, SERVICE_INPUT_BUTTON, sizeof("input_") - 1) == 0;
|
||||
resp.service =
|
||||
input_helper ? ProgmemStringRef::from_lit(SERVICE_INPUT_BUTTON) : ProgmemStringRef::from_lit(SERVICE_BUTTON);
|
||||
if (strncmp(this->entity_id_, INPUT_PREFIX, sizeof(INPUT_PREFIX) - 1) == 0) {
|
||||
resp.service = SERVICE_INPUT_BUTTON;
|
||||
} else {
|
||||
resp.service = SERVICE_BUTTON;
|
||||
}
|
||||
|
||||
resp.data.init(1);
|
||||
auto &entity_id_kv = resp.data.emplace_back();
|
||||
entity_id_kv.key = ProgmemStringRef::from_lit(ENTITY_ID_KEY);
|
||||
entity_id_kv.value = ProgmemStringRef(StringRef(this->entity_id_));
|
||||
entity_id_kv.key = ENTITY_ID_KEY;
|
||||
entity_id_kv.value = StringRef(this->entity_id_);
|
||||
|
||||
api::global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "esphome/components/api/api_pb2.h"
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::homeassistant {
|
||||
@@ -32,7 +31,7 @@ void HomeassistantNumber::min_retrieved_(StringRef min) {
|
||||
ESP_LOGE(TAG, "'%s': Can't convert 'min' value '%s' to number!", this->entity_id_, min.c_str());
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s': Min retrieved: %s", LOG_STR_ARG(this->get_log_name()), min.c_str());
|
||||
ESP_LOGD(TAG, "'%s': Min retrieved: %s", get_name().c_str(), min.c_str());
|
||||
this->traits.set_min_value(min_value.value());
|
||||
}
|
||||
|
||||
@@ -42,7 +41,7 @@ void HomeassistantNumber::max_retrieved_(StringRef max) {
|
||||
ESP_LOGE(TAG, "'%s': Can't convert 'max' value '%s' to number!", this->entity_id_, max.c_str());
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s': Max retrieved: %s", LOG_STR_ARG(this->get_log_name()), max.c_str());
|
||||
ESP_LOGD(TAG, "'%s': Max retrieved: %s", get_name().c_str(), max.c_str());
|
||||
this->traits.set_max_value(max_value.value());
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ void HomeassistantNumber::step_retrieved_(StringRef step) {
|
||||
ESP_LOGE(TAG, "'%s': Can't convert 'step' value '%s' to number!", this->entity_id_, step.c_str());
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s': Step Retrieved %s", LOG_STR_ARG(this->get_log_name()), step.c_str());
|
||||
ESP_LOGD(TAG, "'%s': Step Retrieved %s", get_name().c_str(), step.c_str());
|
||||
this->traits.set_step(step_value.value());
|
||||
}
|
||||
|
||||
@@ -83,36 +82,38 @@ void HomeassistantNumber::control(float value) {
|
||||
|
||||
#ifdef USE_API_WIZARD_LINKED_INPUTS
|
||||
if (this->entity_id_[0] == '\0') {
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
this->publish_state(value);
|
||||
|
||||
// In flash on the ESP8266 and encoded from there
|
||||
static const char NUMBER_SERVICE_NAME[] PROGMEM = "number.set_value";
|
||||
static const char INPUT_NUMBER_SERVICE_NAME[] PROGMEM = "input_number.set_value";
|
||||
static const char ENTITY_ID_KEY[] PROGMEM = "entity_id";
|
||||
static const char VALUE_KEY[] PROGMEM = "value";
|
||||
static constexpr auto NUMBER_SERVICE_NAME = StringRef::from_lit("number.set_value");
|
||||
static constexpr auto INPUT_NUMBER_SERVICE_NAME = StringRef::from_lit("input_number.set_value");
|
||||
static constexpr char INPUT_PREFIX[] = "input_";
|
||||
static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
|
||||
static constexpr auto VALUE_KEY = StringRef::from_lit("value");
|
||||
|
||||
api::HomeassistantActionRequest resp;
|
||||
// An input helper entity id starts with the "input_" its action name starts with
|
||||
const bool input_helper = ESPHOME_strncmp_P(this->entity_id_, INPUT_NUMBER_SERVICE_NAME, sizeof("input_") - 1) == 0;
|
||||
resp.service = input_helper ? ProgmemStringRef::from_lit(INPUT_NUMBER_SERVICE_NAME)
|
||||
: ProgmemStringRef::from_lit(NUMBER_SERVICE_NAME);
|
||||
// input_number entities have their own set_value action
|
||||
if (strncmp(this->entity_id_, INPUT_PREFIX, sizeof(INPUT_PREFIX) - 1) == 0) {
|
||||
resp.service = INPUT_NUMBER_SERVICE_NAME;
|
||||
} else {
|
||||
resp.service = NUMBER_SERVICE_NAME;
|
||||
}
|
||||
|
||||
resp.data.init(2);
|
||||
auto &entity_id = resp.data.emplace_back();
|
||||
entity_id.key = ProgmemStringRef::from_lit(ENTITY_ID_KEY);
|
||||
entity_id.value = ProgmemStringRef(StringRef(this->entity_id_));
|
||||
entity_id.key = ENTITY_ID_KEY;
|
||||
entity_id.value = StringRef(this->entity_id_);
|
||||
|
||||
auto &entity_value = resp.data.emplace_back();
|
||||
entity_value.key = ProgmemStringRef::from_lit(VALUE_KEY);
|
||||
entity_value.key = VALUE_KEY;
|
||||
// Stack buffer - no heap allocation; %g produces shortest representation
|
||||
char value_buf[16];
|
||||
buf_append_printf(value_buf, sizeof(value_buf), 0, "%g", value);
|
||||
entity_value.value = ProgmemStringRef(StringRef(value_buf));
|
||||
entity_value.value = StringRef(value_buf);
|
||||
|
||||
api::global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::homeassistant {
|
||||
@@ -233,31 +232,32 @@ void HomeassistantSelect::control(size_t index) {
|
||||
|
||||
#ifdef USE_API_WIZARD_LINKED_INPUTS
|
||||
if (this->entity_id_[0] == '\0') {
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// In flash on the ESP8266 and encoded from there
|
||||
static const char SERVICE_SELECT[] PROGMEM = "select.select_option";
|
||||
static const char SERVICE_INPUT_SELECT[] PROGMEM = "input_select.select_option";
|
||||
static const char ENTITY_ID_KEY[] PROGMEM = "entity_id";
|
||||
static const char OPTION_KEY[] PROGMEM = "option";
|
||||
static constexpr auto SERVICE_SELECT = StringRef::from_lit("select.select_option");
|
||||
static constexpr auto SERVICE_INPUT_SELECT = StringRef::from_lit("input_select.select_option");
|
||||
static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
|
||||
static constexpr auto OPTION_KEY = StringRef::from_lit("option");
|
||||
static constexpr char INPUT_PREFIX[] = "input_";
|
||||
|
||||
api::HomeassistantActionRequest resp;
|
||||
// An input helper entity id starts with the "input_" its action name starts with
|
||||
const bool input_helper = ESPHOME_strncmp_P(this->entity_id_, SERVICE_INPUT_SELECT, sizeof("input_") - 1) == 0;
|
||||
resp.service =
|
||||
input_helper ? ProgmemStringRef::from_lit(SERVICE_INPUT_SELECT) : ProgmemStringRef::from_lit(SERVICE_SELECT);
|
||||
if (strncmp(this->entity_id_, INPUT_PREFIX, sizeof(INPUT_PREFIX) - 1) == 0) {
|
||||
resp.service = SERVICE_INPUT_SELECT;
|
||||
} else {
|
||||
resp.service = SERVICE_SELECT;
|
||||
}
|
||||
|
||||
resp.data.init(2);
|
||||
auto &entity_id = resp.data.emplace_back();
|
||||
entity_id.key = ProgmemStringRef::from_lit(ENTITY_ID_KEY);
|
||||
entity_id.value = ProgmemStringRef(StringRef(this->entity_id_));
|
||||
entity_id.key = ENTITY_ID_KEY;
|
||||
entity_id.value = StringRef(this->entity_id_);
|
||||
|
||||
auto &option = resp.data.emplace_back();
|
||||
option.key = ProgmemStringRef::from_lit(OPTION_KEY);
|
||||
option.value = ProgmemStringRef(StringRef(this->option_at(index)));
|
||||
option.key = OPTION_KEY;
|
||||
option.value = StringRef(this->option_at(index));
|
||||
|
||||
api::global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "homeassistant_switch.h"
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::homeassistant {
|
||||
@@ -43,23 +42,26 @@ void HomeassistantSwitch::write_state(bool state) {
|
||||
|
||||
#ifdef USE_API_WIZARD_LINKED_INPUTS
|
||||
if (this->entity_id_[0] == '\0') {
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// In flash on the ESP8266 and encoded from there
|
||||
static const char SERVICE_ON[] PROGMEM = "homeassistant.turn_on";
|
||||
static const char SERVICE_OFF[] PROGMEM = "homeassistant.turn_off";
|
||||
static const char ENTITY_ID_KEY[] PROGMEM = "entity_id";
|
||||
static constexpr auto SERVICE_ON = StringRef::from_lit("homeassistant.turn_on");
|
||||
static constexpr auto SERVICE_OFF = StringRef::from_lit("homeassistant.turn_off");
|
||||
static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
|
||||
|
||||
api::HomeassistantActionRequest resp;
|
||||
resp.service = state ? ProgmemStringRef::from_lit(SERVICE_ON) : ProgmemStringRef::from_lit(SERVICE_OFF);
|
||||
if (state) {
|
||||
resp.service = SERVICE_ON;
|
||||
} else {
|
||||
resp.service = SERVICE_OFF;
|
||||
}
|
||||
|
||||
resp.data.init(1);
|
||||
auto &entity_id_kv = resp.data.emplace_back();
|
||||
entity_id_kv.key = ProgmemStringRef::from_lit(ENTITY_ID_KEY);
|
||||
entity_id_kv.value = ProgmemStringRef(StringRef(this->entity_id_));
|
||||
entity_id_kv.key = ENTITY_ID_KEY;
|
||||
entity_id_kv.value = StringRef(this->entity_id_);
|
||||
|
||||
api::global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "esphome/components/api/api_server.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/progmem.h"
|
||||
#include "esphome/core/string_ref.h"
|
||||
|
||||
namespace esphome::homeassistant {
|
||||
@@ -82,31 +81,32 @@ void HomeassistantText::control(const std::string &value) {
|
||||
|
||||
#ifdef USE_API_WIZARD_LINKED_INPUTS
|
||||
if (this->entity_id_[0] == '\0') {
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s': No entity ID set yet", this->get_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// In flash on the ESP8266 and encoded from there
|
||||
static const char SERVICE_TEXT[] PROGMEM = "text.set_value";
|
||||
static const char SERVICE_INPUT_TEXT[] PROGMEM = "input_text.set_value";
|
||||
static const char ENTITY_ID_KEY[] PROGMEM = "entity_id";
|
||||
static const char VALUE_KEY[] PROGMEM = "value";
|
||||
static constexpr auto SERVICE_TEXT = StringRef::from_lit("text.set_value");
|
||||
static constexpr auto SERVICE_INPUT_TEXT = StringRef::from_lit("input_text.set_value");
|
||||
static constexpr auto ENTITY_ID_KEY = StringRef::from_lit("entity_id");
|
||||
static constexpr auto VALUE_KEY = StringRef::from_lit("value");
|
||||
static constexpr char INPUT_PREFIX[] = "input_";
|
||||
|
||||
api::HomeassistantActionRequest resp;
|
||||
// An input helper entity id starts with the "input_" its action name starts with
|
||||
const bool input_helper = ESPHOME_strncmp_P(this->entity_id_, SERVICE_INPUT_TEXT, sizeof("input_") - 1) == 0;
|
||||
resp.service =
|
||||
input_helper ? ProgmemStringRef::from_lit(SERVICE_INPUT_TEXT) : ProgmemStringRef::from_lit(SERVICE_TEXT);
|
||||
if (strncmp(this->entity_id_, INPUT_PREFIX, sizeof(INPUT_PREFIX) - 1) == 0) {
|
||||
resp.service = SERVICE_INPUT_TEXT;
|
||||
} else {
|
||||
resp.service = SERVICE_TEXT;
|
||||
}
|
||||
|
||||
resp.data.init(2);
|
||||
auto &entity_id_kv = resp.data.emplace_back();
|
||||
entity_id_kv.key = ProgmemStringRef::from_lit(ENTITY_ID_KEY);
|
||||
entity_id_kv.value = ProgmemStringRef(StringRef(this->entity_id_));
|
||||
entity_id_kv.key = ENTITY_ID_KEY;
|
||||
entity_id_kv.value = StringRef(this->entity_id_);
|
||||
|
||||
auto &value_kv = resp.data.emplace_back();
|
||||
value_kv.key = ProgmemStringRef::from_lit(VALUE_KEY);
|
||||
value_kv.value = ProgmemStringRef(value.data(), value.size());
|
||||
value_kv.key = VALUE_KEY;
|
||||
value_kv.value = StringRef(value.data(), value.size());
|
||||
|
||||
api::global_api_server->send_homeassistant_action(resp);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ void HX711Sensor::update() {
|
||||
uint32_t result;
|
||||
if (this->read_sensor_(&result)) {
|
||||
int32_t value = static_cast<int32_t>(result);
|
||||
ESP_LOGD(TAG, "'%s': Got value %" PRId32, LOG_STR_ARG(this->get_log_name()), value);
|
||||
ESP_LOGD(TAG, "'%s': Got value %" PRId32, this->name_.c_str(), value);
|
||||
this->publish_state(value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import audio, esp32, speaker
|
||||
from esphome.components.microphone import DOMAIN as MICROPHONE_DOMAIN
|
||||
from esphome.config_helpers import filter_source_files_from_defines
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -15,11 +14,9 @@ from esphome.const import (
|
||||
CONF_SAMPLE_RATE,
|
||||
CONF_TIMEOUT,
|
||||
)
|
||||
import esphome.final_validate as fv
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .. import (
|
||||
CONF_I2S_AUDIO_ID,
|
||||
CONF_I2S_DOUT_PIN,
|
||||
CONF_I2S_MODE,
|
||||
CONF_LEFT,
|
||||
@@ -47,7 +44,6 @@ I2SAudioSpeaker = i2s_audio_ns.class_("I2SAudioSpeaker", I2SAudioSpeakerBase)
|
||||
|
||||
CONF_DAC_TYPE = "dac_type"
|
||||
CONF_I2S_COMM_FMT = "i2s_comm_fmt"
|
||||
CONF_KEEP_ALIVE = "keep_alive"
|
||||
CONF_SPDIF_MODE = "spdif_mode"
|
||||
|
||||
I2SAudioSpeakerBase = i2s_audio_ns.class_(
|
||||
@@ -177,7 +173,6 @@ BASE_SCHEMA = (
|
||||
cv.positive_time_period_milliseconds,
|
||||
cv.one_of(CONF_NEVER, lower=True),
|
||||
),
|
||||
cv.Optional(CONF_KEEP_ALIVE, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
@@ -240,23 +235,6 @@ def _final_validate(config: ConfigType) -> None:
|
||||
raise cv.Invalid("SPDIF mode requires 'i2s_comm_fmt: stand_i2s'")
|
||||
if config[CONF_MCLK_MULTIPLE] != 256:
|
||||
raise cv.Invalid("SPDIF mode requires 'mclk_multiple: 256'")
|
||||
if config[CONF_KEEP_ALIVE]:
|
||||
raise cv.Invalid("SPDIF mode does not support 'keep_alive'")
|
||||
|
||||
if config[CONF_KEEP_ALIVE]:
|
||||
# A kept channel holds the port between sessions, so nothing else may share the bus
|
||||
bus = config[CONF_I2S_AUDIO_ID]
|
||||
full_config = fv.full_config.get()
|
||||
on_bus = sum(
|
||||
1
|
||||
for domain in (speaker.DOMAIN, MICROPHONE_DOMAIN)
|
||||
for entry in full_config.get(domain, [])
|
||||
if entry.get(CONF_I2S_AUDIO_ID) == bus
|
||||
)
|
||||
if on_bus > 1:
|
||||
raise cv.Invalid(
|
||||
"'keep_alive' needs its own I2S bus; another speaker or microphone shares this one"
|
||||
)
|
||||
|
||||
|
||||
FINAL_VALIDATE_SCHEMA = _final_validate
|
||||
@@ -284,8 +262,6 @@ async def to_code(config: ConfigType) -> None:
|
||||
if config[CONF_TIMEOUT] != CONF_NEVER:
|
||||
cg.add(var.set_timeout(config[CONF_TIMEOUT]))
|
||||
cg.add(var.set_buffer_duration(config[CONF_BUFFER_DURATION]))
|
||||
if config[CONF_KEEP_ALIVE]:
|
||||
cg.add(var.set_keep_alive(True))
|
||||
|
||||
|
||||
# The SPDIF encoder and speaker are fully #ifdef'd on USE_I2S_AUDIO_SPDIF_MODE,
|
||||
|
||||
@@ -56,9 +56,8 @@ void I2SAudioSpeakerBase::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"Speaker:\n"
|
||||
" Pin: %d\n"
|
||||
" Buffer duration: %" PRIu32 "\n"
|
||||
" Keep alive: %s",
|
||||
static_cast<int8_t>(this->dout_pin_), this->buffer_duration_ms_, YESNO(this->keep_alive_));
|
||||
" Buffer duration: %" PRIu32,
|
||||
static_cast<int8_t>(this->dout_pin_), this->buffer_duration_ms_);
|
||||
if (this->timeout_.has_value()) {
|
||||
ESP_LOGCONFIG(TAG, " Timeout: %" PRIu32 " ms", this->timeout_.value());
|
||||
}
|
||||
@@ -106,13 +105,7 @@ void I2SAudioSpeakerBase::loop() {
|
||||
vTaskDelete(this->speaker_task_handle_);
|
||||
this->speaker_task_handle_ = nullptr;
|
||||
|
||||
// The task raises this bit before it exits, possibly a loop pass before TASK_STOPPED is seen, so read it
|
||||
// live here; a channel the task could not bring up is rebuilt next time rather than kept
|
||||
const bool task_failed = xEventGroupGetBits(this->event_group_) & SpeakerEventGroupBits::ERR_ESP_NO_MEM;
|
||||
if (task_failed) {
|
||||
ESP_LOGE(TAG, "Speaker task setup failed (allocation, preload, or channel enable)");
|
||||
}
|
||||
this->stop_i2s_driver_(this->keep_alive_ && !task_failed);
|
||||
this->stop_i2s_driver_();
|
||||
// ALL_BITS includes COMMAND_START. Take the bits from the clear itself, not from the snapshot at
|
||||
// the top of loop(): the audio source's task can raise a start at any point above, including
|
||||
// during stop_i2s_driver_(), and nothing would ever re-issue it.
|
||||
@@ -128,6 +121,11 @@ void I2SAudioSpeakerBase::loop() {
|
||||
this->state_ = speaker::STATE_STOPPED;
|
||||
}
|
||||
|
||||
if (event_group_bits & SpeakerEventGroupBits::ERR_ESP_NO_MEM) {
|
||||
ESP_LOGE(TAG, "Speaker task setup failed (allocation, preload, or channel enable)");
|
||||
xEventGroupClearBits(this->event_group_, SpeakerEventGroupBits::ERR_ESP_NO_MEM);
|
||||
}
|
||||
|
||||
// Handle the speaker's state
|
||||
switch (this->state_) {
|
||||
case speaker::STATE_STARTING:
|
||||
@@ -135,8 +133,8 @@ void I2SAudioSpeakerBase::loop() {
|
||||
break;
|
||||
}
|
||||
|
||||
// Still winding down from a previous run
|
||||
if (this->speaker_task_handle_ != nullptr) {
|
||||
// Still starting up or winding down from a previous run
|
||||
if ((this->tx_handle_ != nullptr) || (this->speaker_task_handle_ != nullptr)) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -156,7 +154,7 @@ void I2SAudioSpeakerBase::loop() {
|
||||
if (this->speaker_task_handle_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Task failed to start, retrying in 1 second");
|
||||
this->status_momentary_error(1000);
|
||||
this->stop_i2s_driver_(false); // Stops the driver to return the lock; will be reloaded in next attempt
|
||||
this->stop_i2s_driver_(); // Stops the driver to return the lock; will be reloaded in next attempt
|
||||
}
|
||||
break;
|
||||
case speaker::STATE_RUNNING: // Intentional fallthrough
|
||||
@@ -272,25 +270,31 @@ esp_err_t I2SAudioSpeakerBase::init_i2s_channel_(const i2s_chan_config_t &chan_c
|
||||
err = i2s_channel_init_std_mode(this->tx_handle_, &std_cfg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to initialize I2S channel");
|
||||
this->delete_channel_();
|
||||
i2s_del_channel(this->tx_handle_);
|
||||
this->tx_handle_ = nullptr;
|
||||
this->parent_->unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
// Both queues are drained by the speaker task before it preloads, whether the channel is new or kept
|
||||
if (this->i2s_event_queue_ == nullptr) {
|
||||
this->i2s_event_queue_ = xQueueCreate(event_queue_size, sizeof(int64_t));
|
||||
} else {
|
||||
// Reset queue to clear any stale events from previous task
|
||||
xQueueReset(this->i2s_event_queue_);
|
||||
}
|
||||
|
||||
// Lockstep records queue. One record per in-flight DMA buffer; sized to match the I2S event queue
|
||||
// so a fully-saturated DMA pipeline cannot overflow either side before drain.
|
||||
if (this->write_records_queue_ == nullptr) {
|
||||
this->write_records_queue_ = xQueueCreate(event_queue_size, sizeof(uint32_t));
|
||||
} else {
|
||||
xQueueReset(this->write_records_queue_);
|
||||
}
|
||||
|
||||
if (this->i2s_event_queue_ == nullptr || this->write_records_queue_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate I2S event queue(s)");
|
||||
this->delete_channel_();
|
||||
i2s_del_channel(this->tx_handle_);
|
||||
this->tx_handle_ = nullptr;
|
||||
this->parent_->unlock();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
@@ -298,30 +302,22 @@ esp_err_t I2SAudioSpeakerBase::init_i2s_channel_(const i2s_chan_config_t &chan_c
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void I2SAudioSpeakerBase::stop_i2s_driver_(bool keep_channel) {
|
||||
void I2SAudioSpeakerBase::stop_i2s_driver_() {
|
||||
if (this->tx_handle_ != nullptr) {
|
||||
i2s_channel_disable(this->tx_handle_);
|
||||
// A kept channel lets the next start skip i2s_new_channel and i2s_channel_init_std_mode, whose GPIO and
|
||||
// clock reconfiguration is the audible pop
|
||||
if (!keep_channel) {
|
||||
this->delete_channel_();
|
||||
}
|
||||
i2s_del_channel(this->tx_handle_);
|
||||
this->tx_handle_ = nullptr;
|
||||
|
||||
// i2s_del_channel() leaves dout wired to this port's data-out signal in the GPIO matrix: it only
|
||||
// clears an internal reservation mask, never the esp_rom_gpio_connect_out_signal() routing that
|
||||
// setup installed. If another speaker reuses this port (shared bus), its audio still reaches our
|
||||
// dout. Detach the pin and drive it low so a stale output stops driving downstream hardware: a
|
||||
// SPDIF optical transmitter would otherwise stay lit, and an analog DAC would emit noise.
|
||||
this->park_dout_pin_();
|
||||
}
|
||||
this->parent_->unlock();
|
||||
}
|
||||
|
||||
void I2SAudioSpeakerBase::delete_channel_() {
|
||||
i2s_del_channel(this->tx_handle_);
|
||||
this->tx_handle_ = nullptr;
|
||||
|
||||
// i2s_del_channel() leaves dout wired to this port's data-out signal in the GPIO matrix: it only
|
||||
// clears an internal reservation mask, never the esp_rom_gpio_connect_out_signal() routing that
|
||||
// setup installed. If another speaker reuses this port (shared bus), its audio still reaches our
|
||||
// dout. Detach the pin and drive it low so a stale output stops driving downstream hardware: a
|
||||
// SPDIF optical transmitter would otherwise stay lit, and an analog DAC would emit noise.
|
||||
this->park_dout_pin_();
|
||||
}
|
||||
|
||||
bool IRAM_ATTR I2SAudioSpeakerBase::i2s_on_sent_cb(i2s_chan_handle_t handle, i2s_event_data_t *event, void *user_ctx) {
|
||||
int64_t now = esp_timer_get_time();
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@ class I2SAudioSpeakerBase : public I2SAudioOut, public speaker::Speaker, public
|
||||
|
||||
void set_buffer_duration(uint32_t buffer_duration_ms) { this->buffer_duration_ms_ = buffer_duration_ms; }
|
||||
void set_timeout(uint32_t ms) { this->timeout_ = ms; }
|
||||
void set_keep_alive(bool keep_alive) { this->keep_alive_ = keep_alive; }
|
||||
void set_dout_pin(uint8_t pin) { this->dout_pin_ = (gpio_num_t) pin; }
|
||||
|
||||
/// @brief Get the I2S TX channel handle
|
||||
@@ -127,15 +126,12 @@ class I2SAudioSpeakerBase : public I2SAudioOut, public speaker::Speaker, public
|
||||
esp_err_t init_i2s_channel_(const i2s_chan_config_t &chan_cfg, const i2s_std_config_t &std_cfg,
|
||||
size_t event_queue_size);
|
||||
|
||||
/// @brief Stops the I2S driver and unlocks the I2S port; keep_channel leaves the disabled channel allocated
|
||||
void stop_i2s_driver_(bool keep_channel);
|
||||
/// @brief Stops the I2S driver and unlocks the I2S port
|
||||
void stop_i2s_driver_();
|
||||
|
||||
/// @brief Detaches dout from the I2S signal and drives it low
|
||||
void park_dout_pin_();
|
||||
|
||||
/// @brief Deletes the I2S channel and parks dout; the caller holds the bus lock
|
||||
void delete_channel_();
|
||||
|
||||
/// @brief Called in loop() when the task has stopped. Override for mode-specific cleanup.
|
||||
virtual void on_task_stopped() {}
|
||||
|
||||
@@ -181,7 +177,6 @@ class I2SAudioSpeakerBase : public I2SAudioOut, public speaker::Speaker, public
|
||||
optional<uint32_t> timeout_;
|
||||
|
||||
bool pause_state_{false};
|
||||
bool keep_alive_{false};
|
||||
|
||||
// Smooths software gain changes. The main loop posts targets, the speaker task processes;
|
||||
// GainRamp's mailbox makes that safe. The main loop is the only poster.
|
||||
|
||||
@@ -75,9 +75,6 @@ void I2SAudioSpeaker::dump_config() {
|
||||
|
||||
void I2SAudioSpeaker::run_speaker_task() {
|
||||
xEventGroupSetBits(this->event_group_, SpeakerEventGroupBits::TASK_STARTING);
|
||||
// Stale records from the previous run would pair with the wrong DMA events
|
||||
xQueueReset(this->i2s_event_queue_);
|
||||
xQueueReset(this->write_records_queue_);
|
||||
|
||||
const uint32_t dma_buffers_duration_ms = DMA_BUFFER_DURATION_MS * DMA_BUFFERS_COUNT;
|
||||
// Ensure ring buffer duration is at least the duration of all DMA buffers
|
||||
@@ -392,6 +389,8 @@ void I2SAudioSpeaker::run_speaker_task() {
|
||||
}
|
||||
|
||||
esp_err_t I2SAudioSpeaker::start_i2s_driver(audio::AudioStreamInfo &audio_stream_info) {
|
||||
this->current_stream_info_ = audio_stream_info;
|
||||
|
||||
if ((this->i2s_role_ & I2S_ROLE_SLAVE) && (this->sample_rate_ != audio_stream_info.get_sample_rate())) { // NOLINT
|
||||
// Can't reconfigure I2S bus, so the sample rate must match the configured value
|
||||
ESP_LOGE(TAG, "Incompatible stream settings");
|
||||
@@ -429,16 +428,6 @@ esp_err_t I2SAudioSpeaker::start_i2s_driver(audio::AudioStreamInfo &audio_stream
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
// Reuse a kept channel while the stream format matches
|
||||
if (this->tx_handle_ != nullptr) {
|
||||
if (this->current_stream_info_ == audio_stream_info) {
|
||||
return ESP_OK;
|
||||
}
|
||||
this->delete_channel_();
|
||||
}
|
||||
|
||||
this->current_stream_info_ = audio_stream_info;
|
||||
|
||||
// The DMA buffers hold output-format (post-narrowing) samples, so size them from the output stream info.
|
||||
uint32_t dma_buffer_length = dma_buffer_frames(this->output_stream_info_);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ void Infrared::dump_config() {
|
||||
"Infrared '%s'\n"
|
||||
" Supports Transmitter: %s\n"
|
||||
" Supports Receiver: %s",
|
||||
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
|
||||
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
|
||||
YESNO(this->get_supports_receiver()));
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ bool IrRfEntity::expect_api_reply_(api::APIConnection *conn) {
|
||||
if (this->api_reply_ == ApiReply::API_REPLY_WAITING)
|
||||
this->finish_api_reply_(false);
|
||||
if (this->api_reply_ != ApiReply::API_REPLY_NONE && !this->send_api_reply_()) {
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()), LOG_STR_LITERAL("refused, reply still owed"));
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("refused, reply still owed"));
|
||||
this->refuse_api_call_(conn);
|
||||
return false;
|
||||
}
|
||||
@@ -198,14 +198,13 @@ void IrRfEntity::loop() {
|
||||
if (this->api_reply_ != ApiReply::API_REPLY_WAITING) {
|
||||
if (this->send_api_reply_() || remaining > 0)
|
||||
return;
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()),
|
||||
LOG_STR_LITERAL("reply dropped, client not reading"));
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("reply dropped, client not reading"));
|
||||
this->clear_api_reply_();
|
||||
return;
|
||||
}
|
||||
if (remaining > 0)
|
||||
return;
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", LOG_STR_ARG(this->get_log_name()), LOG_STR_LITERAL("never reported completion"));
|
||||
ESP_LOGW(TAG, "'%s': transmit %s", this->get_name().c_str(), LOG_STR_LITERAL("never reported completion"));
|
||||
this->finish_api_reply_(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ void IrRfProxy::dump_config() {
|
||||
"IR Proxy '%s'\n"
|
||||
" Supports Transmitter: %s\n"
|
||||
" Supports Receiver: %s",
|
||||
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
|
||||
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
|
||||
YESNO(this->get_supports_receiver()));
|
||||
|
||||
if (this->is_rf()) {
|
||||
@@ -44,7 +44,7 @@ void RfProxy::dump_config() {
|
||||
"RF Proxy '%s'\n"
|
||||
" Supports Transmitter: %s\n"
|
||||
" Supports Receiver: %s",
|
||||
LOG_STR_ARG(this->get_log_name()), YESNO(this->get_supports_transmitter()),
|
||||
this->get_name().c_str(), YESNO(this->get_supports_transmitter()),
|
||||
YESNO(this->get_supports_receiver()));
|
||||
|
||||
const auto &traits = this->traits_;
|
||||
|
||||
@@ -1058,8 +1058,8 @@ void LD6002BComponent::publish_number_clamped_(number::Number *number, float val
|
||||
// Outside the declared range the user cannot write the value back, so publish
|
||||
// what they can reach and say what the module actually sent.
|
||||
if (value < min_value || value > max_value) {
|
||||
ESP_LOGW(TAG, "'%s': module reported %.1f, clamped to %.1f..%.1f", LOG_STR_ARG(number->get_log_name()), value,
|
||||
min_value, max_value);
|
||||
ESP_LOGW(TAG, "'%s': module reported %.1f, clamped to %.1f..%.1f", number->get_name().c_str(), value, min_value,
|
||||
max_value);
|
||||
value = std::clamp(value, min_value, max_value);
|
||||
}
|
||||
number->publish_state(value);
|
||||
|
||||
@@ -10,7 +10,7 @@ void AddressableLight::call_setup() {
|
||||
|
||||
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
|
||||
this->set_interval(5000, [this]() {
|
||||
const char *name = this->state_parent_ == nullptr ? "" : LOG_STR_ARG(this->state_parent_->get_log_name());
|
||||
const char *name = this->state_parent_ == nullptr ? "" : this->state_parent_->get_name().c_str();
|
||||
ESP_LOGVV(TAG, "Addressable Light '%s' (effect_active=%s)", name, YESNO(this->effect_active_));
|
||||
for (int i = 0; i < this->size(); i++) {
|
||||
auto color = this->get(i);
|
||||
|
||||
@@ -74,7 +74,7 @@ static void log_percent(const LogString *param, float value) {
|
||||
#endif
|
||||
|
||||
void LightCall::perform() {
|
||||
const char *name = LOG_STR_ARG(this->parent_->get_log_name());
|
||||
const char *name = this->parent_->get_name().c_str();
|
||||
LightColorValues v = this->validate_();
|
||||
const bool publish = this->get_publish_();
|
||||
|
||||
@@ -182,7 +182,7 @@ void LightCall::perform() {
|
||||
}
|
||||
|
||||
void LightCall::log_and_clear_unsupported_(FieldFlags flag, const LogString *feature, bool use_color_mode_log) {
|
||||
auto *name = LOG_STR_ARG(this->parent_->get_log_name());
|
||||
auto *name = this->parent_->get_name().c_str();
|
||||
if (use_color_mode_log) {
|
||||
log_color_mode_not_supported(name, feature);
|
||||
} else {
|
||||
@@ -192,7 +192,7 @@ void LightCall::log_and_clear_unsupported_(FieldFlags flag, const LogString *fea
|
||||
}
|
||||
|
||||
LightColorValues LightCall::validate_() {
|
||||
auto *name = LOG_STR_ARG(this->parent_->get_log_name());
|
||||
auto *name = this->parent_->get_name().c_str();
|
||||
auto traits = this->parent_->get_traits();
|
||||
|
||||
// Snapshot before the adjustments below add flags of their own
|
||||
@@ -446,7 +446,7 @@ void LightCall::transform_parameters_(const LightTraits &traits) {
|
||||
!(this->color_mode_ & ColorCapability::COLOR_TEMPERATURE) && //
|
||||
min_mireds > 0.0f && max_mireds > 0.0f) {
|
||||
ESP_LOGV(TAG, "'%s': setting cold/warm white channels using white/color temperature values",
|
||||
LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
this->parent_->get_name().c_str());
|
||||
// Only compute cold_white/warm_white from color_temperature if they're not already explicitly set.
|
||||
// This is important for state restoration, where both color_temperature and cold_white/warm_white
|
||||
// are restored from flash - we want to preserve the saved cold_white/warm_white values.
|
||||
@@ -492,7 +492,7 @@ ColorMode LightCall::compute_color_mode_(const LightTraits &traits) {
|
||||
|
||||
// Don't change if the current mode is in the intersection (suitable AND supported)
|
||||
if (ColorModeMask::mask_contains(intersection, current_mode)) {
|
||||
ESP_LOGV(TAG, "'%s': color mode not specified; retaining %s", LOG_STR_ARG(this->parent_->get_log_name()),
|
||||
ESP_LOGV(TAG, "'%s': color mode not specified; retaining %s", this->parent_->get_name().c_str(),
|
||||
LOG_STR_ARG(color_mode_to_human(current_mode)));
|
||||
return current_mode;
|
||||
}
|
||||
@@ -500,7 +500,7 @@ ColorMode LightCall::compute_color_mode_(const LightTraits &traits) {
|
||||
// Use the preferred suitable mode.
|
||||
if (intersection != 0) {
|
||||
ColorMode mode = ColorModeMask::first_value_from_mask(intersection);
|
||||
ESP_LOGV(TAG, "'%s': color mode not specified; using %s", LOG_STR_ARG(this->parent_->get_log_name()),
|
||||
ESP_LOGV(TAG, "'%s': color mode not specified; using %s", this->parent_->get_name().c_str(),
|
||||
LOG_STR_ARG(color_mode_to_human(mode)));
|
||||
return mode;
|
||||
}
|
||||
@@ -508,7 +508,7 @@ ColorMode LightCall::compute_color_mode_(const LightTraits &traits) {
|
||||
// There's no supported mode for this call, so warn, use the current more or a mode at random and let validation strip
|
||||
// out whatever we don't support.
|
||||
auto color_mode = current_mode != ColorMode::UNKNOWN ? current_mode : *supported_modes.begin();
|
||||
ESP_LOGW(TAG, "'%s': no suitable color mode supported; defaulting to %s", LOG_STR_ARG(this->parent_->get_log_name()),
|
||||
ESP_LOGW(TAG, "'%s': no suitable color mode supported; defaulting to %s", this->parent_->get_name().c_str(),
|
||||
LOG_STR_ARG(color_mode_to_human(color_mode)));
|
||||
return color_mode;
|
||||
}
|
||||
@@ -587,7 +587,7 @@ LightCall &LightCall::set_effect(const char *effect, size_t len) {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ESP_LOGW(TAG, "'%s': no such effect '%.*s'", LOG_STR_ARG(this->parent_->get_log_name()), (int) len, effect);
|
||||
ESP_LOGW(TAG, "'%s': no such effect '%.*s'", this->parent_->get_name().c_str(), (int) len, effect);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ void LightState::setup() {
|
||||
call.perform();
|
||||
}
|
||||
void LightState::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Light '%s'", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGCONFIG(TAG, "Light '%s'", this->get_name().c_str());
|
||||
auto traits = this->get_traits();
|
||||
if (traits.supports_color_capability(ColorCapability::BRIGHTNESS)) {
|
||||
#ifdef USE_LIGHT_GAMMA_LUT
|
||||
|
||||
@@ -30,10 +30,10 @@ void Lock::lock() { this->set_state_(LOCK_STATE_LOCKED); }
|
||||
void Lock::unlock() { this->set_state_(LOCK_STATE_UNLOCKED); }
|
||||
void Lock::open() {
|
||||
if (traits.get_supports_open()) {
|
||||
ESP_LOGD(TAG, "'%s' Opening.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGD(TAG, "'%s' Opening.", this->get_name().c_str());
|
||||
this->open_latch();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' Does not support Open.", LOG_STR_ARG(this->get_log_name()));
|
||||
ESP_LOGW(TAG, "'%s' Does not support Open.", this->get_name().c_str());
|
||||
}
|
||||
}
|
||||
void Lock::publish_state(LockState state) {
|
||||
@@ -42,7 +42,7 @@ void Lock::publish_state(LockState state) {
|
||||
|
||||
this->state = state;
|
||||
this->rtc_.save(&this->state);
|
||||
ESP_LOGV(TAG, "'%s' >> %s", LOG_STR_ARG(this->get_log_name()), LOG_STR_ARG(lock_state_to_string(state)));
|
||||
ESP_LOGV(TAG, "'%s' >> %s", this->name_.c_str(), LOG_STR_ARG(lock_state_to_string(state)));
|
||||
this->state_callback_.call(state);
|
||||
#if defined(USE_LOCK) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_lock_update(this);
|
||||
@@ -50,7 +50,7 @@ void Lock::publish_state(LockState state) {
|
||||
}
|
||||
|
||||
void LockCall::perform() {
|
||||
ESP_LOGV(TAG, "'%s' - Setting", LOG_STR_ARG(this->parent_->get_log_name()));
|
||||
ESP_LOGV(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
|
||||
this->validate_();
|
||||
if (this->state_.has_value()) {
|
||||
ESP_LOGV(TAG, " State: %s", LOG_STR_ARG(lock_state_to_string(*this->state_)));
|
||||
@@ -92,7 +92,7 @@ LockCall &LockCall::set_state(const char *state) {
|
||||
} else if (ESPHOME_strcasecmp_P(state, ESPHOME_PSTR("NONE")) == 0) {
|
||||
this->set_state(LOCK_STATE_NONE);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized state %s", LOG_STR_ARG(this->parent_->get_log_name()), state);
|
||||
ESP_LOGW(TAG, "'%s' - Unrecognized state %s", this->parent_->get_name().c_str(), state);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class Lock;
|
||||
|
||||
#define LOG_LOCK(prefix, type, obj) \
|
||||
if ((obj) != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), LOG_STR_ARG((obj)->get_log_name())); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, LOG_STR_LITERAL(type), (obj)->get_name().c_str()); \
|
||||
LOG_ENTITY_ICON(TAG, prefix, *(obj)); \
|
||||
if ((obj)->traits.get_assumed_state()) { \
|
||||
ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user