mirror of
https://github.com/esphome/esphome.git
synced 2025-10-05 19:33:47 +01:00
Merge branch 'message_creator_ram' into integration
This commit is contained in:
@@ -12,7 +12,7 @@ repos:
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 7.2.0
|
||||
rev: 7.3.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies:
|
||||
|
@@ -323,6 +323,7 @@ esphome/components/one_wire/* @ssieb
|
||||
esphome/components/online_image/* @clydebarrow @guillempages
|
||||
esphome/components/opentherm/* @olegtarasov
|
||||
esphome/components/openthread/* @mrene
|
||||
esphome/components/opt3001/* @ccutrer
|
||||
esphome/components/ota/* @esphome/core
|
||||
esphome/components/output/* @esphome/core
|
||||
esphome/components/packet_transport/* @clydebarrow
|
||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -149,6 +149,9 @@ _ALARM_CONTROL_PANEL_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_ALARM_CONTROL_PANEL_SCHEMA.add_extra(entity_duplicate_validator("alarm_control_panel"))
|
||||
|
||||
|
||||
def alarm_control_panel_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -190,7 +193,7 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id(
|
||||
|
||||
|
||||
async def setup_alarm_control_panel_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "alarm_control_panel")
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
@@ -188,6 +188,17 @@ message DeviceInfoRequest {
|
||||
// Empty
|
||||
}
|
||||
|
||||
message AreaInfo {
|
||||
uint32 area_id = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
message DeviceInfo {
|
||||
uint32 device_id = 1;
|
||||
string name = 2;
|
||||
uint32 area_id = 3;
|
||||
}
|
||||
|
||||
message DeviceInfoResponse {
|
||||
option (id) = 10;
|
||||
option (source) = SOURCE_SERVER;
|
||||
@@ -236,6 +247,12 @@ message DeviceInfoResponse {
|
||||
|
||||
// Supports receiving and saving api encryption key
|
||||
bool api_encryption_supported = 19;
|
||||
|
||||
repeated DeviceInfo devices = 20;
|
||||
repeated AreaInfo areas = 21;
|
||||
|
||||
// Top-level area info to phase out suggested_area
|
||||
AreaInfo area = 22;
|
||||
}
|
||||
|
||||
message ListEntitiesRequest {
|
||||
@@ -280,6 +297,7 @@ message ListEntitiesBinarySensorResponse {
|
||||
bool disabled_by_default = 7;
|
||||
string icon = 8;
|
||||
EntityCategory entity_category = 9;
|
||||
uint32 device_id = 10;
|
||||
}
|
||||
message BinarySensorStateResponse {
|
||||
option (id) = 21;
|
||||
@@ -315,6 +333,7 @@ message ListEntitiesCoverResponse {
|
||||
string icon = 10;
|
||||
EntityCategory entity_category = 11;
|
||||
bool supports_stop = 12;
|
||||
uint32 device_id = 13;
|
||||
}
|
||||
|
||||
enum LegacyCoverState {
|
||||
@@ -388,6 +407,7 @@ message ListEntitiesFanResponse {
|
||||
string icon = 10;
|
||||
EntityCategory entity_category = 11;
|
||||
repeated string supported_preset_modes = 12;
|
||||
uint32 device_id = 13;
|
||||
}
|
||||
enum FanSpeed {
|
||||
FAN_SPEED_LOW = 0;
|
||||
@@ -471,6 +491,7 @@ message ListEntitiesLightResponse {
|
||||
bool disabled_by_default = 13;
|
||||
string icon = 14;
|
||||
EntityCategory entity_category = 15;
|
||||
uint32 device_id = 16;
|
||||
}
|
||||
message LightStateResponse {
|
||||
option (id) = 24;
|
||||
@@ -563,6 +584,7 @@ message ListEntitiesSensorResponse {
|
||||
SensorLastResetType legacy_last_reset_type = 11;
|
||||
bool disabled_by_default = 12;
|
||||
EntityCategory entity_category = 13;
|
||||
uint32 device_id = 14;
|
||||
}
|
||||
message SensorStateResponse {
|
||||
option (id) = 25;
|
||||
@@ -595,6 +617,7 @@ message ListEntitiesSwitchResponse {
|
||||
bool disabled_by_default = 7;
|
||||
EntityCategory entity_category = 8;
|
||||
string device_class = 9;
|
||||
uint32 device_id = 10;
|
||||
}
|
||||
message SwitchStateResponse {
|
||||
option (id) = 26;
|
||||
@@ -632,6 +655,7 @@ message ListEntitiesTextSensorResponse {
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
string device_class = 8;
|
||||
uint32 device_id = 9;
|
||||
}
|
||||
message TextSensorStateResponse {
|
||||
option (id) = 27;
|
||||
@@ -814,6 +838,7 @@ message ListEntitiesCameraResponse {
|
||||
bool disabled_by_default = 5;
|
||||
string icon = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
uint32 device_id = 8;
|
||||
}
|
||||
|
||||
message CameraImageResponse {
|
||||
@@ -916,6 +941,7 @@ message ListEntitiesClimateResponse {
|
||||
bool supports_target_humidity = 23;
|
||||
float visual_min_humidity = 24;
|
||||
float visual_max_humidity = 25;
|
||||
uint32 device_id = 26;
|
||||
}
|
||||
message ClimateStateResponse {
|
||||
option (id) = 47;
|
||||
@@ -999,6 +1025,7 @@ message ListEntitiesNumberResponse {
|
||||
string unit_of_measurement = 11;
|
||||
NumberMode mode = 12;
|
||||
string device_class = 13;
|
||||
uint32 device_id = 14;
|
||||
}
|
||||
message NumberStateResponse {
|
||||
option (id) = 50;
|
||||
@@ -1039,6 +1066,7 @@ message ListEntitiesSelectResponse {
|
||||
repeated string options = 6;
|
||||
bool disabled_by_default = 7;
|
||||
EntityCategory entity_category = 8;
|
||||
uint32 device_id = 9;
|
||||
}
|
||||
message SelectStateResponse {
|
||||
option (id) = 53;
|
||||
@@ -1081,6 +1109,7 @@ message ListEntitiesSirenResponse {
|
||||
bool supports_duration = 8;
|
||||
bool supports_volume = 9;
|
||||
EntityCategory entity_category = 10;
|
||||
uint32 device_id = 11;
|
||||
}
|
||||
message SirenStateResponse {
|
||||
option (id) = 56;
|
||||
@@ -1144,6 +1173,7 @@ message ListEntitiesLockResponse {
|
||||
|
||||
// Not yet implemented:
|
||||
string code_format = 11;
|
||||
uint32 device_id = 12;
|
||||
}
|
||||
message LockStateResponse {
|
||||
option (id) = 59;
|
||||
@@ -1183,6 +1213,7 @@ message ListEntitiesButtonResponse {
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
string device_class = 8;
|
||||
uint32 device_id = 9;
|
||||
}
|
||||
message ButtonCommandRequest {
|
||||
option (id) = 62;
|
||||
@@ -1238,6 +1269,8 @@ message ListEntitiesMediaPlayerResponse {
|
||||
bool supports_pause = 8;
|
||||
|
||||
repeated MediaPlayerSupportedFormat supported_formats = 9;
|
||||
|
||||
uint32 device_id = 10;
|
||||
}
|
||||
message MediaPlayerStateResponse {
|
||||
option (id) = 64;
|
||||
@@ -1778,6 +1811,7 @@ message ListEntitiesAlarmControlPanelResponse {
|
||||
uint32 supported_features = 8;
|
||||
bool requires_code = 9;
|
||||
bool requires_code_to_arm = 10;
|
||||
uint32 device_id = 11;
|
||||
}
|
||||
|
||||
message AlarmControlPanelStateResponse {
|
||||
@@ -1823,6 +1857,7 @@ message ListEntitiesTextResponse {
|
||||
uint32 max_length = 9;
|
||||
string pattern = 10;
|
||||
TextMode mode = 11;
|
||||
uint32 device_id = 12;
|
||||
}
|
||||
message TextStateResponse {
|
||||
option (id) = 98;
|
||||
@@ -1863,6 +1898,7 @@ message ListEntitiesDateResponse {
|
||||
string icon = 5;
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
uint32 device_id = 8;
|
||||
}
|
||||
message DateStateResponse {
|
||||
option (id) = 101;
|
||||
@@ -1906,6 +1942,7 @@ message ListEntitiesTimeResponse {
|
||||
string icon = 5;
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
uint32 device_id = 8;
|
||||
}
|
||||
message TimeStateResponse {
|
||||
option (id) = 104;
|
||||
@@ -1952,6 +1989,7 @@ message ListEntitiesEventResponse {
|
||||
string device_class = 8;
|
||||
|
||||
repeated string event_types = 9;
|
||||
uint32 device_id = 10;
|
||||
}
|
||||
message EventResponse {
|
||||
option (id) = 108;
|
||||
@@ -1983,6 +2021,7 @@ message ListEntitiesValveResponse {
|
||||
bool assumed_state = 9;
|
||||
bool supports_position = 10;
|
||||
bool supports_stop = 11;
|
||||
uint32 device_id = 12;
|
||||
}
|
||||
|
||||
enum ValveOperation {
|
||||
@@ -2029,6 +2068,7 @@ message ListEntitiesDateTimeResponse {
|
||||
string icon = 5;
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
uint32 device_id = 8;
|
||||
}
|
||||
message DateTimeStateResponse {
|
||||
option (id) = 113;
|
||||
@@ -2069,6 +2109,7 @@ message ListEntitiesUpdateResponse {
|
||||
bool disabled_by_default = 6;
|
||||
EntityCategory entity_category = 7;
|
||||
string device_class = 8;
|
||||
uint32 device_id = 9;
|
||||
}
|
||||
message UpdateStateResponse {
|
||||
option (id) = 117;
|
||||
|
@@ -1440,7 +1440,7 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
|
||||
|
||||
#ifdef USE_EVENT
|
||||
void APIConnection::send_event(event::Event *event, const std::string &event_type) {
|
||||
this->schedule_message_(event, MessageCreator(event_type, EventResponse::MESSAGE_TYPE), EventResponse::MESSAGE_TYPE);
|
||||
this->schedule_message_(event, MessageCreator(event_type), EventResponse::MESSAGE_TYPE);
|
||||
}
|
||||
void APIConnection::send_event_info(event::Event *event) {
|
||||
this->schedule_message_(event, &APIConnection::try_send_event_info, ListEntitiesEventResponse::MESSAGE_TYPE);
|
||||
@@ -1629,6 +1629,23 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
||||
#endif
|
||||
#ifdef USE_API_NOISE
|
||||
resp.api_encryption_supported = true;
|
||||
#endif
|
||||
#ifdef USE_DEVICES
|
||||
for (auto const &device : App.get_devices()) {
|
||||
DeviceInfo device_info;
|
||||
device_info.device_id = device->get_device_id();
|
||||
device_info.name = device->get_name();
|
||||
device_info.area_id = device->get_area_id();
|
||||
resp.devices.push_back(device_info);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AREAS
|
||||
for (auto const &area : App.get_areas()) {
|
||||
AreaInfo area_info;
|
||||
area_info.area_id = area->get_area_id();
|
||||
area_info.name = area->get_name();
|
||||
resp.areas.push_back(area_info);
|
||||
}
|
||||
#endif
|
||||
return resp;
|
||||
}
|
||||
@@ -1778,7 +1795,8 @@ void APIConnection::process_batch_() {
|
||||
const auto &item = this->deferred_batch_.items[0];
|
||||
|
||||
// Let the creator calculate size and encode if it fits
|
||||
uint16_t payload_size = item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true);
|
||||
uint16_t payload_size =
|
||||
item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type);
|
||||
|
||||
if (payload_size > 0 &&
|
||||
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
|
||||
@@ -1828,7 +1846,7 @@ void APIConnection::process_batch_() {
|
||||
for (const auto &item : this->deferred_batch_.items) {
|
||||
// Try to encode message
|
||||
// The creator will calculate overhead to determine if the message fits
|
||||
uint16_t payload_size = item.creator(item.entity, this, remaining_size, false);
|
||||
uint16_t payload_size = item.creator(item.entity, this, remaining_size, false, item.message_type);
|
||||
|
||||
if (payload_size == 0) {
|
||||
// Message won't fit, stop processing
|
||||
@@ -1891,22 +1909,24 @@ void APIConnection::process_batch_() {
|
||||
}
|
||||
|
||||
uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
bool is_single) const {
|
||||
switch (message_type_) {
|
||||
case 0: // Function pointer
|
||||
return data_.ptr(entity, conn, remaining_size, is_single);
|
||||
|
||||
bool is_single, uint16_t message_type) const {
|
||||
if (is_string()) {
|
||||
// Handle string-based messages
|
||||
switch (message_type) {
|
||||
#ifdef USE_EVENT
|
||||
case EventResponse::MESSAGE_TYPE: {
|
||||
auto *e = static_cast<event::Event *>(entity);
|
||||
return APIConnection::try_send_event_response(e, *data_.string_ptr, conn, remaining_size, is_single);
|
||||
return APIConnection::try_send_event_response(e, *get_string_ptr(), conn, remaining_size, is_single);
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
// Should not happen, return 0 to indicate no message
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
// Function pointer case
|
||||
return data_.ptr(entity, conn, remaining_size, is_single);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t APIConnection::try_send_list_info_done(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||
|
@@ -301,6 +301,9 @@ 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());
|
||||
#ifdef USE_DEVICES
|
||||
response.device_id = entity->get_device_id();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper function to fill common entity state fields
|
||||
@@ -480,55 +483,57 @@ class APIConnection : public APIServerConnection {
|
||||
// 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
|
||||
// Optimized MessageCreator class using tagged pointer
|
||||
class MessageCreator {
|
||||
// Ensure pointer alignment allows LSB tagging
|
||||
static_assert(alignof(std::string *) > 1, "String pointer alignment must be > 1 for LSB tagging");
|
||||
|
||||
public:
|
||||
// Constructor for function pointer (message_type = 0)
|
||||
MessageCreator(MessageCreatorPtr ptr) : message_type_(0) { data_.ptr = ptr; }
|
||||
// Constructor for function pointer
|
||||
MessageCreator(MessageCreatorPtr ptr) {
|
||||
// Function pointers are always aligned, so LSB is 0
|
||||
data_.ptr = ptr;
|
||||
}
|
||||
|
||||
// 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);
|
||||
explicit MessageCreator(const std::string &str_value) {
|
||||
// Allocate string and tag the pointer
|
||||
auto *str = new std::string(str_value);
|
||||
// Set LSB to 1 to indicate string pointer
|
||||
data_.tagged = reinterpret_cast<uintptr_t>(str) | 1;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
~MessageCreator() {
|
||||
// Clean up string data for string-based message types
|
||||
if (uses_string_data_()) {
|
||||
delete data_.string_ptr;
|
||||
if (has_tagged_string_ptr()) {
|
||||
delete get_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);
|
||||
MessageCreator(const MessageCreator &other) {
|
||||
if (other.has_tagged_string_ptr()) {
|
||||
auto *str = new std::string(*other.get_string_ptr());
|
||||
data_.tagged = reinterpret_cast<uintptr_t>(str) | 1;
|
||||
} else {
|
||||
data_ = other.data_; // For POD types
|
||||
data_ = other.data_;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
MessageCreator(MessageCreator &&other) noexcept : data_(other.data_) { 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;
|
||||
if (has_tagged_string_ptr()) {
|
||||
delete get_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);
|
||||
if (other.has_tagged_string_ptr()) {
|
||||
auto *str = new std::string(*other.get_string_ptr());
|
||||
data_.tagged = reinterpret_cast<uintptr_t>(str) | 1;
|
||||
} else {
|
||||
data_ = other.data_;
|
||||
}
|
||||
@@ -539,30 +544,32 @@ class APIConnection : public APIServerConnection {
|
||||
MessageCreator &operator=(MessageCreator &&other) noexcept {
|
||||
if (this != &other) {
|
||||
// Clean up current string data if needed
|
||||
if (uses_string_data_()) {
|
||||
delete data_.string_ptr;
|
||||
if (has_tagged_string_ptr()) {
|
||||
delete get_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;
|
||||
// Call operator - now accepts message_type as parameter
|
||||
uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single,
|
||||
uint16_t message_type) const;
|
||||
|
||||
private:
|
||||
// Helper to check if this message type uses heap-allocated strings
|
||||
bool uses_string_data_() const { return message_type_ == EventResponse::MESSAGE_TYPE; }
|
||||
union CreatorData {
|
||||
MessageCreatorPtr ptr; // 8 bytes
|
||||
std::string *string_ptr; // 8 bytes
|
||||
} data_; // 8 bytes
|
||||
uint16_t message_type_; // 2 bytes (0 = function ptr, >0 = state capture)
|
||||
// Check if this contains a string pointer
|
||||
bool has_tagged_string_ptr() const { return (data_.tagged & 1) != 0; }
|
||||
|
||||
// Get the actual string pointer (clears the tag bit)
|
||||
std::string *get_string_ptr() const { return reinterpret_cast<std::string *>(data_.tagged & ~uintptr_t(1)); }
|
||||
|
||||
union {
|
||||
MessageCreatorPtr ptr;
|
||||
uintptr_t tagged;
|
||||
} data_; // 4 bytes on 32-bit
|
||||
};
|
||||
|
||||
// Generic batching mechanism for both state updates and entity info
|
||||
|
@@ -812,6 +812,103 @@ void PingResponse::dump_to(std::string &out) const { out.append("PingResponse {}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
|
||||
#endif
|
||||
bool AreaInfo::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
this->area_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool AreaInfo::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->name = value.as_string();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void AreaInfo::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint32(1, this->area_id);
|
||||
buffer.encode_string(2, this->name);
|
||||
}
|
||||
void AreaInfo::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->area_id, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->name, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void AreaInfo::dump_to(std::string &out) const {
|
||||
__attribute__((unused)) char buffer[64];
|
||||
out.append("AreaInfo {\n");
|
||||
out.append(" area_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->area_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
|
||||
out.append(" name: ");
|
||||
out.append("'").append(this->name).append("'");
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
bool DeviceInfo::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
case 3: {
|
||||
this->area_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool DeviceInfo::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->name = value.as_string();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
void DeviceInfo::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint32(1, this->device_id);
|
||||
buffer.encode_string(2, this->name);
|
||||
buffer.encode_uint32(3, this->area_id);
|
||||
}
|
||||
void DeviceInfo::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->name, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->area_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void DeviceInfo::dump_to(std::string &out) const {
|
||||
__attribute__((unused)) char buffer[64];
|
||||
out.append("DeviceInfo {\n");
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
|
||||
out.append(" name: ");
|
||||
out.append("'").append(this->name).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" area_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->area_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
@@ -896,6 +993,18 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
|
||||
this->bluetooth_mac_address = value.as_string();
|
||||
return true;
|
||||
}
|
||||
case 20: {
|
||||
this->devices.push_back(value.as_message<DeviceInfo>());
|
||||
return true;
|
||||
}
|
||||
case 21: {
|
||||
this->areas.push_back(value.as_message<AreaInfo>());
|
||||
return true;
|
||||
}
|
||||
case 22: {
|
||||
this->area = value.as_message<AreaInfo>();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -920,6 +1029,13 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(16, this->suggested_area);
|
||||
buffer.encode_string(18, this->bluetooth_mac_address);
|
||||
buffer.encode_bool(19, this->api_encryption_supported);
|
||||
for (auto &it : this->devices) {
|
||||
buffer.encode_message<DeviceInfo>(20, it, true);
|
||||
}
|
||||
for (auto &it : this->areas) {
|
||||
buffer.encode_message<AreaInfo>(21, it, true);
|
||||
}
|
||||
buffer.encode_message<AreaInfo>(22, this->area);
|
||||
}
|
||||
void DeviceInfoResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->uses_password, false);
|
||||
@@ -941,6 +1057,9 @@ void DeviceInfoResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 2, this->suggested_area, false);
|
||||
ProtoSize::add_string_field(total_size, 2, this->bluetooth_mac_address, false);
|
||||
ProtoSize::add_bool_field(total_size, 2, this->api_encryption_supported, false);
|
||||
ProtoSize::add_repeated_message(total_size, 2, this->devices);
|
||||
ProtoSize::add_repeated_message(total_size, 2, this->areas);
|
||||
ProtoSize::add_message_object(total_size, 2, this->area, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void DeviceInfoResponse::dump_to(std::string &out) const {
|
||||
@@ -1026,6 +1145,22 @@ void DeviceInfoResponse::dump_to(std::string &out) const {
|
||||
out.append(" api_encryption_supported: ");
|
||||
out.append(YESNO(this->api_encryption_supported));
|
||||
out.append("\n");
|
||||
|
||||
for (const auto &it : this->devices) {
|
||||
out.append(" devices: ");
|
||||
it.dump_to(out);
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
for (const auto &it : this->areas) {
|
||||
out.append(" areas: ");
|
||||
it.dump_to(out);
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
out.append(" area: ");
|
||||
this->area.dump_to(out);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -1052,6 +1187,10 @@ bool ListEntitiesBinarySensorResponse::decode_varint(uint32_t field_id, ProtoVar
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 10: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1102,6 +1241,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(7, this->disabled_by_default);
|
||||
buffer.encode_string(8, this->icon);
|
||||
buffer.encode_enum<enums::EntityCategory>(9, this->entity_category);
|
||||
buffer.encode_uint32(10, this->device_id);
|
||||
}
|
||||
void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -1113,6 +1253,7 @@ void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) cons
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
|
||||
@@ -1154,6 +1295,11 @@ void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -1236,6 +1382,10 @@ bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->supports_stop = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 13: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1289,6 +1439,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(10, this->icon);
|
||||
buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
|
||||
buffer.encode_bool(12, this->supports_stop);
|
||||
buffer.encode_uint32(13, this->device_id);
|
||||
}
|
||||
void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -1303,6 +1454,7 @@ void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_stop, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesCoverResponse::dump_to(std::string &out) const {
|
||||
@@ -1356,6 +1508,11 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const {
|
||||
out.append(" supports_stop: ");
|
||||
out.append(YESNO(this->supports_stop));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -1565,6 +1722,10 @@ bool ListEntitiesFanResponse::decode_varint(uint32_t field_id, ProtoVarInt value
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 13: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1620,6 +1781,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
for (auto &it : this->supported_preset_modes) {
|
||||
buffer.encode_string(12, it, true);
|
||||
}
|
||||
buffer.encode_uint32(13, this->device_id);
|
||||
}
|
||||
void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -1638,6 +1800,7 @@ void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, it, true);
|
||||
}
|
||||
}
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesFanResponse::dump_to(std::string &out) const {
|
||||
@@ -1694,6 +1857,11 @@ void ListEntitiesFanResponse::dump_to(std::string &out) const {
|
||||
out.append("'").append(it).append("'");
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -1987,6 +2155,10 @@ bool ListEntitiesLightResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 16: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -2055,6 +2227,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(13, this->disabled_by_default);
|
||||
buffer.encode_string(14, this->icon);
|
||||
buffer.encode_enum<enums::EntityCategory>(15, this->entity_category);
|
||||
buffer.encode_uint32(16, this->device_id);
|
||||
}
|
||||
void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -2080,6 +2253,7 @@ void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 2, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesLightResponse::dump_to(std::string &out) const {
|
||||
@@ -2151,6 +2325,11 @@ void ListEntitiesLightResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -2658,6 +2837,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 14: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -2716,6 +2899,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type);
|
||||
buffer.encode_bool(12, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(13, this->entity_category);
|
||||
buffer.encode_uint32(14, this->device_id);
|
||||
}
|
||||
void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -2731,6 +2915,7 @@ void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->legacy_last_reset_type), false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesSensorResponse::dump_to(std::string &out) const {
|
||||
@@ -2789,6 +2974,11 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -2860,6 +3050,10 @@ bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 10: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -2910,6 +3104,7 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(7, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
|
||||
buffer.encode_string(9, this->device_class);
|
||||
buffer.encode_uint32(10, this->device_id);
|
||||
}
|
||||
void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -2921,6 +3116,7 @@ void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
|
||||
@@ -2962,6 +3158,11 @@ void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
|
||||
out.append(" device_class: ");
|
||||
out.append("'").append(this->device_class).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -3061,6 +3262,10 @@ bool ListEntitiesTextSensorResponse::decode_varint(uint32_t field_id, ProtoVarIn
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 9: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -3110,6 +3315,7 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_string(8, this->device_class);
|
||||
buffer.encode_uint32(9, this->device_id);
|
||||
}
|
||||
void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -3120,6 +3326,7 @@ void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
|
||||
@@ -3157,6 +3364,11 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
|
||||
out.append(" device_class: ");
|
||||
out.append("'").append(this->device_class).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -3922,6 +4134,10 @@ bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -3966,6 +4182,7 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(5, this->disabled_by_default);
|
||||
buffer.encode_string(6, this->icon);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_uint32(8, this->device_id);
|
||||
}
|
||||
void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -3975,6 +4192,7 @@ void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesCameraResponse::dump_to(std::string &out) const {
|
||||
@@ -4008,6 +4226,11 @@ void ListEntitiesCameraResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -4156,6 +4379,10 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
|
||||
this->supports_target_humidity = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 26: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -4262,6 +4489,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(23, this->supports_target_humidity);
|
||||
buffer.encode_float(24, this->visual_min_humidity);
|
||||
buffer.encode_float(25, this->visual_max_humidity);
|
||||
buffer.encode_uint32(26, this->device_id);
|
||||
}
|
||||
void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -4313,6 +4541,7 @@ void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 2, this->supports_target_humidity, false);
|
||||
ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_min_humidity != 0.0f, false);
|
||||
ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_max_humidity != 0.0f, false);
|
||||
ProtoSize::add_uint32_field(total_size, 2, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
||||
@@ -4436,6 +4665,11 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
||||
sprintf(buffer, "%g", this->visual_max_humidity);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -4901,6 +5135,10 @@ bool ListEntitiesNumberResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->mode = value.as_enum<enums::NumberMode>();
|
||||
return true;
|
||||
}
|
||||
case 14: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -4971,6 +5209,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(11, this->unit_of_measurement);
|
||||
buffer.encode_enum<enums::NumberMode>(12, this->mode);
|
||||
buffer.encode_string(13, this->device_class);
|
||||
buffer.encode_uint32(14, this->device_id);
|
||||
}
|
||||
void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -4986,6 +5225,7 @@ void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->unit_of_measurement, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->mode), false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
||||
@@ -5046,6 +5286,11 @@ void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
||||
out.append(" device_class: ");
|
||||
out.append("'").append(this->device_class).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -5151,6 +5396,10 @@ bool ListEntitiesSelectResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 9: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5202,6 +5451,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
}
|
||||
buffer.encode_bool(7, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
|
||||
buffer.encode_uint32(9, this->device_id);
|
||||
}
|
||||
void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -5216,6 +5466,7 @@ void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const {
|
||||
}
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesSelectResponse::dump_to(std::string &out) const {
|
||||
@@ -5255,6 +5506,11 @@ void ListEntitiesSelectResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -5378,6 +5634,10 @@ bool ListEntitiesSirenResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 11: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5431,6 +5691,7 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(8, this->supports_duration);
|
||||
buffer.encode_bool(9, this->supports_volume);
|
||||
buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
|
||||
buffer.encode_uint32(11, this->device_id);
|
||||
}
|
||||
void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -5447,6 +5708,7 @@ void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_duration, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_volume, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesSirenResponse::dump_to(std::string &out) const {
|
||||
@@ -5494,6 +5756,11 @@ void ListEntitiesSirenResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -5683,6 +5950,10 @@ bool ListEntitiesLockResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
||||
this->requires_code = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 12: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5735,6 +6006,7 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(9, this->supports_open);
|
||||
buffer.encode_bool(10, this->requires_code);
|
||||
buffer.encode_string(11, this->code_format);
|
||||
buffer.encode_uint32(12, this->device_id);
|
||||
}
|
||||
void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -5748,6 +6020,7 @@ void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_open, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->requires_code, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->code_format, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesLockResponse::dump_to(std::string &out) const {
|
||||
@@ -5797,6 +6070,11 @@ void ListEntitiesLockResponse::dump_to(std::string &out) const {
|
||||
out.append(" code_format: ");
|
||||
out.append("'").append(this->code_format).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -5922,6 +6200,10 @@ bool ListEntitiesButtonResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 9: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5971,6 +6253,7 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_string(8, this->device_class);
|
||||
buffer.encode_uint32(9, this->device_id);
|
||||
}
|
||||
void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -5981,6 +6264,7 @@ void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesButtonResponse::dump_to(std::string &out) const {
|
||||
@@ -6018,6 +6302,11 @@ void ListEntitiesButtonResponse::dump_to(std::string &out) const {
|
||||
out.append(" device_class: ");
|
||||
out.append("'").append(this->device_class).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -6135,6 +6424,10 @@ bool ListEntitiesMediaPlayerResponse::decode_varint(uint32_t field_id, ProtoVarI
|
||||
this->supports_pause = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 10: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -6187,6 +6480,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
for (auto &it : this->supported_formats) {
|
||||
buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true);
|
||||
}
|
||||
buffer.encode_uint32(10, this->device_id);
|
||||
}
|
||||
void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -6198,6 +6492,7 @@ void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_pause, false);
|
||||
ProtoSize::add_repeated_message(total_size, 1, this->supported_formats);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
|
||||
@@ -6241,6 +6536,11 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
|
||||
it.dump_to(out);
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -8551,6 +8851,10 @@ bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, Pro
|
||||
this->requires_code_to_arm = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 11: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -8598,6 +8902,7 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) cons
|
||||
buffer.encode_uint32(8, this->supported_features);
|
||||
buffer.encode_bool(9, this->requires_code);
|
||||
buffer.encode_bool(10, this->requires_code_to_arm);
|
||||
buffer.encode_uint32(11, this->device_id);
|
||||
}
|
||||
void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -8610,6 +8915,7 @@ void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size)
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->supported_features, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->requires_code, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->requires_code_to_arm, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const {
|
||||
@@ -8656,6 +8962,11 @@ void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const {
|
||||
out.append(" requires_code_to_arm: ");
|
||||
out.append(YESNO(this->requires_code_to_arm));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -8783,6 +9094,10 @@ bool ListEntitiesTextResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
||||
this->mode = value.as_enum<enums::TextMode>();
|
||||
return true;
|
||||
}
|
||||
case 12: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -8835,6 +9150,7 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_uint32(9, this->max_length);
|
||||
buffer.encode_string(10, this->pattern);
|
||||
buffer.encode_enum<enums::TextMode>(11, this->mode);
|
||||
buffer.encode_uint32(12, this->device_id);
|
||||
}
|
||||
void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -8848,6 +9164,7 @@ void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->max_length, false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->pattern, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->mode), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesTextResponse::dump_to(std::string &out) const {
|
||||
@@ -8899,6 +9216,11 @@ void ListEntitiesTextResponse::dump_to(std::string &out) const {
|
||||
out.append(" mode: ");
|
||||
out.append(proto_enum_to_string<enums::TextMode>(this->mode));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -9014,6 +9336,10 @@ bool ListEntitiesDateResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -9058,6 +9384,7 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(5, this->icon);
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_uint32(8, this->device_id);
|
||||
}
|
||||
void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -9067,6 +9394,7 @@ void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesDateResponse::dump_to(std::string &out) const {
|
||||
@@ -9100,6 +9428,11 @@ void ListEntitiesDateResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -9255,6 +9588,10 @@ bool ListEntitiesTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -9299,6 +9636,7 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(5, this->icon);
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_uint32(8, this->device_id);
|
||||
}
|
||||
void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -9308,6 +9646,7 @@ void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesTimeResponse::dump_to(std::string &out) const {
|
||||
@@ -9341,6 +9680,11 @@ void ListEntitiesTimeResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -9496,6 +9840,10 @@ bool ListEntitiesEventResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 10: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -9552,6 +9900,7 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
for (auto &it : this->event_types) {
|
||||
buffer.encode_string(9, it, true);
|
||||
}
|
||||
buffer.encode_uint32(10, this->device_id);
|
||||
}
|
||||
void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -9567,6 +9916,7 @@ void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, it, true);
|
||||
}
|
||||
}
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesEventResponse::dump_to(std::string &out) const {
|
||||
@@ -9610,6 +9960,11 @@ void ListEntitiesEventResponse::dump_to(std::string &out) const {
|
||||
out.append("'").append(it).append("'");
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -9678,6 +10033,10 @@ bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->supports_stop = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 12: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -9730,6 +10089,7 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(9, this->assumed_state);
|
||||
buffer.encode_bool(10, this->supports_position);
|
||||
buffer.encode_bool(11, this->supports_stop);
|
||||
buffer.encode_uint32(12, this->device_id);
|
||||
}
|
||||
void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -9743,6 +10103,7 @@ void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->assumed_state, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_position, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->supports_stop, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesValveResponse::dump_to(std::string &out) const {
|
||||
@@ -9792,6 +10153,11 @@ void ListEntitiesValveResponse::dump_to(std::string &out) const {
|
||||
out.append(" supports_stop: ");
|
||||
out.append(YESNO(this->supports_stop));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -9923,6 +10289,10 @@ bool ListEntitiesDateTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -9967,6 +10337,7 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(5, this->icon);
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_uint32(8, this->device_id);
|
||||
}
|
||||
void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -9976,6 +10347,7 @@ void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->icon, false);
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesDateTimeResponse::dump_to(std::string &out) const {
|
||||
@@ -10009,6 +10381,11 @@ void ListEntitiesDateTimeResponse::dump_to(std::string &out) const {
|
||||
out.append(" entity_category: ");
|
||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
@@ -10114,6 +10491,10 @@ bool ListEntitiesUpdateResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||
return true;
|
||||
}
|
||||
case 9: {
|
||||
this->device_id = value.as_uint32();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -10163,6 +10544,7 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(6, this->disabled_by_default);
|
||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||
buffer.encode_string(8, this->device_class);
|
||||
buffer.encode_uint32(9, this->device_id);
|
||||
}
|
||||
void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
||||
@@ -10173,6 +10555,7 @@ void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
|
||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||
ProtoSize::add_enum_field(total_size, 1, static_cast<uint32_t>(this->entity_category), false);
|
||||
ProtoSize::add_string_field(total_size, 1, this->device_class, false);
|
||||
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void ListEntitiesUpdateResponse::dump_to(std::string &out) const {
|
||||
@@ -10210,6 +10593,11 @@ void ListEntitiesUpdateResponse::dump_to(std::string &out) const {
|
||||
out.append(" device_class: ");
|
||||
out.append("'").append(this->device_class).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" device_id: ");
|
||||
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
|
@@ -264,6 +264,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
|
||||
bool disabled_by_default{false};
|
||||
std::string icon{};
|
||||
enums::EntityCategory entity_category{};
|
||||
uint32_t device_id{0};
|
||||
|
||||
protected:
|
||||
};
|
||||
@@ -415,10 +416,39 @@ class DeviceInfoRequest : public ProtoMessage {
|
||||
|
||||
protected:
|
||||
};
|
||||
class AreaInfo : public ProtoMessage {
|
||||
public:
|
||||
uint32_t area_id{0};
|
||||
std::string name{};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(uint32_t &total_size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void dump_to(std::string &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class DeviceInfo : public ProtoMessage {
|
||||
public:
|
||||
uint32_t device_id{0};
|
||||
std::string name{};
|
||||
uint32_t area_id{0};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(uint32_t &total_size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void dump_to(std::string &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class DeviceInfoResponse : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 10;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 129;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 219;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "device_info_response"; }
|
||||
#endif
|
||||
@@ -441,6 +471,9 @@ class DeviceInfoResponse : public ProtoMessage {
|
||||
std::string suggested_area{};
|
||||
std::string bluetooth_mac_address{};
|
||||
bool api_encryption_supported{false};
|
||||
std::vector<DeviceInfo> devices{};
|
||||
std::vector<AreaInfo> areas{};
|
||||
AreaInfo area{};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void calculate_size(uint32_t &total_size) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
@@ -493,7 +526,7 @@ class SubscribeStatesRequest : public ProtoMessage {
|
||||
class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 12;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 56;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 60;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; }
|
||||
#endif
|
||||
@@ -532,7 +565,7 @@ class BinarySensorStateResponse : public StateResponseProtoMessage {
|
||||
class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 13;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 62;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 66;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_cover_response"; }
|
||||
#endif
|
||||
@@ -601,7 +634,7 @@ class CoverCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesFanResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 14;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 73;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 77;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_fan_response"; }
|
||||
#endif
|
||||
@@ -679,7 +712,7 @@ class FanCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesLightResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 15;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 85;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 90;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_light_response"; }
|
||||
#endif
|
||||
@@ -780,7 +813,7 @@ class LightCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 16;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 73;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 77;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_sensor_response"; }
|
||||
#endif
|
||||
@@ -823,7 +856,7 @@ class SensorStateResponse : public StateResponseProtoMessage {
|
||||
class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 17;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 56;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 60;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_switch_response"; }
|
||||
#endif
|
||||
@@ -880,7 +913,7 @@ class SwitchCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 18;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 54;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 58;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_text_sensor_response"; }
|
||||
#endif
|
||||
@@ -1196,7 +1229,7 @@ class ExecuteServiceRequest : public ProtoMessage {
|
||||
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 43;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 45;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 49;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_camera_response"; }
|
||||
#endif
|
||||
@@ -1253,7 +1286,7 @@ class CameraImageRequest : public ProtoMessage {
|
||||
class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 46;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 151;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 156;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_climate_response"; }
|
||||
#endif
|
||||
@@ -1362,7 +1395,7 @@ class ClimateCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 49;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 80;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 84;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_number_response"; }
|
||||
#endif
|
||||
@@ -1423,7 +1456,7 @@ class NumberCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 52;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 63;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 67;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_select_response"; }
|
||||
#endif
|
||||
@@ -1481,7 +1514,7 @@ class SelectCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 55;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 67;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 71;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_siren_response"; }
|
||||
#endif
|
||||
@@ -1547,7 +1580,7 @@ class SirenCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesLockResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 58;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 60;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 64;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_lock_response"; }
|
||||
#endif
|
||||
@@ -1609,7 +1642,7 @@ class LockCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesButtonResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 61;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 54;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 58;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_button_response"; }
|
||||
#endif
|
||||
@@ -1662,7 +1695,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage {
|
||||
class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 63;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 81;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 85;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_media_player_response"; }
|
||||
#endif
|
||||
@@ -2532,7 +2565,7 @@ class VoiceAssistantSetConfiguration : public ProtoMessage {
|
||||
class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 94;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 53;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 57;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; }
|
||||
#endif
|
||||
@@ -2592,7 +2625,7 @@ class AlarmControlPanelCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesTextResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 97;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 64;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 68;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_text_response"; }
|
||||
#endif
|
||||
@@ -2653,7 +2686,7 @@ class TextCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesDateResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 100;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 45;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 49;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_date_response"; }
|
||||
#endif
|
||||
@@ -2713,7 +2746,7 @@ class DateCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 103;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 45;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 49;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_time_response"; }
|
||||
#endif
|
||||
@@ -2773,7 +2806,7 @@ class TimeCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesEventResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 107;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 72;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 76;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_event_response"; }
|
||||
#endif
|
||||
@@ -2811,7 +2844,7 @@ class EventResponse : public StateResponseProtoMessage {
|
||||
class ListEntitiesValveResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 109;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 60;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 64;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_valve_response"; }
|
||||
#endif
|
||||
@@ -2873,7 +2906,7 @@ class ValveCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 112;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 45;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 49;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_date_time_response"; }
|
||||
#endif
|
||||
@@ -2928,7 +2961,7 @@ class DateTimeCommandRequest : public ProtoMessage {
|
||||
class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
|
||||
public:
|
||||
static constexpr uint16_t MESSAGE_TYPE = 116;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 54;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 58;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
static constexpr const char *message_name() { return "list_entities_update_response"; }
|
||||
#endif
|
||||
|
@@ -86,7 +86,7 @@ bool AudioTransferBuffer::reallocate(size_t new_buffer_size) {
|
||||
bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
||||
this->buffer_size_ = buffer_size;
|
||||
|
||||
RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
|
||||
this->buffer_ = allocator.allocate(this->buffer_size_);
|
||||
if (this->buffer_ == nullptr) {
|
||||
@@ -101,7 +101,7 @@ bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
||||
|
||||
void AudioTransferBuffer::deallocate_buffer_() {
|
||||
if (this->buffer_ != nullptr) {
|
||||
RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
allocator.deallocate(this->buffer_, this->buffer_size_);
|
||||
this->buffer_ = nullptr;
|
||||
this->data_start_ = nullptr;
|
||||
|
@@ -7,11 +7,13 @@
|
||||
|
||||
extern "C" {
|
||||
#include "rtos_pub.h"
|
||||
#include "spi.h"
|
||||
// rtos_pub.h must be included before the rest of the includes
|
||||
|
||||
#include "arm_arch.h"
|
||||
#include "general_dma_pub.h"
|
||||
#include "gpio_pub.h"
|
||||
#include "icu_pub.h"
|
||||
#include "spi.h"
|
||||
#undef SPI_DAT
|
||||
#undef SPI_BASE
|
||||
};
|
||||
@@ -124,7 +126,7 @@ void BekenSPILEDStripLightOutput::setup() {
|
||||
size_t buffer_size = this->get_buffer_size_();
|
||||
size_t dma_buffer_size = (buffer_size * 8) + (2 * 64);
|
||||
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->buf_ = allocator.allocate(buffer_size);
|
||||
if (this->buf_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Cannot allocate LED buffer!");
|
||||
|
@@ -50,7 +50,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
|
||||
// turn on (after one-shot sensor automatically powers down)
|
||||
uint8_t turn_on = BH1750_COMMAND_POWER_ON;
|
||||
if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Turning on BH1750 failed");
|
||||
ESP_LOGW(TAG, "Power on failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
|
||||
uint8_t mtreg_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> 5) & 0b111);
|
||||
uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> 0) & 0b11111);
|
||||
if (this->write(&mtreg_hi, 1) != i2c::ERROR_OK || this->write(&mtreg_lo, 1) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Setting measurement time for BH1750 failed");
|
||||
ESP_LOGW(TAG, "Set measurement time failed");
|
||||
active_mtreg_ = 0;
|
||||
f(NAN);
|
||||
return;
|
||||
@@ -88,7 +88,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
|
||||
return;
|
||||
}
|
||||
if (this->write(&cmd, 1) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Starting measurement for BH1750 failed");
|
||||
ESP_LOGW(TAG, "Start measurement failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
@@ -99,7 +99,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
|
||||
this->set_timeout("read", meas_time, [this, mode, mtreg, f]() {
|
||||
uint16_t raw_value;
|
||||
if (this->read(reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Reading BH1750 data failed");
|
||||
ESP_LOGW(TAG, "Read data failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ void BH1750Sensor::update() {
|
||||
this->publish_state(NAN);
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s': Got illuminance=%.1flx", this->get_name().c_str(), val);
|
||||
ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), val);
|
||||
this->status_clear_warning();
|
||||
this->publish_state(val);
|
||||
});
|
||||
|
@@ -60,8 +60,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_WINDOW,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
from esphome.util import Registry
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
@@ -148,6 +148,7 @@ BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Conditi
|
||||
|
||||
# Filters
|
||||
Filter = binary_sensor_ns.class_("Filter")
|
||||
TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
|
||||
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
|
||||
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
|
||||
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Component)
|
||||
@@ -171,6 +172,19 @@ async def invert_filter_to_code(config, filter_id):
|
||||
return cg.new_Pvariable(filter_id)
|
||||
|
||||
|
||||
@register_filter(
|
||||
"timeout",
|
||||
TimeoutFilter,
|
||||
cv.templatable(cv.positive_time_period_milliseconds),
|
||||
)
|
||||
async def timeout_filter_to_code(config, filter_id):
|
||||
var = cg.new_Pvariable(filter_id)
|
||||
await cg.register_component(var, {})
|
||||
template_ = await cg.templatable(config, [], cg.uint32)
|
||||
cg.add(var.set_timeout_value(template_))
|
||||
return var
|
||||
|
||||
|
||||
@register_filter(
|
||||
"delayed_on_off",
|
||||
DelayedOnOffFilter,
|
||||
@@ -491,6 +505,9 @@ _BINARY_SENSOR_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_BINARY_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("binary_sensor"))
|
||||
|
||||
|
||||
def binary_sensor_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -521,7 +538,7 @@ BINARY_SENSOR_SCHEMA.add_extra(cv.deprecated_schema_constant("binary_sensor"))
|
||||
|
||||
|
||||
async def setup_binary_sensor_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "binary_sensor")
|
||||
|
||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||
cg.add(var.set_device_class(device_class))
|
||||
|
@@ -25,6 +25,12 @@ void Filter::input(bool value) {
|
||||
}
|
||||
}
|
||||
|
||||
void TimeoutFilter::input(bool value) {
|
||||
this->set_timeout("timeout", this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
|
||||
// we do not de-dup here otherwise changes from invalid to valid state will not be output
|
||||
this->output(value);
|
||||
}
|
||||
|
||||
optional<bool> DelayedOnOffFilter::new_value(bool value) {
|
||||
if (value) {
|
||||
this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });
|
||||
|
@@ -16,7 +16,7 @@ class Filter {
|
||||
public:
|
||||
virtual optional<bool> new_value(bool value) = 0;
|
||||
|
||||
void input(bool value);
|
||||
virtual void input(bool value);
|
||||
|
||||
void output(bool value);
|
||||
|
||||
@@ -28,6 +28,16 @@ class Filter {
|
||||
Deduplicator<bool> dedup_;
|
||||
};
|
||||
|
||||
class TimeoutFilter : public Filter, public Component {
|
||||
public:
|
||||
optional<bool> new_value(bool value) override { return value; }
|
||||
void input(bool value) override;
|
||||
template<typename T> void set_timeout_value(T timeout) { this->timeout_delay_ = timeout; }
|
||||
|
||||
protected:
|
||||
TemplatableValue<uint32_t> timeout_delay_{};
|
||||
};
|
||||
|
||||
class DelayedOnOffFilter : public Filter, public Component {
|
||||
public:
|
||||
optional<bool> new_value(bool value) override;
|
||||
|
@@ -18,8 +18,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_UPDATE,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -61,6 +61,9 @@ _BUTTON_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_BUTTON_SCHEMA.add_extra(entity_duplicate_validator("button"))
|
||||
|
||||
|
||||
def button_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -87,7 +90,7 @@ BUTTON_SCHEMA.add_extra(cv.deprecated_schema_constant("button"))
|
||||
|
||||
|
||||
async def setup_button_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "button")
|
||||
|
||||
for conf in config.get(CONF_ON_PRESS, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
|
@@ -48,8 +48,8 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
@@ -247,6 +247,9 @@ _CLIMATE_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_CLIMATE_SCHEMA.add_extra(entity_duplicate_validator("climate"))
|
||||
|
||||
|
||||
def climate_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -273,7 +276,7 @@ CLIMATE_SCHEMA.add_extra(cv.deprecated_schema_constant("climate"))
|
||||
|
||||
|
||||
async def setup_climate_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "climate")
|
||||
|
||||
visual = config[CONF_VISUAL]
|
||||
if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None:
|
||||
|
@@ -33,8 +33,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_WINDOW,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
@@ -126,6 +126,9 @@ _COVER_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_COVER_SCHEMA.add_extra(entity_duplicate_validator("cover"))
|
||||
|
||||
|
||||
def cover_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -154,7 +157,7 @@ COVER_SCHEMA.add_extra(cv.deprecated_schema_constant("cover"))
|
||||
|
||||
|
||||
async def setup_cover_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "cover")
|
||||
|
||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||
cg.add(var.set_device_class(device_class))
|
||||
|
@@ -22,8 +22,8 @@ from esphome.const import (
|
||||
CONF_YEAR,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@rfdarter", "@jesserockz"]
|
||||
|
||||
@@ -84,6 +84,8 @@ _DATETIME_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
||||
).add_extra(_validate_time_present)
|
||||
|
||||
_DATETIME_SCHEMA.add_extra(entity_duplicate_validator("datetime"))
|
||||
|
||||
|
||||
def date_schema(class_: MockObjClass) -> cv.Schema:
|
||||
schema = cv.Schema(
|
||||
@@ -133,7 +135,7 @@ def datetime_schema(class_: MockObjClass) -> cv.Schema:
|
||||
|
||||
|
||||
async def setup_datetime_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "datetime")
|
||||
|
||||
if (mqtt_id := config.get(CONF_MQTT_ID)) is not None:
|
||||
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||
|
@@ -455,7 +455,7 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
CONF_NAME: "Demo Plain Sensor",
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Demo Temperature Sensor",
|
||||
CONF_NAME: "Demo Temperature Sensor 1",
|
||||
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
||||
CONF_ICON: ICON_THERMOMETER,
|
||||
CONF_ACCURACY_DECIMALS: 1,
|
||||
@@ -463,7 +463,7 @@ CONFIG_SCHEMA = cv.Schema(
|
||||
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
},
|
||||
{
|
||||
CONF_NAME: "Demo Temperature Sensor",
|
||||
CONF_NAME: "Demo Temperature Sensor 2",
|
||||
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
||||
CONF_ICON: ICON_THERMOMETER,
|
||||
CONF_ACCURACY_DECIMALS: 1,
|
||||
|
@@ -11,7 +11,7 @@ namespace display {
|
||||
static const char *const TAG = "display";
|
||||
|
||||
void DisplayBuffer::init_internal_(uint32_t buffer_length) {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->buffer_ = allocator.allocate(buffer_length);
|
||||
if (this->buffer_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Could not allocate buffer for display!");
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include "ble_event_pool.h"
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <esp_bt.h>
|
||||
@@ -516,13 +517,12 @@ void ESP32BLE::dump_config() {
|
||||
break;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"ESP32 BLE:\n"
|
||||
" MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n"
|
||||
"BLE:\n"
|
||||
" MAC address: %s\n"
|
||||
" IO Capability: %s",
|
||||
mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5],
|
||||
io_capability_s);
|
||||
format_mac_address_pretty(mac_address).c_str(), io_capability_s);
|
||||
} else {
|
||||
ESP_LOGCONFIG(TAG, "ESP32 BLE: bluetooth stack is not enabled");
|
||||
ESP_LOGCONFIG(TAG, "Bluetooth stack is not enabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -522,6 +522,7 @@ optional<ESPBLEiBeacon> ESPBLEiBeacon::from_manufacturer_data(const ServiceData
|
||||
}
|
||||
|
||||
void ESPBTDevice::parse_scan_rst(const BLEScanResult &scan_result) {
|
||||
this->scan_result_ = &scan_result;
|
||||
for (uint8_t i = 0; i < ESP_BD_ADDR_LEN; i++)
|
||||
this->address_[i] = scan_result.bda[i];
|
||||
this->address_type_ = static_cast<esp_ble_addr_type_t>(scan_result.ble_addr_type);
|
||||
|
@@ -85,6 +85,9 @@ class ESPBTDevice {
|
||||
|
||||
const std::vector<ServiceData> &get_service_datas() const { return service_datas_; }
|
||||
|
||||
// Exposed through a function for use in lambdas
|
||||
const BLEScanResult &get_scan_result() const { return *scan_result_; }
|
||||
|
||||
bool resolve_irk(const uint8_t *irk) const;
|
||||
|
||||
optional<ESPBLEiBeacon> get_ibeacon() const {
|
||||
@@ -111,6 +114,7 @@ class ESPBTDevice {
|
||||
std::vector<ESPBTUUID> service_uuids_{};
|
||||
std::vector<ServiceData> manufacturer_datas_{};
|
||||
std::vector<ServiceData> service_datas_{};
|
||||
const BLEScanResult *scan_result_{nullptr};
|
||||
};
|
||||
|
||||
class ESP32BLETracker;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
from esphome import automation, pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
from esphome.components.esp32 import add_idf_component
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -7,6 +8,7 @@ from esphome.const import (
|
||||
CONF_CONTRAST,
|
||||
CONF_DATA_PINS,
|
||||
CONF_FREQUENCY,
|
||||
CONF_I2C_ID,
|
||||
CONF_ID,
|
||||
CONF_PIN,
|
||||
CONF_RESET_PIN,
|
||||
@@ -17,7 +19,7 @@ from esphome.const import (
|
||||
CONF_VSYNC_PIN,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
from esphome.core.entity_helpers import setup_entity
|
||||
|
||||
DEPENDENCIES = ["esp32"]
|
||||
|
||||
@@ -149,7 +151,8 @@ CONF_ON_IMAGE = "on_image"
|
||||
|
||||
camera_range_param = cv.int_range(min=-2, max=2)
|
||||
|
||||
CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.ENTITY_BASE_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(ESP32Camera),
|
||||
# pin assignment
|
||||
@@ -167,12 +170,16 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Required(CONF_I2C_PINS): cv.Schema(
|
||||
cv.Optional(CONF_I2C_PINS): cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
|
||||
cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_I2C_ID): cv.Any(
|
||||
cv.use_id(i2c.InternalI2CBus),
|
||||
msg="I2C bus must be an internal ESP32 I2C bus",
|
||||
),
|
||||
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
|
||||
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
|
||||
# image
|
||||
@@ -204,7 +211,9 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
ENUM_GAIN_CEILING, upper=True
|
||||
),
|
||||
# white balance
|
||||
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(ENUM_WB_MODE, upper=True),
|
||||
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(
|
||||
ENUM_WB_MODE, upper=True
|
||||
),
|
||||
# test pattern
|
||||
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
|
||||
# framerates
|
||||
@@ -231,11 +240,15 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
),
|
||||
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32CameraImageTrigger),
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||
ESP32CameraImageTrigger
|
||||
),
|
||||
}
|
||||
),
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID),
|
||||
)
|
||||
|
||||
SETTERS = {
|
||||
# pin assignment
|
||||
@@ -271,7 +284,7 @@ SETTERS = {
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "camera")
|
||||
await cg.register_component(var, config)
|
||||
|
||||
for key, setter in SETTERS.items():
|
||||
@@ -280,6 +293,10 @@ async def to_code(config):
|
||||
|
||||
extclk = config[CONF_EXTERNAL_CLOCK]
|
||||
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
|
||||
if i2c_id := config.get(CONF_I2C_ID):
|
||||
i2c_hub = await cg.get_variable(i2c_id)
|
||||
cg.add(var.set_i2c_id(i2c_hub))
|
||||
else:
|
||||
i2c_pins = config[CONF_I2C_PINS]
|
||||
cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
|
||||
cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
|
||||
|
@@ -1,9 +1,9 @@
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esp32_camera.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <freertos/task.h>
|
||||
|
||||
@@ -16,6 +16,12 @@ static const char *const TAG = "esp32_camera";
|
||||
void ESP32Camera::setup() {
|
||||
global_esp32_camera = this;
|
||||
|
||||
#ifdef USE_I2C
|
||||
if (this->i2c_bus_ != nullptr) {
|
||||
this->config_.sccb_i2c_port = this->i2c_bus_->get_port();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initialize time to now */
|
||||
this->last_update_ = millis();
|
||||
|
||||
@@ -246,6 +252,13 @@ void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
|
||||
this->config_.pin_sccb_sda = sda;
|
||||
this->config_.pin_sccb_scl = scl;
|
||||
}
|
||||
#ifdef USE_I2C
|
||||
void ESP32Camera::set_i2c_id(i2c::InternalI2CBus *i2c_bus) {
|
||||
this->i2c_bus_ = i2c_bus;
|
||||
this->config_.pin_sccb_sda = -1;
|
||||
this->config_.pin_sccb_scl = -1;
|
||||
}
|
||||
#endif // USE_I2C
|
||||
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
||||
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
||||
|
||||
|
@@ -2,13 +2,17 @@
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include <esp_camera.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include <esp_camera.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/queue.h>
|
||||
|
||||
#ifdef USE_I2C
|
||||
#include "esphome/components/i2c/i2c_bus.h"
|
||||
#endif // USE_I2C
|
||||
|
||||
namespace esphome {
|
||||
namespace esp32_camera {
|
||||
@@ -118,6 +122,9 @@ class ESP32Camera : public EntityBase, public Component {
|
||||
void set_pixel_clock_pin(uint8_t pin);
|
||||
void set_external_clock(uint8_t pin, uint32_t frequency);
|
||||
void set_i2c_pins(uint8_t sda, uint8_t scl);
|
||||
#ifdef USE_I2C
|
||||
void set_i2c_id(i2c::InternalI2CBus *i2c_bus);
|
||||
#endif // USE_I2C
|
||||
void set_reset_pin(uint8_t pin);
|
||||
void set_power_down_pin(uint8_t pin);
|
||||
/* -- image */
|
||||
@@ -210,6 +217,9 @@ class ESP32Camera : public EntityBase, public Component {
|
||||
|
||||
uint32_t last_idle_request_{0};
|
||||
uint32_t last_update_{0};
|
||||
#ifdef USE_I2C
|
||||
i2c::InternalI2CBus *i2c_bus_{nullptr};
|
||||
#endif // USE_I2C
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
0
esphome/components/esp32_hall/__init__.py
Normal file
0
esphome/components/esp32_hall/__init__.py
Normal file
5
esphome/components/esp32_hall/sensor.py
Normal file
5
esphome/components/esp32_hall/sensor.py
Normal file
@@ -0,0 +1,5 @@
|
||||
import esphome.config_validation as cv
|
||||
|
||||
CONFIG_SCHEMA = cv.invalid(
|
||||
"The esp32_hall component has been removed as of ESPHome 2025.7.0. See https://github.com/esphome/esphome/pull/9117 for details."
|
||||
)
|
@@ -18,8 +18,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_MOTION,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@nohat"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -59,6 +59,9 @@ _EVENT_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_EVENT_SCHEMA.add_extra(entity_duplicate_validator("event"))
|
||||
|
||||
|
||||
def event_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -88,7 +91,7 @@ EVENT_SCHEMA.add_extra(cv.deprecated_schema_constant("event"))
|
||||
|
||||
|
||||
async def setup_event_core_(var, config, *, event_types: list[str]):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "event")
|
||||
|
||||
for conf in config.get(CONF_ON_EVENT, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
|
@@ -32,7 +32,7 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
@@ -161,6 +161,9 @@ _FAN_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_FAN_SCHEMA.add_extra(entity_duplicate_validator("fan"))
|
||||
|
||||
|
||||
def fan_schema(
|
||||
class_: cg.Pvariable,
|
||||
*,
|
||||
@@ -225,7 +228,7 @@ def validate_preset_modes(value):
|
||||
|
||||
|
||||
async def setup_fan_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "fan")
|
||||
|
||||
cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
from collections.abc import MutableMapping
|
||||
import functools
|
||||
import hashlib
|
||||
from itertools import accumulate
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -468,8 +469,9 @@ class EFont:
|
||||
|
||||
|
||||
class GlyphInfo:
|
||||
def __init__(self, data_len, advance, offset_x, offset_y, width, height):
|
||||
self.data_len = data_len
|
||||
def __init__(self, glyph, data, advance, offset_x, offset_y, width, height):
|
||||
self.glyph = glyph
|
||||
self.bitmap_data = data
|
||||
self.advance = advance
|
||||
self.offset_x = offset_x
|
||||
self.offset_y = offset_y
|
||||
@@ -477,6 +479,62 @@ class GlyphInfo:
|
||||
self.height = height
|
||||
|
||||
|
||||
def glyph_to_glyphinfo(glyph, font, size, bpp):
|
||||
scale = 256 // (1 << bpp)
|
||||
if not font.is_scalable:
|
||||
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
||||
if size in sizes:
|
||||
font.select_size(sizes.index(size))
|
||||
else:
|
||||
font.set_pixel_sizes(size, 0)
|
||||
flags = FT_LOAD_RENDER
|
||||
if bpp != 1:
|
||||
flags |= FT_LOAD_NO_BITMAP
|
||||
else:
|
||||
flags |= FT_LOAD_TARGET_MONO
|
||||
font.load_char(glyph, flags)
|
||||
width = font.glyph.bitmap.width
|
||||
height = font.glyph.bitmap.rows
|
||||
buffer = font.glyph.bitmap.buffer
|
||||
pitch = font.glyph.bitmap.pitch
|
||||
glyph_data = [0] * ((height * width * bpp + 7) // 8)
|
||||
src_mode = font.glyph.bitmap.pixel_mode
|
||||
pos = 0
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
if src_mode == ft_pixel_mode_mono:
|
||||
pixel = (
|
||||
(1 << bpp) - 1
|
||||
if buffer[y * pitch + x // 8] & (1 << (7 - x % 8))
|
||||
else 0
|
||||
)
|
||||
else:
|
||||
pixel = buffer[y * pitch + x] // scale
|
||||
for bit_num in range(bpp):
|
||||
if pixel & (1 << (bpp - bit_num - 1)):
|
||||
glyph_data[pos // 8] |= 0x80 >> (pos % 8)
|
||||
pos += 1
|
||||
ascender = pt_to_px(font.size.ascender)
|
||||
if ascender == 0:
|
||||
if not font.is_scalable:
|
||||
ascender = size
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Unable to determine ascender of font %s %s",
|
||||
font.family_name,
|
||||
font.style_name,
|
||||
)
|
||||
return GlyphInfo(
|
||||
glyph,
|
||||
glyph_data,
|
||||
pt_to_px(font.glyph.metrics.horiAdvance),
|
||||
font.glyph.bitmap_left,
|
||||
ascender - font.glyph.bitmap_top,
|
||||
width,
|
||||
height,
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
"""
|
||||
Collect all glyph codepoints, construct a map from a codepoint to a font file.
|
||||
@@ -506,98 +564,47 @@ async def to_code(config):
|
||||
|
||||
codepoints = list(point_set)
|
||||
codepoints.sort(key=functools.cmp_to_key(glyph_comparator))
|
||||
glyph_args = {}
|
||||
data = []
|
||||
bpp = config[CONF_BPP]
|
||||
scale = 256 // (1 << bpp)
|
||||
size = config[CONF_SIZE]
|
||||
# create the data array for all glyphs
|
||||
for codepoint in codepoints:
|
||||
font = point_font_map[codepoint]
|
||||
if not font.is_scalable:
|
||||
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
||||
if size in sizes:
|
||||
font.select_size(sizes.index(size))
|
||||
else:
|
||||
font.set_pixel_sizes(size, 0)
|
||||
flags = FT_LOAD_RENDER
|
||||
if bpp != 1:
|
||||
flags |= FT_LOAD_NO_BITMAP
|
||||
else:
|
||||
flags |= FT_LOAD_TARGET_MONO
|
||||
font.load_char(codepoint, flags)
|
||||
width = font.glyph.bitmap.width
|
||||
height = font.glyph.bitmap.rows
|
||||
buffer = font.glyph.bitmap.buffer
|
||||
pitch = font.glyph.bitmap.pitch
|
||||
glyph_data = [0] * ((height * width * bpp + 7) // 8)
|
||||
src_mode = font.glyph.bitmap.pixel_mode
|
||||
pos = 0
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
if src_mode == ft_pixel_mode_mono:
|
||||
pixel = (
|
||||
(1 << bpp) - 1
|
||||
if buffer[y * pitch + x // 8] & (1 << (7 - x % 8))
|
||||
else 0
|
||||
)
|
||||
else:
|
||||
pixel = buffer[y * pitch + x] // scale
|
||||
for bit_num in range(bpp):
|
||||
if pixel & (1 << (bpp - bit_num - 1)):
|
||||
glyph_data[pos // 8] |= 0x80 >> (pos % 8)
|
||||
pos += 1
|
||||
ascender = pt_to_px(font.size.ascender)
|
||||
if ascender == 0:
|
||||
if not font.is_scalable:
|
||||
ascender = size
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"Unable to determine ascender of font %s", config[CONF_FILE]
|
||||
)
|
||||
glyph_args[codepoint] = GlyphInfo(
|
||||
len(data),
|
||||
pt_to_px(font.glyph.metrics.horiAdvance),
|
||||
font.glyph.bitmap_left,
|
||||
ascender - font.glyph.bitmap_top,
|
||||
width,
|
||||
height,
|
||||
)
|
||||
data += glyph_data
|
||||
|
||||
rhs = [HexInt(x) for x in data]
|
||||
glyph_args = [
|
||||
glyph_to_glyphinfo(x, point_font_map[x], size, bpp) for x in codepoints
|
||||
]
|
||||
rhs = [HexInt(x) for x in flatten([x.bitmap_data for x in glyph_args])]
|
||||
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
||||
|
||||
# Create the glyph table that points to data in the above array.
|
||||
glyph_initializer = []
|
||||
for codepoint in codepoints:
|
||||
glyph_initializer.append(
|
||||
glyph_initializer = [
|
||||
cg.StructInitializer(
|
||||
GlyphData,
|
||||
(
|
||||
"a_char",
|
||||
cg.RawExpression(
|
||||
f"(const uint8_t *){cpp_string_escape(codepoint)}"
|
||||
),
|
||||
cg.RawExpression(f"(const uint8_t *){cpp_string_escape(x.glyph)}"),
|
||||
),
|
||||
(
|
||||
"data",
|
||||
cg.RawExpression(
|
||||
f"{str(prog_arr)} + {str(glyph_args[codepoint].data_len)}"
|
||||
cg.RawExpression(f"{str(prog_arr)} + {str(y - len(x.bitmap_data))}"),
|
||||
),
|
||||
),
|
||||
("advance", glyph_args[codepoint].advance),
|
||||
("offset_x", glyph_args[codepoint].offset_x),
|
||||
("offset_y", glyph_args[codepoint].offset_y),
|
||||
("width", glyph_args[codepoint].width),
|
||||
("height", glyph_args[codepoint].height),
|
||||
("advance", x.advance),
|
||||
("offset_x", x.offset_x),
|
||||
("offset_y", x.offset_y),
|
||||
("width", x.width),
|
||||
("height", x.height),
|
||||
)
|
||||
for (x, y) in zip(
|
||||
glyph_args, list(accumulate([len(x.bitmap_data) for x in glyph_args]))
|
||||
)
|
||||
]
|
||||
|
||||
glyphs = cg.static_const_array(config[CONF_RAW_GLYPH_ID], glyph_initializer)
|
||||
|
||||
font_height = pt_to_px(base_font.size.height)
|
||||
ascender = pt_to_px(base_font.size.ascender)
|
||||
descender = abs(pt_to_px(base_font.size.descender))
|
||||
g = glyph_to_glyphinfo("x", base_font, size, bpp)
|
||||
xheight = g.height if len(g.bitmap_data) > 1 else 0
|
||||
g = glyph_to_glyphinfo("X", base_font, size, bpp)
|
||||
capheight = g.height if len(g.bitmap_data) > 1 else 0
|
||||
if font_height == 0:
|
||||
if not base_font.is_scalable:
|
||||
font_height = size
|
||||
@@ -610,5 +617,8 @@ async def to_code(config):
|
||||
len(glyph_initializer),
|
||||
ascender,
|
||||
font_height,
|
||||
descender,
|
||||
xheight,
|
||||
capheight,
|
||||
bpp,
|
||||
)
|
||||
|
@@ -45,8 +45,15 @@ void Glyph::scan_area(int *x1, int *y1, int *width, int *height) const {
|
||||
*height = this->glyph_data_->height;
|
||||
}
|
||||
|
||||
Font::Font(const GlyphData *data, int data_nr, int baseline, int height, uint8_t bpp)
|
||||
: baseline_(baseline), height_(height), bpp_(bpp) {
|
||||
Font::Font(const GlyphData *data, int data_nr, int baseline, int height, int descender, int xheight, int capheight,
|
||||
uint8_t bpp)
|
||||
: baseline_(baseline),
|
||||
height_(height),
|
||||
descender_(descender),
|
||||
linegap_(height - baseline - descender),
|
||||
xheight_(xheight),
|
||||
capheight_(capheight),
|
||||
bpp_(bpp) {
|
||||
glyphs_.reserve(data_nr);
|
||||
for (int i = 0; i < data_nr; ++i)
|
||||
glyphs_.emplace_back(&data[i]);
|
||||
|
@@ -50,11 +50,17 @@ class Font
|
||||
public:
|
||||
/** Construct the font with the given glyphs.
|
||||
*
|
||||
* @param glyphs A vector of glyphs, must be sorted lexicographically.
|
||||
* @param data A vector of glyphs, must be sorted lexicographically.
|
||||
* @param data_nr The number of glyphs in data.
|
||||
* @param baseline The y-offset from the top of the text to the baseline.
|
||||
* @param bottom The y-offset from the top of the text to the bottom (i.e. height).
|
||||
* @param height The y-offset from the top of the text to the bottom.
|
||||
* @param descender The y-offset from the baseline to the lowest stroke in the font (e.g. from letters like g or p).
|
||||
* @param xheight The height of lowercase letters, usually measured at the "x" glyph.
|
||||
* @param capheight The height of capital letters, usually measured at the "X" glyph.
|
||||
* @param bpp The bits per pixel used for this font. Used to read data out of the glyph bitmaps.
|
||||
*/
|
||||
Font(const GlyphData *data, int data_nr, int baseline, int height, uint8_t bpp = 1);
|
||||
Font(const GlyphData *data, int data_nr, int baseline, int height, int descender, int xheight, int capheight,
|
||||
uint8_t bpp = 1);
|
||||
|
||||
int match_next_glyph(const uint8_t *str, int *match_length);
|
||||
|
||||
@@ -65,14 +71,23 @@ class Font
|
||||
#endif
|
||||
inline int get_baseline() { return this->baseline_; }
|
||||
inline int get_height() { return this->height_; }
|
||||
inline int get_ascender() { return this->baseline_; }
|
||||
inline int get_descender() { return this->descender_; }
|
||||
inline int get_linegap() { return this->linegap_; }
|
||||
inline int get_xheight() { return this->xheight_; }
|
||||
inline int get_capheight() { return this->capheight_; }
|
||||
inline int get_bpp() { return this->bpp_; }
|
||||
|
||||
const std::vector<Glyph, ExternalRAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
|
||||
const std::vector<Glyph, RAMAllocator<Glyph>> &get_glyphs() const { return glyphs_; }
|
||||
|
||||
protected:
|
||||
std::vector<Glyph, ExternalRAMAllocator<Glyph>> glyphs_;
|
||||
std::vector<Glyph, RAMAllocator<Glyph>> glyphs_;
|
||||
int baseline_;
|
||||
int height_;
|
||||
int descender_;
|
||||
int linegap_;
|
||||
int xheight_;
|
||||
int capheight_;
|
||||
uint8_t bpp_; // bits per pixel
|
||||
};
|
||||
|
||||
|
@@ -41,6 +41,6 @@ CONFIG_SCHEMA = cv.All(
|
||||
async def to_code(config):
|
||||
cg.add_build_flag("-DUSE_HOST")
|
||||
cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts)
|
||||
cg.add_build_flag("-std=c++17")
|
||||
cg.add_build_flag("-std=gnu++17")
|
||||
cg.add_define("ESPHOME_BOARD", "host")
|
||||
cg.add_platformio_option("platform", "platformio/native")
|
||||
|
@@ -239,7 +239,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
||||
|
||||
std::string response_body;
|
||||
if (this->capture_response_.value(x...)) {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
uint8_t *buf = allocator.allocate(max_length);
|
||||
if (buf != nullptr) {
|
||||
size_t read_index = 0;
|
||||
|
@@ -54,7 +54,7 @@ void HttpRequestUpdate::update_task(void *params) {
|
||||
UPDATE_RETURN;
|
||||
}
|
||||
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
uint8_t *data = allocator.allocate(container->content_length);
|
||||
if (data == nullptr) {
|
||||
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
||||
|
@@ -22,8 +22,9 @@ import esphome.final_validate as fv
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
i2c_ns = cg.esphome_ns.namespace("i2c")
|
||||
I2CBus = i2c_ns.class_("I2CBus")
|
||||
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", I2CBus, cg.Component)
|
||||
IDFI2CBus = i2c_ns.class_("IDFI2CBus", I2CBus, cg.Component)
|
||||
InternalI2CBus = i2c_ns.class_("InternalI2CBus", I2CBus)
|
||||
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", InternalI2CBus, cg.Component)
|
||||
IDFI2CBus = i2c_ns.class_("IDFI2CBus", InternalI2CBus, cg.Component)
|
||||
I2CDevice = i2c_ns.class_("I2CDevice")
|
||||
|
||||
|
||||
@@ -71,6 +72,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
@coroutine_with_priority(1.0)
|
||||
async def to_code(config):
|
||||
cg.add_global(i2c_ns.using)
|
||||
cg.add_define("USE_I2C")
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -108,5 +108,12 @@ class I2CBus {
|
||||
bool scan_{false}; ///< Should we scan ? Can be set in the yaml
|
||||
};
|
||||
|
||||
class InternalI2CBus : public I2CBus {
|
||||
public:
|
||||
/// @brief Returns the I2C port number.
|
||||
/// @return the port number of the internal I2C bus
|
||||
virtual int get_port() const = 0;
|
||||
};
|
||||
|
||||
} // namespace i2c
|
||||
} // namespace esphome
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#ifdef USE_ARDUINO
|
||||
|
||||
#include "i2c_bus_arduino.h"
|
||||
#include <Arduino.h>
|
||||
#include <cstring>
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include <Arduino.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace esphome {
|
||||
namespace i2c {
|
||||
@@ -23,6 +23,7 @@ void ArduinoI2CBus::setup() {
|
||||
} else {
|
||||
wire_ = new TwoWire(next_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
}
|
||||
this->port_ = next_bus_num;
|
||||
next_bus_num++;
|
||||
#elif defined(USE_ESP8266)
|
||||
wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
|
@@ -2,9 +2,9 @@
|
||||
|
||||
#ifdef USE_ARDUINO
|
||||
|
||||
#include "i2c_bus.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include <Wire.h>
|
||||
#include "esphome/core/component.h"
|
||||
#include "i2c_bus.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace i2c {
|
||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
||||
RECOVERY_COMPLETED,
|
||||
};
|
||||
|
||||
class ArduinoI2CBus : public I2CBus, public Component {
|
||||
class ArduinoI2CBus : public InternalI2CBus, public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
@@ -29,12 +29,15 @@ class ArduinoI2CBus : public I2CBus, public Component {
|
||||
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||
|
||||
int get_port() const override { return this->port_; }
|
||||
|
||||
private:
|
||||
void recover_();
|
||||
void set_pins_and_clock_();
|
||||
RecoveryCode recovery_result_;
|
||||
|
||||
protected:
|
||||
int8_t port_{-1};
|
||||
TwoWire *wire_;
|
||||
uint8_t sda_pin_;
|
||||
uint8_t scl_pin_;
|
||||
|
@@ -2,9 +2,9 @@
|
||||
|
||||
#ifdef USE_ESP_IDF
|
||||
|
||||
#include "i2c_bus.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include <driver/i2c.h>
|
||||
#include "esphome/core/component.h"
|
||||
#include "i2c_bus.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace i2c {
|
||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
||||
RECOVERY_COMPLETED,
|
||||
};
|
||||
|
||||
class IDFI2CBus : public I2CBus, public Component {
|
||||
class IDFI2CBus : public InternalI2CBus, public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
@@ -31,6 +31,8 @@ class IDFI2CBus : public I2CBus, public Component {
|
||||
void set_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||
|
||||
int get_port() const override { return static_cast<int>(this->port_); }
|
||||
|
||||
private:
|
||||
void recover_();
|
||||
RecoveryCode recovery_result_;
|
||||
|
@@ -484,7 +484,7 @@ bool I2SAudioSpeaker::send_esp_err_to_event_group_(esp_err_t err) {
|
||||
esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) {
|
||||
if (this->data_buffer_ == nullptr) {
|
||||
// Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->data_buffer_ = allocator.allocate(data_buffer_size);
|
||||
}
|
||||
|
||||
@@ -698,7 +698,7 @@ void I2SAudioSpeaker::delete_task_(size_t buffer_size) {
|
||||
this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
|
||||
|
||||
if (this->data_buffer_ != nullptr) {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
allocator.deallocate(this->data_buffer_, buffer_size);
|
||||
this->data_buffer_ = nullptr;
|
||||
}
|
||||
|
@@ -57,8 +57,8 @@ void Inkplate6::setup() {
|
||||
* Allocate buffers. May be called after setup to re-initialise if e.g. greyscale is changed.
|
||||
*/
|
||||
void Inkplate6::initialize_() {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
ExternalRAMAllocator<uint32_t> allocator32(ExternalRAMAllocator<uint32_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
RAMAllocator<uint32_t> allocator32;
|
||||
uint32_t buffer_size = this->get_buffer_length_();
|
||||
if (buffer_size == 0)
|
||||
return;
|
||||
|
@@ -8,6 +8,8 @@
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
#define highbyte(val) (uint8_t)((val) >> 8)
|
||||
#define lowbyte(val) (uint8_t)((val) &0xff)
|
||||
|
||||
@@ -73,9 +75,9 @@ void LD2410Component::dump_config() {
|
||||
#endif
|
||||
this->read_all_info();
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Throttle_ : %ums\n"
|
||||
" MAC Address : %s\n"
|
||||
" Firmware Version : %s",
|
||||
" Throttle: %ums\n"
|
||||
" MAC address: %s\n"
|
||||
" Firmware version: %s",
|
||||
this->throttle_, const_cast<char *>(this->mac_.c_str()), const_cast<char *>(this->version_.c_str()));
|
||||
}
|
||||
|
||||
@@ -153,7 +155,7 @@ void LD2410Component::handle_periodic_data_(uint8_t *buffer, int len) {
|
||||
/*
|
||||
Reduce data update rate to prevent home assistant database size grow fast
|
||||
*/
|
||||
int32_t current_millis = millis();
|
||||
int32_t current_millis = App.get_loop_component_start_time();
|
||||
if (current_millis - last_periodic_millis_ < this->throttle_)
|
||||
return;
|
||||
last_periodic_millis_ = current_millis;
|
||||
@@ -299,21 +301,6 @@ const char MAC_FMT[] = "%02X:%02X:%02X:%02X:%02X:%02X";
|
||||
const std::string UNKNOWN_MAC("unknown");
|
||||
const std::string NO_MAC("08:05:04:03:02:01");
|
||||
|
||||
std::string format_mac(uint8_t *buffer) {
|
||||
std::string::size_type mac_size = 256;
|
||||
std::string mac;
|
||||
do {
|
||||
mac.resize(mac_size + 1);
|
||||
mac_size = std::snprintf(&mac[0], mac.size(), MAC_FMT, buffer[10], buffer[11], buffer[12], buffer[13], buffer[14],
|
||||
buffer[15]);
|
||||
} while (mac_size + 1 > mac.size());
|
||||
mac.resize(mac_size);
|
||||
if (mac == NO_MAC) {
|
||||
return UNKNOWN_MAC;
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
#ifdef USE_NUMBER
|
||||
std::function<void(void)> set_number_value(number::Number *n, float value) {
|
||||
float normalized_value = value * 1.0;
|
||||
@@ -328,40 +315,40 @@ std::function<void(void)> set_number_value(number::Number *n, float value) {
|
||||
bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", buffer[COMMAND]);
|
||||
if (len < 10) {
|
||||
ESP_LOGE(TAG, "Error with last command : incorrect length");
|
||||
ESP_LOGE(TAG, "Invalid length");
|
||||
return true;
|
||||
}
|
||||
if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // check 4 frame start bytes
|
||||
ESP_LOGE(TAG, "Error with last command : incorrect Header");
|
||||
ESP_LOGE(TAG, "Invalid header");
|
||||
return true;
|
||||
}
|
||||
if (buffer[COMMAND_STATUS] != 0x01) {
|
||||
ESP_LOGE(TAG, "Error with last command : status != 0x01");
|
||||
ESP_LOGE(TAG, "Invalid status");
|
||||
return true;
|
||||
}
|
||||
if (this->two_byte_to_int_(buffer[8], buffer[9]) != 0x00) {
|
||||
ESP_LOGE(TAG, "Error with last command , last buffer was: %u , %u", buffer[8], buffer[9]);
|
||||
ESP_LOGE(TAG, "Invalid command: %u, %u", buffer[8], buffer[9]);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (buffer[COMMAND]) {
|
||||
case lowbyte(CMD_ENABLE_CONF):
|
||||
ESP_LOGV(TAG, "Handled Enable conf command");
|
||||
ESP_LOGV(TAG, "Enable conf");
|
||||
break;
|
||||
case lowbyte(CMD_DISABLE_CONF):
|
||||
ESP_LOGV(TAG, "Handled Disabled conf command");
|
||||
ESP_LOGV(TAG, "Disabled conf");
|
||||
break;
|
||||
case lowbyte(CMD_SET_BAUD_RATE):
|
||||
ESP_LOGV(TAG, "Handled baud rate change command");
|
||||
ESP_LOGV(TAG, "Baud rate change");
|
||||
#ifdef USE_SELECT
|
||||
if (this->baud_rate_select_ != nullptr) {
|
||||
ESP_LOGE(TAG, "Change baud rate component config to %s and reinstall", this->baud_rate_select_->state.c_str());
|
||||
ESP_LOGE(TAG, "Configure baud rate to %s and reinstall", this->baud_rate_select_->state.c_str());
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_VERSION):
|
||||
this->version_ = format_version(buffer);
|
||||
ESP_LOGV(TAG, "FW Version is: %s", const_cast<char *>(this->version_.c_str()));
|
||||
ESP_LOGV(TAG, "Firmware version: %s", const_cast<char *>(this->version_.c_str()));
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
if (this->version_text_sensor_ != nullptr) {
|
||||
this->version_text_sensor_->publish_state(this->version_);
|
||||
@@ -371,7 +358,7 @@ bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
case lowbyte(CMD_QUERY_DISTANCE_RESOLUTION): {
|
||||
std::string distance_resolution =
|
||||
DISTANCE_RESOLUTION_INT_TO_ENUM.at(this->two_byte_to_int_(buffer[10], buffer[11]));
|
||||
ESP_LOGV(TAG, "Distance resolution is: %s", const_cast<char *>(distance_resolution.c_str()));
|
||||
ESP_LOGV(TAG, "Distance resolution: %s", const_cast<char *>(distance_resolution.c_str()));
|
||||
#ifdef USE_SELECT
|
||||
if (this->distance_resolution_select_ != nullptr &&
|
||||
this->distance_resolution_select_->state != distance_resolution) {
|
||||
@@ -383,9 +370,9 @@ bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
this->light_function_ = LIGHT_FUNCTION_INT_TO_ENUM.at(buffer[10]);
|
||||
this->light_threshold_ = buffer[11] * 1.0;
|
||||
this->out_pin_level_ = OUT_PIN_LEVEL_INT_TO_ENUM.at(buffer[12]);
|
||||
ESP_LOGV(TAG, "Light function is: %s", const_cast<char *>(this->light_function_.c_str()));
|
||||
ESP_LOGV(TAG, "Light threshold is: %f", this->light_threshold_);
|
||||
ESP_LOGV(TAG, "Out pin level is: %s", const_cast<char *>(this->out_pin_level_.c_str()));
|
||||
ESP_LOGV(TAG, "Light function: %s", const_cast<char *>(this->light_function_.c_str()));
|
||||
ESP_LOGV(TAG, "Light threshold: %f", this->light_threshold_);
|
||||
ESP_LOGV(TAG, "Out pin level: %s", const_cast<char *>(this->out_pin_level_.c_str()));
|
||||
#ifdef USE_SELECT
|
||||
if (this->light_function_select_ != nullptr && this->light_function_select_->state != this->light_function_) {
|
||||
this->light_function_select_->publish_state(this->light_function_);
|
||||
@@ -406,11 +393,11 @@ bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
if (len < 20) {
|
||||
return false;
|
||||
}
|
||||
this->mac_ = format_mac(buffer);
|
||||
ESP_LOGV(TAG, "MAC Address is: %s", const_cast<char *>(this->mac_.c_str()));
|
||||
this->mac_ = format_mac_address_pretty(&buffer[10]);
|
||||
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
if (this->mac_text_sensor_ != nullptr) {
|
||||
this->mac_text_sensor_->publish_state(this->mac_);
|
||||
this->mac_text_sensor_->publish_state(this->mac_ == NO_MAC ? UNKNOWN_MAC : this->mac_);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
@@ -420,19 +407,19 @@ bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_GATE_SENS):
|
||||
ESP_LOGV(TAG, "Handled sensitivity command");
|
||||
ESP_LOGV(TAG, "Sensitivity");
|
||||
break;
|
||||
case lowbyte(CMD_BLUETOOTH):
|
||||
ESP_LOGV(TAG, "Handled bluetooth command");
|
||||
ESP_LOGV(TAG, "Bluetooth");
|
||||
break;
|
||||
case lowbyte(CMD_SET_DISTANCE_RESOLUTION):
|
||||
ESP_LOGV(TAG, "Handled set distance resolution command");
|
||||
ESP_LOGV(TAG, "Set distance resolution");
|
||||
break;
|
||||
case lowbyte(CMD_SET_LIGHT_CONTROL):
|
||||
ESP_LOGV(TAG, "Handled set light control command");
|
||||
ESP_LOGV(TAG, "Set light control");
|
||||
break;
|
||||
case lowbyte(CMD_BT_PASSWORD):
|
||||
ESP_LOGV(TAG, "Handled set bluetooth password command");
|
||||
ESP_LOGV(TAG, "Set bluetooth password");
|
||||
break;
|
||||
case lowbyte(CMD_QUERY): // Query parameters response
|
||||
{
|
||||
@@ -532,7 +519,7 @@ void LD2410Component::set_baud_rate(const std::string &state) {
|
||||
|
||||
void LD2410Component::set_bluetooth_password(const std::string &password) {
|
||||
if (password.length() != 6) {
|
||||
ESP_LOGE(TAG, "set_bluetooth_password(): invalid password length, must be exactly 6 chars '%s'", password.c_str());
|
||||
ESP_LOGE(TAG, "Password must be exactly 6 chars");
|
||||
return;
|
||||
}
|
||||
this->set_config_mode_(true);
|
||||
@@ -544,7 +531,7 @@ void LD2410Component::set_bluetooth_password(const std::string &password) {
|
||||
|
||||
void LD2410Component::set_engineering_mode(bool enable) {
|
||||
this->set_config_mode_(true);
|
||||
last_engineering_mode_change_millis_ = millis();
|
||||
last_engineering_mode_change_millis_ = App.get_loop_component_start_time();
|
||||
uint8_t cmd = enable ? CMD_ENABLE_ENG : CMD_DISABLE_ENG;
|
||||
this->send_command_(cmd, nullptr, 0);
|
||||
this->set_config_mode_(false);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "ld2420.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
/*
|
||||
@@ -40,7 +41,7 @@ There are three documented parameters for modes:
|
||||
00 04 = Energy output mode
|
||||
This mode outputs detailed signal energy values for each gate and the target distance.
|
||||
The data format consist of the following.
|
||||
Header HH, Length LL, Persence PP, Distance DD, 16 Gate Energies EE, Footer FF
|
||||
Header HH, Length LL, Presence PP, Distance DD, 16 Gate Energies EE, Footer FF
|
||||
HH HH HH HH LL LL PP DD DD EE EE .. 16x .. FF FF FF FF
|
||||
F4 F3 F2 F1 23 00 00 00 00 00 00 .. .. .. .. F8 F7 F6 F5
|
||||
00 00 = debug output mode
|
||||
@@ -67,10 +68,10 @@ float LD2420Component::get_setup_priority() const { return setup_priority::BUS;
|
||||
void LD2420Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG,
|
||||
"LD2420:\n"
|
||||
" Firmware Version : %7s\n"
|
||||
"LD2420 Number:",
|
||||
" Firmware version: %7s",
|
||||
this->ld2420_firmware_ver_);
|
||||
#ifdef USE_NUMBER
|
||||
ESP_LOGCONFIG(TAG, "Number:");
|
||||
LOG_NUMBER(TAG, " Gate Timeout:", this->gate_timeout_number_);
|
||||
LOG_NUMBER(TAG, " Gate Max Distance:", this->max_gate_distance_number_);
|
||||
LOG_NUMBER(TAG, " Gate Min Distance:", this->min_gate_distance_number_);
|
||||
@@ -86,10 +87,10 @@ void LD2420Component::dump_config() {
|
||||
LOG_BUTTON(TAG, " Factory Reset:", this->factory_reset_button_);
|
||||
LOG_BUTTON(TAG, " Restart Module:", this->restart_module_button_);
|
||||
#endif
|
||||
ESP_LOGCONFIG(TAG, "LD2420 Select:");
|
||||
ESP_LOGCONFIG(TAG, "Select:");
|
||||
LOG_SELECT(TAG, " Operating Mode", this->operating_selector_);
|
||||
if (this->get_firmware_int_(ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
||||
ESP_LOGW(TAG, "LD2420 Firmware Version %s and older are only supported in Simple Mode", ld2420_firmware_ver_);
|
||||
if (LD2420Component::get_firmware_int(this->ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
||||
ESP_LOGW(TAG, "Firmware version %s and older supports Simple Mode only", this->ld2420_firmware_ver_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ uint8_t LD2420Component::calc_checksum(void *data, size_t size) {
|
||||
return checksum;
|
||||
}
|
||||
|
||||
int LD2420Component::get_firmware_int_(const char *version_string) {
|
||||
int LD2420Component::get_firmware_int(const char *version_string) {
|
||||
std::string version_str = version_string;
|
||||
if (version_str[0] == 'v') {
|
||||
version_str = version_str.substr(1);
|
||||
@@ -115,7 +116,7 @@ int LD2420Component::get_firmware_int_(const char *version_string) {
|
||||
void LD2420Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Running setup");
|
||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
||||
ESP_LOGE(TAG, "LD2420 module has failed to respond, check baud rate and serial connections.");
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -127,7 +128,7 @@ void LD2420Component::setup() {
|
||||
const char *pfw = this->ld2420_firmware_ver_;
|
||||
std::string fw_str(pfw);
|
||||
|
||||
for (auto &listener : listeners_) {
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_fw_version(fw_str);
|
||||
}
|
||||
|
||||
@@ -137,11 +138,11 @@ void LD2420Component::setup() {
|
||||
}
|
||||
|
||||
memcpy(&this->new_config, &this->current_config, sizeof(this->current_config));
|
||||
if (get_firmware_int_(ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
||||
if (LD2420Component::get_firmware_int(this->ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
||||
this->set_operating_mode(OP_SIMPLE_MODE_STRING);
|
||||
this->operating_selector_->publish_state(OP_SIMPLE_MODE_STRING);
|
||||
this->set_mode_(CMD_SYSTEM_MODE_SIMPLE);
|
||||
ESP_LOGW(TAG, "LD2420 Frimware Version %s and older are only supported in Simple Mode", ld2420_firmware_ver_);
|
||||
ESP_LOGW(TAG, "Firmware version %s and older supports Simple Mode only", this->ld2420_firmware_ver_);
|
||||
} else {
|
||||
this->set_mode_(CMD_SYSTEM_MODE_ENERGY);
|
||||
this->operating_selector_->publish_state(OP_NORMAL_MODE_STRING);
|
||||
@@ -151,18 +152,17 @@ void LD2420Component::setup() {
|
||||
#endif
|
||||
this->set_system_mode(this->system_mode_);
|
||||
this->set_config_mode(false);
|
||||
ESP_LOGCONFIG(TAG, "LD2420 setup complete.");
|
||||
}
|
||||
|
||||
void LD2420Component::apply_config_action() {
|
||||
const uint8_t checksum = calc_checksum(&this->new_config, sizeof(this->new_config));
|
||||
if (checksum == calc_checksum(&this->current_config, sizeof(this->current_config))) {
|
||||
ESP_LOGCONFIG(TAG, "No configuration change detected");
|
||||
ESP_LOGD(TAG, "No configuration change detected");
|
||||
return;
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, "Reconfiguring LD2420");
|
||||
ESP_LOGD(TAG, "Reconfiguring");
|
||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
||||
ESP_LOGE(TAG, "LD2420 module has failed to respond, check baud rate and serial connections.");
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -178,13 +178,12 @@ void LD2420Component::apply_config_action() {
|
||||
this->set_system_mode(this->system_mode_);
|
||||
this->set_config_mode(false); // Disable config mode to save new values in LD2420 nvm
|
||||
this->set_operating_mode(OP_NORMAL_MODE_STRING);
|
||||
ESP_LOGCONFIG(TAG, "LD2420 reconfig complete.");
|
||||
}
|
||||
|
||||
void LD2420Component::factory_reset_action() {
|
||||
ESP_LOGCONFIG(TAG, "Setting factory defaults");
|
||||
ESP_LOGD(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.");
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -207,18 +206,16 @@ void LD2420Component::factory_reset_action() {
|
||||
this->init_gate_config_numbers();
|
||||
this->refresh_gate_config_numbers();
|
||||
#endif
|
||||
ESP_LOGCONFIG(TAG, "LD2420 factory reset complete.");
|
||||
}
|
||||
|
||||
void LD2420Component::restart_module_action() {
|
||||
ESP_LOGCONFIG(TAG, "Restarting LD2420 module");
|
||||
ESP_LOGD(TAG, "Restarting");
|
||||
this->send_module_restart();
|
||||
this->set_timeout(250, [this]() {
|
||||
this->set_config_mode(true);
|
||||
this->set_system_mode(system_mode_);
|
||||
this->set_system_mode(this->system_mode_);
|
||||
this->set_config_mode(false);
|
||||
});
|
||||
ESP_LOGCONFIG(TAG, "LD2420 Restarted.");
|
||||
}
|
||||
|
||||
void LD2420Component::revert_config_action() {
|
||||
@@ -226,18 +223,18 @@ void LD2420Component::revert_config_action() {
|
||||
#ifdef USE_NUMBER
|
||||
this->init_gate_config_numbers();
|
||||
#endif
|
||||
ESP_LOGCONFIG(TAG, "Reverted config number edits.");
|
||||
ESP_LOGD(TAG, "Reverted config number edits");
|
||||
}
|
||||
|
||||
void LD2420Component::loop() {
|
||||
// If there is a active send command do not process it here, the send command call will handle it.
|
||||
if (!get_cmd_active_()) {
|
||||
if (!available())
|
||||
if (!this->get_cmd_active_()) {
|
||||
if (!this->available())
|
||||
return;
|
||||
static uint8_t buffer[2048];
|
||||
static uint8_t rx_data;
|
||||
while (available()) {
|
||||
rx_data = read();
|
||||
while (this->available()) {
|
||||
rx_data = this->read();
|
||||
this->readline_(rx_data, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
@@ -292,7 +289,7 @@ void LD2420Component::report_gate_data() {
|
||||
|
||||
void LD2420Component::set_operating_mode(const std::string &state) {
|
||||
// If unsupported firmware ignore mode select
|
||||
if (get_firmware_int_(ld2420_firmware_ver_) >= CALIBRATE_VERSION_MIN) {
|
||||
if (LD2420Component::get_firmware_int(ld2420_firmware_ver_) >= CALIBRATE_VERSION_MIN) {
|
||||
this->current_operating_mode = OP_MODE_TO_UINT.at(state);
|
||||
// Entering Auto Calibrate we need to clear the privoiuos data collection
|
||||
this->operating_selector_->publish_state(state);
|
||||
@@ -365,13 +362,13 @@ void LD2420Component::handle_energy_mode_(uint8_t *buffer, int len) {
|
||||
}
|
||||
|
||||
// Resonable refresh rate for home assistant database size health
|
||||
const int32_t current_millis = millis();
|
||||
const int32_t current_millis = App.get_loop_component_start_time();
|
||||
if (current_millis - this->last_periodic_millis < REFRESH_RATE_MS)
|
||||
return;
|
||||
this->last_periodic_millis = current_millis;
|
||||
for (auto &listener : this->listeners_) {
|
||||
listener->on_distance(get_distance_());
|
||||
listener->on_presence(get_presence_());
|
||||
listener->on_distance(this->get_distance_());
|
||||
listener->on_presence(this->get_presence_());
|
||||
listener->on_energy(this->gate_energy_, sizeof(this->gate_energy_) / sizeof(this->gate_energy_[0]));
|
||||
}
|
||||
|
||||
@@ -392,9 +389,9 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) {
|
||||
char outbuf[bufsize]{0};
|
||||
while (true) {
|
||||
if (inbuf[pos - 2] == 'O' && inbuf[pos - 1] == 'F' && inbuf[pos] == 'F') {
|
||||
set_presence_(false);
|
||||
this->set_presence_(false);
|
||||
} else if (inbuf[pos - 1] == 'O' && inbuf[pos] == 'N') {
|
||||
set_presence_(true);
|
||||
this->set_presence_(true);
|
||||
}
|
||||
if (inbuf[pos] >= '0' && inbuf[pos] <= '9') {
|
||||
if (index < bufsize - 1) {
|
||||
@@ -411,18 +408,18 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) {
|
||||
}
|
||||
outbuf[index] = '\0';
|
||||
if (index > 1)
|
||||
set_distance_(strtol(outbuf, &endptr, 10));
|
||||
this->set_distance_(strtol(outbuf, &endptr, 10));
|
||||
|
||||
if (get_mode_() == CMD_SYSTEM_MODE_SIMPLE) {
|
||||
if (this->get_mode_() == CMD_SYSTEM_MODE_SIMPLE) {
|
||||
// Resonable refresh rate for home assistant database size health
|
||||
const int32_t current_millis = millis();
|
||||
const int32_t current_millis = App.get_loop_component_start_time();
|
||||
if (current_millis - this->last_normal_periodic_millis < REFRESH_RATE_MS)
|
||||
return;
|
||||
this->last_normal_periodic_millis = current_millis;
|
||||
for (auto &listener : this->listeners_)
|
||||
listener->on_distance(get_distance_());
|
||||
listener->on_distance(this->get_distance_());
|
||||
for (auto &listener : this->listeners_)
|
||||
listener->on_presence(get_presence_());
|
||||
listener->on_presence(this->get_presence_());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -433,10 +430,10 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
uint8_t data_element = 0;
|
||||
uint16_t data_pos = 0;
|
||||
if (this->cmd_reply_.length > CMD_MAX_BYTES) {
|
||||
ESP_LOGW(TAG, "LD2420 reply - received command reply frame is corrupt, length exceeds %d bytes.", CMD_MAX_BYTES);
|
||||
ESP_LOGW(TAG, "Reply frame too long");
|
||||
return;
|
||||
} else if (this->cmd_reply_.length < 2) {
|
||||
ESP_LOGW(TAG, "LD2420 reply - received command frame is corrupt, length is less than 2 bytes.");
|
||||
ESP_LOGW(TAG, "Command frame too short");
|
||||
return;
|
||||
}
|
||||
memcpy(&this->cmd_reply_.error, &buffer[CMD_ERROR_WORD], sizeof(this->cmd_reply_.error));
|
||||
@@ -447,13 +444,13 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
this->cmd_reply_.ack = true;
|
||||
switch ((uint16_t) this->cmd_reply_.command) {
|
||||
case (CMD_ENABLE_CONF):
|
||||
ESP_LOGD(TAG, "LD2420 reply - set config enable: CMD = %2X %s", CMD_ENABLE_CONF, result);
|
||||
ESP_LOGV(TAG, "Set config enable: CMD = %2X %s", CMD_ENABLE_CONF, result);
|
||||
break;
|
||||
case (CMD_DISABLE_CONF):
|
||||
ESP_LOGD(TAG, "LD2420 reply - set config disable: CMD = %2X %s", CMD_DISABLE_CONF, result);
|
||||
ESP_LOGV(TAG, "Set config disable: CMD = %2X %s", CMD_DISABLE_CONF, result);
|
||||
break;
|
||||
case (CMD_READ_REGISTER):
|
||||
ESP_LOGD(TAG, "LD2420 reply - read register: CMD = %2X %s", CMD_READ_REGISTER, result);
|
||||
ESP_LOGV(TAG, "Read register: CMD = %2X %s", CMD_READ_REGISTER, result);
|
||||
// TODO Read/Write register is not implemented yet, this will get flushed out to a proper header file
|
||||
data_pos = 0x0A;
|
||||
for (uint16_t index = 0; index < (CMD_REG_DATA_REPLY_SIZE * // NOLINT
|
||||
@@ -465,13 +462,13 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
}
|
||||
break;
|
||||
case (CMD_WRITE_REGISTER):
|
||||
ESP_LOGD(TAG, "LD2420 reply - write register: CMD = %2X %s", CMD_WRITE_REGISTER, result);
|
||||
ESP_LOGV(TAG, "Write register: CMD = %2X %s", CMD_WRITE_REGISTER, result);
|
||||
break;
|
||||
case (CMD_WRITE_ABD_PARAM):
|
||||
ESP_LOGD(TAG, "LD2420 reply - write gate parameter(s): %2X %s", CMD_WRITE_ABD_PARAM, result);
|
||||
ESP_LOGV(TAG, "Write gate parameter(s): %2X %s", CMD_WRITE_ABD_PARAM, result);
|
||||
break;
|
||||
case (CMD_READ_ABD_PARAM):
|
||||
ESP_LOGD(TAG, "LD2420 reply - read gate parameter(s): %2X %s", CMD_READ_ABD_PARAM, result);
|
||||
ESP_LOGV(TAG, "Read gate parameter(s): %2X %s", CMD_READ_ABD_PARAM, result);
|
||||
data_pos = CMD_ABD_DATA_REPLY_START;
|
||||
for (uint16_t index = 0; index < (CMD_ABD_DATA_REPLY_SIZE * // NOLINT
|
||||
((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_ABD_DATA_REPLY_SIZE));
|
||||
@@ -483,11 +480,11 @@ void LD2420Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||
}
|
||||
break;
|
||||
case (CMD_WRITE_SYS_PARAM):
|
||||
ESP_LOGD(TAG, "LD2420 reply - set system parameter(s): %2X %s", CMD_WRITE_SYS_PARAM, result);
|
||||
ESP_LOGV(TAG, "Set system parameter(s): %2X %s", CMD_WRITE_SYS_PARAM, result);
|
||||
break;
|
||||
case (CMD_READ_VERSION):
|
||||
memcpy(this->ld2420_firmware_ver_, &buffer[12], buffer[10]);
|
||||
ESP_LOGD(TAG, "LD2420 reply - module firmware version: %7s %s", this->ld2420_firmware_ver_, result);
|
||||
ESP_LOGV(TAG, "Firmware version: %7s %s", this->ld2420_firmware_ver_, result);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -533,7 +530,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
||||
}
|
||||
|
||||
while (!this->cmd_reply_.ack) {
|
||||
while (available()) {
|
||||
while (this->available()) {
|
||||
this->readline_(read(), ack_buffer, sizeof(ack_buffer));
|
||||
}
|
||||
delay_microseconds_safe(1450);
|
||||
@@ -548,7 +545,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
||||
if (this->cmd_reply_.ack)
|
||||
retry = 0;
|
||||
if (this->cmd_reply_.error > 0)
|
||||
handle_cmd_error(error);
|
||||
this->handle_cmd_error(error);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@@ -563,7 +560,7 @@ uint8_t LD2420Component::set_config_mode(bool enable) {
|
||||
cmd_frame.data_length += sizeof(CMD_PROTOCOL_VER);
|
||||
}
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending set config %s command: %2X", enable ? "enable" : "disable", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending set config %s command: %2X", enable ? "enable" : "disable", cmd_frame.command);
|
||||
return this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
@@ -576,7 +573,7 @@ void LD2420Component::ld2420_restart() {
|
||||
cmd_frame.header = CMD_FRAME_HEADER;
|
||||
cmd_frame.command = CMD_RESTART;
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending restart command: %2X", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending restart command: %2X", cmd_frame.command);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
@@ -588,7 +585,7 @@ void LD2420Component::get_reg_value_(uint16_t reg) {
|
||||
cmd_frame.data[1] = reg;
|
||||
cmd_frame.data_length += 2;
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending read register %4X command: %2X", reg, cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending read register %4X command: %2X", reg, cmd_frame.command);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
@@ -602,11 +599,11 @@ void LD2420Component::set_reg_value(uint16_t reg, uint16_t value) {
|
||||
memcpy(&cmd_frame.data[cmd_frame.data_length], &value, sizeof(CMD_REG_DATA_REPLY_SIZE));
|
||||
cmd_frame.data_length += 2;
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending write register %4X command: %2X data = %4X", reg, cmd_frame.command, value);
|
||||
ESP_LOGV(TAG, "Sending write register %4X command: %2X data = %4X", reg, cmd_frame.command, value);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
void LD2420Component::handle_cmd_error(uint8_t error) { ESP_LOGI(TAG, "Command failed: %s", ERR_MESSAGE[error]); }
|
||||
void LD2420Component::handle_cmd_error(uint8_t error) { ESP_LOGE(TAG, "Command failed: %s", ERR_MESSAGE[error]); }
|
||||
|
||||
int LD2420Component::get_gate_threshold_(uint8_t gate) {
|
||||
uint8_t error;
|
||||
@@ -619,7 +616,7 @@ int LD2420Component::get_gate_threshold_(uint8_t gate) {
|
||||
memcpy(&cmd_frame.data[cmd_frame.data_length], &CMD_GATE_STILL_THRESH[gate], sizeof(CMD_GATE_STILL_THRESH[gate]));
|
||||
cmd_frame.data_length += 2;
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending read gate %d high/low theshold command: %2X", gate, cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending read gate %d high/low threshold command: %2X", gate, cmd_frame.command);
|
||||
error = this->send_cmd_from_array(cmd_frame);
|
||||
if (error == 0) {
|
||||
this->current_config.move_thresh[gate] = cmd_reply_.data[0];
|
||||
@@ -644,7 +641,7 @@ int LD2420Component::get_min_max_distances_timeout_() {
|
||||
sizeof(CMD_TIMEOUT_REG)); // Register: global delay time
|
||||
cmd_frame.data_length += sizeof(CMD_TIMEOUT_REG);
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending read gate min max and timeout command: %2X", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending read gate min max and timeout command: %2X", cmd_frame.command);
|
||||
error = this->send_cmd_from_array(cmd_frame);
|
||||
if (error == 0) {
|
||||
this->current_config.min_gate = (uint16_t) cmd_reply_.data[0];
|
||||
@@ -667,9 +664,9 @@ void LD2420Component::set_system_mode(uint16_t mode) {
|
||||
memcpy(&cmd_frame.data[cmd_frame.data_length], &unknown_parm, sizeof(unknown_parm));
|
||||
cmd_frame.data_length += sizeof(unknown_parm);
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending write system mode command: %2X", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending write system mode command: %2X", cmd_frame.command);
|
||||
if (this->send_cmd_from_array(cmd_frame) == 0)
|
||||
set_mode_(mode);
|
||||
this->set_mode_(mode);
|
||||
}
|
||||
|
||||
void LD2420Component::get_firmware_version_() {
|
||||
@@ -679,7 +676,7 @@ void LD2420Component::get_firmware_version_() {
|
||||
cmd_frame.command = CMD_READ_VERSION;
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
|
||||
ESP_LOGD(TAG, "Sending read firmware version command: %2X", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending read firmware version command: %2X", cmd_frame.command);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
@@ -712,7 +709,7 @@ void LD2420Component::set_min_max_distances_timeout(uint32_t max_gate_distance,
|
||||
cmd_frame.data_length += sizeof(timeout);
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
|
||||
ESP_LOGD(TAG, "Sending write gate min max and timeout command: %2X", cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending write gate min max and timeout command: %2X", cmd_frame.command);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
@@ -738,7 +735,7 @@ void LD2420Component::set_gate_threshold(uint8_t gate) {
|
||||
sizeof(this->new_config.still_thresh[gate]));
|
||||
cmd_frame.data_length += sizeof(this->new_config.still_thresh[gate]);
|
||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
||||
ESP_LOGD(TAG, "Sending set gate %4X sensitivity command: %2X", gate, cmd_frame.command);
|
||||
ESP_LOGV(TAG, "Sending set gate %4X sensitivity command: %2X", gate, cmd_frame.command);
|
||||
this->send_cmd_from_array(cmd_frame);
|
||||
}
|
||||
|
||||
|
@@ -179,7 +179,7 @@ class LD2420Component : public Component, public uart::UARTDevice {
|
||||
void set_operating_mode(const std::string &state);
|
||||
void auto_calibrate_sensitivity();
|
||||
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
|
||||
uint8_t calc_checksum(void *data, size_t size);
|
||||
static uint8_t calc_checksum(void *data, size_t size);
|
||||
|
||||
RegConfigT current_config;
|
||||
RegConfigT new_config;
|
||||
@@ -222,7 +222,7 @@ class LD2420Component : public Component, public uart::UARTDevice {
|
||||
volatile bool ack;
|
||||
};
|
||||
|
||||
int get_firmware_int_(const char *version_string);
|
||||
static int get_firmware_int(const char *version_string);
|
||||
void get_firmware_version_();
|
||||
int get_gate_threshold_(uint8_t gate);
|
||||
void get_reg_value_(uint16_t reg);
|
||||
|
@@ -6,7 +6,9 @@
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#define highbyte(val) (uint8_t)((val) >> 8)
|
||||
#define lowbyte(val) (uint8_t)((val) &0xff)
|
||||
@@ -96,11 +98,6 @@ static inline std::string get_direction(int16_t speed) {
|
||||
return STATIONARY;
|
||||
}
|
||||
|
||||
static inline std::string format_mac(uint8_t *buffer) {
|
||||
return str_snprintf("%02X:%02X:%02X:%02X:%02X:%02X", 17, buffer[10], buffer[11], buffer[12], buffer[13], buffer[14],
|
||||
buffer[15]);
|
||||
}
|
||||
|
||||
static inline std::string format_version(uint8_t *buffer) {
|
||||
return str_sprintf("%u.%02X.%02X%02X%02X%02X", buffer[13], buffer[12], buffer[17], buffer[16], buffer[15],
|
||||
buffer[14]);
|
||||
@@ -120,7 +117,7 @@ void LD2450Component::setup() {
|
||||
}
|
||||
|
||||
void LD2450Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "HLK-LD2450 Human motion tracking radar module:");
|
||||
ESP_LOGCONFIG(TAG, "LD2450:");
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_);
|
||||
LOG_BINARY_SENSOR(" ", "MovingTargetBinarySensor", this->moving_target_binary_sensor_);
|
||||
@@ -189,9 +186,9 @@ void LD2450Component::dump_config() {
|
||||
LOG_NUMBER(" ", "PresenceTimeoutNumber", this->presence_timeout_number_);
|
||||
#endif
|
||||
ESP_LOGCONFIG(TAG,
|
||||
" Throttle : %ums\n"
|
||||
" MAC Address : %s\n"
|
||||
" Firmware version : %s",
|
||||
" Throttle: %ums\n"
|
||||
" MAC Address: %s\n"
|
||||
" Firmware version: %s",
|
||||
this->throttle_, const_cast<char *>(this->mac_.c_str()), const_cast<char *>(this->version_.c_str()));
|
||||
}
|
||||
|
||||
@@ -266,8 +263,7 @@ bool LD2450Component::get_timeout_status_(uint32_t check_millis) {
|
||||
if (this->timeout_ == 0) {
|
||||
this->timeout_ = ld2450::convert_seconds_to_ms(DEFAULT_PRESENCE_TIMEOUT);
|
||||
}
|
||||
auto current_millis = millis();
|
||||
return current_millis - check_millis >= this->timeout_;
|
||||
return App.get_loop_component_start_time() - check_millis >= this->timeout_;
|
||||
}
|
||||
|
||||
// Extract, store and publish zone details LD2450 buffer
|
||||
@@ -354,25 +350,24 @@ void LD2450Component::send_command_(uint8_t command, const uint8_t *command_valu
|
||||
// Header Target 1 Target 2 Target 3 End
|
||||
void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
|
||||
if (len < 29) { // header (4 bytes) + 8 x 3 target data + footer (2 bytes)
|
||||
ESP_LOGE(TAG, "Periodic data: invalid message length");
|
||||
ESP_LOGE(TAG, "Invalid message length");
|
||||
return;
|
||||
}
|
||||
if (buffer[0] != 0xAA || buffer[1] != 0xFF || buffer[2] != 0x03 || buffer[3] != 0x00) { // header
|
||||
ESP_LOGE(TAG, "Periodic data: invalid message header");
|
||||
ESP_LOGE(TAG, "Invalid message header");
|
||||
return;
|
||||
}
|
||||
if (buffer[len - 2] != 0x55 || buffer[len - 1] != 0xCC) { // footer
|
||||
ESP_LOGE(TAG, "Periodic data: invalid message footer");
|
||||
ESP_LOGE(TAG, "Invalid message footer");
|
||||
return;
|
||||
}
|
||||
|
||||
auto current_millis = millis();
|
||||
if (current_millis - this->last_periodic_millis_ < this->throttle_) {
|
||||
if (App.get_loop_component_start_time() - this->last_periodic_millis_ < this->throttle_) {
|
||||
ESP_LOGV(TAG, "Throttling: %d", this->throttle_);
|
||||
return;
|
||||
}
|
||||
|
||||
this->last_periodic_millis_ = current_millis;
|
||||
this->last_periodic_millis_ = App.get_loop_component_start_time();
|
||||
|
||||
int16_t target_count = 0;
|
||||
int16_t still_target_count = 0;
|
||||
@@ -555,13 +550,13 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
|
||||
#ifdef USE_SENSOR
|
||||
// For presence timeout check
|
||||
if (target_count > 0) {
|
||||
this->presence_millis_ = millis();
|
||||
this->presence_millis_ = App.get_loop_component_start_time();
|
||||
}
|
||||
if (moving_target_count > 0) {
|
||||
this->moving_presence_millis_ = millis();
|
||||
this->moving_presence_millis_ = App.get_loop_component_start_time();
|
||||
}
|
||||
if (still_target_count > 0) {
|
||||
this->still_presence_millis_ = millis();
|
||||
this->still_presence_millis_ = App.get_loop_component_start_time();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -569,31 +564,31 @@ void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
|
||||
bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
ESP_LOGV(TAG, "Handling ack data for command %02X", buffer[COMMAND]);
|
||||
if (len < 10) {
|
||||
ESP_LOGE(TAG, "Ack data: invalid length");
|
||||
ESP_LOGE(TAG, "Invalid ack length");
|
||||
return true;
|
||||
}
|
||||
if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // frame header
|
||||
ESP_LOGE(TAG, "Ack data: invalid header (command %02X)", buffer[COMMAND]);
|
||||
ESP_LOGE(TAG, "Invalid ack header (command %02X)", buffer[COMMAND]);
|
||||
return true;
|
||||
}
|
||||
if (buffer[COMMAND_STATUS] != 0x01) {
|
||||
ESP_LOGE(TAG, "Ack data: invalid status");
|
||||
ESP_LOGE(TAG, "Invalid ack status");
|
||||
return true;
|
||||
}
|
||||
if (buffer[8] || buffer[9]) {
|
||||
ESP_LOGE(TAG, "Ack data: last buffer was %u, %u", buffer[8], buffer[9]);
|
||||
ESP_LOGE(TAG, "Last buffer was %u, %u", buffer[8], buffer[9]);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (buffer[COMMAND]) {
|
||||
case lowbyte(CMD_ENABLE_CONF):
|
||||
ESP_LOGV(TAG, "Got enable conf command");
|
||||
ESP_LOGV(TAG, "Enable conf command");
|
||||
break;
|
||||
case lowbyte(CMD_DISABLE_CONF):
|
||||
ESP_LOGV(TAG, "Got disable conf command");
|
||||
ESP_LOGV(TAG, "Disable conf command");
|
||||
break;
|
||||
case lowbyte(CMD_SET_BAUD_RATE):
|
||||
ESP_LOGV(TAG, "Got baud rate change command");
|
||||
ESP_LOGV(TAG, "Baud rate change command");
|
||||
#ifdef USE_SELECT
|
||||
if (this->baud_rate_select_ != nullptr) {
|
||||
ESP_LOGV(TAG, "Change baud rate to %s", this->baud_rate_select_->state.c_str());
|
||||
@@ -613,7 +608,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
if (len < 20) {
|
||||
return false;
|
||||
}
|
||||
this->mac_ = ld2450::format_mac(buffer);
|
||||
this->mac_ = format_mac_address_pretty(&buffer[10]);
|
||||
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
if (this->mac_text_sensor_ != nullptr) {
|
||||
@@ -622,15 +617,15 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
#endif
|
||||
#ifdef USE_SWITCH
|
||||
if (this->bluetooth_switch_ != nullptr) {
|
||||
this->bluetooth_switch_->publish_state(this->mac_ != NO_MAC);
|
||||
this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_BLUETOOTH):
|
||||
ESP_LOGV(TAG, "Got Bluetooth command");
|
||||
ESP_LOGV(TAG, "Bluetooth command");
|
||||
break;
|
||||
case lowbyte(CMD_SINGLE_TARGET_MODE):
|
||||
ESP_LOGV(TAG, "Got single target conf command");
|
||||
ESP_LOGV(TAG, "Single target conf command");
|
||||
#ifdef USE_SWITCH
|
||||
if (this->multi_target_switch_ != nullptr) {
|
||||
this->multi_target_switch_->publish_state(false);
|
||||
@@ -638,7 +633,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_MULTI_TARGET_MODE):
|
||||
ESP_LOGV(TAG, "Got multi target conf command");
|
||||
ESP_LOGV(TAG, "Multi target conf command");
|
||||
#ifdef USE_SWITCH
|
||||
if (this->multi_target_switch_ != nullptr) {
|
||||
this->multi_target_switch_->publish_state(true);
|
||||
@@ -646,7 +641,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_QUERY_TARGET_MODE):
|
||||
ESP_LOGV(TAG, "Got query target tracking mode command");
|
||||
ESP_LOGV(TAG, "Query target tracking mode command");
|
||||
#ifdef USE_SWITCH
|
||||
if (this->multi_target_switch_ != nullptr) {
|
||||
this->multi_target_switch_->publish_state(buffer[10] == 0x02);
|
||||
@@ -654,7 +649,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
#endif
|
||||
break;
|
||||
case lowbyte(CMD_QUERY_ZONE):
|
||||
ESP_LOGV(TAG, "Got query zone conf command");
|
||||
ESP_LOGV(TAG, "Query zone conf command");
|
||||
this->zone_type_ = std::stoi(std::to_string(buffer[10]), nullptr, 16);
|
||||
this->publish_zone_type();
|
||||
#ifdef USE_SELECT
|
||||
@@ -674,7 +669,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||
this->process_zone_(buffer);
|
||||
break;
|
||||
case lowbyte(CMD_SET_ZONE):
|
||||
ESP_LOGV(TAG, "Got set zone conf command");
|
||||
ESP_LOGV(TAG, "Set zone conf command");
|
||||
this->query_zone_info();
|
||||
break;
|
||||
default:
|
||||
|
@@ -38,8 +38,8 @@ from esphome.const import (
|
||||
CONF_WHITE,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
from .automation import LIGHT_STATE_SCHEMA
|
||||
from .effects import (
|
||||
@@ -110,6 +110,8 @@ LIGHT_SCHEMA = (
|
||||
)
|
||||
)
|
||||
|
||||
LIGHT_SCHEMA.add_extra(entity_duplicate_validator("light"))
|
||||
|
||||
BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend(
|
||||
{
|
||||
cv.Optional(CONF_EFFECTS): validate_effects(BINARY_EFFECTS),
|
||||
@@ -207,7 +209,7 @@ def validate_color_temperature_channels(value):
|
||||
|
||||
|
||||
async def setup_light_core_(light_var, output_var, config):
|
||||
await setup_entity(light_var, config)
|
||||
await setup_entity(light_var, config, "light")
|
||||
|
||||
cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||
|
||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -67,6 +67,9 @@ _LOCK_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_LOCK_SCHEMA.add_extra(entity_duplicate_validator("lock"))
|
||||
|
||||
|
||||
def lock_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -94,7 +97,7 @@ LOCK_SCHEMA.add_extra(cv.deprecated_schema_constant("lock"))
|
||||
|
||||
|
||||
async def _setup_lock_core(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "lock")
|
||||
|
||||
for conf in config.get(CONF_ON_LOCK, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
|
@@ -184,7 +184,9 @@ CONFIG_SCHEMA = cv.All(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(Logger),
|
||||
cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
|
||||
cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes,
|
||||
cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.All(
|
||||
cv.validate_bytes, cv.int_range(min=160, max=65535)
|
||||
),
|
||||
cv.Optional(CONF_DEASSERT_RTS_DTR, default=False): cv.boolean,
|
||||
cv.SplitDefault(
|
||||
CONF_TASK_LOG_BUFFER_SIZE,
|
||||
|
@@ -24,7 +24,7 @@ static const char *const TAG = "logger";
|
||||
// - Messages are serialized through main loop for proper console output
|
||||
// - Fallback to emergency console logging only if ring buffer is full
|
||||
// - WITHOUT task log buffer: Only emergency console output, no callbacks
|
||||
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
||||
void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
||||
if (level > this->level_for(tag))
|
||||
return;
|
||||
|
||||
@@ -46,8 +46,8 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
||||
bool message_sent = false;
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
// For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered
|
||||
message_sent = this->log_buffer_->send_message_thread_safe(static_cast<uint8_t>(level), tag,
|
||||
static_cast<uint16_t>(line), current_task, format, args);
|
||||
message_sent =
|
||||
this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), current_task, format, args);
|
||||
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
||||
|
||||
// Emergency console logging for non-main tasks when ring buffer is full or disabled
|
||||
@@ -58,7 +58,7 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
||||
// Maximum size for console log messages (includes null terminator)
|
||||
static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144;
|
||||
char console_buffer[MAX_CONSOLE_LOG_MSG_SIZE]; // MUST be stack allocated for thread safety
|
||||
int buffer_at = 0; // Initialize buffer position
|
||||
uint16_t buffer_at = 0; // Initialize buffer position
|
||||
this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, console_buffer, &buffer_at,
|
||||
MAX_CONSOLE_LOG_MSG_SIZE);
|
||||
this->write_msg_(console_buffer);
|
||||
@@ -69,7 +69,7 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
||||
}
|
||||
#else
|
||||
// Implementation for all other platforms
|
||||
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
||||
void HOT Logger::log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
||||
if (level > this->level_for(tag) || global_recursion_guard_)
|
||||
return;
|
||||
|
||||
@@ -85,7 +85,7 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
||||
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
||||
// Implementation for ESP8266 with flash string support.
|
||||
// Note: USE_STORE_LOG_STR_IN_FLASH is only defined for ESP8266.
|
||||
void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format,
|
||||
void Logger::log_vprintf_(uint8_t level, const char *tag, int line, const __FlashStringHelper *format,
|
||||
va_list args) { // NOLINT
|
||||
if (level > this->level_for(tag) || global_recursion_guard_)
|
||||
return;
|
||||
@@ -122,7 +122,7 @@ void Logger::log_vprintf_(int level, const char *tag, int line, const __FlashStr
|
||||
}
|
||||
#endif // USE_STORE_LOG_STR_IN_FLASH
|
||||
|
||||
inline int Logger::level_for(const char *tag) {
|
||||
inline uint8_t Logger::level_for(const char *tag) {
|
||||
auto it = this->log_levels_.find(tag);
|
||||
if (it != this->log_levels_.end())
|
||||
return it->second;
|
||||
@@ -195,13 +195,13 @@ void Logger::loop() {
|
||||
#endif
|
||||
|
||||
void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
|
||||
void Logger::set_log_level(const std::string &tag, int log_level) { this->log_levels_[tag] = log_level; }
|
||||
void Logger::set_log_level(const std::string &tag, uint8_t log_level) { this->log_levels_[tag] = log_level; }
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
||||
UARTSelection Logger::get_uart() const { return this->uart_; }
|
||||
#endif
|
||||
|
||||
void Logger::add_on_log_callback(std::function<void(int, const char *, const char *)> &&callback) {
|
||||
void Logger::add_on_log_callback(std::function<void(uint8_t, const char *, const char *)> &&callback) {
|
||||
this->log_callback_.add(std::move(callback));
|
||||
}
|
||||
float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; }
|
||||
@@ -230,7 +230,7 @@ void Logger::dump_config() {
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::set_log_level(int level) {
|
||||
void Logger::set_log_level(uint8_t level) {
|
||||
if (level > ESPHOME_LOG_LEVEL) {
|
||||
level = ESPHOME_LOG_LEVEL;
|
||||
ESP_LOGW(TAG, "Cannot set log level higher than pre-compiled %s", LOG_LEVELS[ESPHOME_LOG_LEVEL]);
|
||||
|
@@ -61,7 +61,7 @@ static const char *const LOG_LEVEL_LETTERS[] = {
|
||||
*
|
||||
* Advanced configuration (pin selection, etc) is not supported.
|
||||
*/
|
||||
enum UARTSelection {
|
||||
enum UARTSelection : uint8_t {
|
||||
#ifdef USE_LIBRETINY
|
||||
UART_SELECTION_DEFAULT = 0,
|
||||
UART_SELECTION_UART0,
|
||||
@@ -129,10 +129,10 @@ class Logger : public Component {
|
||||
#endif
|
||||
|
||||
/// Set the default log level for this logger.
|
||||
void set_log_level(int level);
|
||||
void set_log_level(uint8_t level);
|
||||
/// Set the log level of the specified tag.
|
||||
void set_log_level(const std::string &tag, int log_level);
|
||||
int get_log_level() { return this->current_level_; }
|
||||
void set_log_level(const std::string &tag, uint8_t log_level);
|
||||
uint8_t get_log_level() { return this->current_level_; }
|
||||
|
||||
// ========== INTERNAL METHODS ==========
|
||||
// (In most use cases you won't need these)
|
||||
@@ -140,19 +140,20 @@ class Logger : public Component {
|
||||
void pre_setup();
|
||||
void dump_config() override;
|
||||
|
||||
inline int level_for(const char *tag);
|
||||
inline uint8_t level_for(const char *tag);
|
||||
|
||||
/// Register a callback that will be called for every log message sent
|
||||
void add_on_log_callback(std::function<void(int, const char *, const char *)> &&callback);
|
||||
void add_on_log_callback(std::function<void(uint8_t, const char *, const char *)> &&callback);
|
||||
|
||||
// add a listener for log level changes
|
||||
void add_listener(std::function<void(int)> &&callback) { this->level_callback_.add(std::move(callback)); }
|
||||
void add_listener(std::function<void(uint8_t)> &&callback) { this->level_callback_.add(std::move(callback)); }
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
void log_vprintf_(int level, const char *tag, int line, const char *format, va_list args); // NOLINT
|
||||
void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args); // NOLINT
|
||||
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
||||
void log_vprintf_(int level, const char *tag, int line, const __FlashStringHelper *format, va_list args); // NOLINT
|
||||
void log_vprintf_(uint8_t level, const char *tag, int line, const __FlashStringHelper *format,
|
||||
va_list args); // NOLINT
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@@ -160,8 +161,9 @@ class Logger : public Component {
|
||||
|
||||
// Format a log message with printf-style arguments and write it to a buffer with header, footer, and null terminator
|
||||
// It's the caller's responsibility to initialize buffer_at (typically to 0)
|
||||
inline void HOT format_log_to_buffer_with_terminator_(int level, const char *tag, int line, const char *format,
|
||||
va_list args, char *buffer, int *buffer_at, int buffer_size) {
|
||||
inline void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format,
|
||||
va_list args, char *buffer, uint16_t *buffer_at,
|
||||
uint16_t buffer_size) {
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size);
|
||||
#else
|
||||
@@ -180,7 +182,7 @@ class Logger : public Component {
|
||||
}
|
||||
|
||||
// Helper to format and send a log message to both console and callbacks
|
||||
inline void HOT log_message_to_buffer_and_send_(int level, const char *tag, int line, const char *format,
|
||||
inline void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format,
|
||||
va_list args) {
|
||||
// Format to tx_buffer and prepare for output
|
||||
this->tx_buffer_at_ = 0; // Initialize buffer position
|
||||
@@ -194,11 +196,12 @@ class Logger : public Component {
|
||||
}
|
||||
|
||||
// Write the body of the log message to the buffer
|
||||
inline void write_body_to_buffer_(const char *value, size_t length, char *buffer, int *buffer_at, int buffer_size) {
|
||||
inline void write_body_to_buffer_(const char *value, size_t length, char *buffer, uint16_t *buffer_at,
|
||||
uint16_t buffer_size) {
|
||||
// Calculate available space
|
||||
const int available = buffer_size - *buffer_at;
|
||||
if (available <= 0)
|
||||
if (*buffer_at >= buffer_size)
|
||||
return;
|
||||
const uint16_t available = buffer_size - *buffer_at;
|
||||
|
||||
// Determine copy length (minimum of remaining capacity and string length)
|
||||
const size_t copy_len = (length < static_cast<size_t>(available)) ? length : available;
|
||||
@@ -211,7 +214,7 @@ class Logger : public Component {
|
||||
}
|
||||
|
||||
// Format string to explicit buffer with varargs
|
||||
inline void printf_to_buffer_(char *buffer, int *buffer_at, int buffer_size, const char *format, ...) {
|
||||
inline void printf_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format, ...) {
|
||||
va_list arg;
|
||||
va_start(arg, format);
|
||||
this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, arg);
|
||||
@@ -222,41 +225,50 @@ class Logger : public Component {
|
||||
const char *get_uart_selection_();
|
||||
#endif
|
||||
|
||||
// Group 4-byte aligned members first
|
||||
uint32_t baud_rate_;
|
||||
char *tx_buffer_{nullptr};
|
||||
int tx_buffer_at_{0};
|
||||
int tx_buffer_size_{0};
|
||||
#ifdef USE_ARDUINO
|
||||
Stream *hw_serial_{nullptr};
|
||||
#endif
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
void *main_task_ = nullptr; // Only used for thread name identification
|
||||
#endif
|
||||
#ifdef USE_ESP32
|
||||
// Task-specific recursion guards:
|
||||
// - Main task uses a dedicated member variable for efficiency
|
||||
// - Other tasks use pthread TLS with a dynamically created key via pthread_key_create
|
||||
pthread_key_t log_recursion_key_; // 4 bytes
|
||||
#endif
|
||||
#ifdef USE_ESP_IDF
|
||||
uart_port_t uart_num_; // 4 bytes (enum defaults to int size)
|
||||
#endif
|
||||
|
||||
// Large objects (internally aligned)
|
||||
std::map<std::string, uint8_t> log_levels_{};
|
||||
CallbackManager<void(uint8_t, const char *, const char *)> log_callback_{};
|
||||
CallbackManager<void(uint8_t)> level_callback_{};
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
|
||||
#endif
|
||||
|
||||
// Group smaller types together at the end
|
||||
uint16_t tx_buffer_at_{0};
|
||||
uint16_t tx_buffer_size_{0};
|
||||
uint8_t current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE};
|
||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040)
|
||||
UARTSelection uart_{UART_SELECTION_UART0};
|
||||
#endif
|
||||
#ifdef USE_LIBRETINY
|
||||
UARTSelection uart_{UART_SELECTION_DEFAULT};
|
||||
#endif
|
||||
#ifdef USE_ARDUINO
|
||||
Stream *hw_serial_{nullptr};
|
||||
#endif
|
||||
#ifdef USE_ESP_IDF
|
||||
uart_port_t uart_num_;
|
||||
#endif
|
||||
std::map<std::string, int> log_levels_{};
|
||||
CallbackManager<void(int, const char *, const char *)> log_callback_{};
|
||||
int current_level_{ESPHOME_LOG_LEVEL_VERY_VERBOSE};
|
||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||
std::unique_ptr<logger::TaskLogBuffer> log_buffer_; // Will be initialized with init_log_buffer
|
||||
#endif
|
||||
#ifdef USE_ESP32
|
||||
// Task-specific recursion guards:
|
||||
// - Main task uses a dedicated member variable for efficiency
|
||||
// - Other tasks use pthread TLS with a dynamically created key via pthread_key_create
|
||||
bool main_task_recursion_guard_{false};
|
||||
pthread_key_t log_recursion_key_;
|
||||
#else
|
||||
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
||||
#endif
|
||||
CallbackManager<void(int)> level_callback_{};
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
void *main_task_ = nullptr; // Only used for thread name identification
|
||||
const char *HOT get_thread_name_() {
|
||||
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
||||
if (current_task == main_task_) {
|
||||
@@ -297,11 +309,10 @@ class Logger : public Component {
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void HOT write_header_to_buffer_(int level, const char *tag, int line, const char *thread_name, char *buffer,
|
||||
int *buffer_at, int buffer_size) {
|
||||
inline void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name,
|
||||
char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
|
||||
// Format header
|
||||
if (level < 0)
|
||||
level = 0;
|
||||
// uint8_t level is already bounded 0-255, just ensure it's <= 7
|
||||
if (level > 7)
|
||||
level = 7;
|
||||
|
||||
@@ -320,12 +331,12 @@ class Logger : public Component {
|
||||
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,
|
||||
inline void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format,
|
||||
va_list args) {
|
||||
// Get remaining capacity in the buffer
|
||||
const int remaining = buffer_size - *buffer_at;
|
||||
if (remaining <= 0)
|
||||
if (*buffer_at >= buffer_size)
|
||||
return;
|
||||
const uint16_t remaining = buffer_size - *buffer_at;
|
||||
|
||||
const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args);
|
||||
|
||||
@@ -334,7 +345,7 @@ class Logger : public Component {
|
||||
}
|
||||
|
||||
// Update buffer_at with the formatted length (handle truncation)
|
||||
int formatted_len = (ret >= remaining) ? remaining : ret;
|
||||
uint16_t formatted_len = (ret >= remaining) ? remaining : ret;
|
||||
*buffer_at += formatted_len;
|
||||
|
||||
// Remove all trailing newlines right after formatting
|
||||
@@ -343,18 +354,18 @@ class Logger : public Component {
|
||||
}
|
||||
}
|
||||
|
||||
inline void HOT write_footer_to_buffer_(char *buffer, int *buffer_at, int buffer_size) {
|
||||
static const int RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR);
|
||||
inline void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
|
||||
static const uint16_t RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR);
|
||||
this->write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size);
|
||||
}
|
||||
};
|
||||
extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
class LoggerMessageTrigger : public Trigger<int, const char *, const char *> {
|
||||
class LoggerMessageTrigger : public Trigger<uint8_t, const char *, const char *> {
|
||||
public:
|
||||
explicit LoggerMessageTrigger(Logger *parent, int level) {
|
||||
explicit LoggerMessageTrigger(Logger *parent, uint8_t level) {
|
||||
this->level_ = level;
|
||||
parent->add_on_log_callback([this](int level, const char *tag, const char *message) {
|
||||
parent->add_on_log_callback([this](uint8_t level, const char *tag, const char *message) {
|
||||
if (level <= this->level_) {
|
||||
this->trigger(level, tag, message);
|
||||
}
|
||||
@@ -362,7 +373,7 @@ class LoggerMessageTrigger : public Trigger<int, const char *, const char *> {
|
||||
}
|
||||
|
||||
protected:
|
||||
int level_;
|
||||
uint8_t level_;
|
||||
};
|
||||
|
||||
} // namespace logger
|
||||
|
@@ -454,9 +454,13 @@ def container_validator(schema, widget_type: WidgetType):
|
||||
"""
|
||||
|
||||
def validator(value):
|
||||
result = schema
|
||||
if w_sch := widget_type.schema:
|
||||
result = result.extend(w_sch)
|
||||
if isinstance(w_sch, dict):
|
||||
w_sch = cv.Schema(w_sch)
|
||||
# order is important here to preserve extras
|
||||
result = w_sch.extend(schema)
|
||||
else:
|
||||
result = schema
|
||||
ltype = df.TYPE_NONE
|
||||
if value and (layout := value.get(df.CONF_LAYOUT)):
|
||||
if not isinstance(layout, dict):
|
||||
|
@@ -3,7 +3,6 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import ID
|
||||
from esphome.cpp_generator import MockObj
|
||||
|
||||
from .defines import (
|
||||
CONF_STYLE_DEFINITIONS,
|
||||
@@ -13,12 +12,13 @@ from .defines import (
|
||||
literal,
|
||||
)
|
||||
from .helpers import add_lv_use
|
||||
from .lvcode import LambdaContext, LocalVariable, lv, lv_assign, lv_variable
|
||||
from .lvcode import LambdaContext, LocalVariable, lv
|
||||
from .schemas import ALL_STYLES, FULL_STYLE_SCHEMA, STYLE_REMAP
|
||||
from .types import ObjUpdateAction, lv_lambda_t, lv_obj_t, lv_obj_t_ptr, lv_style_t
|
||||
from .types import ObjUpdateAction, lv_obj_t, lv_style_t
|
||||
from .widgets import (
|
||||
Widget,
|
||||
add_widgets,
|
||||
collect_parts,
|
||||
set_obj_properties,
|
||||
theme_widget_map,
|
||||
wait_for_widgets,
|
||||
@@ -37,12 +37,18 @@ async def style_set(svar, style):
|
||||
lv.call(f"style_set_{remapped_prop}", svar, literal(value))
|
||||
|
||||
|
||||
async def create_style(style, id_name):
|
||||
style_id = ID(id_name, True, lv_style_t)
|
||||
svar = cg.new_Pvariable(style_id)
|
||||
lv.style_init(svar)
|
||||
await style_set(svar, style)
|
||||
return svar
|
||||
|
||||
|
||||
async def styles_to_code(config):
|
||||
"""Convert styles to C__ code."""
|
||||
for style in config.get(CONF_STYLE_DEFINITIONS, ()):
|
||||
svar = cg.new_Pvariable(style[CONF_ID])
|
||||
lv.style_init(svar)
|
||||
await style_set(svar, style)
|
||||
await create_style(style, style[CONF_ID].id)
|
||||
|
||||
|
||||
@automation.register_action(
|
||||
@@ -68,16 +74,18 @@ async def theme_to_code(config):
|
||||
if theme := config.get(CONF_THEME):
|
||||
add_lv_use(CONF_THEME)
|
||||
for w_name, style in theme.items():
|
||||
if not isinstance(style, dict):
|
||||
continue
|
||||
|
||||
lname = "lv_theme_apply_" + w_name
|
||||
apply = lv_variable(lv_lambda_t, lname)
|
||||
theme_widget_map[w_name] = apply
|
||||
ow = Widget.create("obj", MockObj(ID("obj")), obj_spec)
|
||||
async with LambdaContext([(lv_obj_t_ptr, "obj")], where=w_name) as context:
|
||||
await set_obj_properties(ow, style)
|
||||
lv_assign(apply, await context.get_lambda())
|
||||
# Work around Python 3.10 bug with nested async comprehensions
|
||||
# With Python 3.11 this could be simplified
|
||||
styles = {}
|
||||
for part, states in collect_parts(style).items():
|
||||
styles[part] = {
|
||||
state: await create_style(
|
||||
props,
|
||||
"_lv_theme_style_" + w_name + "_" + part + "_" + state,
|
||||
)
|
||||
for state, props in states.items()
|
||||
}
|
||||
theme_widget_map[w_name] = styles
|
||||
|
||||
|
||||
async def add_top_layer(lv_component, config):
|
||||
|
@@ -6,7 +6,7 @@ from esphome.config_validation import Invalid
|
||||
from esphome.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
||||
from esphome.core import ID, TimePeriod
|
||||
from esphome.coroutine import FakeAwaitable
|
||||
from esphome.cpp_generator import CallExpression, MockObj
|
||||
from esphome.cpp_generator import MockObj
|
||||
|
||||
from ..defines import (
|
||||
CONF_FLEX_ALIGN_CROSS,
|
||||
@@ -453,7 +453,17 @@ async def widget_to_code(w_cnfig, w_type: WidgetType, parent):
|
||||
|
||||
w = Widget.create(wid, var, spec, w_cnfig)
|
||||
if theme := theme_widget_map.get(w_type):
|
||||
lv_add(CallExpression(theme, w.obj))
|
||||
for part, states in theme.items():
|
||||
part = "LV_PART_" + part.upper()
|
||||
for state, style in states.items():
|
||||
state = "LV_STATE_" + state.upper()
|
||||
if state == "LV_STATE_DEFAULT":
|
||||
lv_state = literal(part)
|
||||
elif part == "LV_PART_MAIN":
|
||||
lv_state = literal(state)
|
||||
else:
|
||||
lv_state = join_enums((state, part))
|
||||
lv.obj_add_style(w.obj, style, lv_state)
|
||||
await set_obj_properties(w, w_cnfig)
|
||||
await add_widgets(w, w_cnfig)
|
||||
await spec.to_code(w, w_cnfig)
|
||||
|
@@ -1,8 +1,15 @@
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE
|
||||
|
||||
from ..defines import BAR_MODES, CONF_ANIMATED, CONF_INDICATOR, CONF_MAIN, literal
|
||||
from ..lv_validation import animated, get_start_value, lv_float
|
||||
from ..defines import (
|
||||
BAR_MODES,
|
||||
CONF_ANIMATED,
|
||||
CONF_INDICATOR,
|
||||
CONF_MAIN,
|
||||
CONF_START_VALUE,
|
||||
literal,
|
||||
)
|
||||
from ..lv_validation import animated, lv_int
|
||||
from ..lvcode import lv
|
||||
from ..types import LvNumber, NumberType
|
||||
from . import Widget
|
||||
@@ -10,22 +17,30 @@ from . import Widget
|
||||
# Note this file cannot be called "bar.py" because that name is disallowed.
|
||||
|
||||
CONF_BAR = "bar"
|
||||
BAR_MODIFY_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_VALUE): lv_float,
|
||||
cv.Optional(CONF_ANIMATED, default=True): animated,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def validate_bar(config):
|
||||
if config.get(CONF_MODE) != "LV_BAR_MODE_RANGE" and CONF_START_VALUE in config:
|
||||
raise cv.Invalid(
|
||||
f"{CONF_START_VALUE} is only allowed when {CONF_MODE} is set to 'RANGE'"
|
||||
)
|
||||
if (CONF_MIN_VALUE in config) != (CONF_MAX_VALUE in config):
|
||||
raise cv.Invalid(
|
||||
f"If either {CONF_MIN_VALUE} or {CONF_MAX_VALUE} is set, both must be set"
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
BAR_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_VALUE): lv_float,
|
||||
cv.Optional(CONF_MIN_VALUE, default=0): cv.int_,
|
||||
cv.Optional(CONF_MAX_VALUE, default=100): cv.int_,
|
||||
cv.Optional(CONF_MODE, default="NORMAL"): BAR_MODES.one_of,
|
||||
cv.Optional(CONF_VALUE): lv_int,
|
||||
cv.Optional(CONF_START_VALUE): lv_int,
|
||||
cv.Optional(CONF_MIN_VALUE): lv_int,
|
||||
cv.Optional(CONF_MAX_VALUE): lv_int,
|
||||
cv.Optional(CONF_MODE): BAR_MODES.one_of,
|
||||
cv.Optional(CONF_ANIMATED, default=True): animated,
|
||||
}
|
||||
)
|
||||
).add_extra(validate_bar)
|
||||
|
||||
|
||||
class BarType(NumberType):
|
||||
@@ -35,17 +50,23 @@ class BarType(NumberType):
|
||||
LvNumber("lv_bar_t"),
|
||||
parts=(CONF_MAIN, CONF_INDICATOR),
|
||||
schema=BAR_SCHEMA,
|
||||
modify_schema=BAR_MODIFY_SCHEMA,
|
||||
)
|
||||
|
||||
async def to_code(self, w: Widget, config):
|
||||
var = w.obj
|
||||
if mode := config.get(CONF_MODE):
|
||||
lv.bar_set_mode(var, literal(mode))
|
||||
is_animated = literal(config[CONF_ANIMATED])
|
||||
if CONF_MIN_VALUE in config:
|
||||
lv.bar_set_range(var, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE])
|
||||
lv.bar_set_mode(var, literal(config[CONF_MODE]))
|
||||
value = await get_start_value(config)
|
||||
if value is not None:
|
||||
lv.bar_set_value(var, value, literal(config[CONF_ANIMATED]))
|
||||
lv.bar_set_range(
|
||||
var,
|
||||
await lv_int.process(config[CONF_MIN_VALUE]),
|
||||
await lv_int.process(config[CONF_MAX_VALUE]),
|
||||
)
|
||||
if value := await lv_int.process(config.get(CONF_VALUE)):
|
||||
lv.bar_set_value(var, value, is_animated)
|
||||
if start_value := await lv_int.process(config.get(CONF_START_VALUE)):
|
||||
lv.bar_set_start_value(var, start_value, is_animated)
|
||||
|
||||
@property
|
||||
def animated(self):
|
||||
|
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
||||
from esphome.const import CONF_SIZE, CONF_TEXT
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
|
||||
from ..defines import CONF_MAIN, literal
|
||||
from ..defines import CONF_MAIN
|
||||
from ..lv_validation import color, color_retmapper, lv_text
|
||||
from ..lvcode import LocalVariable, lv, lv_expr
|
||||
from ..schemas import TEXT_SCHEMA
|
||||
@@ -34,7 +34,7 @@ class QrCodeType(WidgetType):
|
||||
)
|
||||
|
||||
def get_uses(self):
|
||||
return ("canvas", "img")
|
||||
return ("canvas", "img", "label")
|
||||
|
||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
||||
dark_color = color_retmapper(config[CONF_DARK_COLOR])
|
||||
@@ -45,10 +45,8 @@ class QrCodeType(WidgetType):
|
||||
async def to_code(self, w: Widget, config):
|
||||
if (value := config.get(CONF_TEXT)) is not None:
|
||||
value = await lv_text.process(value)
|
||||
with LocalVariable(
|
||||
"qr_text", cg.const_char_ptr, value, modifier=""
|
||||
) as str_obj:
|
||||
lv.qrcode_update(w.obj, str_obj, literal(f"strlen({str_obj})"))
|
||||
with LocalVariable("qr_text", cg.std_string, value, modifier="") as str_obj:
|
||||
lv.qrcode_update(w.obj, str_obj.c_str(), str_obj.size())
|
||||
|
||||
|
||||
qr_code_spec = QrCodeType()
|
||||
|
@@ -8,7 +8,7 @@ namespace m5stack_8angle {
|
||||
static const char *const TAG = "m5stack_8angle.light";
|
||||
|
||||
void M5Stack8AngleLightOutput::setup() {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->buf_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
|
||||
if (this->buf_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
|
||||
|
@@ -11,9 +11,9 @@ from esphome.const import (
|
||||
CONF_VOLUME,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.coroutine import coroutine_with_priority
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
|
||||
@@ -81,7 +81,7 @@ IsAnnouncingCondition = media_player_ns.class_(
|
||||
|
||||
|
||||
async def setup_media_player_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "media_player")
|
||||
for conf in config.get(CONF_ON_STATE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
@@ -143,6 +143,8 @@ _MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
||||
}
|
||||
)
|
||||
|
||||
_MEDIA_PLAYER_SCHEMA.add_extra(entity_duplicate_validator("media_player"))
|
||||
|
||||
|
||||
def media_player_schema(
|
||||
class_: MockObjClass,
|
||||
@@ -166,7 +168,6 @@ def media_player_schema(
|
||||
MEDIA_PLAYER_SCHEMA = media_player_schema(MediaPlayer)
|
||||
MEDIA_PLAYER_SCHEMA.add_extra(cv.deprecated_schema_constant("media_player"))
|
||||
|
||||
|
||||
MEDIA_PLAYER_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||
cv.Schema(
|
||||
{
|
||||
|
@@ -27,7 +27,7 @@ void VADModel::log_model_config() {
|
||||
}
|
||||
|
||||
bool StreamingModel::load_model_() {
|
||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> arena_allocator;
|
||||
|
||||
if (this->tensor_arena_ == nullptr) {
|
||||
this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_);
|
||||
@@ -96,7 +96,7 @@ bool StreamingModel::load_model_() {
|
||||
void StreamingModel::unload_model() {
|
||||
this->interpreter_.reset();
|
||||
|
||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> arena_allocator;
|
||||
|
||||
if (this->tensor_arena_ != nullptr) {
|
||||
arena_allocator.deallocate(this->tensor_arena_, this->tensor_arena_size_);
|
||||
|
@@ -472,3 +472,4 @@ async def to_code(config):
|
||||
cg.add(var.set_writer(lambda_))
|
||||
await display.register_display(var, config)
|
||||
await spi.register_spi_device(var, config)
|
||||
cg.add(var.set_write_only(True))
|
||||
|
@@ -64,6 +64,14 @@ class ModbusDevice {
|
||||
this->parent_->send(this->address_, function, start_address, number_of_entities, payload_len, payload);
|
||||
}
|
||||
void send_raw(const std::vector<uint8_t> &payload) { this->parent_->send_raw(payload); }
|
||||
void send_error(uint8_t function_code, uint8_t exception_code) {
|
||||
std::vector<uint8_t> error_response;
|
||||
error_response.reserve(3);
|
||||
error_response.push_back(this->address_);
|
||||
error_response.push_back(function_code | 0x80);
|
||||
error_response.push_back(exception_code);
|
||||
this->send_raw(error_response);
|
||||
}
|
||||
// If more than one device is connected block sending a new command before a response is received
|
||||
bool waiting_for_response() { return parent_->waiting_for_response != 0; }
|
||||
|
||||
|
@@ -112,6 +112,22 @@ TYPE_REGISTER_MAP = {
|
||||
"FP32_R": 2,
|
||||
}
|
||||
|
||||
CPP_TYPE_REGISTER_MAP = {
|
||||
"RAW": cg.uint16,
|
||||
"U_WORD": cg.uint16,
|
||||
"S_WORD": cg.int16,
|
||||
"U_DWORD": cg.uint32,
|
||||
"U_DWORD_R": cg.uint32,
|
||||
"S_DWORD": cg.int32,
|
||||
"S_DWORD_R": cg.int32,
|
||||
"U_QWORD": cg.uint64,
|
||||
"U_QWORD_R": cg.uint64,
|
||||
"S_QWORD": cg.int64,
|
||||
"S_QWORD_R": cg.int64,
|
||||
"FP32": cg.float_,
|
||||
"FP32_R": cg.float_,
|
||||
}
|
||||
|
||||
ModbusCommandSentTrigger = modbus_controller_ns.class_(
|
||||
"ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
||||
)
|
||||
@@ -285,21 +301,24 @@ async def to_code(config):
|
||||
cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
|
||||
if CONF_SERVER_REGISTERS in config:
|
||||
for server_register in config[CONF_SERVER_REGISTERS]:
|
||||
cg.add(
|
||||
var.add_server_register(
|
||||
cg.new_Pvariable(
|
||||
server_register_var = cg.new_Pvariable(
|
||||
server_register[CONF_ID],
|
||||
server_register[CONF_ADDRESS],
|
||||
server_register[CONF_VALUE_TYPE],
|
||||
TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]],
|
||||
)
|
||||
cpp_type = CPP_TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]]
|
||||
cg.add(
|
||||
server_register_var.set_read_lambda(
|
||||
cg.TemplateArguments(cpp_type),
|
||||
await cg.process_lambda(
|
||||
server_register[CONF_READ_LAMBDA],
|
||||
[],
|
||||
return_type=cg.float_,
|
||||
[(cg.uint16, "address")],
|
||||
return_type=cpp_type,
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
cg.add(var.add_server_register(server_register_var))
|
||||
await register_modbus_device(var, config)
|
||||
for conf in config.get(CONF_ON_COMMAND_SENT, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
|
@@ -117,12 +117,17 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
|
||||
bool found = false;
|
||||
for (auto *server_register : this->server_registers_) {
|
||||
if (server_register->address == current_address) {
|
||||
float value = server_register->read_lambda();
|
||||
if (!server_register->read_lambda) {
|
||||
break;
|
||||
}
|
||||
int64_t value = server_register->read_lambda();
|
||||
ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %s.",
|
||||
server_register->address, static_cast<size_t>(server_register->value_type),
|
||||
server_register->register_count, server_register->format_value(value).c_str());
|
||||
|
||||
ESP_LOGD(TAG, "Matched register. Address: 0x%02X. Value type: %zu. Register count: %u. Value: %0.1f.",
|
||||
server_register->address, static_cast<uint8_t>(server_register->value_type),
|
||||
server_register->register_count, value);
|
||||
std::vector<uint16_t> payload = float_to_payload(value, server_register->value_type);
|
||||
std::vector<uint16_t> payload;
|
||||
payload.reserve(server_register->register_count * 2);
|
||||
number_to_payload(payload, value, server_register->value_type);
|
||||
sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend());
|
||||
current_address += server_register->register_count;
|
||||
found = true;
|
||||
@@ -132,11 +137,7 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
|
||||
|
||||
if (!found) {
|
||||
ESP_LOGW(TAG, "Could not match any register to address %02X. Sending exception response.", current_address);
|
||||
std::vector<uint8_t> error_response;
|
||||
error_response.push_back(this->address_);
|
||||
error_response.push_back(0x81);
|
||||
error_response.push_back(0x02);
|
||||
this->send_raw(error_response);
|
||||
send_error(function_code, 0x02);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -63,6 +63,10 @@ enum class SensorValueType : uint8_t {
|
||||
FP32_R = 0xD
|
||||
};
|
||||
|
||||
inline bool value_type_is_float(SensorValueType v) {
|
||||
return v == SensorValueType::FP32 || v == SensorValueType::FP32_R;
|
||||
}
|
||||
|
||||
inline ModbusFunctionCode modbus_register_read_function(ModbusRegisterType reg_type) {
|
||||
switch (reg_type) {
|
||||
case ModbusRegisterType::COIL:
|
||||
@@ -253,18 +257,53 @@ class SensorItem {
|
||||
};
|
||||
|
||||
class ServerRegister {
|
||||
using ReadLambda = std::function<int64_t()>;
|
||||
|
||||
public:
|
||||
ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count,
|
||||
std::function<float()> read_lambda) {
|
||||
ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count) {
|
||||
this->address = address;
|
||||
this->value_type = value_type;
|
||||
this->register_count = register_count;
|
||||
this->read_lambda = std::move(read_lambda);
|
||||
}
|
||||
|
||||
template<typename T> void set_read_lambda(const std::function<T(uint16_t address)> &&user_read_lambda) {
|
||||
this->read_lambda = [this, user_read_lambda]() -> int64_t {
|
||||
T user_value = user_read_lambda(this->address);
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
return bit_cast<uint32_t>(user_value);
|
||||
} else {
|
||||
return static_cast<int64_t>(user_value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Formats a raw value into a string representation based on the value type for debugging
|
||||
std::string format_value(int64_t value) const {
|
||||
switch (this->value_type) {
|
||||
case SensorValueType::U_WORD:
|
||||
case SensorValueType::U_DWORD:
|
||||
case SensorValueType::U_DWORD_R:
|
||||
case SensorValueType::U_QWORD:
|
||||
case SensorValueType::U_QWORD_R:
|
||||
return std::to_string(static_cast<uint64_t>(value));
|
||||
case SensorValueType::S_WORD:
|
||||
case SensorValueType::S_DWORD:
|
||||
case SensorValueType::S_DWORD_R:
|
||||
case SensorValueType::S_QWORD:
|
||||
case SensorValueType::S_QWORD_R:
|
||||
return std::to_string(value);
|
||||
case SensorValueType::FP32_R:
|
||||
case SensorValueType::FP32:
|
||||
return str_sprintf("%.1f", bit_cast<float>(static_cast<uint32_t>(value)));
|
||||
default:
|
||||
return std::to_string(value);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t address{0};
|
||||
SensorValueType value_type{SensorValueType::RAW};
|
||||
uint8_t register_count{0};
|
||||
std::function<float()> read_lambda;
|
||||
ReadLambda read_lambda;
|
||||
};
|
||||
|
||||
// ModbusController::create_register_ranges_ tries to optimize register range
|
||||
@@ -444,7 +483,7 @@ class ModbusController : public PollingComponent, public modbus::ModbusDevice {
|
||||
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
||||
/// called when a modbus error response was received
|
||||
void on_modbus_error(uint8_t function_code, uint8_t exception_code) override;
|
||||
/// called when a modbus request (function code 3 or 4) was parsed without errors
|
||||
/// called when a modbus request (function code 0x03 or 0x04) was parsed without errors
|
||||
void on_modbus_read_registers(uint8_t function_code, uint16_t start_address, uint16_t number_of_registers) final;
|
||||
/// default delegate called by process_modbus_data when a response has retrieved from the incoming queue
|
||||
void on_register_data(ModbusRegisterType register_type, uint16_t start_address, const std::vector<uint8_t> &data);
|
||||
@@ -529,7 +568,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem
|
||||
int64_t number = payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask);
|
||||
|
||||
float float_value;
|
||||
if (item.sensor_value_type == SensorValueType::FP32 || item.sensor_value_type == SensorValueType::FP32_R) {
|
||||
if (value_type_is_float(item.sensor_value_type)) {
|
||||
float_value = bit_cast<float>(static_cast<uint32_t>(number));
|
||||
} else {
|
||||
float_value = static_cast<float>(number);
|
||||
@@ -541,7 +580,7 @@ inline float payload_to_float(const std::vector<uint8_t> &data, const SensorItem
|
||||
inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) {
|
||||
int64_t val;
|
||||
|
||||
if (value_type == SensorValueType::FP32 || value_type == SensorValueType::FP32_R) {
|
||||
if (value_type_is_float(value_type)) {
|
||||
val = bit_cast<uint32_t>(value);
|
||||
} else {
|
||||
val = llroundf(value);
|
||||
|
@@ -68,6 +68,7 @@ def AUTO_LOAD():
|
||||
|
||||
CONF_DISCOVER_IP = "discover_ip"
|
||||
CONF_IDF_SEND_ASYNC = "idf_send_async"
|
||||
CONF_WAIT_FOR_CONNECTION = "wait_for_connection"
|
||||
|
||||
|
||||
def validate_message_just_topic(value):
|
||||
@@ -298,6 +299,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_PUBLISH_NAN_AS_NONE, default=False): cv.boolean,
|
||||
cv.Optional(CONF_WAIT_FOR_CONNECTION, default=False): cv.boolean,
|
||||
}
|
||||
),
|
||||
validate_config,
|
||||
@@ -453,6 +455,8 @@ async def to_code(config):
|
||||
|
||||
cg.add(var.set_publish_nan_as_none(config[CONF_PUBLISH_NAN_AS_NONE]))
|
||||
|
||||
cg.add(var.set_wait_for_connection(config[CONF_WAIT_FOR_CONNECTION]))
|
||||
|
||||
|
||||
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
|
||||
{
|
||||
|
@@ -17,7 +17,8 @@ enum class MQTTClientDisconnectReason : int8_t {
|
||||
MQTT_MALFORMED_CREDENTIALS = 4,
|
||||
MQTT_NOT_AUTHORIZED = 5,
|
||||
ESP8266_NOT_ENOUGH_SPACE = 6,
|
||||
TLS_BAD_FINGERPRINT = 7
|
||||
TLS_BAD_FINGERPRINT = 7,
|
||||
DNS_RESOLVE_ERROR = 8
|
||||
};
|
||||
|
||||
/// internal struct for MQTT messages.
|
||||
|
@@ -176,7 +176,8 @@ void MQTTClientComponent::dump_config() {
|
||||
}
|
||||
}
|
||||
bool MQTTClientComponent::can_proceed() {
|
||||
return network::is_disabled() || this->state_ == MQTT_CLIENT_DISABLED || this->is_connected();
|
||||
return network::is_disabled() || this->state_ == MQTT_CLIENT_DISABLED || this->is_connected() ||
|
||||
!this->wait_for_connection_;
|
||||
}
|
||||
|
||||
void MQTTClientComponent::start_dnslookup_() {
|
||||
@@ -228,6 +229,8 @@ void MQTTClientComponent::check_dnslookup_() {
|
||||
if (this->dns_resolve_error_) {
|
||||
ESP_LOGW(TAG, "Couldn't resolve IP address for '%s'", this->credentials_.address.c_str());
|
||||
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
||||
this->disconnect_reason_ = MQTTClientDisconnectReason::DNS_RESOLVE_ERROR;
|
||||
this->on_disconnect_.call(MQTTClientDisconnectReason::DNS_RESOLVE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -697,7 +700,9 @@ void MQTTClientComponent::set_on_connect(mqtt_on_connect_callback_t &&callback)
|
||||
}
|
||||
|
||||
void MQTTClientComponent::set_on_disconnect(mqtt_on_disconnect_callback_t &&callback) {
|
||||
auto callback_copy = callback;
|
||||
this->mqtt_backend_.set_on_disconnect(std::forward<mqtt_on_disconnect_callback_t>(callback));
|
||||
this->on_disconnect_.add(std::move(callback_copy));
|
||||
}
|
||||
|
||||
#if ASYNC_TCP_SSL_ENABLED
|
||||
|
@@ -4,11 +4,12 @@
|
||||
|
||||
#ifdef USE_MQTT
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/json/json_util.h"
|
||||
#include "esphome/components/network/ip_address.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#if defined(USE_ESP32)
|
||||
#include "mqtt_backend_esp32.h"
|
||||
#elif defined(USE_ESP8266)
|
||||
@@ -267,6 +268,8 @@ class MQTTClientComponent : public Component {
|
||||
void set_publish_nan_as_none(bool publish_nan_as_none);
|
||||
bool is_publish_nan_as_none() const;
|
||||
|
||||
void set_wait_for_connection(bool wait_for_connection) { this->wait_for_connection_ = wait_for_connection; }
|
||||
|
||||
protected:
|
||||
void send_device_info_();
|
||||
|
||||
@@ -332,8 +335,10 @@ class MQTTClientComponent : public Component {
|
||||
uint32_t connect_begin_;
|
||||
uint32_t last_connected_{0};
|
||||
optional<MQTTClientDisconnectReason> disconnect_reason_{};
|
||||
CallbackManager<MQTTBackend::on_disconnect_callback_t> on_disconnect_;
|
||||
|
||||
bool publish_nan_as_none_{false};
|
||||
bool wait_for_connection_{false};
|
||||
};
|
||||
|
||||
extern MQTTClientComponent *global_mqtt_client; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#include "nextion.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <cinttypes>
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace nextion {
|
||||
@@ -33,6 +33,7 @@ bool Nextion::send_command_(const std::string &command) {
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
||||
ESP_LOGN(TAG, "Command spacing: delaying command '%s'", command.c_str());
|
||||
return false;
|
||||
}
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
@@ -43,10 +44,6 @@ bool Nextion::send_command_(const std::string &command) {
|
||||
const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
|
||||
this->write_array(to_send, sizeof(to_send));
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
this->command_pacer_.mark_sent();
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -74,13 +71,13 @@ bool Nextion::check_connect_() {
|
||||
}
|
||||
this->send_command_("connect");
|
||||
|
||||
this->comok_sent_ = millis();
|
||||
this->comok_sent_ = App.get_loop_component_start_time();
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (millis() - this->comok_sent_ <= 500) // Wait 500 ms
|
||||
if (App.get_loop_component_start_time() - this->comok_sent_ <= 500) // Wait 500 ms
|
||||
return false;
|
||||
|
||||
std::string response;
|
||||
@@ -321,15 +318,38 @@ void Nextion::loop() {
|
||||
|
||||
if (!this->nextion_reports_is_setup_) {
|
||||
if (this->started_ms_ == 0)
|
||||
this->started_ms_ = millis();
|
||||
this->started_ms_ = App.get_loop_component_start_time();
|
||||
|
||||
if (this->started_ms_ + this->startup_override_ms_ < millis()) {
|
||||
if (this->started_ms_ + this->startup_override_ms_ < App.get_loop_component_start_time()) {
|
||||
ESP_LOGD(TAG, "Manual ready set");
|
||||
this->nextion_reports_is_setup_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
// Try to send any pending commands if spacing allows
|
||||
this->process_pending_in_queue_();
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
void Nextion::process_pending_in_queue_() {
|
||||
if (this->nextion_queue_.empty() || !this->command_pacer_.can_send()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if first item in queue has a pending command
|
||||
auto *front_item = this->nextion_queue_.front();
|
||||
if (front_item && !front_item->pending_command.empty()) {
|
||||
if (this->send_command_(front_item->pending_command)) {
|
||||
// Command sent successfully, clear the pending command
|
||||
front_item->pending_command.clear();
|
||||
ESP_LOGVV(TAG, "Pending command sent: %s", front_item->component->get_variable_name().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
bool Nextion::remove_from_q_(bool report_empty) {
|
||||
if (this->nextion_queue_.empty()) {
|
||||
if (report_empty) {
|
||||
@@ -377,12 +397,6 @@ void Nextion::process_nextion_commands_() {
|
||||
size_t commands_processed = 0;
|
||||
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
if (!this->command_pacer_.can_send()) {
|
||||
return; // Will try again in next loop iteration
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t to_process_length = 0;
|
||||
std::string to_process;
|
||||
|
||||
@@ -418,7 +432,7 @@ void Nextion::process_nextion_commands_() {
|
||||
case 0x01: // instruction sent by user was successful
|
||||
|
||||
ESP_LOGVV(TAG, "Cmd OK");
|
||||
ESP_LOGN(TAG, "this->nextion_queue_.empty() %s", this->nextion_queue_.empty() ? "True" : "False");
|
||||
ESP_LOGN(TAG, "this->nextion_queue_.empty() %s", YESNO(this->nextion_queue_.empty()));
|
||||
|
||||
this->remove_from_q_();
|
||||
if (!this->is_setup_) {
|
||||
@@ -430,6 +444,7 @@ void Nextion::process_nextion_commands_() {
|
||||
}
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
||||
ESP_LOGN(TAG, "Command spacing: marked command sent");
|
||||
#endif
|
||||
break;
|
||||
case 0x02: // invalid Component ID or name was used
|
||||
@@ -813,7 +828,7 @@ void Nextion::process_nextion_commands_() {
|
||||
this->command_data_.erase(0, to_process_length + COMMAND_DELIMITER.length() + 1);
|
||||
}
|
||||
|
||||
uint32_t ms = millis();
|
||||
uint32_t ms = App.get_loop_component_start_time();
|
||||
|
||||
if (!this->nextion_queue_.empty() && this->nextion_queue_.front()->queue_time + this->max_q_age_ms_ < ms) {
|
||||
for (size_t i = 0; i < this->nextion_queue_.size(); i++) {
|
||||
@@ -948,11 +963,10 @@ uint16_t Nextion::recv_ret_string_(std::string &response, uint32_t timeout, bool
|
||||
uint16_t ret = 0;
|
||||
uint8_t c = 0;
|
||||
uint8_t nr_of_ff_bytes = 0;
|
||||
uint64_t start;
|
||||
bool exit_flag = false;
|
||||
bool ff_flag = false;
|
||||
|
||||
start = millis();
|
||||
const uint32_t start = millis();
|
||||
|
||||
while ((timeout == 0 && this->available()) || millis() - start <= timeout) {
|
||||
if (!this->available()) {
|
||||
@@ -1011,7 +1025,7 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
||||
}
|
||||
#endif
|
||||
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
RAMAllocator<nextion::NextionQueue> allocator;
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Queue alloc failed");
|
||||
@@ -1042,9 +1056,42 @@ void Nextion::add_no_result_to_queue_with_command_(const std::string &variable_n
|
||||
|
||||
if (this->send_command_(command)) {
|
||||
this->add_no_result_to_queue_(variable_name);
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
} else {
|
||||
// Command blocked by spacing, add to queue WITH the command for retry
|
||||
this->add_no_result_to_queue_with_pending_command_(variable_name, command);
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
void Nextion::add_no_result_to_queue_with_pending_command_(const std::string &variable_name,
|
||||
const std::string &command) {
|
||||
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||
if (this->max_queue_size_ > 0 && this->nextion_queue_.size() >= this->max_queue_size_) {
|
||||
ESP_LOGW(TAG, "Queue full (%zu), drop: %s", this->nextion_queue_.size(), variable_name.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
RAMAllocator<nextion::NextionQueue> allocator;
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Queue alloc failed");
|
||||
return;
|
||||
}
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = new nextion::NextionComponentBase;
|
||||
nextion_queue->component->set_variable_name(variable_name);
|
||||
nextion_queue->queue_time = App.get_loop_component_start_time();
|
||||
nextion_queue->pending_command = command; // Store command for retry
|
||||
|
||||
this->nextion_queue_.push_back(nextion_queue);
|
||||
ESP_LOGVV(TAG, "Queue with pending command: %s", variable_name.c_str());
|
||||
}
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
bool Nextion::add_no_result_to_queue_with_ignore_sleep_printf_(const std::string &variable_name, const char *format,
|
||||
...) {
|
||||
if ((!this->is_setup() && !this->ignore_is_setup_))
|
||||
@@ -1167,7 +1214,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
||||
}
|
||||
#endif
|
||||
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
RAMAllocator<nextion::NextionQueue> allocator;
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Queue alloc failed");
|
||||
@@ -1176,7 +1223,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = component;
|
||||
nextion_queue->queue_time = millis();
|
||||
nextion_queue->queue_time = App.get_loop_component_start_time();
|
||||
|
||||
ESP_LOGN(TAG, "Queue %s: %s", component->get_queue_type_string().c_str(), component->get_variable_name().c_str());
|
||||
|
||||
@@ -1199,7 +1246,7 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) {
|
||||
if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
|
||||
return;
|
||||
|
||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
||||
RAMAllocator<nextion::NextionQueue> allocator;
|
||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||
if (nextion_queue == nullptr) {
|
||||
ESP_LOGW(TAG, "Queue alloc failed");
|
||||
@@ -1208,7 +1255,7 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) {
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = component;
|
||||
nextion_queue->queue_time = millis();
|
||||
nextion_queue->queue_time = App.get_loop_component_start_time();
|
||||
|
||||
this->waveform_queue_.push_back(nextion_queue);
|
||||
if (this->waveform_queue_.size() == 1)
|
||||
|
@@ -1309,9 +1309,23 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
#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};
|
||||
|
||||
/**
|
||||
* @brief Process any commands in the queue that are pending due to command spacing
|
||||
*
|
||||
* This method checks if the first item in the nextion_queue_ has a pending command
|
||||
* that was previously blocked by command spacing. If spacing now allows and a
|
||||
* pending command exists, it attempts to send the command. Once successfully sent,
|
||||
* the pending command is cleared and the queue item continues normal processing.
|
||||
*
|
||||
* Called from loop() to retry sending commands that were delayed by spacing.
|
||||
*/
|
||||
void process_pending_in_queue_();
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
std::deque<NextionQueue *> nextion_queue_;
|
||||
std::deque<NextionQueue *> waveform_queue_;
|
||||
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag);
|
||||
@@ -1348,6 +1362,23 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
void add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command);
|
||||
|
||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||
/**
|
||||
* @brief Add a command to the Nextion queue with a pending command for retry
|
||||
*
|
||||
* This method creates a queue entry for a command that was blocked by command spacing.
|
||||
* The command string is stored in the queue item's pending_command field so it can
|
||||
* be retried later when spacing allows. This ensures commands are not lost when
|
||||
* sent too quickly.
|
||||
*
|
||||
* If the max_queue_size limit is configured and reached, the command will be dropped.
|
||||
*
|
||||
* @param variable_name Name of the variable or component associated with the command
|
||||
* @param command The actual command string to be sent when spacing allows
|
||||
*/
|
||||
void add_no_result_to_queue_with_pending_command_(const std::string &variable_name, const std::string &command);
|
||||
#endif // USE_NEXTION_COMMAND_SPACING
|
||||
|
||||
bool add_no_result_to_queue_with_printf_(const std::string &variable_name, const char *format, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
|
||||
|
@@ -25,6 +25,9 @@ class NextionQueue {
|
||||
virtual ~NextionQueue() = default;
|
||||
NextionComponentBase *component;
|
||||
uint32_t queue_time = 0;
|
||||
|
||||
// Store command for retry if spacing blocked it
|
||||
std::string pending_command; // Empty if command was sent successfully
|
||||
};
|
||||
|
||||
class NextionComponentBase {
|
||||
|
36
esphome/components/nextion/nextion_upload.cpp
Normal file
36
esphome/components/nextion/nextion_upload.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "nextion.h"
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace nextion {
|
||||
static const char *const TAG = "nextion.upload";
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Upload successful");
|
||||
delay(1500); // NOLINT
|
||||
App.safe_reboot();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Upload failed");
|
||||
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Baud: %" PRIu32 "->%" PRIu32, baud_rate, this->original_baud_rate_);
|
||||
this->parent_->set_baud_rate(this->original_baud_rate_);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
@@ -3,12 +3,12 @@
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ARDUINO
|
||||
|
||||
#include <cinttypes>
|
||||
#include "esphome/components/network/util.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/network/util.h"
|
||||
#include <cinttypes>
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include <esp_heap_caps.h>
|
||||
@@ -52,7 +52,7 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
}
|
||||
|
||||
// Allocate the buffer dynamically
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
uint8_t *buffer = allocator.allocate(4096);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
||||
@@ -67,8 +67,8 @@ int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
ESP_LOGV(TAG, "Fetch %" PRIu16 " bytes", buffer_size);
|
||||
uint16_t read_len = 0;
|
||||
int partial_read_len = 0;
|
||||
const uint32_t start_time = millis();
|
||||
while (read_len < buffer_size && millis() - start_time < 5000) {
|
||||
const uint32_t start_time = App.get_loop_component_start_time();
|
||||
while (read_len < buffer_size && App.get_loop_component_start_time() - start_time < 5000) {
|
||||
if (http_client.getStreamPtr()->available() > 0) {
|
||||
partial_read_len =
|
||||
http_client.getStreamPtr()->readBytes(reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
|
||||
@@ -335,31 +335,6 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
return upload_end_(true);
|
||||
}
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
ESP_LOGD(TAG, "TFT upload done: %s", YESNO(successful));
|
||||
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Restart");
|
||||
delay(1500); // NOLINT
|
||||
App.safe_reboot();
|
||||
delay(1500); // NOLINT
|
||||
} else {
|
||||
ESP_LOGE(TAG, "TFT upload failed");
|
||||
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Baud back: %" PRIu32 "->%" PRIu32, baud_rate, this->original_baud_rate_);
|
||||
this->parent_->set_baud_rate(this->original_baud_rate_);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
WiFiClient *Nextion::get_wifi_client_() {
|
||||
if (this->tft_url_.compare(0, 6, "https:") == 0) {
|
||||
|
@@ -3,14 +3,14 @@
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ESP_IDF
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/network/util.h"
|
||||
#include <cinttypes>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_http_client.h>
|
||||
#include <cinttypes>
|
||||
#include "esphome/components/network/util.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/util.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace nextion {
|
||||
@@ -51,7 +51,7 @@ int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &r
|
||||
}
|
||||
|
||||
// Allocate the buffer dynamically
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
uint8_t *buffer = allocator.allocate(4096);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
||||
@@ -335,30 +335,6 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
return this->upload_end_(true);
|
||||
}
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
ESP_LOGD(TAG, "TFT upload done: %s", YESNO(successful));
|
||||
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Restart");
|
||||
delay(1500); // NOLINT
|
||||
App.safe_reboot();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "TFT upload failed");
|
||||
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Baud back: %" PRIu32 "->%" PRIu32, baud_rate, this->original_baud_rate_);
|
||||
this->parent_->set_baud_rate(this->original_baud_rate_);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
}
|
||||
|
||||
return successful;
|
||||
}
|
||||
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
||||
|
@@ -76,8 +76,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_WIND_SPEED,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
DEVICE_CLASSES = [
|
||||
@@ -207,6 +207,9 @@ _NUMBER_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_NUMBER_SCHEMA.add_extra(entity_duplicate_validator("number"))
|
||||
|
||||
|
||||
def number_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -237,7 +240,7 @@ NUMBER_SCHEMA.add_extra(cv.deprecated_schema_constant("number"))
|
||||
async def setup_number_core_(
|
||||
var, config, *, min_value: float, max_value: float, step: float
|
||||
):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "number")
|
||||
|
||||
cg.add(var.traits.set_min_value(min_value))
|
||||
cg.add(var.traits.set_max_value(max_value))
|
||||
|
@@ -34,6 +34,7 @@ MULTI_CONF = True
|
||||
|
||||
CONF_ON_DOWNLOAD_FINISHED = "on_download_finished"
|
||||
CONF_PLACEHOLDER = "placeholder"
|
||||
CONF_UPDATE = "update"
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -167,6 +168,7 @@ SET_URL_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.use_id(OnlineImage),
|
||||
cv.Required(CONF_URL): cv.templatable(cv.url),
|
||||
cv.Optional(CONF_UPDATE, default=True): cv.templatable(bool),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -188,6 +190,9 @@ async def online_image_action_to_code(config, action_id, template_arg, args):
|
||||
if CONF_URL in config:
|
||||
template_ = await cg.templatable(config[CONF_URL], args, cg.std_string)
|
||||
cg.add(var.set_url(template_))
|
||||
if CONF_UPDATE in config:
|
||||
template_ = await cg.templatable(config[CONF_UPDATE], args, bool)
|
||||
cg.add(var.set_update(template_))
|
||||
return var
|
||||
|
||||
|
||||
|
@@ -201,10 +201,13 @@ template<typename... Ts> class OnlineImageSetUrlAction : public Action<Ts...> {
|
||||
public:
|
||||
OnlineImageSetUrlAction(OnlineImage *parent) : parent_(parent) {}
|
||||
TEMPLATABLE_VALUE(std::string, url)
|
||||
TEMPLATABLE_VALUE(bool, update)
|
||||
void play(Ts... x) override {
|
||||
this->parent_->set_url(this->url_.value(x...));
|
||||
if (this->update_.value(x...)) {
|
||||
this->parent_->update();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
OnlineImage *parent_;
|
||||
|
@@ -46,7 +46,7 @@ def set_sdkconfig_options(config):
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_PANID", config[CONF_PAN_ID])
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_CHANNEL", config[CONF_CHANNEL])
|
||||
add_idf_sdkconfig_option(
|
||||
"CONFIG_OPENTHREAD_NETWORK_MASTERKEY", f"{config[CONF_NETWORK_KEY]:X}"
|
||||
"CONFIG_OPENTHREAD_NETWORK_MASTERKEY", f"{config[CONF_NETWORK_KEY]:X}".lower()
|
||||
)
|
||||
|
||||
if network_name := config.get(CONF_NETWORK_NAME):
|
||||
@@ -54,14 +54,14 @@ def set_sdkconfig_options(config):
|
||||
|
||||
if (ext_pan_id := config.get(CONF_EXT_PAN_ID)) is not None:
|
||||
add_idf_sdkconfig_option(
|
||||
"CONFIG_OPENTHREAD_NETWORK_EXTPANID", f"{ext_pan_id:X}"
|
||||
"CONFIG_OPENTHREAD_NETWORK_EXTPANID", f"{ext_pan_id:X}".lower()
|
||||
)
|
||||
if (mesh_local_prefix := config.get(CONF_MESH_LOCAL_PREFIX)) is not None:
|
||||
add_idf_sdkconfig_option(
|
||||
"CONFIG_OPENTHREAD_MESH_LOCAL_PREFIX", f"{mesh_local_prefix:X}"
|
||||
"CONFIG_OPENTHREAD_MESH_LOCAL_PREFIX", f"{mesh_local_prefix}".lower()
|
||||
)
|
||||
if (pskc := config.get(CONF_PSKC)) is not None:
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_PSKC", f"{pskc:X}")
|
||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_PSKC", f"{pskc:X}".lower())
|
||||
|
||||
if CONF_FORCE_DATASET in config:
|
||||
if config[CONF_FORCE_DATASET]:
|
||||
@@ -98,7 +98,7 @@ _CONNECTION_SCHEMA = cv.Schema(
|
||||
cv.Optional(CONF_EXT_PAN_ID): cv.hex_int,
|
||||
cv.Optional(CONF_NETWORK_NAME): cv.string_strict,
|
||||
cv.Optional(CONF_PSKC): cv.hex_int,
|
||||
cv.Optional(CONF_MESH_LOCAL_PREFIX): cv.hex_int,
|
||||
cv.Optional(CONF_MESH_LOCAL_PREFIX): cv.ipv6network,
|
||||
}
|
||||
)
|
||||
|
||||
|
@@ -137,7 +137,7 @@ void OpenThreadSrpComponent::setup() {
|
||||
// Copy the mdns services to our local instance so that the c_str pointers remain valid for the lifetime of this
|
||||
// component
|
||||
this->mdns_services_ = this->mdns_->get_services();
|
||||
ESP_LOGW(TAG, "Setting up SRP services. count = %d\n", this->mdns_services_.size());
|
||||
ESP_LOGD(TAG, "Setting up SRP services. count = %d\n", this->mdns_services_.size());
|
||||
for (const auto &service : this->mdns_services_) {
|
||||
otSrpClientBuffersServiceEntry *entry = otSrpClientBuffersAllocateService(instance);
|
||||
if (!entry) {
|
||||
@@ -185,11 +185,11 @@ void OpenThreadSrpComponent::setup() {
|
||||
if (error != OT_ERROR_NONE) {
|
||||
ESP_LOGW(TAG, "Failed to add service: %s", otThreadErrorToString(error));
|
||||
}
|
||||
ESP_LOGW(TAG, "Added service: %s", full_service.c_str());
|
||||
ESP_LOGD(TAG, "Added service: %s", full_service.c_str());
|
||||
}
|
||||
|
||||
otSrpClientEnableAutoStartMode(instance, srp_start_callback, nullptr);
|
||||
ESP_LOGW(TAG, "Finished SRP setup");
|
||||
ESP_LOGD(TAG, "Finished SRP setup");
|
||||
}
|
||||
|
||||
void *OpenThreadSrpComponent::pool_alloc_(size_t size) {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# Sourced from https://gist.github.com/agners/0338576e0003318b63ec1ea75adc90f9
|
||||
import binascii
|
||||
import ipaddress
|
||||
|
||||
from esphome.const import CONF_CHANNEL
|
||||
|
||||
@@ -37,6 +38,12 @@ def parse_tlv(tlv) -> dict:
|
||||
if tag in TLV_TYPES:
|
||||
if tag == 3:
|
||||
output[TLV_TYPES[tag]] = val.decode("utf-8")
|
||||
elif tag == 7:
|
||||
mesh_local_prefix = binascii.hexlify(val).decode("utf-8")
|
||||
mesh_local_prefix_str = f"{mesh_local_prefix}0000000000000000"
|
||||
ipv6_bytes = bytes.fromhex(mesh_local_prefix_str)
|
||||
ipv6_address = ipaddress.IPv6Address(ipv6_bytes)
|
||||
output[TLV_TYPES[tag]] = f"{ipv6_address}/64"
|
||||
else:
|
||||
output[TLV_TYPES[tag]] = int.from_bytes(val)
|
||||
return output
|
||||
|
0
esphome/components/opt3001/__init__.py
Normal file
0
esphome/components/opt3001/__init__.py
Normal file
122
esphome/components/opt3001/opt3001.cpp
Normal file
122
esphome/components/opt3001/opt3001.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "opt3001.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace opt3001 {
|
||||
|
||||
static const char *const TAG = "opt3001.sensor";
|
||||
|
||||
static const uint8_t OPT3001_REG_RESULT = 0x00;
|
||||
static const uint8_t OPT3001_REG_CONFIGURATION = 0x01;
|
||||
// See datasheet for full description of each bit.
|
||||
static const uint16_t OPT3001_CONFIGURATION_RANGE_FULL = 0b1100000000000000;
|
||||
static const uint16_t OPT3001_CONFIGURATION_CONVERSION_TIME_800 = 0b100000000000;
|
||||
static const uint16_t OPT3001_CONFIGURATION_CONVERSION_MODE_MASK = 0b11000000000;
|
||||
static const uint16_t OPT3001_CONFIGURATION_CONVERSION_MODE_SINGLE_SHOT = 0b01000000000;
|
||||
static const uint16_t OPT3001_CONFIGURATION_CONVERSION_MODE_SHUTDOWN = 0b00000000000;
|
||||
// tl;dr: Configure an automatic-ranged, 800ms single shot reading,
|
||||
// with INT processing disabled
|
||||
static const uint16_t OPT3001_CONFIGURATION_FULL_RANGE_ONE_SHOT = OPT3001_CONFIGURATION_RANGE_FULL |
|
||||
OPT3001_CONFIGURATION_CONVERSION_TIME_800 |
|
||||
OPT3001_CONFIGURATION_CONVERSION_MODE_SINGLE_SHOT;
|
||||
static const uint16_t OPT3001_CONVERSION_TIME_800 = 825; // give it 25 extra ms; it seems to not be ready quite often
|
||||
|
||||
/*
|
||||
opt3001 properties:
|
||||
|
||||
- e (exponent) = high 4 bits of result register
|
||||
- m (mantissa) = low 12 bits of result register
|
||||
- formula: (0.01 * 2^e) * m lx
|
||||
|
||||
*/
|
||||
|
||||
void OPT3001Sensor::read_result_(const std::function<void(float)> &f) {
|
||||
// ensure the single shot flag is clear, indicating it's done
|
||||
uint16_t raw_value;
|
||||
if (this->read(reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Reading configuration register failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
raw_value = i2c::i2ctohs(raw_value);
|
||||
|
||||
if ((raw_value & OPT3001_CONFIGURATION_CONVERSION_MODE_MASK) != OPT3001_CONFIGURATION_CONVERSION_MODE_SHUTDOWN) {
|
||||
// not ready; wait 10ms and try again
|
||||
ESP_LOGW(TAG, "Data not ready; waiting 10ms");
|
||||
this->set_timeout("opt3001_wait", 10, [this, f]() { read_result_(f); });
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->read_register(OPT3001_REG_RESULT, reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Reading result register failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
raw_value = i2c::i2ctohs(raw_value);
|
||||
|
||||
uint8_t exponent = raw_value >> 12;
|
||||
uint16_t mantissa = raw_value & 0b111111111111;
|
||||
|
||||
double lx = 0.01 * pow(2.0, double(exponent)) * double(mantissa);
|
||||
f(float(lx));
|
||||
}
|
||||
|
||||
void OPT3001Sensor::read_lx_(const std::function<void(float)> &f) {
|
||||
// turn on (after one-shot sensor automatically powers down)
|
||||
uint16_t start_measurement = i2c::htoi2cs(OPT3001_CONFIGURATION_FULL_RANGE_ONE_SHOT);
|
||||
if (this->write_register(OPT3001_REG_CONFIGURATION, reinterpret_cast<uint8_t *>(&start_measurement), 2) !=
|
||||
i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Triggering one shot measurement failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
|
||||
this->set_timeout("read", OPT3001_CONVERSION_TIME_800, [this, f]() {
|
||||
if (this->write(&OPT3001_REG_CONFIGURATION, 1, true) != i2c::ERROR_OK) {
|
||||
ESP_LOGW(TAG, "Starting configuration register read failed");
|
||||
f(NAN);
|
||||
return;
|
||||
}
|
||||
|
||||
this->read_result_(f);
|
||||
});
|
||||
}
|
||||
|
||||
void OPT3001Sensor::dump_config() {
|
||||
LOG_SENSOR("", "OPT3001", this);
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||
}
|
||||
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void OPT3001Sensor::update() {
|
||||
// Set a flag and skip just in case the sensor isn't responding,
|
||||
// and we just keep waiting for it in read_result_.
|
||||
// This way we don't end up with potentially boundless "threads"
|
||||
// using up memory and eventually crashing the device
|
||||
if (this->updating_) {
|
||||
return;
|
||||
}
|
||||
this->updating_ = true;
|
||||
|
||||
this->read_lx_([this](float val) {
|
||||
this->updating_ = false;
|
||||
|
||||
if (std::isnan(val)) {
|
||||
this->status_set_warning();
|
||||
this->publish_state(NAN);
|
||||
return;
|
||||
}
|
||||
ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), val);
|
||||
this->status_clear_warning();
|
||||
this->publish_state(val);
|
||||
});
|
||||
}
|
||||
|
||||
float OPT3001Sensor::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
} // namespace opt3001
|
||||
} // namespace esphome
|
27
esphome/components/opt3001/opt3001.h
Normal file
27
esphome/components/opt3001/opt3001.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace opt3001 {
|
||||
|
||||
/// This class implements support for the i2c-based OPT3001 ambient light sensor.
|
||||
class OPT3001Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void dump_config() override;
|
||||
void update() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
protected:
|
||||
// checks if one-shot is complete before reading the result and returning it
|
||||
void read_result_(const std::function<void(float)> &f);
|
||||
// begins a one-shot measurement
|
||||
void read_lx_(const std::function<void(float)> &f);
|
||||
|
||||
bool updating_{false};
|
||||
};
|
||||
|
||||
} // namespace opt3001
|
||||
} // namespace esphome
|
35
esphome/components/opt3001/sensor.py
Normal file
35
esphome/components/opt3001/sensor.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_LUX,
|
||||
)
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
CODEOWNERS = ["@ccutrer"]
|
||||
|
||||
opt3001_ns = cg.esphome_ns.namespace("opt3001")
|
||||
|
||||
OPT3001Sensor = opt3001_ns.class_(
|
||||
"OPT3001Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
sensor.sensor_schema(
|
||||
OPT3001Sensor,
|
||||
unit_of_measurement=UNIT_LUX,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_ILLUMINANCE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x44))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await sensor.new_sensor(config)
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
@@ -9,8 +9,8 @@
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/irq.h>
|
||||
#include <hardware/pio.h>
|
||||
#include <pico/stdlib.h>
|
||||
#include <pico/sem.h>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace rp2040_pio_led_strip {
|
||||
@@ -44,7 +44,7 @@ void RP2040PIOLEDStripLightOutput::setup() {
|
||||
|
||||
size_t buffer_size = this->get_buffer_size_();
|
||||
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->buf_ = allocator.allocate(buffer_size);
|
||||
if (this->buf_ == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", buffer_size);
|
||||
|
@@ -17,8 +17,8 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -65,6 +65,9 @@ _SELECT_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_SELECT_SCHEMA.add_extra(entity_duplicate_validator("select"))
|
||||
|
||||
|
||||
def select_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -89,7 +92,7 @@ SELECT_SCHEMA.add_extra(cv.deprecated_schema_constant("select"))
|
||||
|
||||
|
||||
async def setup_select_core_(var, config, *, options: list[str]):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "select")
|
||||
|
||||
cg.add(var.traits.set_options(options))
|
||||
|
||||
|
@@ -101,8 +101,8 @@ from esphome.const import (
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
from esphome.util import Registry
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
@@ -318,6 +318,8 @@ _SENSOR_SCHEMA = (
|
||||
)
|
||||
)
|
||||
|
||||
_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("sensor"))
|
||||
|
||||
|
||||
def sensor_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
@@ -787,7 +789,7 @@ async def build_filters(config):
|
||||
|
||||
|
||||
async def setup_sensor_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "sensor")
|
||||
|
||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||
cg.add(var.set_device_class(device_class))
|
||||
|
@@ -79,6 +79,7 @@ CONF_SPI_MODE = "spi_mode"
|
||||
CONF_FORCE_SW = "force_sw"
|
||||
CONF_INTERFACE = "interface"
|
||||
CONF_INTERFACE_INDEX = "interface_index"
|
||||
CONF_RELEASE_DEVICE = "release_device"
|
||||
TYPE_SINGLE = "single"
|
||||
TYPE_QUAD = "quad"
|
||||
TYPE_OCTAL = "octal"
|
||||
@@ -378,6 +379,7 @@ def spi_device_schema(
|
||||
cv.Optional(CONF_SPI_MODE, default=default_mode): cv.enum(
|
||||
SPI_MODE_OPTIONS, upper=True
|
||||
),
|
||||
cv.Optional(CONF_RELEASE_DEVICE): cv.All(cv.boolean, cv.only_with_esp_idf),
|
||||
}
|
||||
if cs_pin_required:
|
||||
schema[cv.Required(CONF_CS_PIN)] = pins.gpio_output_pin_schema
|
||||
@@ -389,13 +391,15 @@ def spi_device_schema(
|
||||
async def register_spi_device(var, config):
|
||||
parent = await cg.get_variable(config[CONF_SPI_ID])
|
||||
cg.add(var.set_spi_parent(parent))
|
||||
if CONF_CS_PIN in config:
|
||||
pin = await cg.gpio_pin_expression(config[CONF_CS_PIN])
|
||||
if cs_pin := config.get(CONF_CS_PIN):
|
||||
pin = await cg.gpio_pin_expression(cs_pin)
|
||||
cg.add(var.set_cs_pin(pin))
|
||||
if CONF_DATA_RATE in config:
|
||||
cg.add(var.set_data_rate(config[CONF_DATA_RATE]))
|
||||
if CONF_SPI_MODE in config:
|
||||
cg.add(var.set_mode(config[CONF_SPI_MODE]))
|
||||
if data_rate := config.get(CONF_DATA_RATE):
|
||||
cg.add(var.set_data_rate(data_rate))
|
||||
if spi_mode := config.get(CONF_SPI_MODE):
|
||||
cg.add(var.set_mode(spi_mode))
|
||||
if release_device := config.get(CONF_RELEASE_DEVICE):
|
||||
cg.add(var.set_release_device(release_device))
|
||||
|
||||
|
||||
def final_validate_device_schema(name: str, *, require_mosi: bool, require_miso: bool):
|
||||
|
@@ -16,12 +16,13 @@ bool SPIDelegate::is_ready() { return true; }
|
||||
GPIOPin *const NullPin::NULL_PIN = new NullPin(); // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
SPIDelegate *SPIComponent::register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate,
|
||||
GPIOPin *cs_pin) {
|
||||
GPIOPin *cs_pin, bool release_device, bool write_only) {
|
||||
if (this->devices_.count(device) != 0) {
|
||||
ESP_LOGE(TAG, "Device already registered");
|
||||
return this->devices_[device];
|
||||
}
|
||||
SPIDelegate *delegate = this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin); // NOLINT
|
||||
SPIDelegate *delegate =
|
||||
this->spi_bus_->get_delegate(data_rate, bit_order, mode, cs_pin, release_device, write_only); // NOLINT
|
||||
this->devices_[device] = delegate;
|
||||
return delegate;
|
||||
}
|
||||
|
@@ -317,7 +317,8 @@ class SPIBus {
|
||||
|
||||
SPIBus(GPIOPin *clk, GPIOPin *sdo, GPIOPin *sdi) : clk_pin_(clk), sdo_pin_(sdo), sdi_pin_(sdi) {}
|
||||
|
||||
virtual SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) {
|
||||
virtual SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||
bool release_device, bool write_only) {
|
||||
return new SPIDelegateBitBash(data_rate, bit_order, mode, cs_pin, this->clk_pin_, this->sdo_pin_, this->sdi_pin_);
|
||||
}
|
||||
|
||||
@@ -334,7 +335,7 @@ class SPIClient;
|
||||
class SPIComponent : public Component {
|
||||
public:
|
||||
SPIDelegate *register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate,
|
||||
GPIOPin *cs_pin);
|
||||
GPIOPin *cs_pin, bool release_device, bool write_only);
|
||||
void unregister_device(SPIClient *device);
|
||||
|
||||
void set_clk(GPIOPin *clk) { this->clk_pin_ = clk; }
|
||||
@@ -390,7 +391,8 @@ class SPIClient {
|
||||
|
||||
virtual void spi_setup() {
|
||||
esph_log_d("spi_device", "mode %u, data_rate %ukHz", (unsigned) this->mode_, (unsigned) (this->data_rate_ / 1000));
|
||||
this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_);
|
||||
this->delegate_ = this->parent_->register_device(this, this->mode_, this->bit_order_, this->data_rate_, this->cs_,
|
||||
this->release_device_, this->write_only_);
|
||||
}
|
||||
|
||||
virtual void spi_teardown() {
|
||||
@@ -399,6 +401,8 @@ class SPIClient {
|
||||
}
|
||||
|
||||
bool spi_is_ready() { return this->delegate_->is_ready(); }
|
||||
void set_release_device(bool release) { this->release_device_ = release; }
|
||||
void set_write_only(bool write_only) { this->write_only_ = write_only; }
|
||||
|
||||
protected:
|
||||
SPIBitOrder bit_order_{BIT_ORDER_MSB_FIRST};
|
||||
@@ -406,6 +410,8 @@ class SPIClient {
|
||||
uint32_t data_rate_{1000000};
|
||||
SPIComponent *parent_{nullptr};
|
||||
GPIOPin *cs_{nullptr};
|
||||
bool release_device_{false};
|
||||
bool write_only_{false};
|
||||
SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE};
|
||||
};
|
||||
|
||||
|
@@ -43,10 +43,7 @@ class SPIDelegateHw : public SPIDelegate {
|
||||
return;
|
||||
}
|
||||
#ifdef USE_RP2040
|
||||
// avoid overwriting the supplied buffer. Use vector for automatic deallocation
|
||||
auto rxbuf = std::vector<uint8_t>(length);
|
||||
memcpy(rxbuf.data(), ptr, length);
|
||||
this->channel_->transfer((void *) rxbuf.data(), length);
|
||||
this->channel_->transfer(ptr, nullptr, length);
|
||||
#elif defined(USE_ESP8266)
|
||||
// ESP8266 SPI library requires the pointer to be word aligned, but the data may not be
|
||||
// so we need to copy the data to a temporary buffer
|
||||
@@ -89,7 +86,8 @@ class SPIBusHw : public SPIBus {
|
||||
#endif
|
||||
}
|
||||
|
||||
SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) override {
|
||||
SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||
bool release_device, bool write_only) override {
|
||||
return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin);
|
||||
}
|
||||
|
||||
|
@@ -11,34 +11,26 @@ static const size_t MAX_TRANSFER_SIZE = 4092; // dictated by ESP-IDF API.
|
||||
class SPIDelegateHw : public SPIDelegate {
|
||||
public:
|
||||
SPIDelegateHw(SPIInterface channel, uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||
bool write_only)
|
||||
: SPIDelegate(data_rate, bit_order, mode, cs_pin), channel_(channel), write_only_(write_only) {
|
||||
spi_device_interface_config_t config = {};
|
||||
config.mode = static_cast<uint8_t>(mode);
|
||||
config.clock_speed_hz = static_cast<int>(data_rate);
|
||||
config.spics_io_num = -1;
|
||||
config.flags = 0;
|
||||
config.queue_size = 1;
|
||||
config.pre_cb = nullptr;
|
||||
config.post_cb = nullptr;
|
||||
if (bit_order == BIT_ORDER_LSB_FIRST)
|
||||
config.flags |= SPI_DEVICE_BIT_LSBFIRST;
|
||||
if (write_only)
|
||||
config.flags |= SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY;
|
||||
esp_err_t const err = spi_bus_add_device(channel, &config, &this->handle_);
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGE(TAG, "Add device failed - err %X", err);
|
||||
bool release_device, bool write_only)
|
||||
: SPIDelegate(data_rate, bit_order, mode, cs_pin),
|
||||
channel_(channel),
|
||||
release_device_(release_device),
|
||||
write_only_(write_only) {
|
||||
if (!this->release_device_)
|
||||
add_device_();
|
||||
}
|
||||
|
||||
bool is_ready() override { return this->handle_ != nullptr; }
|
||||
|
||||
void begin_transaction() override {
|
||||
if (this->release_device_)
|
||||
this->add_device_();
|
||||
if (this->is_ready()) {
|
||||
if (spi_device_acquire_bus(this->handle_, portMAX_DELAY) != ESP_OK)
|
||||
ESP_LOGE(TAG, "Failed to acquire SPI bus");
|
||||
SPIDelegate::begin_transaction();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "spi_setup called before initialisation");
|
||||
ESP_LOGW(TAG, "SPI device not ready, cannot begin transaction");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +38,10 @@ class SPIDelegateHw : public SPIDelegate {
|
||||
if (this->is_ready()) {
|
||||
SPIDelegate::end_transaction();
|
||||
spi_device_release_bus(this->handle_);
|
||||
if (this->release_device_) {
|
||||
spi_bus_remove_device(this->handle_);
|
||||
this->handle_ = nullptr; // reset handle to indicate no device is registered
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,8 +185,30 @@ class SPIDelegateHw : public SPIDelegate {
|
||||
void read_array(uint8_t *ptr, size_t length) override { this->transfer(nullptr, ptr, length); }
|
||||
|
||||
protected:
|
||||
bool add_device_() {
|
||||
spi_device_interface_config_t config = {};
|
||||
config.mode = static_cast<uint8_t>(this->mode_);
|
||||
config.clock_speed_hz = static_cast<int>(this->data_rate_);
|
||||
config.spics_io_num = -1;
|
||||
config.flags = 0;
|
||||
config.queue_size = 1;
|
||||
config.pre_cb = nullptr;
|
||||
config.post_cb = nullptr;
|
||||
if (this->bit_order_ == BIT_ORDER_LSB_FIRST)
|
||||
config.flags |= SPI_DEVICE_BIT_LSBFIRST;
|
||||
if (this->write_only_)
|
||||
config.flags |= SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_NO_DUMMY;
|
||||
esp_err_t const err = spi_bus_add_device(this->channel_, &config, &this->handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Add device failed - err %X", err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SPIInterface channel_{};
|
||||
spi_device_handle_t handle_{};
|
||||
bool release_device_{false};
|
||||
bool write_only_{false};
|
||||
};
|
||||
|
||||
@@ -231,9 +249,10 @@ class SPIBusHw : public SPIBus {
|
||||
ESP_LOGE(TAG, "Bus init failed - err %X", err);
|
||||
}
|
||||
|
||||
SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin) override {
|
||||
return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin,
|
||||
Utility::get_pin_no(this->sdi_pin_) == -1);
|
||||
SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||
bool release_device, bool write_only) override {
|
||||
return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin, release_device,
|
||||
write_only || Utility::get_pin_no(this->sdi_pin_) == -1);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@@ -5,7 +5,7 @@ namespace spi_led_strip {
|
||||
|
||||
SpiLedStrip::SpiLedStrip(uint16_t num_leds) {
|
||||
this->num_leds_ = num_leds;
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
RAMAllocator<uint8_t> allocator;
|
||||
this->buffer_size_ = num_leds * 4 + 8;
|
||||
this->buf_ = allocator.allocate(this->buffer_size_);
|
||||
if (this->buf_ == nullptr) {
|
||||
|
@@ -20,8 +20,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_SWITCH,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -91,6 +91,9 @@ _SWITCH_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_SWITCH_SCHEMA.add_extra(entity_duplicate_validator("switch"))
|
||||
|
||||
|
||||
def switch_schema(
|
||||
class_: MockObjClass,
|
||||
*,
|
||||
@@ -131,7 +134,7 @@ SWITCH_SCHEMA.add_extra(cv.deprecated_schema_constant("switch"))
|
||||
|
||||
|
||||
async def setup_switch_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "switch")
|
||||
|
||||
if (inverted := config.get(CONF_INVERTED)) is not None:
|
||||
cg.add(var.set_inverted(inverted))
|
||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
||||
CONF_WEB_SERVER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@mauritskorse"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -58,6 +58,9 @@ _TEXT_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_TEXT_SCHEMA.add_extra(entity_duplicate_validator("text"))
|
||||
|
||||
|
||||
def text_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -94,7 +97,7 @@ async def setup_text_core_(
|
||||
max_length: int | None,
|
||||
pattern: str | None,
|
||||
):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "text")
|
||||
|
||||
cg.add(var.traits.set_min_length(min_length))
|
||||
cg.add(var.traits.set_max_length(max_length))
|
||||
|
@@ -21,8 +21,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
from esphome.util import Registry
|
||||
|
||||
DEVICE_CLASSES = [
|
||||
@@ -153,6 +153,9 @@ _TEXT_SENSOR_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_TEXT_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("text_sensor"))
|
||||
|
||||
|
||||
def text_sensor_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -186,7 +189,7 @@ async def build_filters(config):
|
||||
|
||||
|
||||
async def setup_text_sensor_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "text_sensor")
|
||||
|
||||
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||
cg.add(var.set_device_class(device_class))
|
||||
|
@@ -15,8 +15,8 @@ from esphome.const import (
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
CODEOWNERS = ["@jesserockz"]
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
@@ -58,6 +58,9 @@ _UPDATE_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_UPDATE_SCHEMA.add_extra(entity_duplicate_validator("update"))
|
||||
|
||||
|
||||
def update_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -87,7 +90,7 @@ UPDATE_SCHEMA.add_extra(cv.deprecated_schema_constant("update"))
|
||||
|
||||
|
||||
async def setup_update_core_(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "update")
|
||||
|
||||
if device_class_config := config.get(CONF_DEVICE_CLASS):
|
||||
cg.add(var.set_device_class(device_class_config))
|
||||
|
@@ -6,7 +6,7 @@ from esphome.components.esp32 import (
|
||||
only_on_variant,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.const import CONF_DEVICES, CONF_ID
|
||||
from esphome.cpp_types import Component
|
||||
|
||||
AUTO_LOAD = ["bytebuffer"]
|
||||
@@ -16,9 +16,9 @@ usb_host_ns = cg.esphome_ns.namespace("usb_host")
|
||||
USBHost = usb_host_ns.class_("USBHost", Component)
|
||||
USBClient = usb_host_ns.class_("USBClient", Component)
|
||||
|
||||
CONF_DEVICES = "devices"
|
||||
CONF_VID = "vid"
|
||||
CONF_PID = "pid"
|
||||
CONF_ENABLE_HUBS = "enable_hubs"
|
||||
|
||||
|
||||
def usb_device_schema(cls=USBClient, vid: int = None, pid: [int] = None) -> cv.Schema:
|
||||
@@ -42,6 +42,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.COMPONENT_SCHEMA.extend(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(USBHost),
|
||||
cv.Optional(CONF_ENABLE_HUBS, default=False): cv.boolean,
|
||||
cv.Optional(CONF_DEVICES): cv.ensure_list(usb_device_schema()),
|
||||
}
|
||||
),
|
||||
@@ -58,6 +59,8 @@ async def register_usb_client(config):
|
||||
|
||||
async def to_code(config):
|
||||
add_idf_sdkconfig_option("CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE", 1024)
|
||||
if config.get(CONF_ENABLE_HUBS):
|
||||
add_idf_sdkconfig_option("CONFIG_USB_HOST_HUBS_SUPPORTED", True)
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
for device in config.get(CONF_DEVICES) or ():
|
||||
|
@@ -22,8 +22,8 @@ from esphome.const import (
|
||||
DEVICE_CLASS_WATER,
|
||||
)
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
from esphome.core.entity_helpers import entity_duplicate_validator, setup_entity
|
||||
from esphome.cpp_generator import MockObjClass
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
|
||||
IS_PLATFORM_COMPONENT = True
|
||||
|
||||
@@ -103,6 +103,9 @@ _VALVE_SCHEMA = (
|
||||
)
|
||||
|
||||
|
||||
_VALVE_SCHEMA.add_extra(entity_duplicate_validator("valve"))
|
||||
|
||||
|
||||
def valve_schema(
|
||||
class_: MockObjClass = cv.UNDEFINED,
|
||||
*,
|
||||
@@ -132,7 +135,7 @@ VALVE_SCHEMA.add_extra(cv.deprecated_schema_constant("valve"))
|
||||
|
||||
|
||||
async def _setup_valve_core(var, config):
|
||||
await setup_entity(var, config)
|
||||
await setup_entity(var, config, "valve")
|
||||
|
||||
if device_class_config := config.get(CONF_DEVICE_CLASS):
|
||||
cg.add(var.set_device_class(device_class_config))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user