Compare commits
193 Commits
bluetooth_
...
send_overh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
396005db62 | ||
|
|
c6f605ce96 | ||
|
|
da6520586c | ||
|
|
fd22033bda | ||
|
|
bb6586d365 | ||
|
|
552dbca56b | ||
|
|
0c04364525 | ||
|
|
c4ebdd3875 | ||
|
|
7f8b277ea4 | ||
|
|
0261168b08 | ||
|
|
0187820475 | ||
|
|
3b226625c6 | ||
|
|
af060b4692 | ||
|
|
32be69f7f2 | ||
|
|
a89c60cf10 | ||
|
|
2f230f32fa | ||
|
|
4b50b51faf | ||
|
|
fb92cbad59 | ||
|
|
5c2f68dcb1 | ||
|
|
661fb1e74f | ||
|
|
4ec0cf6edc | ||
|
|
a0b71b9930 | ||
|
|
6d11b80684 | ||
|
|
83dab69d6a | ||
|
|
1f64cb446d | ||
|
|
d45a04df3f | ||
|
|
b2bd0d2318 | ||
|
|
259e513293 | ||
|
|
1226e581ec | ||
|
|
3271f74b1b | ||
|
|
efe3ffe1da | ||
|
|
051aee5228 | ||
|
|
b62de22175 | ||
|
|
7cf06eb0d5 | ||
|
|
add7593b4a | ||
|
|
858ea16f91 | ||
|
|
160e2593cd | ||
|
|
5794472828 | ||
|
|
c85f7adbb6 | ||
|
|
9a5ddb9619 | ||
|
|
a6f75ce357 | ||
|
|
a89aaaf69a | ||
|
|
0f3db32b46 | ||
|
|
684c5a42fb | ||
|
|
b4198e6592 | ||
|
|
b335f628e7 | ||
|
|
8b12096c6a | ||
|
|
15b7481c4a | ||
|
|
bec1aa9a10 | ||
|
|
30ae1c860a | ||
|
|
413a6db11c | ||
|
|
fa918b4129 | ||
|
|
f362e1c72e | ||
|
|
759a92a87a | ||
|
|
f4adf70228 | ||
|
|
bad165c804 | ||
|
|
c541955298 | ||
|
|
c9de67208c | ||
|
|
d732cb6339 | ||
|
|
ecb508ad46 | ||
|
|
60ff1f6564 | ||
|
|
a44af63baf | ||
|
|
88414a6144 | ||
|
|
7902382742 | ||
|
|
3244aeba06 | ||
|
|
fb1bc3d627 | ||
|
|
1785fa181c | ||
|
|
1a8a3c16e8 | ||
|
|
856cdd47c1 | ||
|
|
2a7f657a76 | ||
|
|
e771b13fa5 | ||
|
|
4091f39355 | ||
|
|
d6106f9832 | ||
|
|
8988234ae5 | ||
|
|
de907e238d | ||
|
|
9fcd6cbb4b | ||
|
|
2d80759c17 | ||
|
|
ffa2cbeb3f | ||
|
|
5ef8968149 | ||
|
|
efacf2110b | ||
|
|
f8fc6d66e3 | ||
|
|
5390a17298 | ||
|
|
04757766a4 | ||
|
|
7c637d7ff5 | ||
|
|
6c913fa0c2 | ||
|
|
f70b826507 | ||
|
|
020c4af218 | ||
|
|
44062ea7f2 | ||
|
|
d87eeea439 | ||
|
|
71125a1137 | ||
|
|
7fa779be4e | ||
|
|
c90fe742b7 | ||
|
|
707346b6de | ||
|
|
fbb519140d | ||
|
|
f77544c9b5 | ||
|
|
f5611bccb6 | ||
|
|
431316cd2f | ||
|
|
da3d51f159 | ||
|
|
ce98cec9e7 | ||
|
|
e01e8302f3 | ||
|
|
782a46b777 | ||
|
|
a6dd079059 | ||
|
|
12778d28c4 | ||
|
|
411ba5f288 | ||
|
|
19dba53f07 | ||
|
|
4a85abd18f | ||
|
|
afc2dd77f0 | ||
|
|
1e3a6d121f | ||
|
|
de2176de20 | ||
|
|
c4319a8b39 | ||
|
|
e7d8501ca9 | ||
|
|
a486e92507 | ||
|
|
e4df8a70ef | ||
|
|
7cc2d059bc | ||
|
|
8c709179ce | ||
|
|
1dec3ebd3b | ||
|
|
1aad0f9b88 | ||
|
|
9902759068 | ||
|
|
84f4613ee0 | ||
|
|
fdb33a893f | ||
|
|
7b2e9fa7d9 | ||
|
|
847ba64245 | ||
|
|
4777d6b374 | ||
|
|
e1c17ecac3 | ||
|
|
6daca23225 | ||
|
|
aa2b49178d | ||
|
|
aa2f0e8ff9 | ||
|
|
a4d3849ef4 | ||
|
|
0ff647909d | ||
|
|
27204e0598 | ||
|
|
24b2fe8375 | ||
|
|
50310fe494 | ||
|
|
99e98f5655 | ||
|
|
14f147fd1c | ||
|
|
6d982e76fe | ||
|
|
60dcb64da1 | ||
|
|
2bb7a1a9db | ||
|
|
29ec9da864 | ||
|
|
127f2a699a | ||
|
|
1b7e1afd9b | ||
|
|
d19997a056 | ||
|
|
de7591882d | ||
|
|
a00fc75c77 | ||
|
|
80fd827f8b | ||
|
|
1dd3c6de90 | ||
|
|
c8c43f13fd | ||
|
|
518bce50a5 | ||
|
|
4f87bea788 | ||
|
|
8054c9b4f5 | ||
|
|
935e0a365f | ||
|
|
b39a9924d8 | ||
|
|
19ec922e28 | ||
|
|
a225d6881f | ||
|
|
6675e99862 | ||
|
|
8cbe2b41f6 | ||
|
|
6a225cb4c0 | ||
|
|
e62d8bfabe | ||
|
|
d4cea84b1b | ||
|
|
b63f90a6c0 | ||
|
|
4370b6695e | ||
|
|
589f13f0f7 | ||
|
|
367017b352 | ||
|
|
ec26d31499 | ||
|
|
1bbc6db1c3 | ||
|
|
162472bdc2 | ||
|
|
aecac15809 | ||
|
|
6554af21b9 | ||
|
|
8583466c6a | ||
|
|
6666604069 | ||
|
|
13e7aacc9d | ||
|
|
737d502614 | ||
|
|
67dd649d00 | ||
|
|
b2fc51367b | ||
|
|
5771bb4907 | ||
|
|
9ba9674437 | ||
|
|
acb1532e34 | ||
|
|
e2093c34da | ||
|
|
a2e4ad90ba | ||
|
|
32e69c67f2 | ||
|
|
df0b5a187e | ||
|
|
cee0e5379b | ||
|
|
daf2bd7e66 | ||
|
|
98a2f23024 | ||
|
|
c955897d1b | ||
|
|
cfdb0925ce | ||
|
|
83db3eddd9 | ||
|
|
cc2c5a544e | ||
|
|
8fba8c2800 | ||
|
|
51d1da8460 | ||
|
|
2f1257056d | ||
|
|
2f8f6967bf | ||
|
|
246527e618 | ||
|
|
3857cc9c83 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -296,7 +296,7 @@ jobs:
|
||||
name: Run script/clang-tidy for ZEPHYR
|
||||
options: --environment nrf52-tidy --grep USE_ZEPHYR
|
||||
pio_cache_key: tidy-zephyr
|
||||
ignore_errors: true
|
||||
ignore_errors: false
|
||||
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
|
||||
@@ -235,6 +235,7 @@ esphome/components/kamstrup_kmp/* @cfeenstra1024
|
||||
esphome/components/key_collector/* @ssieb
|
||||
esphome/components/key_provider/* @ssieb
|
||||
esphome/components/kuntze/* @ssieb
|
||||
esphome/components/lc709203f/* @ilikecake
|
||||
esphome/components/lcd_menu/* @numo68
|
||||
esphome/components/ld2410/* @regevbr @sebcaps
|
||||
esphome/components/ld2420/* @descipher
|
||||
|
||||
@@ -22,7 +22,7 @@ static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1;
|
||||
static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1;
|
||||
|
||||
void ADCSensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'...", this->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'", this->get_name().c_str());
|
||||
|
||||
if (this->channel1_ != ADC1_CHANNEL_MAX) {
|
||||
adc1_config_width(ADC_WIDTH_MAX_SOC_BITS);
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace adc {
|
||||
static const char *const TAG = "adc.esp8266";
|
||||
|
||||
void ADCSensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'...", this->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'", this->get_name().c_str());
|
||||
#ifndef USE_ADC_SENSOR_VCC
|
||||
this->pin_->setup();
|
||||
#endif
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace adc {
|
||||
static const char *const TAG = "adc.libretiny";
|
||||
|
||||
void ADCSensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'...", this->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'", this->get_name().c_str());
|
||||
#ifndef USE_ADC_SENSOR_VCC
|
||||
this->pin_->setup();
|
||||
#endif // !USE_ADC_SENSOR_VCC
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace adc {
|
||||
static const char *const TAG = "adc.rp2040";
|
||||
|
||||
void ADCSensor::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'...", this->get_name().c_str());
|
||||
ESP_LOGCONFIG(TAG, "Running setup for '%s'", this->get_name().c_str());
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
adc_init();
|
||||
|
||||
@@ -115,7 +115,7 @@ void AHT10Component::read_data_() {
|
||||
if (this->humidity_sensor_ == nullptr) {
|
||||
ESP_LOGV(TAG, "Invalid humidity (reading not required)");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Invalid humidity, retrying...");
|
||||
ESP_LOGD(TAG, "Invalid humidity, retrying");
|
||||
if (this->write(AHT10_MEASURE_CMD, sizeof(AHT10_MEASURE_CMD)) != i2c::ERROR_OK) {
|
||||
this->status_set_warning(ESP_LOG_MSG_COMM_FAIL);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ SERVICE_ARG_NATIVE_TYPES = {
|
||||
"string[]": cg.std_vector.template(cg.std_string),
|
||||
}
|
||||
CONF_ENCRYPTION = "encryption"
|
||||
CONF_BATCH_DELAY = "batch_delay"
|
||||
|
||||
|
||||
def validate_encryption_key(value):
|
||||
@@ -109,6 +110,9 @@ CONFIG_SCHEMA = cv.All(
|
||||
): ACTIONS_SCHEMA,
|
||||
cv.Exclusive(CONF_ACTIONS, group_of_exclusion=CONF_ACTIONS): ACTIONS_SCHEMA,
|
||||
cv.Optional(CONF_ENCRYPTION): _encryption_schema,
|
||||
cv.Optional(
|
||||
CONF_BATCH_DELAY, default="100ms"
|
||||
): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_ON_CLIENT_CONNECTED): automation.validate_automation(
|
||||
single=True
|
||||
),
|
||||
@@ -129,6 +133,7 @@ async def to_code(config):
|
||||
cg.add(var.set_port(config[CONF_PORT]))
|
||||
cg.add(var.set_password(config[CONF_PASSWORD]))
|
||||
cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT]))
|
||||
cg.add(var.set_batch_delay(config[CONF_BATCH_DELAY]))
|
||||
|
||||
for conf in config.get(CONF_ACTIONS, []):
|
||||
template_args = []
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@
|
||||
#include "esphome/core/entity_base.h"
|
||||
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace esphome {
|
||||
namespace api {
|
||||
@@ -18,49 +19,9 @@ namespace api {
|
||||
// Keepalive timeout in milliseconds
|
||||
static constexpr uint32_t KEEPALIVE_TIMEOUT_MS = 60000;
|
||||
|
||||
using send_message_t = bool (APIConnection::*)(void *);
|
||||
|
||||
/*
|
||||
This class holds a pointer to the source component that wants to publish a message, and a pointer to a function that
|
||||
will lazily publish that message. The two pointers allow dedup in the deferred queue if multiple publishes for the
|
||||
same component are backed up, and take up only 8 bytes of memory. The entry in the deferred queue (a std::vector) is
|
||||
the DeferredMessage instance itself (not a pointer to one elsewhere in heap) so still only 8 bytes per entry. Even
|
||||
100 backed up messages (you'd have to have at least 100 sensors publishing because of dedup) would take up only 0.8
|
||||
kB.
|
||||
*/
|
||||
class DeferredMessageQueue {
|
||||
struct DeferredMessage {
|
||||
friend class DeferredMessageQueue;
|
||||
|
||||
protected:
|
||||
void *source_;
|
||||
send_message_t send_message_;
|
||||
|
||||
public:
|
||||
DeferredMessage(void *source, send_message_t send_message) : source_(source), send_message_(send_message) {}
|
||||
bool operator==(const DeferredMessage &test) const {
|
||||
return (source_ == test.source_ && send_message_ == test.send_message_);
|
||||
}
|
||||
} __attribute__((packed));
|
||||
|
||||
protected:
|
||||
// vector is used very specifically for its zero memory overhead even though items are popped from the front (memory
|
||||
// footprint is more important than speed here)
|
||||
std::vector<DeferredMessage> deferred_queue_;
|
||||
APIConnection *api_connection_;
|
||||
|
||||
// helper for allowing only unique entries in the queue
|
||||
void dmq_push_back_with_dedup_(void *source, send_message_t send_message);
|
||||
|
||||
public:
|
||||
DeferredMessageQueue(APIConnection *api_connection) : api_connection_(api_connection) {}
|
||||
void process_queue();
|
||||
void defer(void *source, send_message_t send_message);
|
||||
bool empty() const { return deferred_queue_.empty(); }
|
||||
};
|
||||
|
||||
class APIConnection : public APIServerConnection {
|
||||
public:
|
||||
friend class APIServer;
|
||||
APIConnection(std::unique_ptr<socket::Socket> socket, APIServer *parent);
|
||||
virtual ~APIConnection();
|
||||
|
||||
@@ -68,225 +29,113 @@ class APIConnection : public APIServerConnection {
|
||||
void loop();
|
||||
|
||||
bool send_list_info_done() {
|
||||
ListEntitiesDoneResponse resp;
|
||||
return this->send_list_entities_done_response(resp);
|
||||
return this->schedule_message_(nullptr, &APIConnection::try_send_list_info_done,
|
||||
ListEntitiesDoneResponse::MESSAGE_TYPE);
|
||||
}
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor, bool state);
|
||||
bool send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor);
|
||||
void send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor);
|
||||
|
||||
protected:
|
||||
bool try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor);
|
||||
bool try_send_binary_sensor_state_(binary_sensor::BinarySensor *binary_sensor, bool state);
|
||||
bool try_send_binary_sensor_info_(binary_sensor::BinarySensor *binary_sensor);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
bool send_cover_state(cover::Cover *cover);
|
||||
void send_cover_info(cover::Cover *cover);
|
||||
void cover_command(const CoverCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_cover_state_(cover::Cover *cover);
|
||||
bool try_send_cover_info_(cover::Cover *cover);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
bool send_fan_state(fan::Fan *fan);
|
||||
void send_fan_info(fan::Fan *fan);
|
||||
void fan_command(const FanCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_fan_state_(fan::Fan *fan);
|
||||
bool try_send_fan_info_(fan::Fan *fan);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
bool send_light_state(light::LightState *light);
|
||||
void send_light_info(light::LightState *light);
|
||||
void light_command(const LightCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_light_state_(light::LightState *light);
|
||||
bool try_send_light_info_(light::LightState *light);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool send_sensor_state(sensor::Sensor *sensor, float state);
|
||||
bool send_sensor_state(sensor::Sensor *sensor);
|
||||
void send_sensor_info(sensor::Sensor *sensor);
|
||||
|
||||
protected:
|
||||
bool try_send_sensor_state_(sensor::Sensor *sensor);
|
||||
bool try_send_sensor_state_(sensor::Sensor *sensor, float state);
|
||||
bool try_send_sensor_info_(sensor::Sensor *sensor);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool send_switch_state(switch_::Switch *a_switch, bool state);
|
||||
bool send_switch_state(switch_::Switch *a_switch);
|
||||
void send_switch_info(switch_::Switch *a_switch);
|
||||
void switch_command(const SwitchCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_switch_state_(switch_::Switch *a_switch);
|
||||
bool try_send_switch_state_(switch_::Switch *a_switch, bool state);
|
||||
bool try_send_switch_info_(switch_::Switch *a_switch);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, std::string state);
|
||||
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor, const std::string &state);
|
||||
bool send_text_sensor_state(text_sensor::TextSensor *text_sensor);
|
||||
void send_text_sensor_info(text_sensor::TextSensor *text_sensor);
|
||||
|
||||
protected:
|
||||
bool try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor);
|
||||
bool try_send_text_sensor_state_(text_sensor::TextSensor *text_sensor, std::string state);
|
||||
bool try_send_text_sensor_info_(text_sensor::TextSensor *text_sensor);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
void set_camera_state(std::shared_ptr<esp32_camera::CameraImage> image);
|
||||
void send_camera_info(esp32_camera::ESP32Camera *camera);
|
||||
void camera_image(const CameraImageRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_camera_info_(esp32_camera::ESP32Camera *camera);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool send_climate_state(climate::Climate *climate);
|
||||
void send_climate_info(climate::Climate *climate);
|
||||
void climate_command(const ClimateCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_climate_state_(climate::Climate *climate);
|
||||
bool try_send_climate_info_(climate::Climate *climate);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool send_number_state(number::Number *number, float state);
|
||||
bool send_number_state(number::Number *number);
|
||||
void send_number_info(number::Number *number);
|
||||
void number_command(const NumberCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_number_state_(number::Number *number);
|
||||
bool try_send_number_state_(number::Number *number, float state);
|
||||
bool try_send_number_info_(number::Number *number);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool send_date_state(datetime::DateEntity *date);
|
||||
void send_date_info(datetime::DateEntity *date);
|
||||
void date_command(const DateCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_date_state_(datetime::DateEntity *date);
|
||||
bool try_send_date_info_(datetime::DateEntity *date);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
bool send_time_state(datetime::TimeEntity *time);
|
||||
void send_time_info(datetime::TimeEntity *time);
|
||||
void time_command(const TimeCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_time_state_(datetime::TimeEntity *time);
|
||||
bool try_send_time_info_(datetime::TimeEntity *time);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
bool send_datetime_state(datetime::DateTimeEntity *datetime);
|
||||
void send_datetime_info(datetime::DateTimeEntity *datetime);
|
||||
void datetime_command(const DateTimeCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_datetime_state_(datetime::DateTimeEntity *datetime);
|
||||
bool try_send_datetime_info_(datetime::DateTimeEntity *datetime);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool send_text_state(text::Text *text, std::string state);
|
||||
bool send_text_state(text::Text *text, const std::string &state);
|
||||
bool send_text_state(text::Text *text);
|
||||
void send_text_info(text::Text *text);
|
||||
void text_command(const TextCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_text_state_(text::Text *text);
|
||||
bool try_send_text_state_(text::Text *text, std::string state);
|
||||
bool try_send_text_info_(text::Text *text);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool send_select_state(select::Select *select, std::string state);
|
||||
bool send_select_state(select::Select *select, const std::string &state);
|
||||
bool send_select_state(select::Select *select);
|
||||
void send_select_info(select::Select *select);
|
||||
void select_command(const SelectCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_select_state_(select::Select *select);
|
||||
bool try_send_select_state_(select::Select *select, std::string state);
|
||||
bool try_send_select_info_(select::Select *select);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
void send_button_info(button::Button *button);
|
||||
void button_command(const ButtonCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_button_info_(button::Button *button);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool send_lock_state(lock::Lock *a_lock, lock::LockState state);
|
||||
bool send_lock_state(lock::Lock *a_lock);
|
||||
void send_lock_info(lock::Lock *a_lock);
|
||||
void lock_command(const LockCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_lock_state_(lock::Lock *a_lock);
|
||||
bool try_send_lock_state_(lock::Lock *a_lock, lock::LockState state);
|
||||
bool try_send_lock_info_(lock::Lock *a_lock);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool send_valve_state(valve::Valve *valve);
|
||||
void send_valve_info(valve::Valve *valve);
|
||||
void valve_command(const ValveCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_valve_state_(valve::Valve *valve);
|
||||
bool try_send_valve_info_(valve::Valve *valve);
|
||||
|
||||
public:
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
bool send_media_player_state(media_player::MediaPlayer *media_player);
|
||||
void send_media_player_info(media_player::MediaPlayer *media_player);
|
||||
void media_player_command(const MediaPlayerCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_media_player_state_(media_player::MediaPlayer *media_player);
|
||||
bool try_send_media_player_info_(media_player::MediaPlayer *media_player);
|
||||
|
||||
public:
|
||||
#endif
|
||||
bool try_send_log_message(int level, const char *tag, const char *line);
|
||||
void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
|
||||
if (!this->service_call_subscription_)
|
||||
return;
|
||||
this->send_homeassistant_service_response(call);
|
||||
this->send_message(call);
|
||||
}
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override;
|
||||
@@ -308,7 +157,7 @@ class APIConnection : public APIServerConnection {
|
||||
#ifdef USE_HOMEASSISTANT_TIME
|
||||
void send_time_request() {
|
||||
GetTimeRequest req;
|
||||
this->send_get_time_request(req);
|
||||
this->send_message(req);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -328,36 +177,17 @@ class APIConnection : public APIServerConnection {
|
||||
bool send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
|
||||
void send_alarm_control_panel_info(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
|
||||
void alarm_control_panel_command(const AlarmControlPanelCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_alarm_control_panel_state_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
|
||||
bool try_send_alarm_control_panel_info_(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
#ifdef USE_EVENT
|
||||
void send_event(event::Event *event, std::string event_type);
|
||||
void send_event(event::Event *event, const std::string &event_type);
|
||||
void send_event_info(event::Event *event);
|
||||
|
||||
protected:
|
||||
bool try_send_event_(event::Event *event);
|
||||
bool try_send_event_(event::Event *event, std::string event_type);
|
||||
bool try_send_event_info_(event::Event *event);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
#ifdef USE_UPDATE
|
||||
bool send_update_state(update::UpdateEntity *update);
|
||||
void send_update_info(update::UpdateEntity *update);
|
||||
void update_command(const UpdateCommandRequest &msg) override;
|
||||
|
||||
protected:
|
||||
bool try_send_update_state_(update::UpdateEntity *update);
|
||||
bool try_send_update_info_(update::UpdateEntity *update);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
void on_disconnect_response(const DisconnectResponse &value) override;
|
||||
@@ -407,102 +237,67 @@ class APIConnection : public APIServerConnection {
|
||||
void on_no_setup_connection() override;
|
||||
ProtoWriteBuffer create_buffer(uint32_t reserve_size) override {
|
||||
// FIXME: ensure no recursive writes can happen
|
||||
this->proto_write_buffer_.clear();
|
||||
|
||||
// Get header padding size - used for both reserve and insert
|
||||
uint8_t header_padding = this->helper_->frame_header_padding();
|
||||
|
||||
// Get shared buffer from parent server
|
||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
||||
shared_buf.clear();
|
||||
// Reserve space for header padding + message + footer
|
||||
// - Header padding: space for protocol headers (7 bytes for Noise, 6 for Plaintext)
|
||||
// - Footer: space for MAC (16 bytes for Noise, 0 for Plaintext)
|
||||
this->proto_write_buffer_.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
|
||||
shared_buf.reserve(reserve_size + header_padding + this->helper_->frame_footer_size());
|
||||
// Insert header padding bytes so message encoding starts at the correct position
|
||||
this->proto_write_buffer_.insert(this->proto_write_buffer_.begin(), header_padding, 0);
|
||||
return {&this->proto_write_buffer_};
|
||||
shared_buf.insert(shared_buf.begin(), header_padding, 0);
|
||||
return {&shared_buf};
|
||||
}
|
||||
|
||||
// Prepare buffer for next message in batch
|
||||
ProtoWriteBuffer prepare_message_buffer(uint16_t message_size, bool is_first_message) {
|
||||
// Get reference to shared buffer (it maintains state between batch messages)
|
||||
std::vector<uint8_t> &shared_buf = this->parent_->get_shared_buffer_ref();
|
||||
size_t current_size = shared_buf.size();
|
||||
|
||||
if (is_first_message) {
|
||||
// For first message, initialize buffer with header padding
|
||||
uint8_t header_padding = this->helper_->frame_header_padding();
|
||||
shared_buf.clear();
|
||||
shared_buf.reserve(message_size + header_padding);
|
||||
shared_buf.resize(header_padding);
|
||||
// Fill header padding with zeros
|
||||
std::fill(shared_buf.begin(), shared_buf.end(), 0);
|
||||
} else {
|
||||
// For subsequent messages, add footer space for previous message and header for this message
|
||||
uint8_t footer_size = this->helper_->frame_footer_size();
|
||||
uint8_t header_padding = this->helper_->frame_header_padding();
|
||||
|
||||
// Reserve additional space for everything
|
||||
shared_buf.reserve(current_size + footer_size + header_padding + message_size);
|
||||
|
||||
// Single resize to add both footer and header padding
|
||||
size_t new_size = current_size + footer_size + header_padding;
|
||||
shared_buf.resize(new_size);
|
||||
|
||||
// Fill the newly added bytes with zeros (footer + header padding)
|
||||
std::fill(shared_buf.begin() + current_size, shared_buf.end(), 0);
|
||||
}
|
||||
|
||||
return {&shared_buf};
|
||||
}
|
||||
|
||||
bool try_to_clear_buffer(bool log_out_of_space);
|
||||
bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) override;
|
||||
bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) override;
|
||||
|
||||
std::string get_client_combined_info() const { return this->client_combined_info_; }
|
||||
|
||||
// Buffer allocator methods for batch processing
|
||||
ProtoWriteBuffer allocate_single_message_buffer(uint16_t size);
|
||||
ProtoWriteBuffer allocate_batch_message_buffer(uint16_t size);
|
||||
|
||||
protected:
|
||||
friend APIServer;
|
||||
|
||||
/**
|
||||
* Generic send entity state method to reduce code duplication.
|
||||
* Only attempts to build and send the message if the transmit buffer is available.
|
||||
*
|
||||
* This is the base version for entities that use their current state.
|
||||
*
|
||||
* @param entity The entity to send state for
|
||||
* @param try_send_func The function that tries to send the state
|
||||
* @return True on success or message deferred, false if subscription check failed
|
||||
*/
|
||||
bool send_state_(esphome::EntityBase *entity, send_message_t try_send_func) {
|
||||
if (!this->state_subscription_)
|
||||
return false;
|
||||
if (this->try_to_clear_buffer(true) && (this->*try_send_func)(entity)) {
|
||||
return true;
|
||||
}
|
||||
this->deferred_message_queue_.defer(entity, try_send_func);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send entity state method that handles explicit state values.
|
||||
* Only attempts to build and send the message if the transmit buffer is available.
|
||||
*
|
||||
* This method accepts a state parameter to be used instead of the entity's current state.
|
||||
* It attempts to send the state with the provided value first, and if that fails due to buffer constraints,
|
||||
* it defers the entity for later processing using the entity-only function.
|
||||
*
|
||||
* @tparam EntityT The entity type
|
||||
* @tparam StateT Type of the state parameter
|
||||
* @tparam Args Additional argument types (if any)
|
||||
* @param entity The entity to send state for
|
||||
* @param try_send_entity_func The function that tries to send the state with entity pointer only
|
||||
* @param try_send_state_func The function that tries to send the state with entity and state parameters
|
||||
* @param state The state value to send
|
||||
* @param args Additional arguments to pass to the try_send_state_func
|
||||
* @return True on success or message deferred, false if subscription check failed
|
||||
*/
|
||||
template<typename EntityT, typename StateT, typename... Args>
|
||||
bool send_state_with_value_(EntityT *entity, bool (APIConnection::*try_send_entity_func)(EntityT *),
|
||||
bool (APIConnection::*try_send_state_func)(EntityT *, StateT, Args...), StateT state,
|
||||
Args... args) {
|
||||
if (!this->state_subscription_)
|
||||
return false;
|
||||
if (this->try_to_clear_buffer(true) && (this->*try_send_state_func)(entity, state, args...)) {
|
||||
return true;
|
||||
}
|
||||
this->deferred_message_queue_.defer(entity, reinterpret_cast<send_message_t>(try_send_entity_func));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic send entity info method to reduce code duplication.
|
||||
* Only attempts to build and send the message if the transmit buffer is available.
|
||||
*
|
||||
* @param entity The entity to send info for
|
||||
* @param try_send_func The function that tries to send the info
|
||||
*/
|
||||
void send_info_(esphome::EntityBase *entity, send_message_t try_send_func) {
|
||||
if (this->try_to_clear_buffer(true) && (this->*try_send_func)(entity)) {
|
||||
return;
|
||||
}
|
||||
this->deferred_message_queue_.defer(entity, try_send_func);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic function for generating entity info response messages.
|
||||
* This is used to reduce duplication in the try_send_*_info functions.
|
||||
*
|
||||
* @param entity The entity to generate info for
|
||||
* @param response The response object
|
||||
* @param send_response_func Function pointer to send the response
|
||||
* @return True if the message was sent successfully
|
||||
*/
|
||||
template<typename ResponseT>
|
||||
bool try_send_entity_info_(esphome::EntityBase *entity, ResponseT &response,
|
||||
bool (APIServerConnectionBase::*send_response_func)(const ResponseT &)) {
|
||||
// Helper function to fill common entity fields
|
||||
template<typename ResponseT> static void fill_entity_info_base(esphome::EntityBase *entity, ResponseT &response) {
|
||||
// Set common fields that are shared by all entity types
|
||||
response.key = entity->get_object_id_hash();
|
||||
response.object_id = entity->get_object_id();
|
||||
@@ -514,12 +309,149 @@ class APIConnection : public APIServerConnection {
|
||||
response.icon = entity->get_icon();
|
||||
response.disabled_by_default = entity->is_disabled_by_default();
|
||||
response.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category());
|
||||
|
||||
// Send the response using the provided send method
|
||||
return (this->*send_response_func)(response);
|
||||
}
|
||||
|
||||
bool send_(const void *buf, size_t len, bool force);
|
||||
// Non-template helper to encode any ProtoMessage
|
||||
static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
static uint16_t try_send_binary_sensor_state_response(binary_sensor::BinarySensor *binary_sensor, bool state,
|
||||
APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_binary_sensor_state(EntityBase *binary_sensor, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_binary_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
static uint16_t try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_cover_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
static uint16_t try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_fan_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
static uint16_t try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_light_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
static uint16_t try_send_sensor_state_response(sensor::Sensor *sensor, float state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
static uint16_t try_send_switch_state_response(switch_::Switch *a_switch, bool state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_switch_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
static uint16_t try_send_text_sensor_state_response(text_sensor::TextSensor *text_sensor, const std::string &state,
|
||||
APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_text_sensor_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
static uint16_t try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_climate_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
static uint16_t try_send_number_state_response(number::Number *number, float state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_number_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
static uint16_t try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_date_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
static uint16_t try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_time_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
static uint16_t try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_datetime_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
static uint16_t try_send_text_state_response(text::Text *text, const std::string &state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_text_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
static uint16_t try_send_select_state_response(select::Select *select, const std::string &state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_select_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
static uint16_t try_send_button_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
static uint16_t try_send_lock_state_response(lock::Lock *a_lock, lock::LockState state, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_lock_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
static uint16_t try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_valve_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
static uint16_t try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_media_player_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
static uint16_t try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_alarm_control_panel_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
static uint16_t try_send_event_response(event::Event *event, const std::string &event_type, APIConnection *conn,
|
||||
uint32_t remaining_size, bool is_single);
|
||||
static uint16_t try_send_event_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single);
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
static uint16_t try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
static uint16_t try_send_update_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
static uint16_t try_send_camera_info(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
#endif
|
||||
|
||||
// Method for ListEntitiesDone batching
|
||||
static uint16_t try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single);
|
||||
|
||||
// Helper function to get estimated message size for buffer pre-allocation
|
||||
static uint16_t get_estimated_message_size(uint16_t message_type);
|
||||
|
||||
enum class ConnectionState {
|
||||
WAITING_FOR_HELLO,
|
||||
@@ -529,9 +461,6 @@ class APIConnection : public APIServerConnection {
|
||||
|
||||
bool remove_{false};
|
||||
|
||||
// Buffer used to encode proto messages
|
||||
// Re-use to prevent allocations
|
||||
std::vector<uint8_t> proto_write_buffer_;
|
||||
std::unique_ptr<APIFrameHelper> helper_;
|
||||
|
||||
std::string client_info_;
|
||||
@@ -552,10 +481,180 @@ class APIConnection : public APIServerConnection {
|
||||
bool service_call_subscription_{false};
|
||||
bool next_close_ = false;
|
||||
APIServer *parent_;
|
||||
DeferredMessageQueue deferred_message_queue_;
|
||||
InitialStateIterator initial_state_iterator_;
|
||||
ListEntitiesIterator list_entities_iterator_;
|
||||
int state_subs_at_ = -1;
|
||||
|
||||
// Function pointer type for message encoding
|
||||
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single);
|
||||
|
||||
// Optimized MessageCreator class using union dispatch
|
||||
class MessageCreator {
|
||||
public:
|
||||
// Constructor for function pointer (message_type = 0)
|
||||
MessageCreator(MessageCreatorPtr ptr) : message_type_(0) { data_.ptr = ptr; }
|
||||
|
||||
// Constructor for bool state capture
|
||||
MessageCreator(bool value, uint16_t msg_type) : message_type_(msg_type) { data_.bool_value = value; }
|
||||
|
||||
// Constructor for float state capture
|
||||
MessageCreator(float value, uint16_t msg_type) : message_type_(msg_type) { data_.float_value = value; }
|
||||
|
||||
// Constructor for string state capture
|
||||
MessageCreator(const std::string &value, uint16_t msg_type) : message_type_(msg_type) {
|
||||
data_.string_ptr = new std::string(value);
|
||||
}
|
||||
|
||||
#ifdef USE_LOCK
|
||||
// Constructor for lock state capture
|
||||
MessageCreator(lock::LockState value, uint16_t msg_type) : message_type_(msg_type) { data_.lock_value = value; }
|
||||
#endif
|
||||
|
||||
// Destructor
|
||||
~MessageCreator() {
|
||||
// Clean up string data for string-based message types
|
||||
if (uses_string_data_()) {
|
||||
delete data_.string_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
MessageCreator(const MessageCreator &other) : message_type_(other.message_type_) {
|
||||
if (message_type_ == 0) {
|
||||
data_.ptr = other.data_.ptr;
|
||||
} else if (uses_string_data_()) {
|
||||
data_.string_ptr = new std::string(*other.data_.string_ptr);
|
||||
} else {
|
||||
data_ = other.data_; // For POD types
|
||||
}
|
||||
}
|
||||
|
||||
// Move constructor
|
||||
MessageCreator(MessageCreator &&other) noexcept : data_(other.data_), message_type_(other.message_type_) {
|
||||
other.message_type_ = 0; // Reset other to function pointer type
|
||||
other.data_.ptr = nullptr;
|
||||
}
|
||||
|
||||
// Assignment operators (needed for batch deduplication)
|
||||
MessageCreator &operator=(const MessageCreator &other) {
|
||||
if (this != &other) {
|
||||
// Clean up current string data if needed
|
||||
if (uses_string_data_()) {
|
||||
delete data_.string_ptr;
|
||||
}
|
||||
// Copy new data
|
||||
message_type_ = other.message_type_;
|
||||
if (other.message_type_ == 0) {
|
||||
data_.ptr = other.data_.ptr;
|
||||
} else if (other.uses_string_data_()) {
|
||||
data_.string_ptr = new std::string(*other.data_.string_ptr);
|
||||
} else {
|
||||
data_ = other.data_;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageCreator &operator=(MessageCreator &&other) noexcept {
|
||||
if (this != &other) {
|
||||
// Clean up current string data if needed
|
||||
if (uses_string_data_()) {
|
||||
delete data_.string_ptr;
|
||||
}
|
||||
// Move data
|
||||
message_type_ = other.message_type_;
|
||||
data_ = other.data_;
|
||||
// Reset other to safe state
|
||||
other.message_type_ = 0;
|
||||
other.data_.ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Call operator
|
||||
uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) const;
|
||||
|
||||
private:
|
||||
// Helper to check if this message type uses heap-allocated strings
|
||||
bool uses_string_data_() const {
|
||||
return message_type_ == TextSensorStateResponse::MESSAGE_TYPE ||
|
||||
message_type_ == SelectStateResponse::MESSAGE_TYPE || message_type_ == TextStateResponse::MESSAGE_TYPE ||
|
||||
message_type_ == EventResponse::MESSAGE_TYPE;
|
||||
}
|
||||
union CreatorData {
|
||||
MessageCreatorPtr ptr; // 8 bytes
|
||||
bool bool_value; // 1 byte
|
||||
float float_value; // 4 bytes
|
||||
std::string *string_ptr; // 8 bytes
|
||||
#ifdef USE_LOCK
|
||||
lock::LockState lock_value; // 4 bytes
|
||||
#endif
|
||||
} data_; // 8 bytes
|
||||
uint16_t message_type_; // 2 bytes (0 = function ptr, >0 = state capture)
|
||||
};
|
||||
|
||||
// Generic batching mechanism for both state updates and entity info
|
||||
struct DeferredBatch {
|
||||
struct BatchItem {
|
||||
EntityBase *entity; // Entity pointer
|
||||
MessageCreator creator; // Function that creates the message when needed
|
||||
uint16_t message_type; // Message type for overhead calculation
|
||||
|
||||
// Constructor for creating BatchItem
|
||||
BatchItem(EntityBase *entity, MessageCreator creator, uint16_t message_type)
|
||||
: entity(entity), creator(std::move(creator)), message_type(message_type) {}
|
||||
};
|
||||
|
||||
std::vector<BatchItem> items;
|
||||
uint32_t batch_start_time{0};
|
||||
bool batch_scheduled{false};
|
||||
|
||||
DeferredBatch() {
|
||||
// Pre-allocate capacity for typical batch sizes to avoid reallocation
|
||||
items.reserve(8);
|
||||
}
|
||||
|
||||
// Add item to the batch
|
||||
void add_item(EntityBase *entity, MessageCreator creator, uint16_t message_type);
|
||||
void clear() {
|
||||
items.clear();
|
||||
batch_scheduled = false;
|
||||
batch_start_time = 0;
|
||||
}
|
||||
bool empty() const { return items.empty(); }
|
||||
};
|
||||
|
||||
DeferredBatch deferred_batch_;
|
||||
uint32_t get_batch_delay_ms_() const;
|
||||
// Message will use 8 more bytes than the minimum size, and typical
|
||||
// MTU is 1500. Sometimes users will see as low as 1460 MTU.
|
||||
// If its IPv6 the header is 40 bytes, and if its IPv4
|
||||
// the header is 20 bytes. So we have 1460 - 40 = 1420 bytes
|
||||
// available for the payload. But we also need to add the size of
|
||||
// the protobuf overhead, which is 8 bytes.
|
||||
//
|
||||
// To be safe we pick 1390 bytes as the maximum size
|
||||
// to send in one go. This is the maximum size of a single packet
|
||||
// that can be sent over the network.
|
||||
// This is to avoid fragmentation of the packet.
|
||||
static constexpr size_t MAX_PACKET_SIZE = 1390; // MTU
|
||||
|
||||
bool schedule_batch_();
|
||||
void process_batch_();
|
||||
|
||||
// State for batch buffer allocation
|
||||
bool batch_first_message_{false};
|
||||
|
||||
// Helper function to schedule a deferred message with known message type
|
||||
bool schedule_message_(EntityBase *entity, MessageCreator creator, uint16_t message_type) {
|
||||
this->deferred_batch_.add_item(entity, std::move(creator), message_type);
|
||||
return this->schedule_batch_();
|
||||
}
|
||||
|
||||
// Overload for function pointers (for info messages and current state reads)
|
||||
bool schedule_message_(EntityBase *entity, MessageCreatorPtr function_ptr, uint16_t message_type) {
|
||||
return schedule_message_(entity, MessageCreator(function_ptr), message_type);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
@@ -605,9 +605,21 @@ APIError APINoiseFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
return APIError::OK;
|
||||
}
|
||||
APIError APINoiseFrameHelper::write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) {
|
||||
int err;
|
||||
APIError aerr;
|
||||
aerr = state_action_();
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
uint16_t payload_len = static_cast<uint16_t>(raw_buffer->size() - frame_header_padding_);
|
||||
|
||||
// Resize to include MAC space (required for Noise encryption)
|
||||
raw_buffer->resize(raw_buffer->size() + frame_footer_size_);
|
||||
|
||||
// Use write_protobuf_packets with a single packet
|
||||
std::vector<PacketInfo> packets;
|
||||
packets.emplace_back(type, 0, payload_len);
|
||||
|
||||
return write_protobuf_packets(buffer, packets);
|
||||
}
|
||||
|
||||
APIError APINoiseFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector<PacketInfo> &packets) {
|
||||
APIError aerr = state_action_();
|
||||
if (aerr != APIError::OK) {
|
||||
return aerr;
|
||||
}
|
||||
@@ -616,56 +628,66 @@ APIError APINoiseFrameHelper::write_protobuf_packet(uint16_t type, ProtoWriteBuf
|
||||
return APIError::WOULD_BLOCK;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
// Message data starts after padding
|
||||
uint16_t payload_len = raw_buffer->size() - frame_header_padding_;
|
||||
uint16_t padding = 0;
|
||||
uint16_t msg_len = 4 + payload_len + padding;
|
||||
|
||||
// We need to resize to include MAC space, but we already reserved it in create_buffer
|
||||
raw_buffer->resize(raw_buffer->size() + frame_footer_size_);
|
||||
|
||||
// Write the noise header in the padded area
|
||||
// Buffer layout:
|
||||
// [0] - 0x01 indicator byte
|
||||
// [1-2] - Size of encrypted payload (filled after encryption)
|
||||
// [3-4] - Message type (encrypted)
|
||||
// [5-6] - Payload length (encrypted)
|
||||
// [7...] - Actual payload data (encrypted)
|
||||
uint8_t *buf_start = raw_buffer->data();
|
||||
buf_start[0] = 0x01; // indicator
|
||||
// buf_start[1], buf_start[2] to be set later after encryption
|
||||
const uint8_t msg_offset = 3;
|
||||
buf_start[msg_offset + 0] = (uint8_t) (type >> 8); // type high byte
|
||||
buf_start[msg_offset + 1] = (uint8_t) type; // type low byte
|
||||
buf_start[msg_offset + 2] = (uint8_t) (payload_len >> 8); // data_len high byte
|
||||
buf_start[msg_offset + 3] = (uint8_t) payload_len; // data_len low byte
|
||||
// payload data is already in the buffer starting at position 7
|
||||
|
||||
NoiseBuffer mbuf;
|
||||
noise_buffer_init(mbuf);
|
||||
// The capacity parameter should be msg_len + frame_footer_size_ (MAC length) to allow space for encryption
|
||||
noise_buffer_set_inout(mbuf, buf_start + msg_offset, msg_len, msg_len + frame_footer_size_);
|
||||
err = noise_cipherstate_encrypt(send_cipher_, &mbuf);
|
||||
if (err != 0) {
|
||||
state_ = State::FAILED;
|
||||
HELPER_LOG("noise_cipherstate_encrypt failed: %s", noise_err_to_str(err).c_str());
|
||||
return APIError::CIPHERSTATE_ENCRYPT_FAILED;
|
||||
if (packets.empty()) {
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
uint16_t total_len = 3 + mbuf.size;
|
||||
buf_start[1] = (uint8_t) (mbuf.size >> 8);
|
||||
buf_start[2] = (uint8_t) mbuf.size;
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
this->reusable_iovs_.clear();
|
||||
this->reusable_iovs_.reserve(packets.size());
|
||||
|
||||
struct iovec iov;
|
||||
// Point iov_base to the beginning of the buffer (no unused padding in Noise)
|
||||
// We send the entire frame: indicator + size + encrypted(type + data_len + payload + MAC)
|
||||
iov.iov_base = buf_start;
|
||||
iov.iov_len = total_len;
|
||||
// We need to encrypt each packet in place
|
||||
for (const auto &packet : packets) {
|
||||
uint16_t type = packet.message_type;
|
||||
uint16_t offset = packet.offset;
|
||||
uint16_t payload_len = packet.payload_size;
|
||||
uint16_t msg_len = 4 + payload_len; // type(2) + data_len(2) + payload
|
||||
|
||||
// write raw to not have two packets sent if NAGLE disabled
|
||||
return this->write_raw_(&iov, 1);
|
||||
// The buffer already has padding at offset
|
||||
uint8_t *buf_start = raw_buffer->data() + offset;
|
||||
|
||||
// Write noise header
|
||||
buf_start[0] = 0x01; // indicator
|
||||
// buf_start[1], buf_start[2] to be set after encryption
|
||||
|
||||
// Write message header (to be encrypted)
|
||||
const uint8_t msg_offset = 3;
|
||||
buf_start[msg_offset + 0] = (uint8_t) (type >> 8); // type high byte
|
||||
buf_start[msg_offset + 1] = (uint8_t) type; // type low byte
|
||||
buf_start[msg_offset + 2] = (uint8_t) (payload_len >> 8); // data_len high byte
|
||||
buf_start[msg_offset + 3] = (uint8_t) payload_len; // data_len low byte
|
||||
// payload data is already in the buffer starting at offset + 7
|
||||
|
||||
// Make sure we have space for MAC
|
||||
// The buffer should already have been sized appropriately
|
||||
|
||||
// Encrypt the message in place
|
||||
NoiseBuffer mbuf;
|
||||
noise_buffer_init(mbuf);
|
||||
noise_buffer_set_inout(mbuf, buf_start + msg_offset, msg_len, msg_len + frame_footer_size_);
|
||||
|
||||
int err = noise_cipherstate_encrypt(send_cipher_, &mbuf);
|
||||
if (err != 0) {
|
||||
state_ = State::FAILED;
|
||||
HELPER_LOG("noise_cipherstate_encrypt failed: %s", noise_err_to_str(err).c_str());
|
||||
return APIError::CIPHERSTATE_ENCRYPT_FAILED;
|
||||
}
|
||||
|
||||
// Fill in the encrypted size
|
||||
buf_start[1] = (uint8_t) (mbuf.size >> 8);
|
||||
buf_start[2] = (uint8_t) mbuf.size;
|
||||
|
||||
// Add iovec for this encrypted packet
|
||||
struct iovec iov;
|
||||
iov.iov_base = buf_start;
|
||||
iov.iov_len = 3 + mbuf.size; // indicator + size + encrypted data
|
||||
this->reusable_iovs_.push_back(iov);
|
||||
}
|
||||
|
||||
// Send all encrypted packets in one writev call
|
||||
return this->write_raw_(this->reusable_iovs_.data(), this->reusable_iovs_.size());
|
||||
}
|
||||
|
||||
APIError APINoiseFrameHelper::write_frame_(const uint8_t *data, uint16_t len) {
|
||||
uint8_t header[3];
|
||||
header[0] = 0x01; // indicator
|
||||
@@ -780,7 +802,7 @@ extern "C" {
|
||||
// declare how noise generates random bytes (here with a good HWRNG based on the RF system)
|
||||
void noise_rand_bytes(void *output, size_t len) {
|
||||
if (!esphome::random_bytes(reinterpret_cast<uint8_t *>(output), len)) {
|
||||
ESP_LOGE(TAG, "Failed to acquire random bytes, rebooting!");
|
||||
ESP_LOGE(TAG, "Acquiring random bytes failed; rebooting");
|
||||
arch_restart();
|
||||
}
|
||||
}
|
||||
@@ -1004,65 +1026,86 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
|
||||
return APIError::OK;
|
||||
}
|
||||
APIError APIPlaintextFrameHelper::write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) {
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
uint16_t payload_len = static_cast<uint16_t>(raw_buffer->size() - frame_header_padding_);
|
||||
|
||||
// Use write_protobuf_packets with a single packet
|
||||
std::vector<PacketInfo> packets;
|
||||
packets.emplace_back(type, 0, payload_len);
|
||||
|
||||
return write_protobuf_packets(buffer, packets);
|
||||
}
|
||||
|
||||
APIError APIPlaintextFrameHelper::write_protobuf_packets(ProtoWriteBuffer buffer,
|
||||
const std::vector<PacketInfo> &packets) {
|
||||
if (state_ != State::DATA) {
|
||||
return APIError::BAD_STATE;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
// Message data starts after padding (frame_header_padding_ = 6)
|
||||
uint16_t payload_len = static_cast<uint16_t>(raw_buffer->size() - frame_header_padding_);
|
||||
|
||||
// Calculate varint sizes for header components
|
||||
uint8_t size_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(payload_len));
|
||||
uint8_t type_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(type));
|
||||
uint8_t total_header_len = 1 + size_varint_len + type_varint_len;
|
||||
|
||||
if (total_header_len > frame_header_padding_) {
|
||||
// Header is too large to fit in the padding
|
||||
return APIError::BAD_ARG;
|
||||
if (packets.empty()) {
|
||||
return APIError::OK;
|
||||
}
|
||||
|
||||
// Calculate where to start writing the header
|
||||
// The header starts at the latest possible position to minimize unused padding
|
||||
//
|
||||
// Example 1 (small values): total_header_len = 3, header_offset = 6 - 3 = 3
|
||||
// [0-2] - Unused padding
|
||||
// [3] - 0x00 indicator byte
|
||||
// [4] - Payload size varint (1 byte, for sizes 0-127)
|
||||
// [5] - Message type varint (1 byte, for types 0-127)
|
||||
// [6...] - Actual payload data
|
||||
//
|
||||
// Example 2 (medium values): total_header_len = 4, header_offset = 6 - 4 = 2
|
||||
// [0-1] - Unused padding
|
||||
// [2] - 0x00 indicator byte
|
||||
// [3-4] - Payload size varint (2 bytes, for sizes 128-16383)
|
||||
// [5] - Message type varint (1 byte, for types 0-127)
|
||||
// [6...] - Actual payload data
|
||||
//
|
||||
// Example 3 (large values): total_header_len = 6, header_offset = 6 - 6 = 0
|
||||
// [0] - 0x00 indicator byte
|
||||
// [1-3] - Payload size varint (3 bytes, for sizes 16384-2097151)
|
||||
// [4-5] - Message type varint (2 bytes, for types 128-32767)
|
||||
// [6...] - Actual payload data
|
||||
uint8_t *buf_start = raw_buffer->data();
|
||||
uint8_t header_offset = frame_header_padding_ - total_header_len;
|
||||
std::vector<uint8_t> *raw_buffer = buffer.get_buffer();
|
||||
this->reusable_iovs_.clear();
|
||||
this->reusable_iovs_.reserve(packets.size());
|
||||
|
||||
// Write the plaintext header
|
||||
buf_start[header_offset] = 0x00; // indicator
|
||||
for (const auto &packet : packets) {
|
||||
uint16_t type = packet.message_type;
|
||||
uint16_t offset = packet.offset;
|
||||
uint16_t payload_len = packet.payload_size;
|
||||
|
||||
// Encode size varint directly into buffer
|
||||
ProtoVarInt(payload_len).encode_to_buffer_unchecked(buf_start + header_offset + 1, size_varint_len);
|
||||
// Calculate varint sizes for header layout
|
||||
uint8_t size_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(payload_len));
|
||||
uint8_t type_varint_len = api::ProtoSize::varint(static_cast<uint32_t>(type));
|
||||
uint8_t total_header_len = 1 + size_varint_len + type_varint_len;
|
||||
|
||||
// Encode type varint directly into buffer
|
||||
ProtoVarInt(type).encode_to_buffer_unchecked(buf_start + header_offset + 1 + size_varint_len, type_varint_len);
|
||||
// Calculate where to start writing the header
|
||||
// The header starts at the latest possible position to minimize unused padding
|
||||
//
|
||||
// Example 1 (small values): total_header_len = 3, header_offset = 6 - 3 = 3
|
||||
// [0-2] - Unused padding
|
||||
// [3] - 0x00 indicator byte
|
||||
// [4] - Payload size varint (1 byte, for sizes 0-127)
|
||||
// [5] - Message type varint (1 byte, for types 0-127)
|
||||
// [6...] - Actual payload data
|
||||
//
|
||||
// Example 2 (medium values): total_header_len = 4, header_offset = 6 - 4 = 2
|
||||
// [0-1] - Unused padding
|
||||
// [2] - 0x00 indicator byte
|
||||
// [3-4] - Payload size varint (2 bytes, for sizes 128-16383)
|
||||
// [5] - Message type varint (1 byte, for types 0-127)
|
||||
// [6...] - Actual payload data
|
||||
//
|
||||
// Example 3 (large values): total_header_len = 6, header_offset = 6 - 6 = 0
|
||||
// [0] - 0x00 indicator byte
|
||||
// [1-3] - Payload size varint (3 bytes, for sizes 16384-2097151)
|
||||
// [4-5] - Message type varint (2 bytes, for types 128-32767)
|
||||
// [6...] - Actual payload data
|
||||
//
|
||||
// The message starts at offset + frame_header_padding_
|
||||
// So we write the header starting at offset + frame_header_padding_ - total_header_len
|
||||
uint8_t *buf_start = raw_buffer->data() + offset;
|
||||
uint32_t header_offset = frame_header_padding_ - total_header_len;
|
||||
|
||||
struct iovec iov;
|
||||
// Point iov_base to the beginning of our header (skip unused padding)
|
||||
// This ensures we only send the actual header and payload, not the empty padding bytes
|
||||
iov.iov_base = buf_start + header_offset;
|
||||
iov.iov_len = total_header_len + payload_len;
|
||||
// Write the plaintext header
|
||||
buf_start[header_offset] = 0x00; // indicator
|
||||
|
||||
return write_raw_(&iov, 1);
|
||||
// Encode size varint directly into buffer
|
||||
ProtoVarInt(payload_len).encode_to_buffer_unchecked(buf_start + header_offset + 1, size_varint_len);
|
||||
|
||||
// Encode type varint directly into buffer
|
||||
ProtoVarInt(type).encode_to_buffer_unchecked(buf_start + header_offset + 1 + size_varint_len, type_varint_len);
|
||||
|
||||
// Add iovec for this packet (header + payload)
|
||||
struct iovec iov;
|
||||
iov.iov_base = buf_start + header_offset;
|
||||
iov.iov_len = total_header_len + payload_len;
|
||||
this->reusable_iovs_.push_back(iov);
|
||||
}
|
||||
|
||||
// Send all packets in one writev call
|
||||
return write_raw_(this->reusable_iovs_.data(), this->reusable_iovs_.size());
|
||||
}
|
||||
|
||||
#endif // USE_API_PLAINTEXT
|
||||
|
||||
@@ -27,6 +27,17 @@ struct ReadPacketBuffer {
|
||||
uint16_t data_len;
|
||||
};
|
||||
|
||||
// Packed packet info structure to minimize memory usage
|
||||
struct PacketInfo {
|
||||
uint16_t message_type; // 2 bytes
|
||||
uint16_t offset; // 2 bytes (sufficient for packet size ~1460 bytes)
|
||||
uint16_t payload_size; // 2 bytes (up to 65535 bytes)
|
||||
uint16_t padding; // 2 byte (for alignment)
|
||||
|
||||
PacketInfo(uint16_t type, uint16_t off, uint16_t size)
|
||||
: message_type(type), offset(off), payload_size(size), padding(0) {}
|
||||
};
|
||||
|
||||
enum class APIError : int {
|
||||
OK = 0,
|
||||
WOULD_BLOCK = 1001,
|
||||
@@ -87,6 +98,10 @@ class APIFrameHelper {
|
||||
// Give this helper a name for logging
|
||||
void set_log_info(std::string info) { info_ = std::move(info); }
|
||||
virtual APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) = 0;
|
||||
// Write multiple protobuf packets in a single operation
|
||||
// packets contains (message_type, offset, length) for each message in the buffer
|
||||
// The buffer contains all messages with appropriate padding before each
|
||||
virtual APIError write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector<PacketInfo> &packets) = 0;
|
||||
// Get the frame header padding required by this protocol
|
||||
virtual uint8_t frame_header_padding() = 0;
|
||||
// Get the frame footer size required by this protocol
|
||||
@@ -157,6 +172,9 @@ class APIFrameHelper {
|
||||
uint8_t frame_header_padding_{0};
|
||||
uint8_t frame_footer_size_{0};
|
||||
|
||||
// Reusable IOV array for write_protobuf_packets to avoid repeated allocations
|
||||
std::vector<struct iovec> reusable_iovs_;
|
||||
|
||||
// Receive buffer for reading frame data
|
||||
std::vector<uint8_t> rx_buf_;
|
||||
uint16_t rx_buf_len_ = 0;
|
||||
@@ -182,6 +200,7 @@ class APINoiseFrameHelper : public APIFrameHelper {
|
||||
APIError loop() override;
|
||||
APIError read_packet(ReadPacketBuffer *buffer) override;
|
||||
APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override;
|
||||
APIError write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector<PacketInfo> &packets) override;
|
||||
// Get the frame header padding required by this protocol
|
||||
uint8_t frame_header_padding() override { return frame_header_padding_; }
|
||||
// Get the frame footer size required by this protocol
|
||||
@@ -226,6 +245,7 @@ class APIPlaintextFrameHelper : public APIFrameHelper {
|
||||
APIError loop() override;
|
||||
APIError read_packet(ReadPacketBuffer *buffer) override;
|
||||
APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override;
|
||||
APIError write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector<PacketInfo> &packets) override;
|
||||
uint8_t frame_header_padding() override { return frame_header_padding_; }
|
||||
// Get the frame footer size required by this protocol
|
||||
uint8_t frame_footer_size() override { return frame_footer_size_; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,688 +8,12 @@ namespace api {
|
||||
|
||||
static const char *const TAG = "api.service";
|
||||
|
||||
bool APIServerConnectionBase::send_hello_response(const HelloResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_hello_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<HelloResponse>(msg, 2);
|
||||
}
|
||||
bool APIServerConnectionBase::send_connect_response(const ConnectResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_connect_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ConnectResponse>(msg, 4);
|
||||
}
|
||||
bool APIServerConnectionBase::send_disconnect_request(const DisconnectRequest &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_disconnect_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<DisconnectRequest>(msg, 5);
|
||||
}
|
||||
bool APIServerConnectionBase::send_disconnect_response(const DisconnectResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_disconnect_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<DisconnectResponse>(msg, 6);
|
||||
}
|
||||
bool APIServerConnectionBase::send_ping_request(const PingRequest &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_ping_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<PingRequest>(msg, 7);
|
||||
}
|
||||
bool APIServerConnectionBase::send_ping_response(const PingResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_ping_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<PingResponse>(msg, 8);
|
||||
}
|
||||
bool APIServerConnectionBase::send_device_info_response(const DeviceInfoResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_device_info_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<DeviceInfoResponse>(msg, 10);
|
||||
}
|
||||
bool APIServerConnectionBase::send_list_entities_done_response(const ListEntitiesDoneResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_done_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesDoneResponse>(msg, 19);
|
||||
}
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool APIServerConnectionBase::send_list_entities_binary_sensor_response(const ListEntitiesBinarySensorResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_binary_sensor_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesBinarySensorResponse>(msg, 12);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool APIServerConnectionBase::send_binary_sensor_state_response(const BinarySensorStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_binary_sensor_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BinarySensorStateResponse>(msg, 21);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
bool APIServerConnectionBase::send_list_entities_cover_response(const ListEntitiesCoverResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_cover_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesCoverResponse>(msg, 13);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
bool APIServerConnectionBase::send_cover_state_response(const CoverStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_cover_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<CoverStateResponse>(msg, 22);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
bool APIServerConnectionBase::send_list_entities_fan_response(const ListEntitiesFanResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_fan_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesFanResponse>(msg, 14);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
bool APIServerConnectionBase::send_fan_state_response(const FanStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_fan_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<FanStateResponse>(msg, 23);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
bool APIServerConnectionBase::send_list_entities_light_response(const ListEntitiesLightResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_light_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesLightResponse>(msg, 15);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
bool APIServerConnectionBase::send_light_state_response(const LightStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_light_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<LightStateResponse>(msg, 24);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool APIServerConnectionBase::send_list_entities_sensor_response(const ListEntitiesSensorResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_sensor_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesSensorResponse>(msg, 16);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool APIServerConnectionBase::send_sensor_state_response(const SensorStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_sensor_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<SensorStateResponse>(msg, 25);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool APIServerConnectionBase::send_list_entities_switch_response(const ListEntitiesSwitchResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_switch_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesSwitchResponse>(msg, 17);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool APIServerConnectionBase::send_switch_state_response(const SwitchStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_switch_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<SwitchStateResponse>(msg, 26);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool APIServerConnectionBase::send_list_entities_text_sensor_response(const ListEntitiesTextSensorResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_text_sensor_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesTextSensorResponse>(msg, 18);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool APIServerConnectionBase::send_text_sensor_state_response(const TextSensorStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_text_sensor_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<TextSensorStateResponse>(msg, 27);
|
||||
}
|
||||
#endif
|
||||
bool APIServerConnectionBase::send_subscribe_logs_response(const SubscribeLogsResponse &msg) {
|
||||
return this->send_message_<SubscribeLogsResponse>(msg, 29);
|
||||
}
|
||||
#ifdef USE_API_NOISE
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
bool APIServerConnectionBase::send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_noise_encryption_set_key_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<NoiseEncryptionSetKeyResponse>(msg, 125);
|
||||
}
|
||||
#endif
|
||||
bool APIServerConnectionBase::send_homeassistant_service_response(const HomeassistantServiceResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_homeassistant_service_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<HomeassistantServiceResponse>(msg, 35);
|
||||
}
|
||||
bool APIServerConnectionBase::send_subscribe_home_assistant_state_response(
|
||||
const SubscribeHomeAssistantStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_subscribe_home_assistant_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<SubscribeHomeAssistantStateResponse>(msg, 39);
|
||||
}
|
||||
bool APIServerConnectionBase::send_get_time_request(const GetTimeRequest &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_get_time_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<GetTimeRequest>(msg, 36);
|
||||
}
|
||||
bool APIServerConnectionBase::send_get_time_response(const GetTimeResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_get_time_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<GetTimeResponse>(msg, 37);
|
||||
}
|
||||
bool APIServerConnectionBase::send_list_entities_services_response(const ListEntitiesServicesResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_services_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesServicesResponse>(msg, 41);
|
||||
}
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
bool APIServerConnectionBase::send_list_entities_camera_response(const ListEntitiesCameraResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_camera_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesCameraResponse>(msg, 43);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
bool APIServerConnectionBase::send_camera_image_response(const CameraImageResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_camera_image_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<CameraImageResponse>(msg, 44);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool APIServerConnectionBase::send_list_entities_climate_response(const ListEntitiesClimateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_climate_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesClimateResponse>(msg, 46);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool APIServerConnectionBase::send_climate_state_response(const ClimateStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_climate_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ClimateStateResponse>(msg, 47);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool APIServerConnectionBase::send_list_entities_number_response(const ListEntitiesNumberResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_number_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesNumberResponse>(msg, 49);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool APIServerConnectionBase::send_number_state_response(const NumberStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_number_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<NumberStateResponse>(msg, 50);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool APIServerConnectionBase::send_list_entities_select_response(const ListEntitiesSelectResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_select_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesSelectResponse>(msg, 52);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool APIServerConnectionBase::send_select_state_response(const SelectStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_select_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<SelectStateResponse>(msg, 53);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
bool APIServerConnectionBase::send_list_entities_siren_response(const ListEntitiesSirenResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_siren_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesSirenResponse>(msg, 55);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
bool APIServerConnectionBase::send_siren_state_response(const SirenStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_siren_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<SirenStateResponse>(msg, 56);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool APIServerConnectionBase::send_list_entities_lock_response(const ListEntitiesLockResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_lock_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesLockResponse>(msg, 58);
|
||||
void APIServerConnectionBase::log_send_message_(const char *name, const std::string &dump) {
|
||||
ESP_LOGVV(TAG, "send_message %s: %s", name, dump.c_str());
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool APIServerConnectionBase::send_lock_state_response(const LockStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_lock_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<LockStateResponse>(msg, 59);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
bool APIServerConnectionBase::send_list_entities_button_response(const ListEntitiesButtonResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_button_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesButtonResponse>(msg, 61);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
bool APIServerConnectionBase::send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_media_player_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesMediaPlayerResponse>(msg, 63);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
bool APIServerConnectionBase::send_media_player_state_response(const MediaPlayerStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_media_player_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<MediaPlayerStateResponse>(msg, 64);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_le_advertisement_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothLEAdvertisementResponse>(msg, 67);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_le_raw_advertisements_response(
|
||||
const BluetoothLERawAdvertisementsResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_le_raw_advertisements_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothLERawAdvertisementsResponse>(msg, 93);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_device_connection_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothDeviceConnectionResponse>(msg, 69);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTGetServicesResponse>(msg, 71);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_get_services_done_response(
|
||||
const BluetoothGATTGetServicesDoneResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_done_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTGetServicesDoneResponse>(msg, 72);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_read_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTReadResponse>(msg, 74);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_notify_data_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTNotifyDataResponse>(msg, 79);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_connections_free_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothConnectionsFreeResponse>(msg, 81);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_error_response(const BluetoothGATTErrorResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_error_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTErrorResponse>(msg, 82);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_write_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTWriteResponse>(msg, 83);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_gatt_notify_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothGATTNotifyResponse>(msg, 84);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_device_pairing_response(const BluetoothDevicePairingResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_device_pairing_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothDevicePairingResponse>(msg, 85);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_device_unpairing_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothDeviceUnpairingResponse>(msg, 86);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_device_clear_cache_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothDeviceClearCacheResponse>(msg, 88);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool APIServerConnectionBase::send_bluetooth_scanner_state_response(const BluetoothScannerStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_bluetooth_scanner_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<BluetoothScannerStateResponse>(msg, 126);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool APIServerConnectionBase::send_voice_assistant_request(const VoiceAssistantRequest &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_voice_assistant_request: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<VoiceAssistantRequest>(msg, 90);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool APIServerConnectionBase::send_voice_assistant_audio(const VoiceAssistantAudio &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_voice_assistant_audio: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<VoiceAssistantAudio>(msg, 106);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool APIServerConnectionBase::send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_voice_assistant_announce_finished: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<VoiceAssistantAnnounceFinished>(msg, 120);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool APIServerConnectionBase::send_voice_assistant_configuration_response(
|
||||
const VoiceAssistantConfigurationResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_voice_assistant_configuration_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<VoiceAssistantConfigurationResponse>(msg, 122);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
bool APIServerConnectionBase::send_list_entities_alarm_control_panel_response(
|
||||
const ListEntitiesAlarmControlPanelResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_alarm_control_panel_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesAlarmControlPanelResponse>(msg, 94);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
bool APIServerConnectionBase::send_alarm_control_panel_state_response(const AlarmControlPanelStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_alarm_control_panel_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<AlarmControlPanelStateResponse>(msg, 95);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool APIServerConnectionBase::send_list_entities_text_response(const ListEntitiesTextResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_text_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesTextResponse>(msg, 97);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool APIServerConnectionBase::send_text_state_response(const TextStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_text_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<TextStateResponse>(msg, 98);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool APIServerConnectionBase::send_list_entities_date_response(const ListEntitiesDateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_date_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesDateResponse>(msg, 100);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool APIServerConnectionBase::send_date_state_response(const DateStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_date_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<DateStateResponse>(msg, 101);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
bool APIServerConnectionBase::send_list_entities_time_response(const ListEntitiesTimeResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_time_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesTimeResponse>(msg, 103);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
bool APIServerConnectionBase::send_time_state_response(const TimeStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_time_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<TimeStateResponse>(msg, 104);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
bool APIServerConnectionBase::send_list_entities_event_response(const ListEntitiesEventResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_event_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesEventResponse>(msg, 107);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
bool APIServerConnectionBase::send_event_response(const EventResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_event_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<EventResponse>(msg, 108);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool APIServerConnectionBase::send_list_entities_valve_response(const ListEntitiesValveResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_valve_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesValveResponse>(msg, 109);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool APIServerConnectionBase::send_valve_state_response(const ValveStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_valve_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ValveStateResponse>(msg, 110);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
bool APIServerConnectionBase::send_list_entities_date_time_response(const ListEntitiesDateTimeResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_date_time_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesDateTimeResponse>(msg, 112);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
bool APIServerConnectionBase::send_date_time_state_response(const DateTimeStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_date_time_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<DateTimeStateResponse>(msg, 113);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
bool APIServerConnectionBase::send_list_entities_update_response(const ListEntitiesUpdateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_list_entities_update_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<ListEntitiesUpdateResponse>(msg, 116);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
bool APIServerConnectionBase::send_update_state_response(const UpdateStateResponse &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
ESP_LOGVV(TAG, "send_update_state_response: %s", msg.dump().c_str());
|
||||
#endif
|
||||
return this->send_message_<UpdateStateResponse>(msg, 117);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
#endif
|
||||
|
||||
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
|
||||
switch (msg_type) {
|
||||
case 1: {
|
||||
@@ -1273,25 +597,25 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
|
||||
void APIServerConnection::on_hello_request(const HelloRequest &msg) {
|
||||
HelloResponse ret = this->hello(msg);
|
||||
if (!this->send_hello_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
void APIServerConnection::on_connect_request(const ConnectRequest &msg) {
|
||||
ConnectResponse ret = this->connect(msg);
|
||||
if (!this->send_connect_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
void APIServerConnection::on_disconnect_request(const DisconnectRequest &msg) {
|
||||
DisconnectResponse ret = this->disconnect(msg);
|
||||
if (!this->send_disconnect_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
void APIServerConnection::on_ping_request(const PingRequest &msg) {
|
||||
PingResponse ret = this->ping(msg);
|
||||
if (!this->send_ping_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
@@ -1301,7 +625,7 @@ void APIServerConnection::on_device_info_request(const DeviceInfoRequest &msg) {
|
||||
return;
|
||||
}
|
||||
DeviceInfoResponse ret = this->device_info(msg);
|
||||
if (!this->send_device_info_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
@@ -1367,7 +691,7 @@ void APIServerConnection::on_get_time_request(const GetTimeRequest &msg) {
|
||||
return;
|
||||
}
|
||||
GetTimeResponse ret = this->get_time(msg);
|
||||
if (!this->send_get_time_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
@@ -1393,7 +717,7 @@ void APIServerConnection::on_noise_encryption_set_key_request(const NoiseEncrypt
|
||||
return;
|
||||
}
|
||||
NoiseEncryptionSetKeyResponse ret = this->noise_encryption_set_key(msg);
|
||||
if (!this->send_noise_encryption_set_key_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
@@ -1749,7 +1073,7 @@ void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
|
||||
return;
|
||||
}
|
||||
BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg);
|
||||
if (!this->send_bluetooth_connections_free_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
@@ -1805,7 +1129,7 @@ void APIServerConnection::on_voice_assistant_configuration_request(const VoiceAs
|
||||
return;
|
||||
}
|
||||
VoiceAssistantConfigurationResponse ret = this->voice_assistant_get_configuration(msg);
|
||||
if (!this->send_voice_assistant_configuration_response(ret)) {
|
||||
if (!this->send_message(ret)) {
|
||||
this->on_fatal_error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,162 +10,94 @@ namespace api {
|
||||
|
||||
class APIServerConnectionBase : public ProtoService {
|
||||
public:
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
protected:
|
||||
void log_send_message_(const char *name, const std::string &dump);
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
template<typename T> bool send_message(const T &msg) {
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_send_message_(T::message_name(), msg.dump());
|
||||
#endif
|
||||
return this->send_message_(msg, T::MESSAGE_TYPE);
|
||||
}
|
||||
|
||||
virtual void on_hello_request(const HelloRequest &value){};
|
||||
bool send_hello_response(const HelloResponse &msg);
|
||||
|
||||
virtual void on_connect_request(const ConnectRequest &value){};
|
||||
bool send_connect_response(const ConnectResponse &msg);
|
||||
bool send_disconnect_request(const DisconnectRequest &msg);
|
||||
|
||||
virtual void on_disconnect_request(const DisconnectRequest &value){};
|
||||
bool send_disconnect_response(const DisconnectResponse &msg);
|
||||
virtual void on_disconnect_response(const DisconnectResponse &value){};
|
||||
bool send_ping_request(const PingRequest &msg);
|
||||
virtual void on_ping_request(const PingRequest &value){};
|
||||
bool send_ping_response(const PingResponse &msg);
|
||||
virtual void on_ping_response(const PingResponse &value){};
|
||||
virtual void on_device_info_request(const DeviceInfoRequest &value){};
|
||||
bool send_device_info_response(const DeviceInfoResponse &msg);
|
||||
|
||||
virtual void on_list_entities_request(const ListEntitiesRequest &value){};
|
||||
bool send_list_entities_done_response(const ListEntitiesDoneResponse &msg);
|
||||
|
||||
virtual void on_subscribe_states_request(const SubscribeStatesRequest &value){};
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool send_list_entities_binary_sensor_response(const ListEntitiesBinarySensorResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool send_binary_sensor_state_response(const BinarySensorStateResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
bool send_list_entities_cover_response(const ListEntitiesCoverResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
bool send_cover_state_response(const CoverStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_COVER
|
||||
virtual void on_cover_command_request(const CoverCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
bool send_list_entities_fan_response(const ListEntitiesFanResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
bool send_fan_state_response(const FanStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_FAN
|
||||
virtual void on_fan_command_request(const FanCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
bool send_list_entities_light_response(const ListEntitiesLightResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
bool send_light_state_response(const LightStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
virtual void on_light_command_request(const LightCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool send_list_entities_sensor_response(const ListEntitiesSensorResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool send_sensor_state_response(const SensorStateResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool send_list_entities_switch_response(const ListEntitiesSwitchResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool send_switch_state_response(const SwitchStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWITCH
|
||||
virtual void on_switch_command_request(const SwitchCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool send_list_entities_text_sensor_response(const ListEntitiesTextSensorResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool send_text_sensor_state_response(const TextSensorStateResponse &msg);
|
||||
#endif
|
||||
|
||||
virtual void on_subscribe_logs_request(const SubscribeLogsRequest &value){};
|
||||
bool send_subscribe_logs_response(const SubscribeLogsResponse &msg);
|
||||
|
||||
#ifdef USE_API_NOISE
|
||||
virtual void on_noise_encryption_set_key_request(const NoiseEncryptionSetKeyRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
bool send_noise_encryption_set_key_response(const NoiseEncryptionSetKeyResponse &msg);
|
||||
#endif
|
||||
|
||||
virtual void on_subscribe_homeassistant_services_request(const SubscribeHomeassistantServicesRequest &value){};
|
||||
bool send_homeassistant_service_response(const HomeassistantServiceResponse &msg);
|
||||
|
||||
virtual void on_subscribe_home_assistant_states_request(const SubscribeHomeAssistantStatesRequest &value){};
|
||||
bool send_subscribe_home_assistant_state_response(const SubscribeHomeAssistantStateResponse &msg);
|
||||
|
||||
virtual void on_home_assistant_state_response(const HomeAssistantStateResponse &value){};
|
||||
bool send_get_time_request(const GetTimeRequest &msg);
|
||||
virtual void on_get_time_request(const GetTimeRequest &value){};
|
||||
bool send_get_time_response(const GetTimeResponse &msg);
|
||||
virtual void on_get_time_response(const GetTimeResponse &value){};
|
||||
bool send_list_entities_services_response(const ListEntitiesServicesResponse &msg);
|
||||
|
||||
virtual void on_execute_service_request(const ExecuteServiceRequest &value){};
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
bool send_list_entities_camera_response(const ListEntitiesCameraResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
bool send_camera_image_response(const CameraImageResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
virtual void on_camera_image_request(const CameraImageRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool send_list_entities_climate_response(const ListEntitiesClimateResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool send_climate_state_response(const ClimateStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_CLIMATE
|
||||
virtual void on_climate_command_request(const ClimateCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool send_list_entities_number_response(const ListEntitiesNumberResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool send_number_state_response(const NumberStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_NUMBER
|
||||
virtual void on_number_command_request(const NumberCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool send_list_entities_select_response(const ListEntitiesSelectResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool send_select_state_response(const SelectStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SELECT
|
||||
virtual void on_select_command_request(const SelectCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
bool send_list_entities_siren_response(const ListEntitiesSirenResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
bool send_siren_state_response(const SirenStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_SIREN
|
||||
virtual void on_siren_command_request(const SirenCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool send_list_entities_lock_response(const ListEntitiesLockResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool send_lock_state_response(const LockStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_LOCK
|
||||
virtual void on_lock_command_request(const LockCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
bool send_list_entities_button_response(const ListEntitiesButtonResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BUTTON
|
||||
virtual void on_button_command_request(const ButtonCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
bool send_media_player_state_response(const MediaPlayerStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){};
|
||||
#endif
|
||||
@@ -173,33 +105,19 @@ class APIServerConnectionBase : public ProtoService {
|
||||
virtual void on_subscribe_bluetooth_le_advertisements_request(
|
||||
const SubscribeBluetoothLEAdvertisementsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_le_raw_advertisements_response(const BluetoothLERawAdvertisementsResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_device_request(const BluetoothDeviceRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_get_services_done_response(const BluetoothGATTGetServicesDoneResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &value){};
|
||||
#endif
|
||||
@@ -212,49 +130,23 @@ class APIServerConnectionBase : public ProtoService {
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_error_response(const BluetoothGATTErrorResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_pairing_response(const BluetoothDevicePairingResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_unpairing_response(const BluetoothDeviceUnpairingResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_unsubscribe_bluetooth_le_advertisements_request(
|
||||
const UnsubscribeBluetoothLEAdvertisementsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_device_clear_cache_response(const BluetoothDeviceClearCacheResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool send_bluetooth_scanner_state_response(const BluetoothScannerStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
virtual void on_subscribe_voice_assistant_request(const SubscribeVoiceAssistantRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool send_voice_assistant_request(const VoiceAssistantRequest &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
virtual void on_voice_assistant_response(const VoiceAssistantResponse &value){};
|
||||
#endif
|
||||
@@ -262,7 +154,6 @@ class APIServerConnectionBase : public ProtoService {
|
||||
virtual void on_voice_assistant_event_response(const VoiceAssistantEventResponse &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool send_voice_assistant_audio(const VoiceAssistantAudio &msg);
|
||||
virtual void on_voice_assistant_audio(const VoiceAssistantAudio &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
@@ -271,84 +162,39 @@ class APIServerConnectionBase : public ProtoService {
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
virtual void on_voice_assistant_announce_request(const VoiceAssistantAnnounceRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool send_voice_assistant_announce_finished(const VoiceAssistantAnnounceFinished &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
virtual void on_voice_assistant_configuration_request(const VoiceAssistantConfigurationRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
bool send_voice_assistant_configuration_response(const VoiceAssistantConfigurationResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
virtual void on_voice_assistant_set_configuration(const VoiceAssistantSetConfiguration &value){};
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
bool send_list_entities_alarm_control_panel_response(const ListEntitiesAlarmControlPanelResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
bool send_alarm_control_panel_state_response(const AlarmControlPanelStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ALARM_CONTROL_PANEL
|
||||
virtual void on_alarm_control_panel_command_request(const AlarmControlPanelCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool send_list_entities_text_response(const ListEntitiesTextResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool send_text_state_response(const TextStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_TEXT
|
||||
virtual void on_text_command_request(const TextCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool send_list_entities_date_response(const ListEntitiesDateResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool send_date_state_response(const DateStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DATETIME_DATE
|
||||
virtual void on_date_command_request(const DateCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
bool send_list_entities_time_response(const ListEntitiesTimeResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
bool send_time_state_response(const TimeStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DATETIME_TIME
|
||||
virtual void on_time_command_request(const TimeCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
bool send_list_entities_event_response(const ListEntitiesEventResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
bool send_event_response(const EventResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool send_list_entities_valve_response(const ListEntitiesValveResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool send_valve_state_response(const ValveStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VALVE
|
||||
virtual void on_valve_command_request(const ValveCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
bool send_list_entities_date_time_response(const ListEntitiesDateTimeResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
bool send_date_time_state_response(const DateTimeStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
virtual void on_date_time_command_request(const DateTimeCommandRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
bool send_list_entities_update_response(const ListEntitiesUpdateResponse &msg);
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
bool send_update_state_response(const UpdateStateResponse &msg);
|
||||
#endif
|
||||
|
||||
#ifdef USE_UPDATE
|
||||
virtual void on_update_command_request(const UpdateCommandRequest &value){};
|
||||
#endif
|
||||
|
||||
@@ -24,7 +24,11 @@ static const char *const TAG = "api";
|
||||
// APIServer
|
||||
APIServer *global_api_server = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
APIServer::APIServer() { global_api_server = this; }
|
||||
APIServer::APIServer() {
|
||||
global_api_server = this;
|
||||
// Pre-allocate shared write buffer
|
||||
shared_write_buffer_.reserve(64);
|
||||
}
|
||||
|
||||
void APIServer::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
@@ -218,8 +222,9 @@ void APIServer::handle_disconnect(APIConnection *conn) {}
|
||||
void APIServer::on_binary_sensor_update(binary_sensor::BinarySensor *obj, bool state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_binary_sensor_state(obj, state);
|
||||
use_current ? c->send_binary_sensor_state(obj) : c->send_binary_sensor_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -254,8 +259,9 @@ void APIServer::on_light_update(light::LightState *obj) {
|
||||
void APIServer::on_sensor_update(sensor::Sensor *obj, float state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_sensor_state(obj, state);
|
||||
use_current ? c->send_sensor_state(obj) : c->send_sensor_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -263,8 +269,9 @@ void APIServer::on_sensor_update(sensor::Sensor *obj, float state) {
|
||||
void APIServer::on_switch_update(switch_::Switch *obj, bool state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_switch_state(obj, state);
|
||||
use_current ? c->send_switch_state(obj) : c->send_switch_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -272,8 +279,9 @@ void APIServer::on_switch_update(switch_::Switch *obj, bool state) {
|
||||
void APIServer::on_text_sensor_update(text_sensor::TextSensor *obj, const std::string &state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_text_sensor_state(obj, state);
|
||||
use_current ? c->send_text_sensor_state(obj) : c->send_text_sensor_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -290,8 +298,9 @@ void APIServer::on_climate_update(climate::Climate *obj) {
|
||||
void APIServer::on_number_update(number::Number *obj, float state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_number_state(obj, state);
|
||||
use_current ? c->send_number_state(obj) : c->send_number_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -326,8 +335,9 @@ void APIServer::on_datetime_update(datetime::DateTimeEntity *obj) {
|
||||
void APIServer::on_text_update(text::Text *obj, const std::string &state) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_text_state(obj, state);
|
||||
use_current ? c->send_text_state(obj) : c->send_text_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -335,8 +345,9 @@ void APIServer::on_text_update(text::Text *obj, const std::string &state) {
|
||||
void APIServer::on_select_update(select::Select *obj, const std::string &state, size_t index) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
bool use_current = (state == obj->state);
|
||||
for (auto &c : this->clients_)
|
||||
c->send_select_state(obj, state);
|
||||
use_current ? c->send_select_state(obj) : c->send_select_state(obj, state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -345,7 +356,7 @@ void APIServer::on_lock_update(lock::Lock *obj) {
|
||||
if (obj->is_internal())
|
||||
return;
|
||||
for (auto &c : this->clients_)
|
||||
c->send_lock_state(obj, obj->state);
|
||||
c->send_lock_state(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -396,6 +407,8 @@ void APIServer::set_port(uint16_t port) { this->port_ = port; }
|
||||
|
||||
void APIServer::set_password(const std::string &password) { this->password_ = password; }
|
||||
|
||||
void APIServer::set_batch_delay(uint32_t batch_delay) { this->batch_delay_ = batch_delay; }
|
||||
|
||||
void APIServer::send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
|
||||
for (auto &client : this->clients_) {
|
||||
client->send_homeassistant_service_call(call);
|
||||
@@ -454,7 +467,7 @@ bool APIServer::save_noise_psk(psk_t psk, bool make_active) {
|
||||
ESP_LOGW(TAG, "Disconnecting all clients to reset connections");
|
||||
this->set_noise_psk(psk);
|
||||
for (auto &c : this->clients_) {
|
||||
c->send_disconnect_request(DisconnectRequest());
|
||||
c->send_message(DisconnectRequest());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -475,7 +488,7 @@ bool APIServer::is_connected() const { return !this->clients_.empty(); }
|
||||
|
||||
void APIServer::on_shutdown() {
|
||||
for (auto &c : this->clients_) {
|
||||
c->send_disconnect_request(DisconnectRequest());
|
||||
c->send_message(DisconnectRequest());
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,11 @@ class APIServer : public Component, public Controller {
|
||||
void set_port(uint16_t port);
|
||||
void set_password(const std::string &password);
|
||||
void set_reboot_timeout(uint32_t reboot_timeout);
|
||||
void set_batch_delay(uint32_t batch_delay);
|
||||
uint32_t get_batch_delay() const { return batch_delay_; }
|
||||
|
||||
// Get reference to shared buffer for API connections
|
||||
std::vector<uint8_t> &get_shared_buffer_ref() { return shared_write_buffer_; }
|
||||
|
||||
#ifdef USE_API_NOISE
|
||||
bool save_noise_psk(psk_t psk, bool make_active = true);
|
||||
@@ -139,9 +144,11 @@ class APIServer : public Component, public Controller {
|
||||
std::unique_ptr<socket::Socket> socket_ = nullptr;
|
||||
uint16_t port_{6053};
|
||||
uint32_t reboot_timeout_{300000};
|
||||
uint32_t batch_delay_{100};
|
||||
uint32_t last_connected_{0};
|
||||
std::vector<std::unique_ptr<APIConnection>> clients_;
|
||||
std::string password_;
|
||||
std::vector<uint8_t> shared_write_buffer_; // Shared proto write buffer for all connections
|
||||
std::vector<HomeAssistantStateSubscription> state_subs_;
|
||||
std::vector<UserServiceDescriptor *> user_services_;
|
||||
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
|
||||
|
||||
@@ -73,7 +73,7 @@ bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(
|
||||
ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
|
||||
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
|
||||
auto resp = service->encode_list_service_response();
|
||||
return this->client_->send_list_entities_services_response(resp);
|
||||
return this->client_->send_message(resp);
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32_CAMERA
|
||||
|
||||
@@ -360,11 +360,11 @@ class ProtoService {
|
||||
* @return A ProtoWriteBuffer object with the reserved size.
|
||||
*/
|
||||
virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0;
|
||||
virtual bool send_buffer(ProtoWriteBuffer buffer, uint32_t message_type) = 0;
|
||||
virtual bool send_buffer(ProtoWriteBuffer buffer, uint16_t message_type) = 0;
|
||||
virtual bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) = 0;
|
||||
|
||||
// Optimized method that pre-allocates buffer based on message size
|
||||
template<class C> bool send_message_(const C &msg, uint32_t message_type) {
|
||||
bool send_message_(const ProtoMessage &msg, uint16_t message_type) {
|
||||
uint32_t msg_size = 0;
|
||||
msg.calculate_size(msg_size);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace api {
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
|
||||
return this->client_->send_binary_sensor_state(binary_sensor, binary_sensor->state);
|
||||
return this->client_->send_binary_sensor_state(binary_sensor);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_COVER
|
||||
@@ -21,27 +21,21 @@ bool InitialStateIterator::on_fan(fan::Fan *fan) { return this->client_->send_fa
|
||||
bool InitialStateIterator::on_light(light::LightState *light) { return this->client_->send_light_state(light); }
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool InitialStateIterator::on_sensor(sensor::Sensor *sensor) {
|
||||
return this->client_->send_sensor_state(sensor, sensor->state);
|
||||
}
|
||||
bool InitialStateIterator::on_sensor(sensor::Sensor *sensor) { return this->client_->send_sensor_state(sensor); }
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
bool InitialStateIterator::on_switch(switch_::Switch *a_switch) {
|
||||
return this->client_->send_switch_state(a_switch, a_switch->state);
|
||||
}
|
||||
bool InitialStateIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_state(a_switch); }
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool InitialStateIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
|
||||
return this->client_->send_text_sensor_state(text_sensor, text_sensor->state);
|
||||
return this->client_->send_text_sensor_state(text_sensor);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
bool InitialStateIterator::on_climate(climate::Climate *climate) { return this->client_->send_climate_state(climate); }
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
bool InitialStateIterator::on_number(number::Number *number) {
|
||||
return this->client_->send_number_state(number, number->state);
|
||||
}
|
||||
bool InitialStateIterator::on_number(number::Number *number) { return this->client_->send_number_state(number); }
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
bool InitialStateIterator::on_date(datetime::DateEntity *date) { return this->client_->send_date_state(date); }
|
||||
@@ -55,15 +49,13 @@ bool InitialStateIterator::on_datetime(datetime::DateTimeEntity *datetime) {
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text, text->state); }
|
||||
bool InitialStateIterator::on_text(text::Text *text) { return this->client_->send_text_state(text); }
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
bool InitialStateIterator::on_select(select::Select *select) {
|
||||
return this->client_->send_select_state(select, select->state);
|
||||
}
|
||||
bool InitialStateIterator::on_select(select::Select *select) { return this->client_->send_select_state(select); }
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock, a_lock->state); }
|
||||
bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock); }
|
||||
#endif
|
||||
#ifdef USE_VALVE
|
||||
bool InitialStateIterator::on_valve(valve::Valve *valve) { return this->client_->send_valve_state(valve); }
|
||||
|
||||
@@ -282,7 +282,7 @@ void AS3935Component::display_oscillator(bool state, uint8_t osc) {
|
||||
// based on the resonance frequency of the antenna and so it should be trimmed
|
||||
// before the calibration is done.
|
||||
bool AS3935Component::calibrate_oscillator() {
|
||||
ESP_LOGI(TAG, "Starting oscillators calibration...");
|
||||
ESP_LOGI(TAG, "Starting oscillators calibration");
|
||||
this->write_register(CALIB_RCO, WIPE_ALL, DIRECT_COMMAND, 0); // Send command to calibrate the oscillators
|
||||
|
||||
this->display_oscillator(true, 2);
|
||||
@@ -307,7 +307,7 @@ bool AS3935Component::calibrate_oscillator() {
|
||||
}
|
||||
|
||||
void AS3935Component::tune_antenna() {
|
||||
ESP_LOGI(TAG, "Starting antenna tuning...");
|
||||
ESP_LOGI(TAG, "Starting antenna tuning");
|
||||
uint8_t div_ratio = this->read_div_ratio();
|
||||
uint8_t tune_val = this->read_capacitance();
|
||||
ESP_LOGI(TAG, "Division Ratio is set to: %d", div_ratio);
|
||||
|
||||
@@ -75,7 +75,7 @@ void AT581XComponent::setup() { ESP_LOGCONFIG(TAG, "Running setup"); }
|
||||
void AT581XComponent::dump_config() { LOG_I2C_DEVICE(this); }
|
||||
#define ARRAY_SIZE(X) (sizeof(X) / sizeof((X)[0]))
|
||||
bool AT581XComponent::i2c_write_config() {
|
||||
ESP_LOGCONFIG(TAG, "Writing new config for AT581X...");
|
||||
ESP_LOGCONFIG(TAG, "Writing new config for AT581X");
|
||||
ESP_LOGCONFIG(TAG, "Frequency: %dMHz", this->freq_);
|
||||
ESP_LOGCONFIG(TAG, "Sensing distance: %d", this->delta_);
|
||||
ESP_LOGCONFIG(TAG, "Power: %dµA", this->power_);
|
||||
|
||||
@@ -686,7 +686,7 @@ void ATM90E32Component::restore_power_offset_calibrations_() {
|
||||
}
|
||||
|
||||
void ATM90E32Component::clear_gain_calibrations() {
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Clearing stored gain calibrations and restoring config-defined values...");
|
||||
ESP_LOGI(TAG, "[CALIBRATION] Clearing stored gain calibrations and restoring config-defined values");
|
||||
|
||||
for (int phase = 0; phase < 3; phase++) {
|
||||
gain_phase_[phase].voltage_gain = this->phase_[phase].voltage_gain_;
|
||||
|
||||
@@ -527,7 +527,7 @@ void BedJetHub::dispatch_status_() {
|
||||
}
|
||||
|
||||
if (this->timeout_ > 0 && diff > this->timeout_ && this->parent()->enabled) {
|
||||
ESP_LOGW(TAG, "[%s] Timed out after %" PRId32 " sec. Retrying...", this->get_name().c_str(), this->timeout_);
|
||||
ESP_LOGW(TAG, "[%s] Timed out after %" PRId32 " sec. Retrying", this->get_name().c_str(), this->timeout_);
|
||||
// set_enabled(false) will only close the connection if state != IDLE.
|
||||
this->parent()->set_state(espbt::ClientState::CONNECTING);
|
||||
this->parent()->set_enabled(false);
|
||||
|
||||
@@ -256,7 +256,7 @@ void BekenSPILEDStripLightOutput::write_state(light::LightState *state) {
|
||||
this->last_refresh_ = now;
|
||||
this->mark_shown_();
|
||||
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus...");
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus");
|
||||
|
||||
if (spi_data == nullptr) {
|
||||
ESP_LOGE(TAG, "SPI not initialized");
|
||||
|
||||
@@ -68,8 +68,7 @@ void binary_sensor::MultiClickTrigger::on_state_(bool state) {
|
||||
*this->at_index_ = *this->at_index_ + 1;
|
||||
}
|
||||
void binary_sensor::MultiClickTrigger::schedule_cooldown_() {
|
||||
ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %" PRIu32 " ms...",
|
||||
this->invalid_cooldown_);
|
||||
ESP_LOGV(TAG, "Multi Click: Invalid length of press, starting cooldown of %" PRIu32 " ms", this->invalid_cooldown_);
|
||||
this->is_in_cooldown_ = true;
|
||||
this->set_timeout("cooldown", this->invalid_cooldown_, [this]() {
|
||||
ESP_LOGV(TAG, "Multi Click: Cooldown ended, matching is now enabled again.");
|
||||
|
||||
@@ -100,7 +100,7 @@ void BL0906::handle_actions_() {
|
||||
for (int i = 0; i < this->action_queue_.size(); i++) {
|
||||
ptr_func = this->action_queue_[i];
|
||||
if (ptr_func) {
|
||||
ESP_LOGI(TAG, "HandleActionCallback[%d]...", i);
|
||||
ESP_LOGI(TAG, "HandleActionCallback[%d]", i);
|
||||
(this->*ptr_func)();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
||||
resp.data.reserve(param->read.value_len);
|
||||
// Use bulk insert instead of individual push_backs
|
||||
resp.data.insert(resp.data.end(), param->read.value, param->read.value + param->read.value_len);
|
||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_read_response(resp);
|
||||
this->proxy_->get_api_connection()->send_message(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_WRITE_CHAR_EVT:
|
||||
@@ -89,7 +89,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
||||
api::BluetoothGATTWriteResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->write.handle;
|
||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_write_response(resp);
|
||||
this->proxy_->get_api_connection()->send_message(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_UNREG_FOR_NOTIFY_EVT: {
|
||||
@@ -103,7 +103,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
||||
api::BluetoothGATTNotifyResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->unreg_for_notify.handle;
|
||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_notify_response(resp);
|
||||
this->proxy_->get_api_connection()->send_message(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
|
||||
@@ -116,7 +116,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
||||
api::BluetoothGATTNotifyResponse resp;
|
||||
resp.address = this->address_;
|
||||
resp.handle = param->reg_for_notify.handle;
|
||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_notify_response(resp);
|
||||
this->proxy_->get_api_connection()->send_message(resp);
|
||||
break;
|
||||
}
|
||||
case ESP_GATTC_NOTIFY_EVT: {
|
||||
@@ -128,7 +128,7 @@ bool BluetoothConnection::gattc_event_handler(esp_gattc_cb_event_t event, esp_ga
|
||||
resp.data.reserve(param->notify.value_len);
|
||||
// Use bulk insert instead of individual push_backs
|
||||
resp.data.insert(resp.data.end(), param->notify.value, param->notify.value + param->notify.value_len);
|
||||
this->proxy_->get_api_connection()->send_bluetooth_gatt_notify_data_response(resp);
|
||||
this->proxy_->get_api_connection()->send_message(resp);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -39,7 +39,7 @@ void BluetoothProxy::send_bluetooth_scanner_state_(esp32_ble_tracker::ScannerSta
|
||||
resp.state = static_cast<api::enums::BluetoothScannerState>(state);
|
||||
resp.mode = this->parent_->get_scan_active() ? api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE
|
||||
: api::enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_PASSIVE;
|
||||
this->api_connection_->send_bluetooth_scanner_state_response(resp);
|
||||
this->api_connection_->send_message(resp);
|
||||
}
|
||||
|
||||
bool BluetoothProxy::parse_device(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
@@ -103,7 +103,7 @@ void BluetoothProxy::flush_pending_advertisements() {
|
||||
|
||||
api::BluetoothLERawAdvertisementsResponse resp;
|
||||
resp.advertisements.swap(batch_buffer);
|
||||
this->api_connection_->send_bluetooth_le_raw_advertisements_response(resp);
|
||||
this->api_connection_->send_message(resp);
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &device) {
|
||||
@@ -141,7 +141,7 @@ void BluetoothProxy::send_api_packet_(const esp32_ble_tracker::ESPBTDevice &devi
|
||||
manufacturer_data.data.assign(data.data.begin(), data.data.end());
|
||||
}
|
||||
|
||||
this->api_connection_->send_bluetooth_le_advertisement(resp);
|
||||
this->api_connection_->send_message(resp);
|
||||
}
|
||||
|
||||
void BluetoothProxy::dump_config() {
|
||||
@@ -300,7 +300,7 @@ void BluetoothProxy::loop() {
|
||||
service_resp.characteristics.push_back(std::move(characteristic_resp));
|
||||
}
|
||||
resp.services.push_back(std::move(service_resp));
|
||||
this->api_connection_->send_bluetooth_gatt_get_services_response(resp);
|
||||
this->api_connection_->send_message(resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,7 +453,7 @@ void BluetoothProxy::bluetooth_device_request(const api::BluetoothDeviceRequest
|
||||
call.success = ret == ESP_OK;
|
||||
call.error = ret;
|
||||
|
||||
this->api_connection_->send_bluetooth_device_clear_cache_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -577,7 +577,7 @@ void BluetoothProxy::send_device_connection(uint64_t address, bool connected, ui
|
||||
call.connected = connected;
|
||||
call.mtu = mtu;
|
||||
call.error = error;
|
||||
this->api_connection_->send_bluetooth_device_connection_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
void BluetoothProxy::send_connections_free() {
|
||||
if (this->api_connection_ == nullptr)
|
||||
@@ -590,7 +590,7 @@ void BluetoothProxy::send_connections_free() {
|
||||
call.allocated.push_back(connection->address_);
|
||||
}
|
||||
}
|
||||
this->api_connection_->send_bluetooth_connections_free_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_gatt_services_done(uint64_t address) {
|
||||
@@ -598,7 +598,7 @@ void BluetoothProxy::send_gatt_services_done(uint64_t address) {
|
||||
return;
|
||||
api::BluetoothGATTGetServicesDoneResponse call;
|
||||
call.address = address;
|
||||
this->api_connection_->send_bluetooth_gatt_get_services_done_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_t error) {
|
||||
@@ -608,7 +608,7 @@ void BluetoothProxy::send_gatt_error(uint64_t address, uint16_t handle, esp_err_
|
||||
call.address = address;
|
||||
call.handle = handle;
|
||||
call.error = error;
|
||||
this->api_connection_->send_bluetooth_gatt_error_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_t error) {
|
||||
@@ -617,7 +617,7 @@ void BluetoothProxy::send_device_pairing(uint64_t address, bool paired, esp_err_
|
||||
call.paired = paired;
|
||||
call.error = error;
|
||||
|
||||
this->api_connection_->send_bluetooth_device_pairing_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
|
||||
void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_err_t error) {
|
||||
@@ -626,7 +626,7 @@ void BluetoothProxy::send_device_unpairing(uint64_t address, bool success, esp_e
|
||||
call.success = success;
|
||||
call.error = error;
|
||||
|
||||
this->api_connection_->send_bluetooth_device_unpairing_response(call);
|
||||
this->api_connection_->send_message(call);
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_scanner_set_mode(bool active) {
|
||||
|
||||
@@ -207,7 +207,7 @@ inline uint8_t oversampling_to_time(BME280Oversampling over_sampling) { return (
|
||||
|
||||
void BME280Component::update() {
|
||||
// Enable sensor
|
||||
ESP_LOGV(TAG, "Sending conversion request...");
|
||||
ESP_LOGV(TAG, "Sending conversion request");
|
||||
uint8_t meas_value = 0;
|
||||
meas_value |= (this->temperature_oversampling_ & 0b111) << 5;
|
||||
meas_value |= (this->pressure_oversampling_ & 0b111) << 2;
|
||||
|
||||
@@ -13,7 +13,7 @@ from esphome.const import (
|
||||
CONF_PRESSURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
ICON_GAS_CYLINDER,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
@@ -71,7 +71,7 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_PRESSURE,
|
||||
device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
|
||||
@@ -15,6 +15,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
ICON_GAS_CYLINDER,
|
||||
ICON_GAUGE,
|
||||
ICON_THERMOMETER,
|
||||
ICON_WATER_PERCENT,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_HECTOPASCAL,
|
||||
@@ -27,11 +29,11 @@ from . import CONF_BME680_BSEC_ID, SAMPLE_RATE_OPTIONS, BME680BSECComponent
|
||||
|
||||
DEPENDENCIES = ["bme680_bsec"]
|
||||
|
||||
CONF_IAQ = "iaq"
|
||||
CONF_CO2_EQUIVALENT = "co2_equivalent"
|
||||
CONF_BREATH_VOC_EQUIVALENT = "breath_voc_equivalent"
|
||||
UNIT_IAQ = "IAQ"
|
||||
CONF_CO2_EQUIVALENT = "co2_equivalent"
|
||||
CONF_IAQ = "iaq"
|
||||
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
|
||||
UNIT_IAQ = "IAQ"
|
||||
|
||||
TYPES = [
|
||||
CONF_TEMPERATURE,
|
||||
@@ -49,6 +51,7 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
cv.GenerateID(CONF_BME680_BSEC_ID): cv.use_id(BME680BSECComponent),
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
icon=ICON_THERMOMETER,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
@@ -65,6 +68,7 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
),
|
||||
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
icon=ICON_WATER_PERCENT,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_HUMIDITY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
|
||||
@@ -9,8 +9,10 @@ from esphome.const import (
|
||||
CONF_SAMPLE_RATE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||
DEVICE_CLASS_CARBON_DIOXIDE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
ICON_GAS_CYLINDER,
|
||||
ICON_GAUGE,
|
||||
ICON_THERMOMETER,
|
||||
@@ -32,7 +34,6 @@ CONF_CO2_EQUIVALENT = "co2_equivalent"
|
||||
CONF_IAQ = "iaq"
|
||||
CONF_IAQ_STATIC = "iaq_static"
|
||||
ICON_ACCURACY = "mdi:checkbox-marked-circle-outline"
|
||||
ICON_TEST_TUBE = "mdi:test-tube"
|
||||
UNIT_IAQ = "IAQ"
|
||||
|
||||
TYPES = [
|
||||
@@ -61,7 +62,6 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
),
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
icon=ICON_GAUGE,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_ATMOSPHERIC_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
@@ -102,14 +102,14 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
),
|
||||
cv.Optional(CONF_CO2_EQUIVALENT): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
||||
icon=ICON_TEST_TUBE,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_CARBON_DIOXIDE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
cv.Optional(CONF_BREATH_VOC_EQUIVALENT): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PARTS_PER_MILLION,
|
||||
icon=ICON_TEST_TUBE,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
}
|
||||
|
||||
@@ -126,37 +126,37 @@ void BMI160Component::internal_setup_(int stage) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Bringing accelerometer out of sleep...");
|
||||
ESP_LOGV(TAG, " Bringing accelerometer out of sleep");
|
||||
if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::ACCL_SET_PMU_MODE | (uint8_t) AcclPmuMode::NORMAL)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, " Waiting for accelerometer to wake up...");
|
||||
ESP_LOGV(TAG, " Waiting for accelerometer to wake up");
|
||||
// need to wait (max delay in datasheet) because we can't send commands while another is in progress
|
||||
// min 5ms, 10ms
|
||||
this->set_timeout(10, [this]() { this->internal_setup_(1); });
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ESP_LOGV(TAG, " Bringing gyroscope out of sleep...");
|
||||
ESP_LOGV(TAG, " Bringing gyroscope out of sleep");
|
||||
if (!this->write_byte(BMI160_REGISTER_CMD, (uint8_t) Cmd::GYRO_SET_PMU_MODE | (uint8_t) GyroPmuMode::NORMAL)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, " Waiting for gyroscope to wake up...");
|
||||
ESP_LOGV(TAG, " Waiting for gyroscope to wake up");
|
||||
// wait between 51 & 81ms, doing 100 to be safe
|
||||
this->set_timeout(10, [this]() { this->internal_setup_(2); });
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ESP_LOGV(TAG, " Setting up Gyro Config...");
|
||||
ESP_LOGV(TAG, " Setting up Gyro Config");
|
||||
uint8_t gyro_config = (uint8_t) GyroBandwidth::OSR4 | (uint8_t) GyroOuputDataRate::HZ_25;
|
||||
ESP_LOGV(TAG, " Output gyro_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_config));
|
||||
if (!this->write_byte(BMI160_REGISTER_GYRO_CONFIG, gyro_config)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, " Setting up Gyro Range...");
|
||||
ESP_LOGV(TAG, " Setting up Gyro Range");
|
||||
uint8_t gyro_range = (uint8_t) GyroRange::RANGE_2000_DPS;
|
||||
ESP_LOGV(TAG, " Output gyro_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(gyro_range));
|
||||
if (!this->write_byte(BMI160_REGISTER_GYRO_RANGE, gyro_range)) {
|
||||
@@ -164,7 +164,7 @@ void BMI160Component::internal_setup_(int stage) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Accel Config...");
|
||||
ESP_LOGV(TAG, " Setting up Accel Config");
|
||||
uint8_t accel_config =
|
||||
(uint8_t) AcclFilterMode::PERF | (uint8_t) AcclBandwidth::RES_AVG16 | (uint8_t) AccelOutputDataRate::HZ_25;
|
||||
ESP_LOGV(TAG, " Output accel_config: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_config));
|
||||
@@ -172,7 +172,7 @@ void BMI160Component::internal_setup_(int stage) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, " Setting up Accel Range...");
|
||||
ESP_LOGV(TAG, " Setting up Accel Range");
|
||||
uint8_t accel_range = (uint8_t) AccelRange::RANGE_16G;
|
||||
ESP_LOGV(TAG, " Output accel_range: 0b" BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(accel_range));
|
||||
if (!this->write_byte(BMI160_REGISTER_ACCEL_RANGE, accel_range)) {
|
||||
@@ -219,7 +219,7 @@ void BMI160Component::update() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Updating BMI160...");
|
||||
ESP_LOGV(TAG, " Updating BMI160");
|
||||
int16_t data[6];
|
||||
if (this->read_le_int16_(BMI160_REGISTER_DATA_GYRO_X_LSB, data, 6) != i2c::ERROR_OK) {
|
||||
this->status_set_warning();
|
||||
|
||||
@@ -129,7 +129,7 @@ void BMP085Component::read_pressure_() {
|
||||
this->status_clear_warning();
|
||||
}
|
||||
bool BMP085Component::set_mode_(uint8_t mode) {
|
||||
ESP_LOGV(TAG, "Setting mode to 0x%02X...", mode);
|
||||
ESP_LOGV(TAG, "Setting mode to 0x%02X", mode);
|
||||
return this->write_byte(BMP085_REGISTER_CONTROL, mode);
|
||||
}
|
||||
float BMP085Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
@@ -155,7 +155,7 @@ inline uint8_t oversampling_to_time(BMP280Oversampling over_sampling) { return (
|
||||
|
||||
void BMP280Component::update() {
|
||||
// Enable sensor
|
||||
ESP_LOGV(TAG, "Sending conversion request...");
|
||||
ESP_LOGV(TAG, "Sending conversion request");
|
||||
uint8_t meas_value = 0;
|
||||
meas_value |= (this->temperature_oversampling_ & 0b111) << 5;
|
||||
meas_value |= (this->pressure_oversampling_ & 0b111) << 2;
|
||||
|
||||
@@ -73,7 +73,7 @@ void BMP3XXComponent::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
// Call the Device base class "initialise" function
|
||||
if (!reset()) {
|
||||
ESP_LOGE(TAG, "Failed to reset BMP3XX...");
|
||||
ESP_LOGE(TAG, "Failed to reset");
|
||||
this->error_code_ = ERROR_SENSOR_RESET;
|
||||
this->mark_failed();
|
||||
}
|
||||
@@ -157,16 +157,14 @@ void BMP3XXComponent::dump_config() {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
break;
|
||||
case ERROR_WRONG_CHIP_ID:
|
||||
ESP_LOGE(
|
||||
TAG,
|
||||
"BMP3XX has wrong chip ID (reported id: 0x%X) - please check if you are really using a BMP 388 or BMP 390",
|
||||
this->chip_id_.reg);
|
||||
ESP_LOGE(TAG, "Wrong chip ID (reported id: 0x%X) - please check if you are really using a BMP 388 or BMP 390",
|
||||
this->chip_id_.reg);
|
||||
break;
|
||||
case ERROR_SENSOR_RESET:
|
||||
ESP_LOGE(TAG, "BMP3XX failed to reset");
|
||||
ESP_LOGE(TAG, "Failed to reset");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "BMP3XX error code %d", (int) this->error_code_);
|
||||
ESP_LOGE(TAG, "Error code %d", (int) this->error_code_);
|
||||
break;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " IIR Filter: %s", LOG_STR_ARG(iir_filter_to_str(this->iir_filter_)));
|
||||
@@ -186,7 +184,7 @@ inline uint8_t oversampling_to_time(Oversampling over_sampling) { return (1 << u
|
||||
|
||||
void BMP3XXComponent::update() {
|
||||
// Enable sensor
|
||||
ESP_LOGV(TAG, "Sending conversion request...");
|
||||
ESP_LOGV(TAG, "Sending conversion request");
|
||||
float meas_time = 1.0f;
|
||||
// Ref: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf 3.9.2
|
||||
meas_time += 2.02f * oversampling_to_time(this->temperature_oversampling_) + 0.163f;
|
||||
@@ -296,7 +294,7 @@ bool BMP3XXComponent::get_pressure(float &pressure) {
|
||||
bool BMP3XXComponent::get_measurements(float &temperature, float &pressure) {
|
||||
// Check if a measurement is ready
|
||||
if (!data_ready()) {
|
||||
ESP_LOGD(TAG, "BMP3XX Get measurement - data not ready skipping update");
|
||||
ESP_LOGD(TAG, "Get measurement - data not ready skipping update");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,22 +72,22 @@ void BMP581Component::dump_config() {
|
||||
case NONE:
|
||||
break;
|
||||
case ERROR_COMMUNICATION_FAILED:
|
||||
ESP_LOGE(TAG, " Communication with BMP581 failed!");
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
break;
|
||||
case ERROR_WRONG_CHIP_ID:
|
||||
ESP_LOGE(TAG, " BMP581 has wrong chip ID - please verify you are using a BMP 581");
|
||||
ESP_LOGE(TAG, "Unknown chip ID");
|
||||
break;
|
||||
case ERROR_SENSOR_RESET:
|
||||
ESP_LOGE(TAG, " BMP581 failed to reset");
|
||||
ESP_LOGE(TAG, "Reset failed");
|
||||
break;
|
||||
case ERROR_SENSOR_STATUS:
|
||||
ESP_LOGE(TAG, " BMP581 sensor status failed, there were NVM problems");
|
||||
ESP_LOGE(TAG, "Get status failed");
|
||||
break;
|
||||
case ERROR_PRIME_IIR_FAILED:
|
||||
ESP_LOGE(TAG, " BMP581's IIR Filter failed to prime with an initial measurement");
|
||||
ESP_LOGE(TAG, "IIR Filter failed to prime with initial measurement");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, " BMP581 error code %d", (int) this->error_code_);
|
||||
ESP_LOGE(TAG, "Error %d", (int) this->error_code_);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ void BMP581Component::setup() {
|
||||
|
||||
// Power-On-Reboot bit is asserted if sensor successfully reset
|
||||
if (!this->reset_()) {
|
||||
ESP_LOGE(TAG, "BMP581 failed to reset");
|
||||
ESP_LOGE(TAG, "Reset failed");
|
||||
|
||||
this->error_code_ = ERROR_SENSOR_RESET;
|
||||
this->mark_failed();
|
||||
@@ -146,7 +146,7 @@ void BMP581Component::setup() {
|
||||
|
||||
// read chip id from sensor
|
||||
if (!this->read_byte(BMP581_CHIP_ID, &chip_id)) {
|
||||
ESP_LOGE(TAG, "Failed to read chip id");
|
||||
ESP_LOGE(TAG, "Read chip ID failed");
|
||||
|
||||
this->error_code_ = ERROR_COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
@@ -156,7 +156,7 @@ void BMP581Component::setup() {
|
||||
|
||||
// verify id
|
||||
if (chip_id != BMP581_ASIC_ID) {
|
||||
ESP_LOGE(TAG, "Unknown chip ID, is this a BMP581?");
|
||||
ESP_LOGE(TAG, "Unknown chip ID");
|
||||
|
||||
this->error_code_ = ERROR_WRONG_CHIP_ID;
|
||||
this->mark_failed();
|
||||
@@ -179,7 +179,7 @@ void BMP581Component::setup() {
|
||||
|
||||
// verify status_nvm_rdy bit (it is asserted if boot was successful)
|
||||
if (!(this->status_.bit.status_nvm_rdy)) {
|
||||
ESP_LOGE(TAG, "NVM not ready after boot");
|
||||
ESP_LOGE(TAG, "NVM not ready");
|
||||
|
||||
this->error_code_ = ERROR_SENSOR_STATUS;
|
||||
this->mark_failed();
|
||||
@@ -189,7 +189,7 @@ void BMP581Component::setup() {
|
||||
|
||||
// verify status_nvm_err bit (it is asserted if an error is detected)
|
||||
if (this->status_.bit.status_nvm_err) {
|
||||
ESP_LOGE(TAG, "NVM error detected on boot");
|
||||
ESP_LOGE(TAG, "NVM error detected");
|
||||
|
||||
this->error_code_ = ERROR_SENSOR_STATUS;
|
||||
this->mark_failed();
|
||||
@@ -254,7 +254,7 @@ void BMP581Component::setup() {
|
||||
}
|
||||
|
||||
if (!this->prime_iir_filter_()) {
|
||||
ESP_LOGE(TAG, "Failed to prime the IIR filter with an intiial measurement");
|
||||
ESP_LOGE(TAG, "Failed to prime the IIR filter with an initial measurement");
|
||||
|
||||
this->error_code_ = ERROR_PRIME_IIR_FAILED;
|
||||
this->mark_failed();
|
||||
@@ -286,10 +286,10 @@ void BMP581Component::update() {
|
||||
// 1) Request a measurement //
|
||||
//////////////////////////////
|
||||
|
||||
ESP_LOGVV(TAG, "Requesting a measurement from sensor");
|
||||
ESP_LOGVV(TAG, "Requesting measurement");
|
||||
|
||||
if (!this->start_measurement_()) {
|
||||
ESP_LOGW(TAG, "Failed to request forced measurement of sensor");
|
||||
ESP_LOGW(TAG, "Requesting forced measurement failed");
|
||||
this->status_set_warning();
|
||||
|
||||
return;
|
||||
@@ -299,7 +299,7 @@ void BMP581Component::update() {
|
||||
// 2) Wait for measurement to finish (based on oversampling rates) //
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
ESP_LOGVV(TAG, "Measurement is expected to take %d ms to complete", this->conversion_time_);
|
||||
ESP_LOGVV(TAG, "Measurement should take %d ms", this->conversion_time_);
|
||||
|
||||
this->set_timeout("measurement", this->conversion_time_, [this]() {
|
||||
float temperature = 0.0;
|
||||
@@ -311,14 +311,14 @@ void BMP581Component::update() {
|
||||
|
||||
if (this->pressure_sensor_) {
|
||||
if (!this->read_temperature_and_pressure_(temperature, pressure)) {
|
||||
ESP_LOGW(TAG, "Failed to read temperature and pressure measurements, skipping update");
|
||||
ESP_LOGW(TAG, "Failed to read temperature and pressure; skipping update");
|
||||
this->status_set_warning();
|
||||
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!this->read_temperature_(temperature)) {
|
||||
ESP_LOGW(TAG, "Failed to read temperature measurement, skipping update");
|
||||
ESP_LOGW(TAG, "Failed to read temperature; skipping update");
|
||||
this->status_set_warning();
|
||||
|
||||
return;
|
||||
@@ -349,7 +349,7 @@ bool BMP581Component::check_data_readiness_() {
|
||||
// - returns data readiness state
|
||||
|
||||
if (this->odr_config_.bit.pwr_mode == STANDBY_MODE) {
|
||||
ESP_LOGD(TAG, "Data is not ready, sensor is in standby mode");
|
||||
ESP_LOGD(TAG, "Data not ready, sensor is in standby mode");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ bool BMP581Component::read_temperature_(float &temperature) {
|
||||
// - the measured temperature (in degrees Celsius)
|
||||
|
||||
if (!this->check_data_readiness_()) {
|
||||
ESP_LOGW(TAG, "Data from sensor isn't ready, skipping this update");
|
||||
ESP_LOGW(TAG, "Data not ready, skipping this update");
|
||||
this->status_set_warning();
|
||||
|
||||
return false;
|
||||
@@ -451,7 +451,7 @@ bool BMP581Component::read_temperature_(float &temperature) {
|
||||
|
||||
uint8_t data[3];
|
||||
if (!this->read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 3)) {
|
||||
ESP_LOGW(TAG, "Failed to read sensor's measurement data");
|
||||
ESP_LOGW(TAG, "Failed to read measurement");
|
||||
this->status_set_warning();
|
||||
|
||||
return false;
|
||||
@@ -472,7 +472,7 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float &
|
||||
// - the measured pressure (in Pa)
|
||||
|
||||
if (!this->check_data_readiness_()) {
|
||||
ESP_LOGW(TAG, "Data from sensor isn't ready, skipping this update");
|
||||
ESP_LOGW(TAG, "Data not ready, skipping this update");
|
||||
this->status_set_warning();
|
||||
|
||||
return false;
|
||||
@@ -480,7 +480,7 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float &
|
||||
|
||||
uint8_t data[6];
|
||||
if (!this->read_bytes(BMP581_MEASUREMENT_DATA, &data[0], 6)) {
|
||||
ESP_LOGW(TAG, "Failed to read sensor's measurement data");
|
||||
ESP_LOGW(TAG, "Failed to read measurement");
|
||||
this->status_set_warning();
|
||||
|
||||
return false;
|
||||
|
||||
@@ -38,7 +38,7 @@ void CM1106Component::update() {
|
||||
}
|
||||
|
||||
if (response[0] != 0x16 || response[1] != 0x05 || response[2] != 0x01) {
|
||||
ESP_LOGW(TAG, "Got wrong UART response from CM1106: %02X %02X %02X %02X...", response[0], response[1], response[2],
|
||||
ESP_LOGW(TAG, "Got wrong UART response from CM1106: %02X %02X %02X %02X", response[0], response[1], response[2],
|
||||
response[3]);
|
||||
this->status_set_warning();
|
||||
return;
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
|
||||
CONF_DRAW_ROUNDING = "draw_rounding"
|
||||
CONF_REQUEST_HEADERS = "request_headers"
|
||||
|
||||
@@ -22,7 +22,7 @@ static const uint8_t DAC7678_REG_INTERNAL_REF_1 = 0x90;
|
||||
void DAC7678Output::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
|
||||
ESP_LOGV(TAG, "Resetting device...");
|
||||
ESP_LOGV(TAG, "Resetting device");
|
||||
|
||||
// Reset device
|
||||
if (!this->write_byte_16(DAC7678_REG_SOFTWARE_RESET, 0x0000)) {
|
||||
|
||||
@@ -15,10 +15,6 @@ namespace debug {
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
void DebugComponent::dump_config() {
|
||||
#ifndef ESPHOME_LOG_HAS_DEBUG
|
||||
return; // Can't log below if debug logging is disabled
|
||||
#endif
|
||||
|
||||
ESP_LOGCONFIG(TAG, "Debug component:");
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
LOG_TEXT_SENSOR(" ", "Device info", this->device_info_);
|
||||
|
||||
@@ -21,7 +21,7 @@ uint8_t Command::execute(DfrobotSen0395Component *parent) {
|
||||
if (this->retries_left_ > 0) {
|
||||
this->retries_left_ -= 1;
|
||||
this->cmd_sent_ = false;
|
||||
ESP_LOGD(TAG, "Retrying...");
|
||||
ESP_LOGD(TAG, "Retrying");
|
||||
return 0;
|
||||
} else {
|
||||
this->parent_->find_prompt_();
|
||||
@@ -33,7 +33,7 @@ uint8_t Command::execute(DfrobotSen0395Component *parent) {
|
||||
if (this->retries_left_ > 0) {
|
||||
this->retries_left_ -= 1;
|
||||
this->cmd_sent_ = false;
|
||||
ESP_LOGD(TAG, "Retrying...");
|
||||
ESP_LOGD(TAG, "Retrying");
|
||||
return 0;
|
||||
} else {
|
||||
this->parent_->find_prompt_();
|
||||
@@ -51,7 +51,7 @@ uint8_t Command::execute(DfrobotSen0395Component *parent) {
|
||||
if (this->retries_left_ > 0) {
|
||||
this->retries_left_ -= 1;
|
||||
this->cmd_sent_ = false;
|
||||
ESP_LOGD(TAG, "Retrying...");
|
||||
ESP_LOGD(TAG, "Retrying");
|
||||
} else {
|
||||
return 1; // Command done
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class ESP32Preferences : public ESPPreferences {
|
||||
if (err == 0)
|
||||
return;
|
||||
|
||||
ESP_LOGW(TAG, "nvs_open failed: %s - erasing NVS...", esp_err_to_name(err));
|
||||
ESP_LOGW(TAG, "nvs_open failed: %s - erasing NVS", esp_err_to_name(err));
|
||||
nvs_flash_deinit();
|
||||
nvs_flash_erase();
|
||||
nvs_flash_init();
|
||||
@@ -111,7 +111,7 @@ class ESP32Preferences : public ESPPreferences {
|
||||
if (s_pending_save.empty())
|
||||
return true;
|
||||
|
||||
ESP_LOGD(TAG, "Saving %d preferences to flash...", s_pending_save.size());
|
||||
ESP_LOGV(TAG, "Saving %d items...", s_pending_save.size());
|
||||
// goal try write all pending saves even if one fails
|
||||
int cached = 0, written = 0, failed = 0;
|
||||
esp_err_t last_err = ESP_OK;
|
||||
@@ -139,10 +139,10 @@ class ESP32Preferences : public ESPPreferences {
|
||||
}
|
||||
s_pending_save.erase(s_pending_save.begin() + i);
|
||||
}
|
||||
ESP_LOGD(TAG, "Saving %d preferences to flash: %d cached, %d written, %d failed", cached + written + failed, cached,
|
||||
written, failed);
|
||||
ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written,
|
||||
failed);
|
||||
if (failed > 0) {
|
||||
ESP_LOGE(TAG, "Error saving %d preferences to flash. Last error=%s for key=%s", failed, esp_err_to_name(last_err),
|
||||
ESP_LOGE(TAG, "Writing %d items failed. Last error=%s for key=%s", failed, esp_err_to_name(last_err),
|
||||
last_key.c_str());
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ class ESP32Preferences : public ESPPreferences {
|
||||
}
|
||||
|
||||
bool reset() override {
|
||||
ESP_LOGD(TAG, "Cleaning up preferences in flash...");
|
||||
ESP_LOGD(TAG, "Erasing storage");
|
||||
s_pending_save.clear();
|
||||
|
||||
nvs_flash_deinit();
|
||||
|
||||
@@ -270,14 +270,14 @@ void ESP32BLE::loop() {
|
||||
case BLE_COMPONENT_STATE_DISABLED:
|
||||
return;
|
||||
case BLE_COMPONENT_STATE_DISABLE: {
|
||||
ESP_LOGD(TAG, "Disabling BLE...");
|
||||
ESP_LOGD(TAG, "Disabling");
|
||||
|
||||
for (auto *ble_event_handler : this->ble_status_event_handlers_) {
|
||||
ble_event_handler->ble_before_disabled_event_handler();
|
||||
}
|
||||
|
||||
if (!ble_dismantle_()) {
|
||||
ESP_LOGE(TAG, "BLE could not be dismantled");
|
||||
ESP_LOGE(TAG, "Could not be dismantled");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -285,11 +285,11 @@ void ESP32BLE::loop() {
|
||||
return;
|
||||
}
|
||||
case BLE_COMPONENT_STATE_ENABLE: {
|
||||
ESP_LOGD(TAG, "Enabling BLE...");
|
||||
ESP_LOGD(TAG, "Enabling");
|
||||
this->state_ = BLE_COMPONENT_STATE_OFF;
|
||||
|
||||
if (!ble_setup_()) {
|
||||
ESP_LOGE(TAG, "BLE could not be set up");
|
||||
ESP_LOGE(TAG, "Could not be set up");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ void ESP32BLETracker::loop() {
|
||||
(this->scan_set_param_failed_ && this->scanner_state_ == ScannerState::RUNNING)) {
|
||||
this->stop_scan_();
|
||||
if (this->scan_start_fail_count_ == std::numeric_limits<uint8_t>::max()) {
|
||||
ESP_LOGE(TAG, "ESP-IDF BLE scan could not restart after %d attempts, rebooting to restore BLE stack...",
|
||||
ESP_LOGE(TAG, "Scan could not restart after %d attempts, rebooting to restore stack (IDF)",
|
||||
std::numeric_limits<uint8_t>::max());
|
||||
App.reboot();
|
||||
}
|
||||
@@ -219,10 +219,10 @@ void ESP32BLETracker::loop() {
|
||||
for (auto *client : this->clients_) {
|
||||
if (client->state() == ClientState::DISCOVERED) {
|
||||
if (this->scanner_state_ == ScannerState::RUNNING) {
|
||||
ESP_LOGD(TAG, "Stopping scan to make connection...");
|
||||
ESP_LOGD(TAG, "Stopping scan to make connection");
|
||||
this->stop_scan_();
|
||||
} else if (this->scanner_state_ == ScannerState::IDLE) {
|
||||
ESP_LOGD(TAG, "Promoting client to connect...");
|
||||
ESP_LOGD(TAG, "Promoting client to connect");
|
||||
// We only want to promote one client at a time.
|
||||
// once the scanner is fully stopped.
|
||||
#ifdef USE_ESP32_BLE_SOFTWARE_COEXISTENCE
|
||||
@@ -306,7 +306,7 @@ void ESP32BLETracker::start_scan_(bool first) {
|
||||
|
||||
// Start timeout before scan is started. Otherwise scan never starts if any error.
|
||||
this->set_timeout("scan", this->scan_duration_ * 2000, []() {
|
||||
ESP_LOGE(TAG, "ESP-IDF BLE scan never terminated, rebooting to restore BLE stack...");
|
||||
ESP_LOGE(TAG, "Scan never terminated, rebooting to restore stack (IDF)");
|
||||
App.reboot();
|
||||
});
|
||||
|
||||
|
||||
@@ -324,10 +324,10 @@ void ESP32ImprovComponent::process_incoming_data_() {
|
||||
this->incoming_data_.clear();
|
||||
}
|
||||
} else if (this->incoming_data_.size() - 2 > length) {
|
||||
ESP_LOGV(TAG, "Too much data received or data malformed; resetting buffer...");
|
||||
ESP_LOGV(TAG, "Too much data received or data malformed; resetting buffer");
|
||||
this->incoming_data_.clear();
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Waiting for split data packets...");
|
||||
ESP_LOGV(TAG, "Waiting for split data packets");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ void ESP32RMTLEDStripLightOutput::write_state(light::LightState *state) {
|
||||
this->last_refresh_ = now;
|
||||
this->mark_shown_();
|
||||
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus...");
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus");
|
||||
|
||||
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||
esp_err_t error = rmt_tx_wait_all_done(this->channel_, 1000);
|
||||
|
||||
@@ -40,6 +40,7 @@ struct ISRPinArg {
|
||||
volatile uint32_t *mode_set_reg;
|
||||
volatile uint32_t *mode_clr_reg;
|
||||
volatile uint32_t *func_reg;
|
||||
volatile uint32_t *control_reg;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
@@ -54,6 +55,7 @@ ISRInternalGPIOPin ESP8266GPIOPin::to_isr() const {
|
||||
arg->mode_set_reg = &GPES;
|
||||
arg->mode_clr_reg = &GPEC;
|
||||
arg->func_reg = &GPF(this->pin_);
|
||||
arg->control_reg = &GPC(this->pin_);
|
||||
arg->mask = 1 << this->pin_;
|
||||
} else {
|
||||
arg->in_reg = &GP16I;
|
||||
@@ -62,6 +64,7 @@ ISRInternalGPIOPin ESP8266GPIOPin::to_isr() const {
|
||||
arg->mode_set_reg = &GP16E;
|
||||
arg->mode_clr_reg = nullptr;
|
||||
arg->func_reg = &GPF16;
|
||||
arg->control_reg = nullptr;
|
||||
arg->mask = 1;
|
||||
}
|
||||
return ISRInternalGPIOPin((void *) arg);
|
||||
@@ -143,11 +146,17 @@ void IRAM_ATTR ISRInternalGPIOPin::pin_mode(gpio::Flags flags) {
|
||||
if (arg->pin < 16) {
|
||||
if (flags & gpio::FLAG_OUTPUT) {
|
||||
*arg->mode_set_reg = arg->mask;
|
||||
} else {
|
||||
if (flags & gpio::FLAG_OPEN_DRAIN) {
|
||||
*arg->control_reg |= 1 << GPCD;
|
||||
} else {
|
||||
*arg->control_reg &= ~(1 << GPCD);
|
||||
}
|
||||
} else if (flags & gpio::FLAG_INPUT) {
|
||||
*arg->mode_clr_reg = arg->mask;
|
||||
}
|
||||
if (flags & gpio::FLAG_PULLUP) {
|
||||
*arg->func_reg |= 1 << GPFPU;
|
||||
*arg->control_reg |= 1 << GPCD;
|
||||
} else {
|
||||
*arg->func_reg &= ~(1 << GPFPU);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ class ESP8266Preferences : public ESPPreferences {
|
||||
|
||||
void setup() {
|
||||
s_flash_storage = new uint32_t[ESP8266_FLASH_STORAGE_SIZE]; // NOLINT
|
||||
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
||||
ESP_LOGVV(TAG, "Loading preferences from flash");
|
||||
|
||||
{
|
||||
InterruptLock lock;
|
||||
@@ -235,7 +235,7 @@ class ESP8266Preferences : public ESPPreferences {
|
||||
if (s_prevent_write)
|
||||
return false;
|
||||
|
||||
ESP_LOGD(TAG, "Saving preferences to flash...");
|
||||
ESP_LOGD(TAG, "Saving");
|
||||
SpiFlashOpResult erase_res, write_res = SPI_FLASH_RESULT_OK;
|
||||
{
|
||||
InterruptLock lock;
|
||||
@@ -245,11 +245,11 @@ class ESP8266Preferences : public ESPPreferences {
|
||||
}
|
||||
}
|
||||
if (erase_res != SPI_FLASH_RESULT_OK) {
|
||||
ESP_LOGE(TAG, "Erase ESP8266 flash failed!");
|
||||
ESP_LOGE(TAG, "Erasing failed");
|
||||
return false;
|
||||
}
|
||||
if (write_res != SPI_FLASH_RESULT_OK) {
|
||||
ESP_LOGE(TAG, "Write ESP8266 flash failed!");
|
||||
ESP_LOGE(TAG, "Writing failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -258,14 +258,14 @@ class ESP8266Preferences : public ESPPreferences {
|
||||
}
|
||||
|
||||
bool reset() override {
|
||||
ESP_LOGD(TAG, "Cleaning up preferences in flash...");
|
||||
ESP_LOGD(TAG, "Erasing storage");
|
||||
SpiFlashOpResult erase_res;
|
||||
{
|
||||
InterruptLock lock;
|
||||
erase_res = spi_flash_erase_sector(get_esp8266_flash_sector());
|
||||
}
|
||||
if (erase_res != SPI_FLASH_RESULT_OK) {
|
||||
ESP_LOGE(TAG, "Erase ESP8266 flash failed!");
|
||||
ESP_LOGE(TAG, "Erasing failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ void ESPHomeOTAComponent::handle_() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Starting update from %s...", this->client_->getpeername().c_str());
|
||||
ESP_LOGD(TAG, "Starting update from %s", this->client_->getpeername().c_str());
|
||||
this->status_set_warning();
|
||||
#ifdef USE_OTA_STATE_CALLBACK
|
||||
this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0);
|
||||
|
||||
@@ -245,33 +245,33 @@ void EthernetComponent::loop() {
|
||||
switch (this->state_) {
|
||||
case EthernetComponentState::STOPPED:
|
||||
if (this->started_) {
|
||||
ESP_LOGI(TAG, "Starting ethernet connection");
|
||||
ESP_LOGI(TAG, "Starting connection");
|
||||
this->state_ = EthernetComponentState::CONNECTING;
|
||||
this->start_connect_();
|
||||
}
|
||||
break;
|
||||
case EthernetComponentState::CONNECTING:
|
||||
if (!this->started_) {
|
||||
ESP_LOGI(TAG, "Stopped ethernet connection");
|
||||
ESP_LOGI(TAG, "Stopped connection");
|
||||
this->state_ = EthernetComponentState::STOPPED;
|
||||
} else if (this->connected_) {
|
||||
// connection established
|
||||
ESP_LOGI(TAG, "Connected via Ethernet!");
|
||||
ESP_LOGI(TAG, "Connected");
|
||||
this->state_ = EthernetComponentState::CONNECTED;
|
||||
|
||||
this->dump_connect_params_();
|
||||
this->status_clear_warning();
|
||||
} else if (now - this->connect_begin_ > 15000) {
|
||||
ESP_LOGW(TAG, "Connecting via ethernet failed! Re-connecting...");
|
||||
ESP_LOGW(TAG, "Connecting failed; reconnecting");
|
||||
this->start_connect_();
|
||||
}
|
||||
break;
|
||||
case EthernetComponentState::CONNECTED:
|
||||
if (!this->started_) {
|
||||
ESP_LOGI(TAG, "Stopped ethernet connection");
|
||||
ESP_LOGI(TAG, "Stopped connection");
|
||||
this->state_ = EthernetComponentState::STOPPED;
|
||||
} else if (!this->connected_) {
|
||||
ESP_LOGW(TAG, "Connection via Ethernet lost! Re-connecting...");
|
||||
ESP_LOGW(TAG, "Connection lost; reconnecting");
|
||||
this->state_ = EthernetComponentState::CONNECTING;
|
||||
this->start_connect_();
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ static const char *const TAG = "factory_reset.button";
|
||||
|
||||
void FactoryResetButton::dump_config() { LOG_BUTTON("", "Factory Reset Button", this); }
|
||||
void FactoryResetButton::press_action() {
|
||||
ESP_LOGI(TAG, "Resetting...");
|
||||
ESP_LOGI(TAG, "Resetting");
|
||||
// Let MQTT settle a bit
|
||||
delay(100); // NOLINT
|
||||
global_preferences->reset();
|
||||
|
||||
@@ -14,7 +14,7 @@ void FactoryResetSwitch::write_state(bool state) {
|
||||
this->publish_state(false);
|
||||
|
||||
if (state) {
|
||||
ESP_LOGI(TAG, "Resetting...");
|
||||
ESP_LOGI(TAG, "Resetting");
|
||||
// Let MQTT settle a bit
|
||||
delay(100); // NOLINT
|
||||
global_preferences->reset();
|
||||
|
||||
@@ -33,7 +33,7 @@ void FastLEDLightOutput::write_state(light::LightState *state) {
|
||||
this->last_refresh_ = now;
|
||||
this->mark_shown_();
|
||||
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus...");
|
||||
ESP_LOGVV(TAG, "Writing RGB values to bus");
|
||||
this->controller_->showLeds(this->state_parent_->current_values.get_brightness() * 255);
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ haier_protocol::HandlerError HaierClimateBase::timeout_default_handler_(haier_pr
|
||||
}
|
||||
|
||||
void HaierClimateBase::setup() {
|
||||
ESP_LOGI(TAG, "Haier initialization...");
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
// Set timestamp here to give AC time to boot
|
||||
this->last_request_timestamp_ = std::chrono::steady_clock::now();
|
||||
this->set_phase(ProtocolPhases::SENDING_INIT_1);
|
||||
@@ -286,7 +286,7 @@ void HaierClimateBase::loop() {
|
||||
if (this->action_request_.has_value() && this->prepare_pending_action()) {
|
||||
this->set_phase(ProtocolPhases::SENDING_ACTION_COMMAND);
|
||||
} else if (this->next_hvac_settings_.valid || this->force_send_control_) {
|
||||
ESP_LOGV(TAG, "Control packet is pending...");
|
||||
ESP_LOGV(TAG, "Control packet is pending");
|
||||
this->set_phase(ProtocolPhases::SENDING_CONTROL);
|
||||
if (this->next_hvac_settings_.valid) {
|
||||
this->current_hvac_settings_ = this->next_hvac_settings_;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import esp32
|
||||
from esphome.components.const import CONF_REQUEST_HEADERS
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ESP8266_DISABLE_SSL_SUPPORT,
|
||||
@@ -51,7 +52,6 @@ CONF_CA_CERTIFICATE_PATH = "ca_certificate_path"
|
||||
CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size"
|
||||
CONF_ON_RESPONSE = "on_response"
|
||||
CONF_HEADERS = "headers"
|
||||
CONF_REQUEST_HEADERS = "request_headers"
|
||||
CONF_COLLECT_HEADERS = "collect_headers"
|
||||
CONF_BODY = "body"
|
||||
CONF_JSON = "json"
|
||||
|
||||
@@ -48,7 +48,7 @@ void OtaHttpRequestComponent::flash() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting update...");
|
||||
ESP_LOGI(TAG, "Starting update");
|
||||
#ifdef USE_OTA_STATE_CALLBACK
|
||||
this->state_callback_.call(ota::OTA_STARTED, 0.0f, 0);
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ void ArduinoI2CBus::setup() {
|
||||
|
||||
this->initialized_ = true;
|
||||
if (this->scan_) {
|
||||
ESP_LOGV(TAG, "Scanning i2c bus for active devices...");
|
||||
ESP_LOGV(TAG, "Scanning bus for active devices");
|
||||
this->i2c_scan_();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ void IDFI2CBus::setup() {
|
||||
}
|
||||
initialized_ = true;
|
||||
if (this->scan_) {
|
||||
ESP_LOGV(TAG, "Scanning i2c bus for active devices...");
|
||||
ESP_LOGV(TAG, "Scanning bus for active devices");
|
||||
this->i2c_scan_();
|
||||
}
|
||||
}
|
||||
|
||||
1
esphome/components/lc709203f/__init__.py
Normal file
1
esphome/components/lc709203f/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@ilikecake"]
|
||||
297
esphome/components/lc709203f/lc709203f.cpp
Normal file
297
esphome/components/lc709203f/lc709203f.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "lc709203f.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace lc709203f {
|
||||
|
||||
static const char *const TAG = "lc709203f.sensor";
|
||||
|
||||
// Device I2C address. This address is fixed.
|
||||
static const uint8_t LC709203F_I2C_ADDR_DEFAULT = 0x0B;
|
||||
|
||||
// Device registers
|
||||
static const uint8_t LC709203F_BEFORE_RSOC = 0x04;
|
||||
static const uint8_t LC709203F_THERMISTOR_B = 0x06;
|
||||
static const uint8_t LC709203F_INITIAL_RSOC = 0x07;
|
||||
static const uint8_t LC709203F_CELL_TEMPERATURE = 0x08;
|
||||
static const uint8_t LC709203F_CELL_VOLTAGE = 0x09;
|
||||
static const uint8_t LC709203F_CURRENT_DIRECTION = 0x0A;
|
||||
static const uint8_t LC709203F_APA = 0x0B;
|
||||
static const uint8_t LC709203F_APT = 0x0C;
|
||||
static const uint8_t LC709203F_RSOC = 0x0D;
|
||||
static const uint8_t LC709203F_ITE = 0x0F;
|
||||
static const uint8_t LC709203F_IC_VERSION = 0x11;
|
||||
static const uint8_t LC709203F_CHANGE_OF_THE_PARAMETER = 0x12;
|
||||
static const uint8_t LC709203F_ALARM_LOW_RSOC = 0x13;
|
||||
static const uint8_t LC709203F_ALARM_LOW_CELL_VOLTAGE = 0x14;
|
||||
static const uint8_t LC709203F_IC_POWER_MODE = 0x15;
|
||||
static const uint8_t LC709203F_STATUS_BIT = 0x16;
|
||||
static const uint8_t LC709203F_NUMBER_OF_THE_PARAMETER = 0x1A;
|
||||
|
||||
static const uint8_t LC709203F_POWER_MODE_ON = 0x0001;
|
||||
static const uint8_t LC709203F_POWER_MODE_SLEEP = 0x0002;
|
||||
|
||||
// The number of times to retry an I2C transaction before giving up. In my experience,
|
||||
// 10 is a good number here that will take care of most bus issues that require retry.
|
||||
static const uint8_t LC709203F_I2C_RETRY_COUNT = 10;
|
||||
|
||||
void Lc709203f::setup() {
|
||||
// Note: The setup implements a small state machine. This is because we want to have
|
||||
// delays before and after sending the RSOC command. The full init process should be:
|
||||
// INIT->RSOC->TEMP_SETUP->NORMAL
|
||||
// The setup() function will only perform the first part of the initialization process.
|
||||
// Assuming no errors, the whole process should occur during the setup() function and
|
||||
// the first two calls to update(). After that, the part should remain in normal mode
|
||||
// until a device reset.
|
||||
//
|
||||
// This device can be picky about I2C communication and can error out occasionally. The
|
||||
// get/set register functions impelment retry logic to retry the I2C transactions. The
|
||||
// initialization code checks the return code from those functions. If they don't return
|
||||
// NO_ERROR (0x00), that part of the initialization aborts and will be retried on the next
|
||||
// call to update().
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
|
||||
// Set power mode to on. Note that, unlike some other similar devices, in sleep mode the IC
|
||||
// does not record power usage. If there is significant power consumption during sleep mode,
|
||||
// the pack RSOC will likely no longer be correct. Because of that, I do not implement
|
||||
// sleep mode on this device.
|
||||
|
||||
// Initialize device registers. If any of these fail, retry during the update() function.
|
||||
if (this->set_register_(LC709203F_IC_POWER_MODE, LC709203F_POWER_MODE_ON) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->set_register_(LC709203F_APA, this->apa_) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->set_register_(LC709203F_CHANGE_OF_THE_PARAMETER, this->pack_voltage_) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->state_ = STATE_RSOC;
|
||||
// Note: Initialization continues in the update() function.
|
||||
}
|
||||
|
||||
void Lc709203f::update() {
|
||||
uint16_t buffer;
|
||||
|
||||
if (this->state_ == STATE_NORMAL) {
|
||||
// Note: If we fail to read from the data registers, we do not report any sensor reading.
|
||||
if (this->voltage_sensor_ != nullptr) {
|
||||
if (this->get_register_(LC709203F_CELL_VOLTAGE, &buffer) == i2c::NO_ERROR) {
|
||||
// Raw units are mV
|
||||
this->voltage_sensor_->publish_state(static_cast<float>(buffer) / 1000.0f);
|
||||
this->status_clear_warning();
|
||||
}
|
||||
}
|
||||
if (this->battery_remaining_sensor_ != nullptr) {
|
||||
if (this->get_register_(LC709203F_ITE, &buffer) == i2c::NO_ERROR) {
|
||||
// Raw units are .1%
|
||||
this->battery_remaining_sensor_->publish_state(static_cast<float>(buffer) / 10.0f);
|
||||
this->status_clear_warning();
|
||||
}
|
||||
}
|
||||
if (this->temperature_sensor_ != nullptr) {
|
||||
// I can't test this with a real thermistor because I don't have a device with
|
||||
// an attached thermistor. I have turned on the sensor and made sure that it
|
||||
// sets up the registers properly.
|
||||
if (this->get_register_(LC709203F_CELL_TEMPERATURE, &buffer) == i2c::NO_ERROR) {
|
||||
// Raw units are .1 K
|
||||
this->temperature_sensor_->publish_state((static_cast<float>(buffer) / 10.0f) - 273.15f);
|
||||
this->status_clear_warning();
|
||||
}
|
||||
}
|
||||
} else if (this->state_ == STATE_INIT) {
|
||||
// Retry initializing the device registers. We should only get here if the init sequence
|
||||
// failed during the setup() function. This would likely occur because of a repeated failures
|
||||
// on the I2C bus. If any of these fail, retry the next time the update() function is called.
|
||||
if (this->set_register_(LC709203F_IC_POWER_MODE, LC709203F_POWER_MODE_ON) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->set_register_(LC709203F_APA, this->apa_) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->set_register_(LC709203F_CHANGE_OF_THE_PARAMETER, this->pack_voltage_) != i2c::NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->state_ = STATE_RSOC;
|
||||
|
||||
} else if (this->state_ == STATE_RSOC) {
|
||||
// We implement a delay here to send the initial RSOC command.
|
||||
// This should run once on the first update() after initialization.
|
||||
if (this->set_register_(LC709203F_INITIAL_RSOC, 0xAA55) == i2c::NO_ERROR) {
|
||||
this->state_ = STATE_TEMP_SETUP;
|
||||
}
|
||||
} else if (this->state_ == STATE_TEMP_SETUP) {
|
||||
// This should run once on the second update() after initialization.
|
||||
if (this->temperature_sensor_ != nullptr) {
|
||||
// This assumes that a thermistor is attached to the device as shown in the datahseet.
|
||||
if (this->set_register_(LC709203F_STATUS_BIT, 0x0001) == i2c::NO_ERROR) {
|
||||
if (this->set_register_(LC709203F_THERMISTOR_B, this->b_constant_) == i2c::NO_ERROR) {
|
||||
this->state_ = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
} else if (this->set_register_(LC709203F_STATUS_BIT, 0x0000) == i2c::NO_ERROR) {
|
||||
// The device expects to get updates to the temperature in this mode.
|
||||
// I am not doing that now. The temperature register defaults to 25C.
|
||||
// In theory, we could have another temperature sensor and have ESPHome
|
||||
// send updated temperature to the device occasionally, but I have no idea
|
||||
// how to make that happen.
|
||||
this->state_ = STATE_NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lc709203f::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "LC709203F:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
ESP_LOGCONFIG(TAG, " Pack Size: %d mAH", this->pack_size_);
|
||||
ESP_LOGCONFIG(TAG, " Pack APA: 0x%02X", this->apa_);
|
||||
|
||||
// This is only true if the pack_voltage_ is either 0x0000 or 0x0001. The config validator
|
||||
// should have already verified this.
|
||||
ESP_LOGCONFIG(TAG, " Pack Rated Voltage: 3.%sV", this->pack_voltage_ == 0x0000 ? "8" : "7");
|
||||
|
||||
LOG_SENSOR(" ", "Voltage", this->voltage_sensor_);
|
||||
LOG_SENSOR(" ", "Battery Remaining", this->battery_remaining_sensor_);
|
||||
|
||||
if (this->temperature_sensor_ != nullptr) {
|
||||
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||
ESP_LOGCONFIG(TAG, " B_Constant: %d", this->b_constant_);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, " No Temperature Sensor");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Lc709203f::get_register_(uint8_t register_to_read, uint16_t *register_value) {
|
||||
i2c::ErrorCode return_code;
|
||||
uint8_t read_buffer[6];
|
||||
|
||||
read_buffer[0] = (this->address_) << 1;
|
||||
read_buffer[1] = register_to_read;
|
||||
read_buffer[2] = ((this->address_) << 1) | 0x01;
|
||||
|
||||
for (uint8_t i = 0; i <= LC709203F_I2C_RETRY_COUNT; i++) {
|
||||
// Note: the read_register() function does not send a stop between the write and
|
||||
// the read portions of the I2C transation when you set the last variable to 'false'
|
||||
// as we do below. Some of the other I2C read functions such as the generic read()
|
||||
// function will send a stop between the read and the write portion of the I2C
|
||||
// transaction. This is bad in this case and will result in reading nothing but 0xFFFF
|
||||
// from the registers.
|
||||
return_code = this->read_register(register_to_read, &read_buffer[3], 3, false);
|
||||
if (return_code != i2c::NO_ERROR) {
|
||||
// Error on the i2c bus
|
||||
this->status_set_warning(
|
||||
str_sprintf("Error code %d when reading from register 0x%02X", return_code, register_to_read).c_str());
|
||||
} else if (this->crc8_(read_buffer, 5) != read_buffer[5]) {
|
||||
// I2C indicated OK, but the CRC of the data does not matcth.
|
||||
this->status_set_warning(str_sprintf("CRC error reading from register 0x%02X", register_to_read).c_str());
|
||||
} else {
|
||||
*register_value = ((uint16_t) read_buffer[4] << 8) | (uint16_t) read_buffer[3];
|
||||
return i2c::NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we tried LC709203F_I2C_RETRY_COUNT times to read the register and
|
||||
// failed each time. Set the register value to 0 and return the I2C error code or 0xFF
|
||||
// to indicate a CRC failure. It will be up to the higher level code what to do when
|
||||
// this happens.
|
||||
*register_value = 0x0000;
|
||||
if (return_code != i2c::NO_ERROR) {
|
||||
return return_code;
|
||||
} else {
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Lc709203f::set_register_(uint8_t register_to_set, uint16_t value_to_set) {
|
||||
i2c::ErrorCode return_code;
|
||||
uint8_t write_buffer[5];
|
||||
|
||||
// Note: We don't actually send byte[0] of the buffer. We include it because it is
|
||||
// part of the CRC calculation.
|
||||
write_buffer[0] = (this->address_) << 1;
|
||||
write_buffer[1] = register_to_set;
|
||||
write_buffer[2] = value_to_set & 0xFF; // Low byte
|
||||
write_buffer[3] = (value_to_set >> 8) & 0xFF; // High byte
|
||||
write_buffer[4] = this->crc8_(write_buffer, 4);
|
||||
|
||||
for (uint8_t i = 0; i <= LC709203F_I2C_RETRY_COUNT; i++) {
|
||||
// Note: we don't write the first byte of the write buffer to the device.
|
||||
// This is done automatically by the write() function.
|
||||
return_code = this->write(&write_buffer[1], 4, true);
|
||||
if (return_code == i2c::NO_ERROR) {
|
||||
return return_code;
|
||||
} else {
|
||||
this->status_set_warning(
|
||||
str_sprintf("Error code %d when writing to register 0x%02X", return_code, register_to_set).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we tried to send the data LC709203F_I2C_RETRY_COUNT times and failed.
|
||||
// We return the I2C error code, it is up to the higher level code what to do about it.
|
||||
return return_code;
|
||||
}
|
||||
|
||||
uint8_t Lc709203f::crc8_(uint8_t *byte_buffer, uint8_t length_of_crc) {
|
||||
uint8_t crc = 0x00;
|
||||
const uint8_t polynomial(0x07);
|
||||
|
||||
for (uint8_t j = length_of_crc; j; --j) {
|
||||
crc ^= *byte_buffer++;
|
||||
|
||||
for (uint8_t i = 8; i; --i) {
|
||||
crc = (crc & 0x80) ? (crc << 1) ^ polynomial : (crc << 1);
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
void Lc709203f::set_pack_size(uint16_t pack_size) {
|
||||
static const uint16_t PACK_SIZE_ARRAY[6] = {100, 200, 500, 1000, 2000, 3000};
|
||||
static const uint16_t APA_ARRAY[6] = {0x08, 0x0B, 0x10, 0x19, 0x2D, 0x36};
|
||||
float slope;
|
||||
float intercept;
|
||||
|
||||
this->pack_size_ = pack_size; // Pack size in mAH
|
||||
|
||||
// The size is used to calculate the 'Adjustment Pack Application' number.
|
||||
// Here we assume a type 01 or type 03 battery and do a linear curve fit to find the APA.
|
||||
for (uint8_t i = 0; i < 6; i++) {
|
||||
if (PACK_SIZE_ARRAY[i] == pack_size) {
|
||||
// If the pack size is exactly one of the values in the array.
|
||||
this->apa_ = APA_ARRAY[i];
|
||||
return;
|
||||
} else if ((i > 0) && (PACK_SIZE_ARRAY[i] > pack_size) && (PACK_SIZE_ARRAY[i - 1] < pack_size)) {
|
||||
// If the pack size is between the current array element and the previous. Do a linear
|
||||
// Curve fit to determine the APA value.
|
||||
|
||||
// Type casting is required here to avoid interger division
|
||||
slope = static_cast<float>(APA_ARRAY[i] - APA_ARRAY[i - 1]) /
|
||||
static_cast<float>(PACK_SIZE_ARRAY[i] - PACK_SIZE_ARRAY[i - 1]);
|
||||
|
||||
// Type casting might not be needed here.
|
||||
intercept = static_cast<float>(APA_ARRAY[i]) - slope * static_cast<float>(PACK_SIZE_ARRAY[i]);
|
||||
|
||||
this->apa_ = static_cast<uint8_t>(slope * pack_size + intercept);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// We should never get here. If we do, it means we never set the pack APA. This should
|
||||
// not be possible because of the config validation. However, if it does happen, the
|
||||
// consequence is that the RSOC values will likley not be as accurate. However, it should
|
||||
// not cause an error or crash, so I am not doing any additional checking here.
|
||||
}
|
||||
|
||||
void Lc709203f::set_thermistor_b_constant(uint16_t b_constant) { this->b_constant_ = b_constant; }
|
||||
|
||||
void Lc709203f::set_pack_voltage(LC709203FBatteryVoltage pack_voltage) { this->pack_voltage_ = pack_voltage; }
|
||||
|
||||
} // namespace lc709203f
|
||||
} // namespace esphome
|
||||
55
esphome/components/lc709203f/lc709203f.h
Normal file
55
esphome/components/lc709203f/lc709203f.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace lc709203f {
|
||||
|
||||
enum LC709203FState {
|
||||
STATE_INIT,
|
||||
STATE_RSOC,
|
||||
STATE_TEMP_SETUP,
|
||||
STATE_NORMAL,
|
||||
};
|
||||
|
||||
/// Enum listing allowable voltage settings for the LC709203F.
|
||||
enum LC709203FBatteryVoltage {
|
||||
LC709203F_BATTERY_VOLTAGE_3_8 = 0x0000,
|
||||
LC709203F_BATTERY_VOLTAGE_3_7 = 0x0001,
|
||||
};
|
||||
|
||||
class Lc709203f : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void update() override;
|
||||
void dump_config() override;
|
||||
|
||||
void set_pack_size(uint16_t pack_size);
|
||||
void set_thermistor_b_constant(uint16_t b_constant);
|
||||
void set_pack_voltage(LC709203FBatteryVoltage pack_voltage);
|
||||
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||
void set_battery_remaining_sensor(sensor::Sensor *battery_remaining_sensor) {
|
||||
battery_remaining_sensor_ = battery_remaining_sensor;
|
||||
}
|
||||
void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; }
|
||||
|
||||
private:
|
||||
uint8_t get_register_(uint8_t register_to_read, uint16_t *register_value);
|
||||
uint8_t set_register_(uint8_t register_to_set, uint16_t value_to_set);
|
||||
uint8_t crc8_(uint8_t *byte_buffer, uint8_t length_of_crc);
|
||||
|
||||
protected:
|
||||
sensor::Sensor *voltage_sensor_{nullptr};
|
||||
sensor::Sensor *battery_remaining_sensor_{nullptr};
|
||||
sensor::Sensor *temperature_sensor_{nullptr};
|
||||
uint16_t pack_size_;
|
||||
uint16_t apa_;
|
||||
uint16_t b_constant_;
|
||||
LC709203FState state_ = STATE_INIT;
|
||||
uint16_t pack_voltage_;
|
||||
};
|
||||
|
||||
} // namespace lc709203f
|
||||
} // namespace esphome
|
||||
93
esphome/components/lc709203f/sensor.py
Normal file
93
esphome/components/lc709203f/sensor.py
Normal file
@@ -0,0 +1,93 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c, sensor
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_BATTERY_LEVEL,
|
||||
CONF_BATTERY_VOLTAGE,
|
||||
CONF_ID,
|
||||
CONF_SIZE,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_VOLTAGE,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_PERCENT,
|
||||
UNIT_VOLT,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
lc709203f_ns = cg.esphome_ns.namespace("lc709203f")
|
||||
|
||||
CONF_B_CONSTANT = "b_constant"
|
||||
|
||||
LC709203FBatteryVoltage = lc709203f_ns.enum("LC709203FBatteryVoltage")
|
||||
BATTERY_VOLTAGE_OPTIONS = {
|
||||
"3.7": LC709203FBatteryVoltage.LC709203F_BATTERY_VOLTAGE_3_7,
|
||||
"3.8": LC709203FBatteryVoltage.LC709203F_BATTERY_VOLTAGE_3_8,
|
||||
}
|
||||
|
||||
lc709203f = lc709203f_ns.class_("Lc709203f", cg.PollingComponent, i2c.I2CDevice)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(lc709203f),
|
||||
cv.Optional(CONF_SIZE, default="500"): cv.int_range(100, 3000),
|
||||
cv.Optional(CONF_VOLTAGE, default="3.7"): cv.enum(
|
||||
BATTERY_VOLTAGE_OPTIONS, upper=True
|
||||
),
|
||||
cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_VOLT,
|
||||
accuracy_decimals=3,
|
||||
device_class=DEVICE_CLASS_VOLTAGE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
),
|
||||
cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
accuracy_decimals=3,
|
||||
device_class=DEVICE_CLASS_BATTERY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
),
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
).extend(
|
||||
{
|
||||
cv.Required(CONF_B_CONSTANT): cv.int_range(0, 0xFFFF),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x0B))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
cg.add(var.set_pack_size(config.get(CONF_SIZE)))
|
||||
cg.add(var.set_pack_voltage(BATTERY_VOLTAGE_OPTIONS[config[CONF_VOLTAGE]]))
|
||||
|
||||
if voltage_config := config.get(CONF_BATTERY_VOLTAGE):
|
||||
sens = await sensor.new_sensor(voltage_config)
|
||||
cg.add(var.set_voltage_sensor(sens))
|
||||
|
||||
if level_config := config.get(CONF_BATTERY_LEVEL):
|
||||
sens = await sensor.new_sensor(level_config)
|
||||
cg.add(var.set_battery_remaining_sensor(sens))
|
||||
|
||||
if temp_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temp_config)
|
||||
cg.add(var.set_temperature_sensor(sens))
|
||||
cg.add(var.set_thermistor_b_constant(temp_config[CONF_B_CONSTANT]))
|
||||
@@ -158,7 +158,7 @@ void LD2420Component::apply_config_action() {
|
||||
ESP_LOGCONFIG(TAG, "No configuration change detected");
|
||||
return;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, "Reconfiguring LD2420...");
|
||||
ESP_LOGCONFIG(TAG, "Reconfiguring LD2420");
|
||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
||||
ESP_LOGE(TAG, "LD2420 module has failed to respond, check baud rate and serial connections.");
|
||||
this->mark_failed();
|
||||
@@ -180,7 +180,7 @@ void LD2420Component::apply_config_action() {
|
||||
}
|
||||
|
||||
void LD2420Component::factory_reset_action() {
|
||||
ESP_LOGCONFIG(TAG, "Setting factory defaults...");
|
||||
ESP_LOGCONFIG(TAG, "Setting factory defaults");
|
||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
||||
ESP_LOGE(TAG, "LD2420 module has failed to respond, check baud rate and serial connections.");
|
||||
this->mark_failed();
|
||||
@@ -209,7 +209,7 @@ void LD2420Component::factory_reset_action() {
|
||||
}
|
||||
|
||||
void LD2420Component::restart_module_action() {
|
||||
ESP_LOGCONFIG(TAG, "Restarting LD2420 module...");
|
||||
ESP_LOGCONFIG(TAG, "Restarting LD2420 module");
|
||||
this->send_module_restart();
|
||||
this->set_timeout(250, [this]() {
|
||||
this->set_config_mode(true);
|
||||
|
||||
@@ -6,6 +6,8 @@ from esphome.const import (
|
||||
CONF_DISTANCE,
|
||||
CONF_RESOLUTION,
|
||||
CONF_SPEED,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
DEVICE_CLASS_DISTANCE,
|
||||
DEVICE_CLASS_SPEED,
|
||||
UNIT_DEGREES,
|
||||
@@ -19,8 +21,6 @@ DEPENDENCIES = ["ld2450"]
|
||||
CONF_MOVING_TARGET_COUNT = "moving_target_count"
|
||||
CONF_STILL_TARGET_COUNT = "still_target_count"
|
||||
CONF_TARGET_COUNT = "target_count"
|
||||
CONF_X = "x"
|
||||
CONF_Y = "y"
|
||||
|
||||
ICON_ACCOUNT_GROUP = "mdi:account-group"
|
||||
ICON_ACCOUNT_SWITCH = "mdi:account-switch"
|
||||
|
||||
@@ -139,7 +139,7 @@ void LEDCOutput::write_state(float state) {
|
||||
}
|
||||
|
||||
void LEDCOutput::setup() {
|
||||
ESP_LOGV(TAG, "Entering setup...");
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
#ifdef USE_ARDUINO
|
||||
this->update_frequency(this->frequency_);
|
||||
this->turn_off();
|
||||
@@ -207,14 +207,14 @@ void LEDCOutput::update_frequency(float frequency) {
|
||||
this->bit_depth_ = bit_depth_opt.value_or(8);
|
||||
this->frequency_ = frequency;
|
||||
#ifdef USE_ARDUINO
|
||||
ESP_LOGV(TAG, "Using Arduino API - Trying to define channel, frequency and bit depth...");
|
||||
ESP_LOGV(TAG, "Using Arduino API - Trying to define channel, frequency and bit depth");
|
||||
u_int32_t configured_frequency = 0;
|
||||
|
||||
// Configure LEDC channel, frequency and bit depth with fallback
|
||||
int attempt_count_max = SETUP_ATTEMPT_COUNT_MAX;
|
||||
while (attempt_count_max > 0 && configured_frequency == 0) {
|
||||
ESP_LOGV(TAG, "Initializing channel %u with frequency %.1f and bit depth of %u...", this->channel_,
|
||||
this->frequency_, this->bit_depth_);
|
||||
ESP_LOGV(TAG, "Initializing channel %u with frequency %.1f and bit depth of %u", this->channel_, this->frequency_,
|
||||
this->bit_depth_);
|
||||
configured_frequency = ledcSetup(this->channel_, frequency, this->bit_depth_);
|
||||
if (configured_frequency != 0) {
|
||||
this->initialized_ = true;
|
||||
|
||||
@@ -101,7 +101,7 @@ class LibreTinyPreferences : public ESPPreferences {
|
||||
if (s_pending_save.empty())
|
||||
return true;
|
||||
|
||||
ESP_LOGD(TAG, "Saving %d preferences to flash...", s_pending_save.size());
|
||||
ESP_LOGV(TAG, "Saving %d items...", s_pending_save.size());
|
||||
// goal try write all pending saves even if one fails
|
||||
int cached = 0, written = 0, failed = 0;
|
||||
fdb_err_t last_err = FDB_NO_ERR;
|
||||
@@ -129,11 +129,10 @@ class LibreTinyPreferences : public ESPPreferences {
|
||||
}
|
||||
s_pending_save.erase(s_pending_save.begin() + i);
|
||||
}
|
||||
ESP_LOGD(TAG, "Saving %d preferences to flash: %d cached, %d written, %d failed", cached + written + failed, cached,
|
||||
written, failed);
|
||||
ESP_LOGD(TAG, "Writing %d items: %d cached, %d written, %d failed", cached + written + failed, cached, written,
|
||||
failed);
|
||||
if (failed > 0) {
|
||||
ESP_LOGE(TAG, "Error saving %d preferences to flash. Last error=%d for key=%s", failed, last_err,
|
||||
last_key.c_str());
|
||||
ESP_LOGE(TAG, "Writing %d items failed. Last error=%d for key=%s", failed, last_err, last_key.c_str());
|
||||
}
|
||||
|
||||
return failed == 0;
|
||||
@@ -158,7 +157,7 @@ class LibreTinyPreferences : public ESPPreferences {
|
||||
}
|
||||
|
||||
bool reset() override {
|
||||
ESP_LOGD(TAG, "Cleaning up preferences in flash...");
|
||||
ESP_LOGD(TAG, "Erasing storage");
|
||||
s_pending_save.clear();
|
||||
|
||||
fdb_kv_set_default(&db);
|
||||
|
||||
@@ -212,9 +212,9 @@ class Logger : public Component {
|
||||
}
|
||||
|
||||
// Format string to explicit buffer with varargs
|
||||
inline void printf_to_buffer_(const char *format, char *buffer, int *buffer_at, int buffer_size, ...) {
|
||||
inline void printf_to_buffer_(char *buffer, int *buffer_at, int buffer_size, const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, buffer_size);
|
||||
va_start(arg, format);
|
||||
this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
@@ -312,13 +312,13 @@ class Logger : public Component {
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
if (thread_name != nullptr) {
|
||||
// Non-main task with thread name
|
||||
this->printf_to_buffer_("%s[%s][%s:%03u]%s[%s]%s: ", buffer, buffer_at, buffer_size, color, letter, tag, line,
|
||||
this->printf_to_buffer_(buffer, buffer_at, buffer_size, "%s[%s][%s:%03u]%s[%s]%s: ", color, letter, tag, line,
|
||||
ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), thread_name, color);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
// Main task or non ESP32/LibreTiny platform
|
||||
this->printf_to_buffer_("%s[%s][%s:%03u]: ", buffer, buffer_at, buffer_size, color, letter, tag, line);
|
||||
this->printf_to_buffer_(buffer, buffer_at, buffer_size, "%s[%s][%s:%03u]: ", color, letter, tag, line);
|
||||
}
|
||||
|
||||
inline void HOT format_body_to_buffer_(char *buffer, int *buffer_at, int buffer_size, const char *format,
|
||||
|
||||
@@ -306,7 +306,7 @@ void LTRAlsPs501Component::configure_als_() {
|
||||
|
||||
uint8_t tries = MAX_TRIES;
|
||||
do {
|
||||
ESP_LOGV(TAG, "Waiting for ALS device to become active...");
|
||||
ESP_LOGV(TAG, "Waiting for ALS device to become active");
|
||||
delay(2);
|
||||
als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get();
|
||||
} while (!als_ctrl.als_mode_active && tries--); // while active mode is not set - keep waiting
|
||||
|
||||
@@ -298,7 +298,7 @@ void LTRAlsPsComponent::configure_als_() {
|
||||
|
||||
uint8_t tries = MAX_TRIES;
|
||||
do {
|
||||
ESP_LOGV(TAG, "Waiting for device to become active...");
|
||||
ESP_LOGV(TAG, "Waiting for device to become active");
|
||||
delay(2);
|
||||
als_ctrl.raw = this->reg((uint8_t) CommandRegisters::ALS_CONTR).get();
|
||||
} while (!als_ctrl.active_mode && tries--); // while active mode is not set - keep waiting
|
||||
|
||||
@@ -519,8 +519,6 @@ CONF_UPDATE_ON_RELEASE = "update_on_release"
|
||||
CONF_VISIBLE_ROW_COUNT = "visible_row_count"
|
||||
CONF_WIDGET = "widget"
|
||||
CONF_WIDGETS = "widgets"
|
||||
CONF_X = "x"
|
||||
CONF_Y = "y"
|
||||
CONF_ZOOM = "zoom"
|
||||
|
||||
# Keypad keys
|
||||
|
||||
@@ -13,13 +13,15 @@ from esphome.const import (
|
||||
CONF_TIME,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_TYPE,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
)
|
||||
from esphome.core import TimePeriod
|
||||
from esphome.core.config import StartupTrigger
|
||||
from esphome.schema_extractors import SCHEMA_EXTRACT
|
||||
|
||||
from . import defines as df, lv_validation as lvalid
|
||||
from .defines import CONF_TIME_FORMAT, CONF_X, CONF_Y, LV_GRAD_DIR
|
||||
from .defines import CONF_TIME_FORMAT, LV_GRAD_DIR
|
||||
from .helpers import add_lv_use, requires_component, validate_printf
|
||||
from .lv_validation import lv_color, lv_font, lv_gradient, lv_image, opacity
|
||||
from .lvcode import LvglComponent, lv_event_t_ptr
|
||||
@@ -354,8 +356,8 @@ ALIGN_TO_SCHEMA = {
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(lv_obj_t),
|
||||
cv.Required(df.CONF_ALIGN): df.ALIGN_ALIGNMENTS.one_of,
|
||||
cv.Optional(df.CONF_X, default=0): lvalid.pixels_or_percent,
|
||||
cv.Optional(df.CONF_Y, default=0): lvalid.pixels_or_percent,
|
||||
cv.Optional(CONF_X, default=0): lvalid.pixels_or_percent,
|
||||
cv.Optional(CONF_Y, default=0): lvalid.pixels_or_percent,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import CONF_ID, CONF_ON_BOOT, CONF_ON_VALUE, CONF_TRIGGER_ID
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ON_BOOT,
|
||||
CONF_ON_VALUE,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
)
|
||||
|
||||
from .defines import (
|
||||
CONF_ALIGN,
|
||||
CONF_ALIGN_TO,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
DIRECTIONS,
|
||||
LV_EVENT_MAP,
|
||||
LV_EVENT_TRIGGERS,
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
from esphome import automation, codegen as cg, config_validation as cv
|
||||
from esphome.components.display_menu_base import CONF_LABEL
|
||||
from esphome.const import CONF_COLOR, CONF_HEIGHT, CONF_ID, CONF_TEXT, CONF_WIDTH
|
||||
from esphome.const import (
|
||||
CONF_COLOR,
|
||||
CONF_HEIGHT,
|
||||
CONF_ID,
|
||||
CONF_TEXT,
|
||||
CONF_WIDTH,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
)
|
||||
from esphome.cpp_generator import Literal, MockObj
|
||||
|
||||
from ..automation import action_to_code
|
||||
@@ -13,8 +21,6 @@ from ..defines import (
|
||||
CONF_POINTS,
|
||||
CONF_SRC,
|
||||
CONF_START_ANGLE,
|
||||
CONF_X,
|
||||
CONF_Y,
|
||||
literal,
|
||||
)
|
||||
from ..lv_validation import (
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_X, CONF_Y
|
||||
from esphome.core import Lambda
|
||||
|
||||
from ..defines import CONF_MAIN, CONF_X, CONF_Y, call_lambda
|
||||
from ..defines import CONF_MAIN, call_lambda
|
||||
from ..lvcode import lv_add
|
||||
from ..schemas import point_schema
|
||||
from ..types import LvCompound, LvType
|
||||
|
||||
@@ -13,14 +13,14 @@ void M5Stack8AngleComponent::setup() {
|
||||
|
||||
err = this->read(nullptr, 0);
|
||||
if (err != i2c::NO_ERROR) {
|
||||
ESP_LOGE(TAG, "I2C error %02X...", err);
|
||||
ESP_LOGE(TAG, "I2C error %02X", err);
|
||||
this->mark_failed();
|
||||
return;
|
||||
};
|
||||
|
||||
err = this->read_register(M5STACK_8ANGLE_REGISTER_FW_VERSION, &this->fw_version_, 1);
|
||||
if (err != i2c::NO_ERROR) {
|
||||
ESP_LOGE(TAG, "I2C error %02X...", err);
|
||||
ESP_LOGE(TAG, "I2C error %02X", err);
|
||||
this->mark_failed();
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -95,28 +95,28 @@ bool MAX31856Sensor::has_fault_() {
|
||||
this->status_set_warning();
|
||||
|
||||
if ((faults & MAX31856_FAULT_CJRANGE) == MAX31856_FAULT_CJRANGE) {
|
||||
ESP_LOGW(TAG, "Cold Junction Out-of-Range: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Cold Junction Out-of-Range: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_TCRANGE) == MAX31856_FAULT_TCRANGE) {
|
||||
ESP_LOGW(TAG, "Thermocouple Out-of-Range: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Thermocouple Out-of-Range: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_CJHIGH) == MAX31856_FAULT_CJHIGH) {
|
||||
ESP_LOGW(TAG, "Cold-Junction High Fault: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Cold-Junction High Fault: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_CJLOW) == MAX31856_FAULT_CJLOW) {
|
||||
ESP_LOGW(TAG, "Cold-Junction Low Fault: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Cold-Junction Low Fault: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_TCHIGH) == MAX31856_FAULT_TCHIGH) {
|
||||
ESP_LOGW(TAG, "Thermocouple Temperature High Fault: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Thermocouple Temperature High Fault: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_TCLOW) == MAX31856_FAULT_TCLOW) {
|
||||
ESP_LOGW(TAG, "Thermocouple Temperature Low Fault: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Thermocouple Temperature Low Fault: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_OVUV) == MAX31856_FAULT_OVUV) {
|
||||
ESP_LOGW(TAG, "Overvoltage or Undervoltage Input Fault: '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Overvoltage or Undervoltage Input Fault: '%s'", this->name_.c_str());
|
||||
}
|
||||
if ((faults & MAX31856_FAULT_OPEN) == MAX31856_FAULT_OPEN) {
|
||||
ESP_LOGW(TAG, "Thermocouple Open-Circuit Fault (possibly not connected): '%s'...", this->name_.c_str());
|
||||
ESP_LOGW(TAG, "Thermocouple Open-Circuit Fault (possibly not connected): '%s'", this->name_.c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -42,17 +42,17 @@ void MAX9611Component::setup() {
|
||||
const uint8_t fast_mode_dat[] = {CONTROL_REGISTER_1_ADRR, MAX9611Multiplexer::MAX9611_MULTIPLEXER_FAST_MODE};
|
||||
|
||||
if (this->write(reinterpret_cast<const uint8_t *>(&setup_dat), sizeof(setup_dat)) != ErrorCode::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Failed to setup Max9611 during GAIN SET");
|
||||
ESP_LOGE(TAG, "GAIN SET failed");
|
||||
return;
|
||||
}
|
||||
delay(SETUP_DELAY);
|
||||
if (this->write(reinterpret_cast<const uint8_t *>(&fast_mode_dat), sizeof(fast_mode_dat)) != ErrorCode::ERROR_OK) {
|
||||
ESP_LOGE(TAG, "Failed to setup Max9611 during FAST MODE SET");
|
||||
ESP_LOGE(TAG, "FAST MODE SET failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
void MAX9611Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Dump Config max9611...");
|
||||
ESP_LOGCONFIG(TAG, "MAX9611:");
|
||||
ESP_LOGCONFIG(TAG, " CSA Gain Register: %x", gain_);
|
||||
LOG_I2C_DEVICE(this);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ void MAX9611Component::update() {
|
||||
// Just read the entire register map in a bulk read, faster than individually querying register.
|
||||
const ErrorCode read_result = this->read(register_map_, sizeof(register_map_));
|
||||
if (write_result != ErrorCode::ERROR_OK || read_result != ErrorCode::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "MAX9611 Update FAILED!");
|
||||
ESP_LOGW(TAG, "Update failed");
|
||||
return;
|
||||
}
|
||||
uint16_t csa_register = ((register_map_[CSA_DATA_BYTE_MSB_ADRR] << 8) | (register_map_[CSA_DATA_BYTE_LSB_ADRR])) >> 4;
|
||||
|
||||
@@ -33,7 +33,7 @@ class MDNSComponent : public Component {
|
||||
#if (defined(USE_ESP8266) || defined(USE_RP2040)) && defined(USE_ARDUINO)
|
||||
void loop() override;
|
||||
#endif
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_WIFI; }
|
||||
float get_setup_priority() const override { return setup_priority::AFTER_CONNECTION; }
|
||||
|
||||
void add_extra_service(MDNSService service) { services_extra_.push_back(std::move(service)); }
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ void MICS4514Component::setup() {
|
||||
uint8_t power_mode;
|
||||
this->read_register(POWER_MODE_REGISTER, &power_mode, 1);
|
||||
if (power_mode == 0x00) {
|
||||
ESP_LOGCONFIG(TAG, "Waking up MICS 4514, sensors will have data after 3 minutes...");
|
||||
ESP_LOGCONFIG(TAG, "Waking up MICS 4514, sensors will have data after 3 minutes");
|
||||
power_mode = 0x01;
|
||||
this->write_register(POWER_MODE_REGISTER, &power_mode, 1);
|
||||
delay(100); // NOLINT
|
||||
|
||||
@@ -29,7 +29,7 @@ void MPU6050Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Power Management...");
|
||||
ESP_LOGV(TAG, " Setting up Power Management");
|
||||
// Setup power management
|
||||
uint8_t power_management;
|
||||
if (!this->read_byte(MPU6050_REGISTER_POWER_MANAGEMENT_1, &power_management)) {
|
||||
@@ -50,7 +50,7 @@ void MPU6050Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Gyro Config...");
|
||||
ESP_LOGV(TAG, " Setting up Gyro Config");
|
||||
// Set scale - 2000DPS
|
||||
uint8_t gyro_config;
|
||||
if (!this->read_byte(MPU6050_REGISTER_GYRO_CONFIG, &gyro_config)) {
|
||||
@@ -66,7 +66,7 @@ void MPU6050Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Accel Config...");
|
||||
ESP_LOGV(TAG, " Setting up Accel Config");
|
||||
// Set range - 2G
|
||||
uint8_t accel_config;
|
||||
if (!this->read_byte(MPU6050_REGISTER_ACCEL_CONFIG, &accel_config)) {
|
||||
@@ -99,7 +99,7 @@ void MPU6050Component::dump_config() {
|
||||
}
|
||||
|
||||
void MPU6050Component::update() {
|
||||
ESP_LOGV(TAG, " Updating MPU6050...");
|
||||
ESP_LOGV(TAG, "Updating");
|
||||
uint16_t raw_data[7];
|
||||
if (!this->read_bytes_16(MPU6050_REGISTER_ACCEL_XOUT_H, raw_data, 7)) {
|
||||
this->status_set_warning();
|
||||
|
||||
@@ -33,7 +33,7 @@ void MPU6886Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Power Management...");
|
||||
ESP_LOGV(TAG, " Setting up Power Management");
|
||||
// Setup power management
|
||||
uint8_t power_management;
|
||||
if (!this->read_byte(MPU6886_REGISTER_POWER_MANAGEMENT_1, &power_management)) {
|
||||
@@ -54,7 +54,7 @@ void MPU6886Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Gyroscope Config...");
|
||||
ESP_LOGV(TAG, " Setting up Gyroscope Config");
|
||||
// Set scale - 2000DPS
|
||||
uint8_t gyro_config;
|
||||
if (!this->read_byte(MPU6886_REGISTER_GYRO_CONFIG, &gyro_config)) {
|
||||
@@ -70,7 +70,7 @@ void MPU6886Component::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, " Setting up Accelerometer Config...");
|
||||
ESP_LOGV(TAG, " Setting up Accelerometer Config");
|
||||
// Set range - 2G
|
||||
uint8_t accel_config;
|
||||
if (!this->read_byte(MPU6886_REGISTER_ACCEL_CONFIG, &accel_config)) {
|
||||
@@ -104,7 +104,7 @@ void MPU6886Component::dump_config() {
|
||||
}
|
||||
|
||||
void MPU6886Component::update() {
|
||||
ESP_LOGV(TAG, " Updating MPU6886...");
|
||||
ESP_LOGV(TAG, " Updating");
|
||||
uint16_t raw_data[7];
|
||||
if (!this->read_bytes_16(MPU6886_REGISTER_ACCEL_XOUT_H, raw_data, 7)) {
|
||||
this->status_set_warning();
|
||||
|
||||
@@ -201,13 +201,13 @@ void MQTTClientComponent::start_dnslookup_() {
|
||||
}
|
||||
case ERR_INPROGRESS: {
|
||||
// wait for callback
|
||||
ESP_LOGD(TAG, "Resolving MQTT broker IP address...");
|
||||
ESP_LOGD(TAG, "Resolving broker IP address");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
case ERR_ARG: {
|
||||
// error
|
||||
ESP_LOGW(TAG, "Error resolving MQTT broker IP address: %d", err);
|
||||
ESP_LOGW(TAG, "Error resolving broker IP address: %d", err);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -221,7 +221,7 @@ void MQTTClientComponent::check_dnslookup_() {
|
||||
}
|
||||
|
||||
if (this->dns_resolve_error_) {
|
||||
ESP_LOGW(TAG, "Couldn't resolve IP address for '%s'!", this->credentials_.address.c_str());
|
||||
ESP_LOGW(TAG, "Couldn't resolve IP address for '%s'", this->credentials_.address.c_str());
|
||||
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
||||
return;
|
||||
}
|
||||
@@ -251,7 +251,7 @@ void MQTTClientComponent::start_connect_() {
|
||||
if (!network::is_connected())
|
||||
return;
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to MQTT...");
|
||||
ESP_LOGI(TAG, "Connecting");
|
||||
// Force disconnect first
|
||||
this->mqtt_backend_.disconnect();
|
||||
|
||||
@@ -292,7 +292,7 @@ void MQTTClientComponent::check_connected() {
|
||||
this->state_ = MQTT_CLIENT_CONNECTED;
|
||||
this->sent_birth_message_ = false;
|
||||
this->status_clear_warning();
|
||||
ESP_LOGI(TAG, "MQTT Connected!");
|
||||
ESP_LOGI(TAG, "Connected");
|
||||
// MQTT Client needs some time to be fully set up.
|
||||
delay(100); // NOLINT
|
||||
|
||||
@@ -341,7 +341,7 @@ void MQTTClientComponent::loop() {
|
||||
if (!network::is_connected()) {
|
||||
reason_s = LOG_STR("WiFi disconnected");
|
||||
}
|
||||
ESP_LOGW(TAG, "MQTT Disconnected: %s.", LOG_STR_ARG(reason_s));
|
||||
ESP_LOGW(TAG, "Disconnected: %s", LOG_STR_ARG(reason_s));
|
||||
this->disconnect_reason_.reset();
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ void MQTTClientComponent::loop() {
|
||||
case MQTT_CLIENT_CONNECTED:
|
||||
if (!this->mqtt_backend_.connected()) {
|
||||
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
||||
ESP_LOGW(TAG, "Lost MQTT Client connection!");
|
||||
ESP_LOGW(TAG, "Lost client connection");
|
||||
this->start_dnslookup_();
|
||||
} else {
|
||||
if (!this->birth_message_.topic.empty() && !this->sent_birth_message_) {
|
||||
@@ -378,7 +378,7 @@ void MQTTClientComponent::loop() {
|
||||
}
|
||||
|
||||
if (millis() - this->last_connected_ > this->reboot_timeout_ && this->reboot_timeout_ != 0) {
|
||||
ESP_LOGE(TAG, "Can't connect to MQTT... Restarting...");
|
||||
ESP_LOGE(TAG, "Can't connect; restarting");
|
||||
App.reboot();
|
||||
}
|
||||
}
|
||||
@@ -396,7 +396,7 @@ bool MQTTClientComponent::subscribe_(const char *topic, uint8_t qos) {
|
||||
ESP_LOGV(TAG, "subscribe(topic='%s')", topic);
|
||||
} else {
|
||||
delay(5);
|
||||
ESP_LOGV(TAG, "Subscribe failed for topic='%s'. Will retry later.", topic);
|
||||
ESP_LOGV(TAG, "Subscribe failed for topic='%s'. Will retry", topic);
|
||||
this->status_momentary_warning("subscribe", 1000);
|
||||
}
|
||||
return ret != 0;
|
||||
@@ -499,7 +499,7 @@ bool MQTTClientComponent::publish(const MQTTMessage &message) {
|
||||
ESP_LOGV(TAG, "Publish(topic='%s' payload='%s' retain=%d qos=%d)", message.topic.c_str(), message.payload.c_str(),
|
||||
message.retain, message.qos);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Publish failed for topic='%s' (len=%u). will retry later..", message.topic.c_str(),
|
||||
ESP_LOGV(TAG, "Publish failed for topic='%s' (len=%u). Will retry", message.topic.c_str(),
|
||||
message.payload.length());
|
||||
this->status_momentary_warning("publish", 1000);
|
||||
}
|
||||
@@ -515,7 +515,7 @@ bool MQTTClientComponent::publish_json(const std::string &topic, const json::jso
|
||||
void MQTTClientComponent::enable() {
|
||||
if (this->state_ != MQTT_CLIENT_DISABLED)
|
||||
return;
|
||||
ESP_LOGD(TAG, "Enabling MQTT...");
|
||||
ESP_LOGD(TAG, "Enabling");
|
||||
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
||||
this->last_connected_ = millis();
|
||||
this->start_dnslookup_();
|
||||
@@ -524,7 +524,7 @@ void MQTTClientComponent::enable() {
|
||||
void MQTTClientComponent::disable() {
|
||||
if (this->state_ == MQTT_CLIENT_DISABLED)
|
||||
return;
|
||||
ESP_LOGD(TAG, "Disabling MQTT...");
|
||||
ESP_LOGD(TAG, "Disabling");
|
||||
this->state_ = MQTT_CLIENT_DISABLED;
|
||||
this->on_shutdown();
|
||||
}
|
||||
|
||||
@@ -64,11 +64,11 @@ bool MQTTComponent::send_discovery_() {
|
||||
const MQTTDiscoveryInfo &discovery_info = global_mqtt_client->get_discovery_info();
|
||||
|
||||
if (discovery_info.clean) {
|
||||
ESP_LOGV(TAG, "'%s': Cleaning discovery...", this->friendly_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s': Cleaning discovery", this->friendly_name().c_str());
|
||||
return global_mqtt_client->publish(this->get_discovery_topic_(discovery_info), "", 0, this->qos_, true);
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "'%s': Sending discovery...", this->friendly_name().c_str());
|
||||
ESP_LOGV(TAG, "'%s': Sending discovery", this->friendly_name().c_str());
|
||||
|
||||
return global_mqtt_client->publish_json(
|
||||
this->get_discovery_topic_(discovery_info),
|
||||
|
||||
@@ -248,10 +248,10 @@ void MSA3xxComponent::loop() {
|
||||
}
|
||||
|
||||
void MSA3xxComponent::update() {
|
||||
ESP_LOGV(TAG, "Updating MSA3xx...");
|
||||
ESP_LOGV(TAG, "Updating");
|
||||
|
||||
if (!this->is_ready()) {
|
||||
ESP_LOGV(TAG, "Component MSA3xx not ready for update");
|
||||
ESP_LOGV(TAG, "Not ready for update");
|
||||
return;
|
||||
}
|
||||
ESP_LOGV(TAG, "Acceleration: {x = %+1.3f m/s², y = %+1.3f m/s², z = %+1.3f m/s²}; ", this->data_.x, this->data_.y,
|
||||
|
||||
@@ -14,6 +14,7 @@ CONF_COMPONENT_NAME = "component_name"
|
||||
CONF_EXIT_REPARSE_ON_START = "exit_reparse_on_start"
|
||||
CONF_FONT_ID = "font_id"
|
||||
CONF_FOREGROUND_PRESSED_COLOR = "foreground_pressed_color"
|
||||
CONF_MAX_QUEUE_SIZE = "max_queue_size"
|
||||
CONF_ON_BUFFER_OVERFLOW = "on_buffer_overflow"
|
||||
CONF_ON_PAGE = "on_page"
|
||||
CONF_ON_SETUP = "on_setup"
|
||||
|
||||
@@ -16,6 +16,7 @@ from .base_component import (
|
||||
CONF_AUTO_WAKE_ON_TOUCH,
|
||||
CONF_COMMAND_SPACING,
|
||||
CONF_EXIT_REPARSE_ON_START,
|
||||
CONF_MAX_QUEUE_SIZE,
|
||||
CONF_ON_BUFFER_OVERFLOW,
|
||||
CONF_ON_SETUP,
|
||||
CONF_ON_SLEEP,
|
||||
@@ -93,6 +94,7 @@ CONFIG_SCHEMA = (
|
||||
cv.positive_time_period_milliseconds,
|
||||
cv.Range(max=TimePeriod(milliseconds=255)),
|
||||
),
|
||||
cv.Optional(CONF_MAX_QUEUE_SIZE): cv.positive_int,
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("5s"))
|
||||
@@ -125,6 +127,10 @@ async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await uart.register_uart_device(var, config)
|
||||
|
||||
if max_queue_size := config.get(CONF_MAX_QUEUE_SIZE):
|
||||
cg.add_define("USE_NEXTION_MAX_QUEUE_SIZE")
|
||||
cg.add(var.set_max_queue_size(max_queue_size))
|
||||
|
||||
if command_spacing := config.get(CONF_COMMAND_SPACING):
|
||||
cg.add_define("USE_NEXTION_COMMAND_SPACING")
|
||||
cg.add(var.set_command_spacing(command_spacing.total_milliseconds))
|
||||
|
||||
@@ -173,6 +173,10 @@ void Nextion::dump_config() {
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
ESP_LOGCONFIG(TAG, " Command spacing: %" PRIu8 "ms", this->command_pacer_.get_spacing());
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
ESP_LOGCONFIG(TAG, " Max queue size: %zu", this->max_queue_size_);
|
||||
#endif
|
||||
}
|
||||
|
||||
float Nextion::get_setup_priority() const { return setup_priority::DATA; }
|
||||
@@ -998,13 +1002,31 @@ uint16_t Nextion::recv_ret_string_(std::string &response, uint32_t timeout, bool
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @brief Add a command to the Nextion queue that expects no response.
|
||||
*
|
||||
* @param variable_name Name for the queue
|
||||
* This is typically used for write-only operations such as variable assignments or component updates
|
||||
* where no return value or acknowledgment is expected from the display.
|
||||
*
|
||||
* If the `max_queue_size` limit is configured and reached, the command will be skipped.
|
||||
*
|
||||
* @param variable_name Name of the variable or component associated with the command.
|
||||
*/
|
||||
void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||
nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
if (this->max_queue_size_ > 0 && this->nextion_queue_.size() >= this->max_queue_size_) {
|
||||
ESP_LOGW(TAG, "Nextion queue full (%zu entries), dropping NORESULT command: %s", this->nextion_queue_.size(),
|
||||
variable_name.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Failed to allocate NextionQueue");
|
||||
return;
|
||||
}
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||
nextion_queue->component = new nextion::NextionComponentBase;
|
||||
@@ -1133,12 +1155,34 @@ void Nextion::add_no_result_to_queue_with_set_internal_(const std::string &varia
|
||||
state_value.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Queue a GET command for a component that expects a response from the Nextion display.
|
||||
*
|
||||
* This method is used for querying values such as sensor states, text content, or switch status.
|
||||
* The component will be added to the Nextion queue only if the display is already set up,
|
||||
* the queue has not reached the configured maximum size (if set), and the command is sent successfully.
|
||||
*
|
||||
* @param component Pointer to the Nextion component that will handle the response.
|
||||
*/
|
||||
void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
||||
if ((!this->is_setup() && !this->ignore_is_setup_))
|
||||
return;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||
nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
if (this->max_queue_size_ > 0 && this->nextion_queue_.size() >= this->max_queue_size_) {
|
||||
ESP_LOGW(TAG, "Nextion queue full (%zu entries), dropping GET for \"%s\"", this->nextion_queue_.size(),
|
||||
component->get_variable_name().c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Failed to allocate NextionQueue");
|
||||
return;
|
||||
}
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = component;
|
||||
nextion_queue->queue_time = millis();
|
||||
@@ -1165,8 +1209,13 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) {
|
||||
if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
|
||||
return;
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||
nextion::NextionQueue *nextion_queue = new nextion::NextionQueue;
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Failed to allocate NextionQueue");
|
||||
return;
|
||||
}
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = component;
|
||||
nextion_queue->queue_time = millis();
|
||||
|
||||
@@ -75,6 +75,20 @@ class NextionCommandPacer {
|
||||
|
||||
class Nextion : public NextionBase, public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
/**
|
||||
* @brief Set the maximum allowed queue size
|
||||
* @param size Max number of entries allowed in nextion_queue_
|
||||
*/
|
||||
inline void set_max_queue_size(size_t size) { this->max_queue_size_ = size; }
|
||||
|
||||
/**
|
||||
* @brief Get the maximum allowed queue size
|
||||
* @return Current limit (0 = unlimited)
|
||||
*/
|
||||
inline size_t get_max_queue_size() const { return this->max_queue_size_; }
|
||||
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
/**
|
||||
* @brief Set the command spacing for the display
|
||||
@@ -1273,6 +1287,9 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
bool is_connected() { return this->is_connected_; }
|
||||
|
||||
protected:
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
size_t max_queue_size_{0};
|
||||
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
NextionCommandPacer command_pacer_{0};
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
@@ -249,7 +249,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding...");
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding");
|
||||
}
|
||||
this->content_length_ = this->tft_size_;
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding...");
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding");
|
||||
}
|
||||
this->content_length_ = this->tft_size_;
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ void OnlineImage::draw(int x, int y, display::Display *display, Color color_on,
|
||||
|
||||
void OnlineImage::release() {
|
||||
if (this->buffer_) {
|
||||
ESP_LOGV(TAG, "Deallocating old buffer...");
|
||||
ESP_LOGV(TAG, "Deallocating old buffer");
|
||||
this->allocator_.deallocate(this->buffer_, this->get_buffer_size_());
|
||||
this->data_start_ = nullptr;
|
||||
this->buffer_ = nullptr;
|
||||
|
||||
@@ -28,7 +28,7 @@ static const uint8_t PCA9685_MODE1_SLEEP = 0b00010000;
|
||||
void PCA9685Output::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
|
||||
ESP_LOGV(TAG, " Resetting devices...");
|
||||
ESP_LOGV(TAG, " Resetting devices");
|
||||
if (!this->write_bytes(PCA9685_REGISTER_SOFTWARE_RESET, nullptr, 0)) {
|
||||
this->mark_failed();
|
||||
return;
|
||||
|
||||
@@ -19,7 +19,7 @@ void PN532::setup() {
|
||||
|
||||
// Get version data
|
||||
if (!this->write_command_({PN532_COMMAND_VERSION_DATA})) {
|
||||
ESP_LOGW(TAG, "Error sending version command, trying again...");
|
||||
ESP_LOGW(TAG, "Error sending version command, trying again");
|
||||
if (!this->write_command_({PN532_COMMAND_VERSION_DATA})) {
|
||||
ESP_LOGE(TAG, "Error sending version command");
|
||||
this->mark_failed();
|
||||
@@ -208,21 +208,21 @@ void PN532::loop() {
|
||||
}
|
||||
}
|
||||
} else if (next_task_ == CLEAN) {
|
||||
ESP_LOGD(TAG, " Tag cleaning...");
|
||||
ESP_LOGD(TAG, " Tag cleaning");
|
||||
if (!this->clean_tag_(nfcid)) {
|
||||
ESP_LOGE(TAG, " Tag was not fully cleaned successfully");
|
||||
}
|
||||
ESP_LOGD(TAG, " Tag cleaned!");
|
||||
} else if (next_task_ == FORMAT) {
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (!this->format_tag_(nfcid)) {
|
||||
ESP_LOGE(TAG, "Error formatting tag as NDEF");
|
||||
}
|
||||
ESP_LOGD(TAG, " Tag formatted!");
|
||||
} else if (next_task_ == WRITE) {
|
||||
if (this->next_task_message_to_write_ != nullptr) {
|
||||
ESP_LOGD(TAG, " Tag writing...");
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag writing");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (!this->format_tag_(nfcid)) {
|
||||
ESP_LOGE(TAG, " Tag could not be formatted for writing");
|
||||
} else {
|
||||
@@ -281,7 +281,7 @@ bool PN532::write_command_(const std::vector<uint8_t> &data) {
|
||||
}
|
||||
|
||||
bool PN532::read_ack_() {
|
||||
ESP_LOGV(TAG, "Reading ACK...");
|
||||
ESP_LOGV(TAG, "Reading ACK");
|
||||
|
||||
std::vector<uint8_t> data;
|
||||
if (!this->read_data(data, 6)) {
|
||||
|
||||
@@ -51,7 +51,7 @@ bool PN532Spi::read_data(std::vector<uint8_t> &data, uint8_t len) {
|
||||
delay(2);
|
||||
this->write_byte(0x03);
|
||||
|
||||
ESP_LOGV(TAG, "Reading data...");
|
||||
ESP_LOGV(TAG, "Reading data");
|
||||
|
||||
data.resize(len);
|
||||
this->read_array(data.data(), len);
|
||||
|
||||
@@ -830,7 +830,7 @@ void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
|
||||
switch (this->next_task_) {
|
||||
case EP_CLEAN:
|
||||
ESP_LOGD(TAG, " Tag cleaning...");
|
||||
ESP_LOGD(TAG, " Tag cleaning");
|
||||
if (this->clean_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, " Tag cleaning incomplete");
|
||||
}
|
||||
@@ -838,7 +838,7 @@ void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
break;
|
||||
|
||||
case EP_FORMAT:
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, "Error formatting tag as NDEF");
|
||||
}
|
||||
@@ -847,8 +847,8 @@ void PN7150::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
|
||||
case EP_WRITE:
|
||||
if (this->next_task_message_to_write_ != nullptr) {
|
||||
ESP_LOGD(TAG, " Tag writing...");
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag writing");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, " Tag could not be formatted for writing");
|
||||
} else {
|
||||
|
||||
@@ -854,7 +854,7 @@ void PN7160::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
|
||||
switch (this->next_task_) {
|
||||
case EP_CLEAN:
|
||||
ESP_LOGD(TAG, " Tag cleaning...");
|
||||
ESP_LOGD(TAG, " Tag cleaning");
|
||||
if (this->clean_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, " Tag cleaning incomplete");
|
||||
}
|
||||
@@ -862,7 +862,7 @@ void PN7160::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
break;
|
||||
|
||||
case EP_FORMAT:
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, "Error formatting tag as NDEF");
|
||||
}
|
||||
@@ -871,8 +871,8 @@ void PN7160::process_rf_intf_activated_oid_(nfc::NciMessage &rx) { // an endpoi
|
||||
|
||||
case EP_WRITE:
|
||||
if (this->next_task_message_to_write_ != nullptr) {
|
||||
ESP_LOGD(TAG, " Tag writing...");
|
||||
ESP_LOGD(TAG, " Tag formatting...");
|
||||
ESP_LOGD(TAG, " Tag writing");
|
||||
ESP_LOGD(TAG, " Tag formatting");
|
||||
if (this->format_endpoint_(working_endpoint.tag->get_uid()) != nfc::STATUS_OK) {
|
||||
ESP_LOGE(TAG, " Tag could not be formatted for writing");
|
||||
} else {
|
||||
|
||||
@@ -24,7 +24,7 @@ void QrCode::set_ecc(qrcodegen_Ecc ecc) {
|
||||
}
|
||||
|
||||
void QrCode::generate_qr_code() {
|
||||
ESP_LOGV(TAG, "Generating QR code...");
|
||||
ESP_LOGV(TAG, "Generating QR code");
|
||||
uint8_t tempbuffer[qrcodegen_BUFFER_LEN_MAX];
|
||||
|
||||
if (!qrcodegen_encodeText(this->value_.c_str(), tempbuffer, this->qr_, this->ecc_, qrcodegen_VERSION_MIN,
|
||||
|
||||
@@ -46,7 +46,7 @@ void RC522::setup() {
|
||||
reset_pin_->pin_mode(gpio::FLAG_INPUT);
|
||||
|
||||
if (!reset_pin_->digital_read()) { // The MFRC522 chip is in power down mode.
|
||||
ESP_LOGV(TAG, "Power down mode detected. Hard resetting...");
|
||||
ESP_LOGV(TAG, "Power down mode detected. Hard resetting");
|
||||
reset_pin_->pin_mode(gpio::FLAG_OUTPUT); // Now set the resetPowerDownPin as digital output.
|
||||
reset_pin_->digital_write(false); // Make sure we have a clean LOW state.
|
||||
delayMicroseconds(2); // 8.8.1 Reset timing requirements says about 100ns. Let us be generous: 2μsl
|
||||
@@ -101,7 +101,7 @@ void RC522::dump_config() {
|
||||
case NONE:
|
||||
break;
|
||||
case RESET_FAILED:
|
||||
ESP_LOGE(TAG, "Reset command failed!");
|
||||
ESP_LOGE(TAG, "Reset command failed");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -292,7 +292,7 @@ void RC522::pcd_reset_() {
|
||||
return;
|
||||
|
||||
if (reset_count_ == RESET_COUNT) {
|
||||
ESP_LOGI(TAG, "Soft reset...");
|
||||
ESP_LOGI(TAG, "Soft reset");
|
||||
// Issue the SoftReset command.
|
||||
pcd_write_register(COMMAND_REG, PCD_SOFT_RESET);
|
||||
}
|
||||
@@ -300,14 +300,14 @@ void RC522::pcd_reset_() {
|
||||
// Expect the PowerDown bit in CommandReg to be cleared (max 3x50ms)
|
||||
if ((pcd_read_register(COMMAND_REG) & (1 << 4)) == 0) {
|
||||
reset_count_ = 0;
|
||||
ESP_LOGI(TAG, "Device online.");
|
||||
ESP_LOGI(TAG, "Device online");
|
||||
// Wait for initialize
|
||||
reset_timeout_ = millis();
|
||||
return;
|
||||
}
|
||||
|
||||
if (--reset_count_ == 0) {
|
||||
ESP_LOGE(TAG, "Unable to reset RC522.");
|
||||
ESP_LOGE(TAG, "Unable to reset");
|
||||
this->error_code_ = RESET_FAILED;
|
||||
mark_failed();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user