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.
|
# Run the formatter.
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 7.2.0
|
rev: 7.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
|
@@ -323,6 +323,7 @@ esphome/components/one_wire/* @ssieb
|
|||||||
esphome/components/online_image/* @clydebarrow @guillempages
|
esphome/components/online_image/* @clydebarrow @guillempages
|
||||||
esphome/components/opentherm/* @olegtarasov
|
esphome/components/opentherm/* @olegtarasov
|
||||||
esphome/components/openthread/* @mrene
|
esphome/components/openthread/* @mrene
|
||||||
|
esphome/components/opt3001/* @ccutrer
|
||||||
esphome/components/ota/* @esphome/core
|
esphome/components/ota/* @esphome/core
|
||||||
esphome/components/output/* @esphome/core
|
esphome/components/output/* @esphome/core
|
||||||
esphome/components/packet_transport/* @clydebarrow
|
esphome/components/packet_transport/* @clydebarrow
|
||||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
CODEOWNERS = ["@grahambrown11", "@hwstar"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
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(
|
def alarm_control_panel_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -190,7 +193,7 @@ ALARM_CONTROL_PANEL_CONDITION_SCHEMA = maybe_simple_id(
|
|||||||
|
|
||||||
|
|
||||||
async def setup_alarm_control_panel_core_(var, config):
|
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, []):
|
for conf in config.get(CONF_ON_STATE, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await automation.build_automation(trigger, [], conf)
|
await automation.build_automation(trigger, [], conf)
|
||||||
|
@@ -188,6 +188,17 @@ message DeviceInfoRequest {
|
|||||||
// Empty
|
// 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 {
|
message DeviceInfoResponse {
|
||||||
option (id) = 10;
|
option (id) = 10;
|
||||||
option (source) = SOURCE_SERVER;
|
option (source) = SOURCE_SERVER;
|
||||||
@@ -236,6 +247,12 @@ message DeviceInfoResponse {
|
|||||||
|
|
||||||
// Supports receiving and saving api encryption key
|
// Supports receiving and saving api encryption key
|
||||||
bool api_encryption_supported = 19;
|
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 {
|
message ListEntitiesRequest {
|
||||||
@@ -280,6 +297,7 @@ message ListEntitiesBinarySensorResponse {
|
|||||||
bool disabled_by_default = 7;
|
bool disabled_by_default = 7;
|
||||||
string icon = 8;
|
string icon = 8;
|
||||||
EntityCategory entity_category = 9;
|
EntityCategory entity_category = 9;
|
||||||
|
uint32 device_id = 10;
|
||||||
}
|
}
|
||||||
message BinarySensorStateResponse {
|
message BinarySensorStateResponse {
|
||||||
option (id) = 21;
|
option (id) = 21;
|
||||||
@@ -315,6 +333,7 @@ message ListEntitiesCoverResponse {
|
|||||||
string icon = 10;
|
string icon = 10;
|
||||||
EntityCategory entity_category = 11;
|
EntityCategory entity_category = 11;
|
||||||
bool supports_stop = 12;
|
bool supports_stop = 12;
|
||||||
|
uint32 device_id = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LegacyCoverState {
|
enum LegacyCoverState {
|
||||||
@@ -388,6 +407,7 @@ message ListEntitiesFanResponse {
|
|||||||
string icon = 10;
|
string icon = 10;
|
||||||
EntityCategory entity_category = 11;
|
EntityCategory entity_category = 11;
|
||||||
repeated string supported_preset_modes = 12;
|
repeated string supported_preset_modes = 12;
|
||||||
|
uint32 device_id = 13;
|
||||||
}
|
}
|
||||||
enum FanSpeed {
|
enum FanSpeed {
|
||||||
FAN_SPEED_LOW = 0;
|
FAN_SPEED_LOW = 0;
|
||||||
@@ -471,6 +491,7 @@ message ListEntitiesLightResponse {
|
|||||||
bool disabled_by_default = 13;
|
bool disabled_by_default = 13;
|
||||||
string icon = 14;
|
string icon = 14;
|
||||||
EntityCategory entity_category = 15;
|
EntityCategory entity_category = 15;
|
||||||
|
uint32 device_id = 16;
|
||||||
}
|
}
|
||||||
message LightStateResponse {
|
message LightStateResponse {
|
||||||
option (id) = 24;
|
option (id) = 24;
|
||||||
@@ -563,6 +584,7 @@ message ListEntitiesSensorResponse {
|
|||||||
SensorLastResetType legacy_last_reset_type = 11;
|
SensorLastResetType legacy_last_reset_type = 11;
|
||||||
bool disabled_by_default = 12;
|
bool disabled_by_default = 12;
|
||||||
EntityCategory entity_category = 13;
|
EntityCategory entity_category = 13;
|
||||||
|
uint32 device_id = 14;
|
||||||
}
|
}
|
||||||
message SensorStateResponse {
|
message SensorStateResponse {
|
||||||
option (id) = 25;
|
option (id) = 25;
|
||||||
@@ -595,6 +617,7 @@ message ListEntitiesSwitchResponse {
|
|||||||
bool disabled_by_default = 7;
|
bool disabled_by_default = 7;
|
||||||
EntityCategory entity_category = 8;
|
EntityCategory entity_category = 8;
|
||||||
string device_class = 9;
|
string device_class = 9;
|
||||||
|
uint32 device_id = 10;
|
||||||
}
|
}
|
||||||
message SwitchStateResponse {
|
message SwitchStateResponse {
|
||||||
option (id) = 26;
|
option (id) = 26;
|
||||||
@@ -632,6 +655,7 @@ message ListEntitiesTextSensorResponse {
|
|||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
string device_class = 8;
|
string device_class = 8;
|
||||||
|
uint32 device_id = 9;
|
||||||
}
|
}
|
||||||
message TextSensorStateResponse {
|
message TextSensorStateResponse {
|
||||||
option (id) = 27;
|
option (id) = 27;
|
||||||
@@ -814,6 +838,7 @@ message ListEntitiesCameraResponse {
|
|||||||
bool disabled_by_default = 5;
|
bool disabled_by_default = 5;
|
||||||
string icon = 6;
|
string icon = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
|
uint32 device_id = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message CameraImageResponse {
|
message CameraImageResponse {
|
||||||
@@ -916,6 +941,7 @@ message ListEntitiesClimateResponse {
|
|||||||
bool supports_target_humidity = 23;
|
bool supports_target_humidity = 23;
|
||||||
float visual_min_humidity = 24;
|
float visual_min_humidity = 24;
|
||||||
float visual_max_humidity = 25;
|
float visual_max_humidity = 25;
|
||||||
|
uint32 device_id = 26;
|
||||||
}
|
}
|
||||||
message ClimateStateResponse {
|
message ClimateStateResponse {
|
||||||
option (id) = 47;
|
option (id) = 47;
|
||||||
@@ -999,6 +1025,7 @@ message ListEntitiesNumberResponse {
|
|||||||
string unit_of_measurement = 11;
|
string unit_of_measurement = 11;
|
||||||
NumberMode mode = 12;
|
NumberMode mode = 12;
|
||||||
string device_class = 13;
|
string device_class = 13;
|
||||||
|
uint32 device_id = 14;
|
||||||
}
|
}
|
||||||
message NumberStateResponse {
|
message NumberStateResponse {
|
||||||
option (id) = 50;
|
option (id) = 50;
|
||||||
@@ -1039,6 +1066,7 @@ message ListEntitiesSelectResponse {
|
|||||||
repeated string options = 6;
|
repeated string options = 6;
|
||||||
bool disabled_by_default = 7;
|
bool disabled_by_default = 7;
|
||||||
EntityCategory entity_category = 8;
|
EntityCategory entity_category = 8;
|
||||||
|
uint32 device_id = 9;
|
||||||
}
|
}
|
||||||
message SelectStateResponse {
|
message SelectStateResponse {
|
||||||
option (id) = 53;
|
option (id) = 53;
|
||||||
@@ -1081,6 +1109,7 @@ message ListEntitiesSirenResponse {
|
|||||||
bool supports_duration = 8;
|
bool supports_duration = 8;
|
||||||
bool supports_volume = 9;
|
bool supports_volume = 9;
|
||||||
EntityCategory entity_category = 10;
|
EntityCategory entity_category = 10;
|
||||||
|
uint32 device_id = 11;
|
||||||
}
|
}
|
||||||
message SirenStateResponse {
|
message SirenStateResponse {
|
||||||
option (id) = 56;
|
option (id) = 56;
|
||||||
@@ -1144,6 +1173,7 @@ message ListEntitiesLockResponse {
|
|||||||
|
|
||||||
// Not yet implemented:
|
// Not yet implemented:
|
||||||
string code_format = 11;
|
string code_format = 11;
|
||||||
|
uint32 device_id = 12;
|
||||||
}
|
}
|
||||||
message LockStateResponse {
|
message LockStateResponse {
|
||||||
option (id) = 59;
|
option (id) = 59;
|
||||||
@@ -1183,6 +1213,7 @@ message ListEntitiesButtonResponse {
|
|||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
string device_class = 8;
|
string device_class = 8;
|
||||||
|
uint32 device_id = 9;
|
||||||
}
|
}
|
||||||
message ButtonCommandRequest {
|
message ButtonCommandRequest {
|
||||||
option (id) = 62;
|
option (id) = 62;
|
||||||
@@ -1238,6 +1269,8 @@ message ListEntitiesMediaPlayerResponse {
|
|||||||
bool supports_pause = 8;
|
bool supports_pause = 8;
|
||||||
|
|
||||||
repeated MediaPlayerSupportedFormat supported_formats = 9;
|
repeated MediaPlayerSupportedFormat supported_formats = 9;
|
||||||
|
|
||||||
|
uint32 device_id = 10;
|
||||||
}
|
}
|
||||||
message MediaPlayerStateResponse {
|
message MediaPlayerStateResponse {
|
||||||
option (id) = 64;
|
option (id) = 64;
|
||||||
@@ -1778,6 +1811,7 @@ message ListEntitiesAlarmControlPanelResponse {
|
|||||||
uint32 supported_features = 8;
|
uint32 supported_features = 8;
|
||||||
bool requires_code = 9;
|
bool requires_code = 9;
|
||||||
bool requires_code_to_arm = 10;
|
bool requires_code_to_arm = 10;
|
||||||
|
uint32 device_id = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AlarmControlPanelStateResponse {
|
message AlarmControlPanelStateResponse {
|
||||||
@@ -1823,6 +1857,7 @@ message ListEntitiesTextResponse {
|
|||||||
uint32 max_length = 9;
|
uint32 max_length = 9;
|
||||||
string pattern = 10;
|
string pattern = 10;
|
||||||
TextMode mode = 11;
|
TextMode mode = 11;
|
||||||
|
uint32 device_id = 12;
|
||||||
}
|
}
|
||||||
message TextStateResponse {
|
message TextStateResponse {
|
||||||
option (id) = 98;
|
option (id) = 98;
|
||||||
@@ -1863,6 +1898,7 @@ message ListEntitiesDateResponse {
|
|||||||
string icon = 5;
|
string icon = 5;
|
||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
|
uint32 device_id = 8;
|
||||||
}
|
}
|
||||||
message DateStateResponse {
|
message DateStateResponse {
|
||||||
option (id) = 101;
|
option (id) = 101;
|
||||||
@@ -1906,6 +1942,7 @@ message ListEntitiesTimeResponse {
|
|||||||
string icon = 5;
|
string icon = 5;
|
||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
|
uint32 device_id = 8;
|
||||||
}
|
}
|
||||||
message TimeStateResponse {
|
message TimeStateResponse {
|
||||||
option (id) = 104;
|
option (id) = 104;
|
||||||
@@ -1952,6 +1989,7 @@ message ListEntitiesEventResponse {
|
|||||||
string device_class = 8;
|
string device_class = 8;
|
||||||
|
|
||||||
repeated string event_types = 9;
|
repeated string event_types = 9;
|
||||||
|
uint32 device_id = 10;
|
||||||
}
|
}
|
||||||
message EventResponse {
|
message EventResponse {
|
||||||
option (id) = 108;
|
option (id) = 108;
|
||||||
@@ -1983,6 +2021,7 @@ message ListEntitiesValveResponse {
|
|||||||
bool assumed_state = 9;
|
bool assumed_state = 9;
|
||||||
bool supports_position = 10;
|
bool supports_position = 10;
|
||||||
bool supports_stop = 11;
|
bool supports_stop = 11;
|
||||||
|
uint32 device_id = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ValveOperation {
|
enum ValveOperation {
|
||||||
@@ -2029,6 +2068,7 @@ message ListEntitiesDateTimeResponse {
|
|||||||
string icon = 5;
|
string icon = 5;
|
||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
|
uint32 device_id = 8;
|
||||||
}
|
}
|
||||||
message DateTimeStateResponse {
|
message DateTimeStateResponse {
|
||||||
option (id) = 113;
|
option (id) = 113;
|
||||||
@@ -2069,6 +2109,7 @@ message ListEntitiesUpdateResponse {
|
|||||||
bool disabled_by_default = 6;
|
bool disabled_by_default = 6;
|
||||||
EntityCategory entity_category = 7;
|
EntityCategory entity_category = 7;
|
||||||
string device_class = 8;
|
string device_class = 8;
|
||||||
|
uint32 device_id = 9;
|
||||||
}
|
}
|
||||||
message UpdateStateResponse {
|
message UpdateStateResponse {
|
||||||
option (id) = 117;
|
option (id) = 117;
|
||||||
|
@@ -1440,7 +1440,7 @@ void APIConnection::alarm_control_panel_command(const AlarmControlPanelCommandRe
|
|||||||
|
|
||||||
#ifdef USE_EVENT
|
#ifdef USE_EVENT
|
||||||
void APIConnection::send_event(event::Event *event, const std::string &event_type) {
|
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) {
|
void APIConnection::send_event_info(event::Event *event) {
|
||||||
this->schedule_message_(event, &APIConnection::try_send_event_info, ListEntitiesEventResponse::MESSAGE_TYPE);
|
this->schedule_message_(event, &APIConnection::try_send_event_info, ListEntitiesEventResponse::MESSAGE_TYPE);
|
||||||
@@ -1629,6 +1629,23 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_API_NOISE
|
#ifdef USE_API_NOISE
|
||||||
resp.api_encryption_supported = true;
|
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
|
#endif
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
@@ -1778,7 +1795,8 @@ void APIConnection::process_batch_() {
|
|||||||
const auto &item = this->deferred_batch_.items[0];
|
const auto &item = this->deferred_batch_.items[0];
|
||||||
|
|
||||||
// Let the creator calculate size and encode if it fits
|
// 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 &&
|
if (payload_size > 0 &&
|
||||||
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
|
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) {
|
for (const auto &item : this->deferred_batch_.items) {
|
||||||
// Try to encode message
|
// Try to encode message
|
||||||
// The creator will calculate overhead to determine if the message fits
|
// 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) {
|
if (payload_size == 0) {
|
||||||
// Message won't fit, stop processing
|
// Message won't fit, stop processing
|
||||||
@@ -1891,21 +1909,23 @@ void APIConnection::process_batch_() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
uint16_t APIConnection::MessageCreator::operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
|
||||||
bool is_single) const {
|
bool is_single, uint16_t message_type) const {
|
||||||
switch (message_type_) {
|
if (is_string()) {
|
||||||
case 0: // Function pointer
|
// Handle string-based messages
|
||||||
return data_.ptr(entity, conn, remaining_size, is_single);
|
switch (message_type) {
|
||||||
|
|
||||||
#ifdef USE_EVENT
|
#ifdef USE_EVENT
|
||||||
case EventResponse::MESSAGE_TYPE: {
|
case EventResponse::MESSAGE_TYPE: {
|
||||||
auto *e = static_cast<event::Event *>(entity);
|
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
|
#endif
|
||||||
|
default:
|
||||||
default:
|
// Should not happen, return 0 to indicate no message
|
||||||
// Should not happen, return 0 to indicate no message
|
return 0;
|
||||||
return 0;
|
}
|
||||||
|
} else {
|
||||||
|
// Function pointer case
|
||||||
|
return data_.ptr(entity, conn, remaining_size, is_single);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -301,6 +301,9 @@ class APIConnection : public APIServerConnection {
|
|||||||
response.icon = entity->get_icon();
|
response.icon = entity->get_icon();
|
||||||
response.disabled_by_default = entity->is_disabled_by_default();
|
response.disabled_by_default = entity->is_disabled_by_default();
|
||||||
response.entity_category = static_cast<enums::EntityCategory>(entity->get_entity_category());
|
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
|
// Helper function to fill common entity state fields
|
||||||
@@ -480,55 +483,57 @@ class APIConnection : public APIServerConnection {
|
|||||||
// Function pointer type for message encoding
|
// Function pointer type for message encoding
|
||||||
using MessageCreatorPtr = uint16_t (*)(EntityBase *, APIConnection *, uint32_t remaining_size, bool is_single);
|
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 {
|
class MessageCreator {
|
||||||
|
// Ensure pointer alignment allows LSB tagging
|
||||||
|
static_assert(alignof(std::string *) > 1, "String pointer alignment must be > 1 for LSB tagging");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor for function pointer (message_type = 0)
|
// Constructor for function pointer
|
||||||
MessageCreator(MessageCreatorPtr ptr) : message_type_(0) { data_.ptr = ptr; }
|
MessageCreator(MessageCreatorPtr ptr) {
|
||||||
|
// Function pointers are always aligned, so LSB is 0
|
||||||
|
data_.ptr = ptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Constructor for string state capture
|
// Constructor for string state capture
|
||||||
MessageCreator(const std::string &value, uint16_t msg_type) : message_type_(msg_type) {
|
explicit MessageCreator(const std::string &str_value) {
|
||||||
data_.string_ptr = new std::string(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
|
// Destructor
|
||||||
~MessageCreator() {
|
~MessageCreator() {
|
||||||
// Clean up string data for string-based message types
|
if (has_tagged_string_ptr()) {
|
||||||
if (uses_string_data_()) {
|
delete get_string_ptr();
|
||||||
delete data_.string_ptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy constructor
|
// Copy constructor
|
||||||
MessageCreator(const MessageCreator &other) : message_type_(other.message_type_) {
|
MessageCreator(const MessageCreator &other) {
|
||||||
if (message_type_ == 0) {
|
if (other.has_tagged_string_ptr()) {
|
||||||
data_.ptr = other.data_.ptr;
|
auto *str = new std::string(*other.get_string_ptr());
|
||||||
} else if (uses_string_data_()) {
|
data_.tagged = reinterpret_cast<uintptr_t>(str) | 1;
|
||||||
data_.string_ptr = new std::string(*other.data_.string_ptr);
|
|
||||||
} else {
|
} else {
|
||||||
data_ = other.data_; // For POD types
|
data_ = other.data_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move constructor
|
// Move constructor
|
||||||
MessageCreator(MessageCreator &&other) noexcept : data_(other.data_), message_type_(other.message_type_) {
|
MessageCreator(MessageCreator &&other) noexcept : data_(other.data_) { other.data_.ptr = nullptr; }
|
||||||
other.message_type_ = 0; // Reset other to function pointer type
|
|
||||||
other.data_.ptr = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Assignment operators (needed for batch deduplication)
|
// Assignment operators (needed for batch deduplication)
|
||||||
MessageCreator &operator=(const MessageCreator &other) {
|
MessageCreator &operator=(const MessageCreator &other) {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
// Clean up current string data if needed
|
// Clean up current string data if needed
|
||||||
if (uses_string_data_()) {
|
if (has_tagged_string_ptr()) {
|
||||||
delete data_.string_ptr;
|
delete get_string_ptr();
|
||||||
}
|
}
|
||||||
// Copy new data
|
// Copy new data
|
||||||
message_type_ = other.message_type_;
|
if (other.has_tagged_string_ptr()) {
|
||||||
if (other.message_type_ == 0) {
|
auto *str = new std::string(*other.get_string_ptr());
|
||||||
data_.ptr = other.data_.ptr;
|
data_.tagged = reinterpret_cast<uintptr_t>(str) | 1;
|
||||||
} else if (other.uses_string_data_()) {
|
|
||||||
data_.string_ptr = new std::string(*other.data_.string_ptr);
|
|
||||||
} else {
|
} else {
|
||||||
data_ = other.data_;
|
data_ = other.data_;
|
||||||
}
|
}
|
||||||
@@ -539,30 +544,32 @@ class APIConnection : public APIServerConnection {
|
|||||||
MessageCreator &operator=(MessageCreator &&other) noexcept {
|
MessageCreator &operator=(MessageCreator &&other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
// Clean up current string data if needed
|
// Clean up current string data if needed
|
||||||
if (uses_string_data_()) {
|
if (has_tagged_string_ptr()) {
|
||||||
delete data_.string_ptr;
|
delete get_string_ptr();
|
||||||
}
|
}
|
||||||
// Move data
|
// Move data
|
||||||
message_type_ = other.message_type_;
|
|
||||||
data_ = other.data_;
|
data_ = other.data_;
|
||||||
// Reset other to safe state
|
// Reset other to safe state
|
||||||
other.message_type_ = 0;
|
|
||||||
other.data_.ptr = nullptr;
|
other.data_.ptr = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call operator
|
// Call operator - now accepts message_type as parameter
|
||||||
uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single) const;
|
uint16_t operator()(EntityBase *entity, APIConnection *conn, uint32_t remaining_size, bool is_single,
|
||||||
|
uint16_t message_type) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Helper to check if this message type uses heap-allocated strings
|
// Check if this contains a string pointer
|
||||||
bool uses_string_data_() const { return message_type_ == EventResponse::MESSAGE_TYPE; }
|
bool has_tagged_string_ptr() const { return (data_.tagged & 1) != 0; }
|
||||||
union CreatorData {
|
|
||||||
MessageCreatorPtr ptr; // 8 bytes
|
// Get the actual string pointer (clears the tag bit)
|
||||||
std::string *string_ptr; // 8 bytes
|
std::string *get_string_ptr() const { return reinterpret_cast<std::string *>(data_.tagged & ~uintptr_t(1)); }
|
||||||
} data_; // 8 bytes
|
|
||||||
uint16_t message_type_; // 2 bytes (0 = function ptr, >0 = state capture)
|
union {
|
||||||
|
MessageCreatorPtr ptr;
|
||||||
|
uintptr_t tagged;
|
||||||
|
} data_; // 4 bytes on 32-bit
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generic batching mechanism for both state updates and entity info
|
// 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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
|
void DeviceInfoRequest::dump_to(std::string &out) const { out.append("DeviceInfoRequest {}"); }
|
||||||
#endif
|
#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) {
|
bool DeviceInfoResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||||
switch (field_id) {
|
switch (field_id) {
|
||||||
case 1: {
|
case 1: {
|
||||||
@@ -896,6 +993,18 @@ bool DeviceInfoResponse::decode_length(uint32_t field_id, ProtoLengthDelimited v
|
|||||||
this->bluetooth_mac_address = value.as_string();
|
this->bluetooth_mac_address = value.as_string();
|
||||||
return true;
|
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:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -920,6 +1029,13 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(16, this->suggested_area);
|
buffer.encode_string(16, this->suggested_area);
|
||||||
buffer.encode_string(18, this->bluetooth_mac_address);
|
buffer.encode_string(18, this->bluetooth_mac_address);
|
||||||
buffer.encode_bool(19, this->api_encryption_supported);
|
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 {
|
void DeviceInfoResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->uses_password, false);
|
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->suggested_area, false);
|
||||||
ProtoSize::add_string_field(total_size, 2, this->bluetooth_mac_address, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void DeviceInfoResponse::dump_to(std::string &out) const {
|
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(" api_encryption_supported: ");
|
||||||
out.append(YESNO(this->api_encryption_supported));
|
out.append(YESNO(this->api_encryption_supported));
|
||||||
out.append("\n");
|
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("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1052,6 +1187,10 @@ bool ListEntitiesBinarySensorResponse::decode_varint(uint32_t field_id, ProtoVar
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 10: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1102,6 +1241,7 @@ void ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(7, this->disabled_by_default);
|
buffer.encode_bool(7, this->disabled_by_default);
|
||||||
buffer.encode_string(8, this->icon);
|
buffer.encode_string(8, this->icon);
|
||||||
buffer.encode_enum<enums::EntityCategory>(9, this->entity_category);
|
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 {
|
void ListEntitiesBinarySensorResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||||
ProtoSize::add_string_field(total_size, 1, this->icon, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesBinarySensorResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1236,6 +1382,10 @@ bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||||||
this->supports_stop = value.as_bool();
|
this->supports_stop = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 13: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1289,6 +1439,7 @@ void ListEntitiesCoverResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(10, this->icon);
|
buffer.encode_string(10, this->icon);
|
||||||
buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(11, this->entity_category);
|
||||||
buffer.encode_bool(12, this->supports_stop);
|
buffer.encode_bool(12, this->supports_stop);
|
||||||
|
buffer.encode_uint32(13, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesCoverResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesCoverResponse::dump_to(std::string &out) const {
|
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(" supports_stop: ");
|
||||||
out.append(YESNO(this->supports_stop));
|
out.append(YESNO(this->supports_stop));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1565,6 +1722,10 @@ bool ListEntitiesFanResponse::decode_varint(uint32_t field_id, ProtoVarInt value
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 13: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1620,6 +1781,7 @@ void ListEntitiesFanResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
for (auto &it : this->supported_preset_modes) {
|
for (auto &it : this->supported_preset_modes) {
|
||||||
buffer.encode_string(12, it, true);
|
buffer.encode_string(12, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(13, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesFanResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_string_field(total_size, 1, it, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesFanResponse::dump_to(std::string &out) const {
|
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("'").append(it).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1987,6 +2155,10 @@ bool ListEntitiesLightResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 16: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2055,6 +2227,7 @@ void ListEntitiesLightResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(13, this->disabled_by_default);
|
buffer.encode_bool(13, this->disabled_by_default);
|
||||||
buffer.encode_string(14, this->icon);
|
buffer.encode_string(14, this->icon);
|
||||||
buffer.encode_enum<enums::EntityCategory>(15, this->entity_category);
|
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 {
|
void ListEntitiesLightResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||||
ProtoSize::add_string_field(total_size, 1, this->icon, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesLightResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2658,6 +2837,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 14: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
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_enum<enums::SensorLastResetType>(11, this->legacy_last_reset_type);
|
||||||
buffer.encode_bool(12, this->disabled_by_default);
|
buffer.encode_bool(12, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(13, this->entity_category);
|
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 {
|
void ListEntitiesSensorResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesSensorResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -2860,6 +3050,10 @@ bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 10: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2910,6 +3104,7 @@ void ListEntitiesSwitchResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(7, this->disabled_by_default);
|
buffer.encode_bool(7, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
|
||||||
buffer.encode_string(9, this->device_class);
|
buffer.encode_string(9, this->device_class);
|
||||||
|
buffer.encode_uint32(10, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesSwitchResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesSwitchResponse::dump_to(std::string &out) const {
|
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(" device_class: ");
|
||||||
out.append("'").append(this->device_class).append("'");
|
out.append("'").append(this->device_class).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3061,6 +3262,10 @@ bool ListEntitiesTextSensorResponse::decode_varint(uint32_t field_id, ProtoVarIn
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 9: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3110,6 +3315,7 @@ void ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||||
buffer.encode_string(8, this->device_class);
|
buffer.encode_string(8, this->device_class);
|
||||||
|
buffer.encode_uint32(9, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesTextSensorResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
|
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(" device_class: ");
|
||||||
out.append("'").append(this->device_class).append("'");
|
out.append("'").append(this->device_class).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -3922,6 +4134,10 @@ bool ListEntitiesCameraResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 8: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3966,6 +4182,7 @@ void ListEntitiesCameraResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(5, this->disabled_by_default);
|
buffer.encode_bool(5, this->disabled_by_default);
|
||||||
buffer.encode_string(6, this->icon);
|
buffer.encode_string(6, this->icon);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
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 {
|
void ListEntitiesCameraResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_bool_field(total_size, 1, this->disabled_by_default, false);
|
||||||
ProtoSize::add_string_field(total_size, 1, this->icon, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesCameraResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4156,6 +4379,10 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
|
|||||||
this->supports_target_humidity = value.as_bool();
|
this->supports_target_humidity = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 26: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4262,6 +4489,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(23, this->supports_target_humidity);
|
buffer.encode_bool(23, this->supports_target_humidity);
|
||||||
buffer.encode_float(24, this->visual_min_humidity);
|
buffer.encode_float(24, this->visual_min_humidity);
|
||||||
buffer.encode_float(25, this->visual_max_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 {
|
void ListEntitiesClimateResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_min_humidity != 0.0f, false);
|
||||||
ProtoSize::add_fixed_field<4>(total_size, 2, this->visual_max_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
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);
|
sprintf(buffer, "%g", this->visual_max_humidity);
|
||||||
out.append(buffer);
|
out.append(buffer);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4901,6 +5135,10 @@ bool ListEntitiesNumberResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->mode = value.as_enum<enums::NumberMode>();
|
this->mode = value.as_enum<enums::NumberMode>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 14: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -4971,6 +5209,7 @@ void ListEntitiesNumberResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(11, this->unit_of_measurement);
|
buffer.encode_string(11, this->unit_of_measurement);
|
||||||
buffer.encode_enum<enums::NumberMode>(12, this->mode);
|
buffer.encode_enum<enums::NumberMode>(12, this->mode);
|
||||||
buffer.encode_string(13, this->device_class);
|
buffer.encode_string(13, this->device_class);
|
||||||
|
buffer.encode_uint32(14, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesNumberResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesNumberResponse::dump_to(std::string &out) const {
|
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(" device_class: ");
|
||||||
out.append("'").append(this->device_class).append("'");
|
out.append("'").append(this->device_class).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5151,6 +5396,10 @@ bool ListEntitiesSelectResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 9: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5202,6 +5451,7 @@ void ListEntitiesSelectResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
}
|
}
|
||||||
buffer.encode_bool(7, this->disabled_by_default);
|
buffer.encode_bool(7, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(8, this->entity_category);
|
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 {
|
void ListEntitiesSelectResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesSelectResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5378,6 +5634,10 @@ bool ListEntitiesSirenResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 11: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5431,6 +5691,7 @@ void ListEntitiesSirenResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(8, this->supports_duration);
|
buffer.encode_bool(8, this->supports_duration);
|
||||||
buffer.encode_bool(9, this->supports_volume);
|
buffer.encode_bool(9, this->supports_volume);
|
||||||
buffer.encode_enum<enums::EntityCategory>(10, this->entity_category);
|
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 {
|
void ListEntitiesSirenResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_duration, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->supports_volume, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesSirenResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5683,6 +5950,10 @@ bool ListEntitiesLockResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
|||||||
this->requires_code = value.as_bool();
|
this->requires_code = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 12: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5735,6 +6006,7 @@ void ListEntitiesLockResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(9, this->supports_open);
|
buffer.encode_bool(9, this->supports_open);
|
||||||
buffer.encode_bool(10, this->requires_code);
|
buffer.encode_bool(10, this->requires_code);
|
||||||
buffer.encode_string(11, this->code_format);
|
buffer.encode_string(11, this->code_format);
|
||||||
|
buffer.encode_uint32(12, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesLockResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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->supports_open, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->requires_code, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesLockResponse::dump_to(std::string &out) const {
|
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(" code_format: ");
|
||||||
out.append("'").append(this->code_format).append("'");
|
out.append("'").append(this->code_format).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -5922,6 +6200,10 @@ bool ListEntitiesButtonResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 9: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -5971,6 +6253,7 @@ void ListEntitiesButtonResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||||
buffer.encode_string(8, this->device_class);
|
buffer.encode_string(8, this->device_class);
|
||||||
|
buffer.encode_uint32(9, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesButtonResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesButtonResponse::dump_to(std::string &out) const {
|
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(" device_class: ");
|
||||||
out.append("'").append(this->device_class).append("'");
|
out.append("'").append(this->device_class).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6135,6 +6424,10 @@ bool ListEntitiesMediaPlayerResponse::decode_varint(uint32_t field_id, ProtoVarI
|
|||||||
this->supports_pause = value.as_bool();
|
this->supports_pause = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 10: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -6187,6 +6480,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
for (auto &it : this->supported_formats) {
|
for (auto &it : this->supported_formats) {
|
||||||
buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true);
|
buffer.encode_message<MediaPlayerSupportedFormat>(9, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(10, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesMediaPlayerResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_bool_field(total_size, 1, this->supports_pause, false);
|
||||||
ProtoSize::add_repeated_message(total_size, 1, this->supported_formats);
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
|
void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
|
||||||
@@ -6241,6 +6536,11 @@ void ListEntitiesMediaPlayerResponse::dump_to(std::string &out) const {
|
|||||||
it.dump_to(out);
|
it.dump_to(out);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -8551,6 +8851,10 @@ bool ListEntitiesAlarmControlPanelResponse::decode_varint(uint32_t field_id, Pro
|
|||||||
this->requires_code_to_arm = value.as_bool();
|
this->requires_code_to_arm = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 11: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -8598,6 +8902,7 @@ void ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer buffer) cons
|
|||||||
buffer.encode_uint32(8, this->supported_features);
|
buffer.encode_uint32(8, this->supported_features);
|
||||||
buffer.encode_bool(9, this->requires_code);
|
buffer.encode_bool(9, this->requires_code);
|
||||||
buffer.encode_bool(10, this->requires_code_to_arm);
|
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 {
|
void ListEntitiesAlarmControlPanelResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->requires_code_to_arm, 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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesAlarmControlPanelResponse::dump_to(std::string &out) const {
|
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(" requires_code_to_arm: ");
|
||||||
out.append(YESNO(this->requires_code_to_arm));
|
out.append(YESNO(this->requires_code_to_arm));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -8783,6 +9094,10 @@ bool ListEntitiesTextResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
|||||||
this->mode = value.as_enum<enums::TextMode>();
|
this->mode = value.as_enum<enums::TextMode>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 12: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -8835,6 +9150,7 @@ void ListEntitiesTextResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_uint32(9, this->max_length);
|
buffer.encode_uint32(9, this->max_length);
|
||||||
buffer.encode_string(10, this->pattern);
|
buffer.encode_string(10, this->pattern);
|
||||||
buffer.encode_enum<enums::TextMode>(11, this->mode);
|
buffer.encode_enum<enums::TextMode>(11, this->mode);
|
||||||
|
buffer.encode_uint32(12, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesTextResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_uint32_field(total_size, 1, this->max_length, false);
|
||||||
ProtoSize::add_string_field(total_size, 1, this->pattern, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesTextResponse::dump_to(std::string &out) const {
|
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(" mode: ");
|
||||||
out.append(proto_enum_to_string<enums::TextMode>(this->mode));
|
out.append(proto_enum_to_string<enums::TextMode>(this->mode));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -9014,6 +9336,10 @@ bool ListEntitiesDateResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 8: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9058,6 +9384,7 @@ void ListEntitiesDateResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(5, this->icon);
|
buffer.encode_string(5, this->icon);
|
||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
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 {
|
void ListEntitiesDateResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_string_field(total_size, 1, this->icon, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesDateResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -9255,6 +9588,10 @@ bool ListEntitiesTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt valu
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 8: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9299,6 +9636,7 @@ void ListEntitiesTimeResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(5, this->icon);
|
buffer.encode_string(5, this->icon);
|
||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
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 {
|
void ListEntitiesTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_string_field(total_size, 1, this->icon, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesTimeResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -9496,6 +9840,10 @@ bool ListEntitiesEventResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 10: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9552,6 +9900,7 @@ void ListEntitiesEventResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
for (auto &it : this->event_types) {
|
for (auto &it : this->event_types) {
|
||||||
buffer.encode_string(9, it, true);
|
buffer.encode_string(9, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(10, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesEventResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_string_field(total_size, 1, it, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ProtoSize::add_uint32_field(total_size, 1, this->device_id, false);
|
||||||
}
|
}
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesEventResponse::dump_to(std::string &out) const {
|
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("'").append(it).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -9678,6 +10033,10 @@ bool ListEntitiesValveResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||||||
this->supports_stop = value.as_bool();
|
this->supports_stop = value.as_bool();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 12: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9730,6 +10089,7 @@ void ListEntitiesValveResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(9, this->assumed_state);
|
buffer.encode_bool(9, this->assumed_state);
|
||||||
buffer.encode_bool(10, this->supports_position);
|
buffer.encode_bool(10, this->supports_position);
|
||||||
buffer.encode_bool(11, this->supports_stop);
|
buffer.encode_bool(11, this->supports_stop);
|
||||||
|
buffer.encode_uint32(12, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesValveResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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->assumed_state, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->supports_position, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesValveResponse::dump_to(std::string &out) const {
|
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(" supports_stop: ");
|
||||||
out.append(YESNO(this->supports_stop));
|
out.append(YESNO(this->supports_stop));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -9923,6 +10289,10 @@ bool ListEntitiesDateTimeResponse::decode_varint(uint32_t field_id, ProtoVarInt
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 8: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9967,6 +10337,7 @@ void ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_string(5, this->icon);
|
buffer.encode_string(5, this->icon);
|
||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
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 {
|
void ListEntitiesDateTimeResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_string_field(total_size, 1, this->icon, false);
|
||||||
ProtoSize::add_bool_field(total_size, 1, this->disabled_by_default, 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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesDateTimeResponse::dump_to(std::string &out) const {
|
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(" entity_category: ");
|
||||||
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
out.append(proto_enum_to_string<enums::EntityCategory>(this->entity_category));
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -10114,6 +10491,10 @@ bool ListEntitiesUpdateResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
|||||||
this->entity_category = value.as_enum<enums::EntityCategory>();
|
this->entity_category = value.as_enum<enums::EntityCategory>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case 9: {
|
||||||
|
this->device_id = value.as_uint32();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -10163,6 +10544,7 @@ void ListEntitiesUpdateResponse::encode(ProtoWriteBuffer buffer) const {
|
|||||||
buffer.encode_bool(6, this->disabled_by_default);
|
buffer.encode_bool(6, this->disabled_by_default);
|
||||||
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
buffer.encode_enum<enums::EntityCategory>(7, this->entity_category);
|
||||||
buffer.encode_string(8, this->device_class);
|
buffer.encode_string(8, this->device_class);
|
||||||
|
buffer.encode_uint32(9, this->device_id);
|
||||||
}
|
}
|
||||||
void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
|
void ListEntitiesUpdateResponse::calculate_size(uint32_t &total_size) const {
|
||||||
ProtoSize::add_string_field(total_size, 1, this->object_id, false);
|
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_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_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_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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
void ListEntitiesUpdateResponse::dump_to(std::string &out) const {
|
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(" device_class: ");
|
||||||
out.append("'").append(this->device_class).append("'");
|
out.append("'").append(this->device_class).append("'");
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
|
|
||||||
|
out.append(" device_id: ");
|
||||||
|
sprintf(buffer, "%" PRIu32, this->device_id);
|
||||||
|
out.append(buffer);
|
||||||
|
out.append("\n");
|
||||||
out.append("}");
|
out.append("}");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -264,6 +264,7 @@ class InfoResponseProtoMessage : public ProtoMessage {
|
|||||||
bool disabled_by_default{false};
|
bool disabled_by_default{false};
|
||||||
std::string icon{};
|
std::string icon{};
|
||||||
enums::EntityCategory entity_category{};
|
enums::EntityCategory entity_category{};
|
||||||
|
uint32_t device_id{0};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
};
|
};
|
||||||
@@ -415,10 +416,39 @@ class DeviceInfoRequest : public ProtoMessage {
|
|||||||
|
|
||||||
protected:
|
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 {
|
class DeviceInfoResponse : public ProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 10;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "device_info_response"; }
|
static constexpr const char *message_name() { return "device_info_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -441,6 +471,9 @@ class DeviceInfoResponse : public ProtoMessage {
|
|||||||
std::string suggested_area{};
|
std::string suggested_area{};
|
||||||
std::string bluetooth_mac_address{};
|
std::string bluetooth_mac_address{};
|
||||||
bool api_encryption_supported{false};
|
bool api_encryption_supported{false};
|
||||||
|
std::vector<DeviceInfo> devices{};
|
||||||
|
std::vector<AreaInfo> areas{};
|
||||||
|
AreaInfo area{};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
void calculate_size(uint32_t &total_size) const override;
|
void calculate_size(uint32_t &total_size) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
@@ -493,7 +526,7 @@ class SubscribeStatesRequest : public ProtoMessage {
|
|||||||
class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
|
class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 12;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; }
|
static constexpr const char *message_name() { return "list_entities_binary_sensor_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -532,7 +565,7 @@ class BinarySensorStateResponse : public StateResponseProtoMessage {
|
|||||||
class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
|
class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 13;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_cover_response"; }
|
static constexpr const char *message_name() { return "list_entities_cover_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -601,7 +634,7 @@ class CoverCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesFanResponse : public InfoResponseProtoMessage {
|
class ListEntitiesFanResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 14;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_fan_response"; }
|
static constexpr const char *message_name() { return "list_entities_fan_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -679,7 +712,7 @@ class FanCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesLightResponse : public InfoResponseProtoMessage {
|
class ListEntitiesLightResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 15;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_light_response"; }
|
static constexpr const char *message_name() { return "list_entities_light_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -780,7 +813,7 @@ class LightCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
|
class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 16;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_sensor_response"; }
|
static constexpr const char *message_name() { return "list_entities_sensor_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -823,7 +856,7 @@ class SensorStateResponse : public StateResponseProtoMessage {
|
|||||||
class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
|
class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 17;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_switch_response"; }
|
static constexpr const char *message_name() { return "list_entities_switch_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -880,7 +913,7 @@ class SwitchCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
|
class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 18;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_text_sensor_response"; }
|
static constexpr const char *message_name() { return "list_entities_text_sensor_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1196,7 +1229,7 @@ class ExecuteServiceRequest : public ProtoMessage {
|
|||||||
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
|
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 43;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_camera_response"; }
|
static constexpr const char *message_name() { return "list_entities_camera_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1253,7 +1286,7 @@ class CameraImageRequest : public ProtoMessage {
|
|||||||
class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
|
class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 46;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_climate_response"; }
|
static constexpr const char *message_name() { return "list_entities_climate_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1362,7 +1395,7 @@ class ClimateCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
|
class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 49;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_number_response"; }
|
static constexpr const char *message_name() { return "list_entities_number_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1423,7 +1456,7 @@ class NumberCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
|
class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 52;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_select_response"; }
|
static constexpr const char *message_name() { return "list_entities_select_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1481,7 +1514,7 @@ class SelectCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
|
class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 55;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_siren_response"; }
|
static constexpr const char *message_name() { return "list_entities_siren_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1547,7 +1580,7 @@ class SirenCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesLockResponse : public InfoResponseProtoMessage {
|
class ListEntitiesLockResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 58;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_lock_response"; }
|
static constexpr const char *message_name() { return "list_entities_lock_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1609,7 +1642,7 @@ class LockCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesButtonResponse : public InfoResponseProtoMessage {
|
class ListEntitiesButtonResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 61;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_button_response"; }
|
static constexpr const char *message_name() { return "list_entities_button_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -1662,7 +1695,7 @@ class MediaPlayerSupportedFormat : public ProtoMessage {
|
|||||||
class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage {
|
class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 63;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_media_player_response"; }
|
static constexpr const char *message_name() { return "list_entities_media_player_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2532,7 +2565,7 @@ class VoiceAssistantSetConfiguration : public ProtoMessage {
|
|||||||
class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
|
class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 94;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; }
|
static constexpr const char *message_name() { return "list_entities_alarm_control_panel_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2592,7 +2625,7 @@ class AlarmControlPanelCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesTextResponse : public InfoResponseProtoMessage {
|
class ListEntitiesTextResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 97;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_text_response"; }
|
static constexpr const char *message_name() { return "list_entities_text_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2653,7 +2686,7 @@ class TextCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesDateResponse : public InfoResponseProtoMessage {
|
class ListEntitiesDateResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 100;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_date_response"; }
|
static constexpr const char *message_name() { return "list_entities_date_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2713,7 +2746,7 @@ class DateCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
|
class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 103;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_time_response"; }
|
static constexpr const char *message_name() { return "list_entities_time_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2773,7 +2806,7 @@ class TimeCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesEventResponse : public InfoResponseProtoMessage {
|
class ListEntitiesEventResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 107;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_event_response"; }
|
static constexpr const char *message_name() { return "list_entities_event_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2811,7 +2844,7 @@ class EventResponse : public StateResponseProtoMessage {
|
|||||||
class ListEntitiesValveResponse : public InfoResponseProtoMessage {
|
class ListEntitiesValveResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 109;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_valve_response"; }
|
static constexpr const char *message_name() { return "list_entities_valve_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2873,7 +2906,7 @@ class ValveCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
|
class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 112;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_date_time_response"; }
|
static constexpr const char *message_name() { return "list_entities_date_time_response"; }
|
||||||
#endif
|
#endif
|
||||||
@@ -2928,7 +2961,7 @@ class DateTimeCommandRequest : public ProtoMessage {
|
|||||||
class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
|
class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
|
||||||
public:
|
public:
|
||||||
static constexpr uint16_t MESSAGE_TYPE = 116;
|
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
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
static constexpr const char *message_name() { return "list_entities_update_response"; }
|
static constexpr const char *message_name() { return "list_entities_update_response"; }
|
||||||
#endif
|
#endif
|
||||||
|
@@ -86,7 +86,7 @@ bool AudioTransferBuffer::reallocate(size_t new_buffer_size) {
|
|||||||
bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
||||||
this->buffer_size_ = 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_);
|
this->buffer_ = allocator.allocate(this->buffer_size_);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
@@ -101,7 +101,7 @@ bool AudioTransferBuffer::allocate_buffer_(size_t buffer_size) {
|
|||||||
|
|
||||||
void AudioTransferBuffer::deallocate_buffer_() {
|
void AudioTransferBuffer::deallocate_buffer_() {
|
||||||
if (this->buffer_ != nullptr) {
|
if (this->buffer_ != nullptr) {
|
||||||
RAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
allocator.deallocate(this->buffer_, this->buffer_size_);
|
allocator.deallocate(this->buffer_, this->buffer_size_);
|
||||||
this->buffer_ = nullptr;
|
this->buffer_ = nullptr;
|
||||||
this->data_start_ = nullptr;
|
this->data_start_ = nullptr;
|
||||||
|
@@ -7,11 +7,13 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "rtos_pub.h"
|
#include "rtos_pub.h"
|
||||||
#include "spi.h"
|
// rtos_pub.h must be included before the rest of the includes
|
||||||
|
|
||||||
#include "arm_arch.h"
|
#include "arm_arch.h"
|
||||||
#include "general_dma_pub.h"
|
#include "general_dma_pub.h"
|
||||||
#include "gpio_pub.h"
|
#include "gpio_pub.h"
|
||||||
#include "icu_pub.h"
|
#include "icu_pub.h"
|
||||||
|
#include "spi.h"
|
||||||
#undef SPI_DAT
|
#undef SPI_DAT
|
||||||
#undef SPI_BASE
|
#undef SPI_BASE
|
||||||
};
|
};
|
||||||
@@ -124,7 +126,7 @@ void BekenSPILEDStripLightOutput::setup() {
|
|||||||
size_t buffer_size = this->get_buffer_size_();
|
size_t buffer_size = this->get_buffer_size_();
|
||||||
size_t dma_buffer_size = (buffer_size * 8) + (2 * 64);
|
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);
|
this->buf_ = allocator.allocate(buffer_size);
|
||||||
if (this->buf_ == nullptr) {
|
if (this->buf_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Cannot allocate LED buffer!");
|
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)
|
// turn on (after one-shot sensor automatically powers down)
|
||||||
uint8_t turn_on = BH1750_COMMAND_POWER_ON;
|
uint8_t turn_on = BH1750_COMMAND_POWER_ON;
|
||||||
if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
|
if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
|
||||||
ESP_LOGW(TAG, "Turning on BH1750 failed");
|
ESP_LOGW(TAG, "Power on failed");
|
||||||
f(NAN);
|
f(NAN);
|
||||||
return;
|
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_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> 5) & 0b111);
|
||||||
uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> 0) & 0b11111);
|
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) {
|
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;
|
active_mtreg_ = 0;
|
||||||
f(NAN);
|
f(NAN);
|
||||||
return;
|
return;
|
||||||
@@ -88,7 +88,7 @@ void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this->write(&cmd, 1) != i2c::ERROR_OK) {
|
if (this->write(&cmd, 1) != i2c::ERROR_OK) {
|
||||||
ESP_LOGW(TAG, "Starting measurement for BH1750 failed");
|
ESP_LOGW(TAG, "Start measurement failed");
|
||||||
f(NAN);
|
f(NAN);
|
||||||
return;
|
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]() {
|
this->set_timeout("read", meas_time, [this, mode, mtreg, f]() {
|
||||||
uint16_t raw_value;
|
uint16_t raw_value;
|
||||||
if (this->read(reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
|
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);
|
f(NAN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -156,7 +156,7 @@ void BH1750Sensor::update() {
|
|||||||
this->publish_state(NAN);
|
this->publish_state(NAN);
|
||||||
return;
|
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->status_clear_warning();
|
||||||
this->publish_state(val);
|
this->publish_state(val);
|
||||||
});
|
});
|
||||||
|
@@ -60,8 +60,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_WINDOW,
|
DEVICE_CLASS_WINDOW,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
@@ -148,6 +148,7 @@ BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Conditi
|
|||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
Filter = binary_sensor_ns.class_("Filter")
|
Filter = binary_sensor_ns.class_("Filter")
|
||||||
|
TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
|
||||||
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
|
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
|
||||||
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
|
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
|
||||||
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", 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)
|
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(
|
@register_filter(
|
||||||
"delayed_on_off",
|
"delayed_on_off",
|
||||||
DelayedOnOffFilter,
|
DelayedOnOffFilter,
|
||||||
@@ -491,6 +505,9 @@ _BINARY_SENSOR_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_BINARY_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("binary_sensor"))
|
||||||
|
|
||||||
|
|
||||||
def binary_sensor_schema(
|
def binary_sensor_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
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):
|
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:
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||||
cg.add(var.set_device_class(device_class))
|
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) {
|
optional<bool> DelayedOnOffFilter::new_value(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });
|
this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });
|
||||||
|
@@ -16,7 +16,7 @@ class Filter {
|
|||||||
public:
|
public:
|
||||||
virtual optional<bool> new_value(bool value) = 0;
|
virtual optional<bool> new_value(bool value) = 0;
|
||||||
|
|
||||||
void input(bool value);
|
virtual void input(bool value);
|
||||||
|
|
||||||
void output(bool value);
|
void output(bool value);
|
||||||
|
|
||||||
@@ -28,6 +28,16 @@ class Filter {
|
|||||||
Deduplicator<bool> dedup_;
|
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 {
|
class DelayedOnOffFilter : public Filter, public Component {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
@@ -18,8 +18,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_UPDATE,
|
DEVICE_CLASS_UPDATE,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -61,6 +61,9 @@ _BUTTON_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_BUTTON_SCHEMA.add_extra(entity_duplicate_validator("button"))
|
||||||
|
|
||||||
|
|
||||||
def button_schema(
|
def button_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -87,7 +90,7 @@ BUTTON_SCHEMA.add_extra(cv.deprecated_schema_constant("button"))
|
|||||||
|
|
||||||
|
|
||||||
async def setup_button_core_(var, config):
|
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, []):
|
for conf in config.get(CONF_ON_PRESS, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
@@ -48,8 +48,8 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
|
|
||||||
@@ -247,6 +247,9 @@ _CLIMATE_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_CLIMATE_SCHEMA.add_extra(entity_duplicate_validator("climate"))
|
||||||
|
|
||||||
|
|
||||||
def climate_schema(
|
def climate_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -273,7 +276,7 @@ CLIMATE_SCHEMA.add_extra(cv.deprecated_schema_constant("climate"))
|
|||||||
|
|
||||||
|
|
||||||
async def setup_climate_core_(var, config):
|
async def setup_climate_core_(var, config):
|
||||||
await setup_entity(var, config)
|
await setup_entity(var, config, "climate")
|
||||||
|
|
||||||
visual = config[CONF_VISUAL]
|
visual = config[CONF_VISUAL]
|
||||||
if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None:
|
if (min_temp := visual.get(CONF_MIN_TEMPERATURE)) is not None:
|
||||||
|
@@ -33,8 +33,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_WINDOW,
|
DEVICE_CLASS_WINDOW,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
|
|
||||||
@@ -126,6 +126,9 @@ _COVER_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_COVER_SCHEMA.add_extra(entity_duplicate_validator("cover"))
|
||||||
|
|
||||||
|
|
||||||
def cover_schema(
|
def cover_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -154,7 +157,7 @@ COVER_SCHEMA.add_extra(cv.deprecated_schema_constant("cover"))
|
|||||||
|
|
||||||
|
|
||||||
async def setup_cover_core_(var, config):
|
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:
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||||
cg.add(var.set_device_class(device_class))
|
cg.add(var.set_device_class(device_class))
|
||||||
|
@@ -22,8 +22,8 @@ from esphome.const import (
|
|||||||
CONF_YEAR,
|
CONF_YEAR,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@rfdarter", "@jesserockz"]
|
CODEOWNERS = ["@rfdarter", "@jesserockz"]
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ _DATETIME_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
|||||||
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
.extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA)
|
||||||
).add_extra(_validate_time_present)
|
).add_extra(_validate_time_present)
|
||||||
|
|
||||||
|
_DATETIME_SCHEMA.add_extra(entity_duplicate_validator("datetime"))
|
||||||
|
|
||||||
|
|
||||||
def date_schema(class_: MockObjClass) -> cv.Schema:
|
def date_schema(class_: MockObjClass) -> cv.Schema:
|
||||||
schema = cv.Schema(
|
schema = cv.Schema(
|
||||||
@@ -133,7 +135,7 @@ def datetime_schema(class_: MockObjClass) -> cv.Schema:
|
|||||||
|
|
||||||
|
|
||||||
async def setup_datetime_core_(var, config):
|
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:
|
if (mqtt_id := config.get(CONF_MQTT_ID)) is not None:
|
||||||
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
mqtt_ = cg.new_Pvariable(mqtt_id, var)
|
||||||
|
@@ -455,7 +455,7 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
CONF_NAME: "Demo Plain Sensor",
|
CONF_NAME: "Demo Plain Sensor",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CONF_NAME: "Demo Temperature Sensor",
|
CONF_NAME: "Demo Temperature Sensor 1",
|
||||||
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
||||||
CONF_ICON: ICON_THERMOMETER,
|
CONF_ICON: ICON_THERMOMETER,
|
||||||
CONF_ACCURACY_DECIMALS: 1,
|
CONF_ACCURACY_DECIMALS: 1,
|
||||||
@@ -463,7 +463,7 @@ CONFIG_SCHEMA = cv.Schema(
|
|||||||
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
CONF_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
CONF_NAME: "Demo Temperature Sensor",
|
CONF_NAME: "Demo Temperature Sensor 2",
|
||||||
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
CONF_UNIT_OF_MEASUREMENT: UNIT_CELSIUS,
|
||||||
CONF_ICON: ICON_THERMOMETER,
|
CONF_ICON: ICON_THERMOMETER,
|
||||||
CONF_ACCURACY_DECIMALS: 1,
|
CONF_ACCURACY_DECIMALS: 1,
|
||||||
|
@@ -11,7 +11,7 @@ namespace display {
|
|||||||
static const char *const TAG = "display";
|
static const char *const TAG = "display";
|
||||||
|
|
||||||
void DisplayBuffer::init_internal_(uint32_t buffer_length) {
|
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);
|
this->buffer_ = allocator.allocate(buffer_length);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Could not allocate buffer for display!");
|
ESP_LOGE(TAG, "Could not allocate buffer for display!");
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "ble_event_pool.h"
|
#include "ble_event_pool.h"
|
||||||
|
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <esp_bt.h>
|
#include <esp_bt.h>
|
||||||
@@ -516,13 +517,12 @@ void ESP32BLE::dump_config() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
"ESP32 BLE:\n"
|
"BLE:\n"
|
||||||
" MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n"
|
" MAC address: %s\n"
|
||||||
" IO Capability: %s",
|
" IO Capability: %s",
|
||||||
mac_address[0], mac_address[1], mac_address[2], mac_address[3], mac_address[4], mac_address[5],
|
format_mac_address_pretty(mac_address).c_str(), io_capability_s);
|
||||||
io_capability_s);
|
|
||||||
} else {
|
} 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) {
|
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++)
|
for (uint8_t i = 0; i < ESP_BD_ADDR_LEN; i++)
|
||||||
this->address_[i] = scan_result.bda[i];
|
this->address_[i] = scan_result.bda[i];
|
||||||
this->address_type_ = static_cast<esp_ble_addr_type_t>(scan_result.ble_addr_type);
|
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_; }
|
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;
|
bool resolve_irk(const uint8_t *irk) const;
|
||||||
|
|
||||||
optional<ESPBLEiBeacon> get_ibeacon() const {
|
optional<ESPBLEiBeacon> get_ibeacon() const {
|
||||||
@@ -111,6 +114,7 @@ class ESPBTDevice {
|
|||||||
std::vector<ESPBTUUID> service_uuids_{};
|
std::vector<ESPBTUUID> service_uuids_{};
|
||||||
std::vector<ServiceData> manufacturer_datas_{};
|
std::vector<ServiceData> manufacturer_datas_{};
|
||||||
std::vector<ServiceData> service_datas_{};
|
std::vector<ServiceData> service_datas_{};
|
||||||
|
const BLEScanResult *scan_result_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
class ESP32BLETracker;
|
class ESP32BLETracker;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
from esphome import automation, pins
|
from esphome import automation, pins
|
||||||
import esphome.codegen as cg
|
import esphome.codegen as cg
|
||||||
|
from esphome.components import i2c
|
||||||
from esphome.components.esp32 import add_idf_component
|
from esphome.components.esp32 import add_idf_component
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
@@ -7,6 +8,7 @@ from esphome.const import (
|
|||||||
CONF_CONTRAST,
|
CONF_CONTRAST,
|
||||||
CONF_DATA_PINS,
|
CONF_DATA_PINS,
|
||||||
CONF_FREQUENCY,
|
CONF_FREQUENCY,
|
||||||
|
CONF_I2C_ID,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_PIN,
|
CONF_PIN,
|
||||||
CONF_RESET_PIN,
|
CONF_RESET_PIN,
|
||||||
@@ -17,7 +19,7 @@ from esphome.const import (
|
|||||||
CONF_VSYNC_PIN,
|
CONF_VSYNC_PIN,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE
|
from esphome.core import CORE
|
||||||
from esphome.cpp_helpers import setup_entity
|
from esphome.core.entity_helpers import setup_entity
|
||||||
|
|
||||||
DEPENDENCIES = ["esp32"]
|
DEPENDENCIES = ["esp32"]
|
||||||
|
|
||||||
@@ -149,93 +151,104 @@ CONF_ON_IMAGE = "on_image"
|
|||||||
|
|
||||||
camera_range_param = cv.int_range(min=-2, max=2)
|
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
|
cv.GenerateID(): cv.declare_id(ESP32Camera),
|
||||||
cv.Required(CONF_DATA_PINS): cv.All(
|
# pin assignment
|
||||||
[pins.internal_gpio_input_pin_number], cv.Length(min=8, max=8)
|
cv.Required(CONF_DATA_PINS): cv.All(
|
||||||
),
|
[pins.internal_gpio_input_pin_number], cv.Length(min=8, max=8)
|
||||||
cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_input_pin_number,
|
),
|
||||||
cv.Required(CONF_HREF_PIN): pins.internal_gpio_input_pin_number,
|
cv.Required(CONF_VSYNC_PIN): pins.internal_gpio_input_pin_number,
|
||||||
cv.Required(CONF_PIXEL_CLOCK_PIN): pins.internal_gpio_input_pin_number,
|
cv.Required(CONF_HREF_PIN): pins.internal_gpio_input_pin_number,
|
||||||
cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema(
|
cv.Required(CONF_PIXEL_CLOCK_PIN): pins.internal_gpio_input_pin_number,
|
||||||
{
|
cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema(
|
||||||
cv.Required(CONF_PIN): pins.internal_gpio_input_pin_number,
|
{
|
||||||
cv.Optional(CONF_FREQUENCY, default="20MHz"): cv.All(
|
cv.Required(CONF_PIN): pins.internal_gpio_input_pin_number,
|
||||||
cv.frequency, cv.Range(min=8e6, max=20e6)
|
cv.Optional(CONF_FREQUENCY, default="20MHz"): cv.All(
|
||||||
),
|
cv.frequency, cv.Range(min=8e6, max=20e6)
|
||||||
}
|
),
|
||||||
),
|
}
|
||||||
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.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
|
||||||
}
|
cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
|
||||||
),
|
}
|
||||||
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
|
),
|
||||||
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
|
cv.Optional(CONF_I2C_ID): cv.Any(
|
||||||
# image
|
cv.use_id(i2c.InternalI2CBus),
|
||||||
cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum(
|
msg="I2C bus must be an internal ESP32 I2C bus",
|
||||||
FRAME_SIZES, upper=True
|
),
|
||||||
),
|
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
|
||||||
cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=6, max=63),
|
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
|
||||||
cv.Optional(CONF_CONTRAST, default=0): camera_range_param,
|
# image
|
||||||
cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
|
cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum(
|
||||||
cv.Optional(CONF_SATURATION, default=0): camera_range_param,
|
FRAME_SIZES, upper=True
|
||||||
cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean,
|
),
|
||||||
cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean,
|
cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=6, max=63),
|
||||||
cv.Optional(CONF_SPECIAL_EFFECT, default="NONE"): cv.enum(
|
cv.Optional(CONF_CONTRAST, default=0): camera_range_param,
|
||||||
ENUM_SPECIAL_EFFECT, upper=True
|
cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param,
|
||||||
),
|
cv.Optional(CONF_SATURATION, default=0): camera_range_param,
|
||||||
# exposure
|
cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean,
|
||||||
cv.Optional(CONF_AGC_MODE, default="AUTO"): cv.enum(
|
cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean,
|
||||||
ENUM_GAIN_CONTROL_MODE, upper=True
|
cv.Optional(CONF_SPECIAL_EFFECT, default="NONE"): cv.enum(
|
||||||
),
|
ENUM_SPECIAL_EFFECT, upper=True
|
||||||
cv.Optional(CONF_AEC2, default=False): cv.boolean,
|
),
|
||||||
cv.Optional(CONF_AE_LEVEL, default=0): camera_range_param,
|
# exposure
|
||||||
cv.Optional(CONF_AEC_VALUE, default=300): cv.int_range(min=0, max=1200),
|
cv.Optional(CONF_AGC_MODE, default="AUTO"): cv.enum(
|
||||||
# gains
|
ENUM_GAIN_CONTROL_MODE, upper=True
|
||||||
cv.Optional(CONF_AEC_MODE, default="AUTO"): cv.enum(
|
),
|
||||||
ENUM_GAIN_CONTROL_MODE, upper=True
|
cv.Optional(CONF_AEC2, default=False): cv.boolean,
|
||||||
),
|
cv.Optional(CONF_AE_LEVEL, default=0): camera_range_param,
|
||||||
cv.Optional(CONF_AGC_VALUE, default=0): cv.int_range(min=0, max=30),
|
cv.Optional(CONF_AEC_VALUE, default=300): cv.int_range(min=0, max=1200),
|
||||||
cv.Optional(CONF_AGC_GAIN_CEILING, default="2X"): cv.enum(
|
# gains
|
||||||
ENUM_GAIN_CEILING, upper=True
|
cv.Optional(CONF_AEC_MODE, default="AUTO"): cv.enum(
|
||||||
),
|
ENUM_GAIN_CONTROL_MODE, upper=True
|
||||||
# white balance
|
),
|
||||||
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(ENUM_WB_MODE, upper=True),
|
cv.Optional(CONF_AGC_VALUE, default=0): cv.int_range(min=0, max=30),
|
||||||
# test pattern
|
cv.Optional(CONF_AGC_GAIN_CEILING, default="2X"): cv.enum(
|
||||||
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
|
ENUM_GAIN_CEILING, upper=True
|
||||||
# framerates
|
),
|
||||||
cv.Optional(CONF_MAX_FRAMERATE, default="10 fps"): cv.All(
|
# white balance
|
||||||
cv.framerate, cv.Range(min=0, min_included=False, max=60)
|
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(
|
||||||
),
|
ENUM_WB_MODE, upper=True
|
||||||
cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All(
|
),
|
||||||
cv.framerate, cv.Range(min=0, max=1)
|
# test pattern
|
||||||
),
|
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
|
||||||
cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2),
|
# framerates
|
||||||
cv.Optional(CONF_ON_STREAM_START): automation.validate_automation(
|
cv.Optional(CONF_MAX_FRAMERATE, default="10 fps"): cv.All(
|
||||||
{
|
cv.framerate, cv.Range(min=0, min_included=False, max=60)
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
),
|
||||||
ESP32CameraStreamStartTrigger
|
cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All(
|
||||||
),
|
cv.framerate, cv.Range(min=0, max=1)
|
||||||
}
|
),
|
||||||
),
|
cv.Optional(CONF_FRAME_BUFFER_COUNT, default=1): cv.int_range(min=1, max=2),
|
||||||
cv.Optional(CONF_ON_STREAM_STOP): automation.validate_automation(
|
cv.Optional(CONF_ON_STREAM_START): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
ESP32CameraStreamStopTrigger
|
ESP32CameraStreamStartTrigger
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
|
cv.Optional(CONF_ON_STREAM_STOP): automation.validate_automation(
|
||||||
{
|
{
|
||||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32CameraImageTrigger),
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
}
|
ESP32CameraStreamStopTrigger
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
),
|
||||||
|
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
|
||||||
|
{
|
||||||
|
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
|
||||||
|
ESP32CameraImageTrigger
|
||||||
|
),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
}
|
||||||
|
).extend(cv.COMPONENT_SCHEMA),
|
||||||
|
cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID),
|
||||||
|
)
|
||||||
|
|
||||||
SETTERS = {
|
SETTERS = {
|
||||||
# pin assignment
|
# pin assignment
|
||||||
@@ -271,7 +284,7 @@ SETTERS = {
|
|||||||
|
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await setup_entity(var, config)
|
await setup_entity(var, config, "camera")
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
for key, setter in SETTERS.items():
|
for key, setter in SETTERS.items():
|
||||||
@@ -280,8 +293,12 @@ async def to_code(config):
|
|||||||
|
|
||||||
extclk = config[CONF_EXTERNAL_CLOCK]
|
extclk = config[CONF_EXTERNAL_CLOCK]
|
||||||
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
|
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
|
||||||
i2c_pins = config[CONF_I2C_PINS]
|
if i2c_id := config.get(CONF_I2C_ID):
|
||||||
cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
|
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]))
|
cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))
|
||||||
if config[CONF_IDLE_FRAMERATE] == 0:
|
if config[CONF_IDLE_FRAMERATE] == 0:
|
||||||
cg.add(var.set_idle_update_interval(0))
|
cg.add(var.set_idle_update_interval(0))
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "esp32_camera.h"
|
#include "esp32_camera.h"
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/core/hal.h"
|
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
|
||||||
@@ -16,6 +16,12 @@ static const char *const TAG = "esp32_camera";
|
|||||||
void ESP32Camera::setup() {
|
void ESP32Camera::setup() {
|
||||||
global_esp32_camera = this;
|
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 */
|
/* initialize time to now */
|
||||||
this->last_update_ = millis();
|
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_sda = sda;
|
||||||
this->config_.pin_sccb_scl = scl;
|
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_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
|
||||||
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }
|
||||||
|
|
||||||
|
@@ -2,13 +2,17 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
#include <esp_camera.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/queue.h>
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/core/entity_base.h"
|
#include "esphome/core/entity_base.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include <esp_camera.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#ifdef USE_I2C
|
||||||
#include <freertos/queue.h>
|
#include "esphome/components/i2c/i2c_bus.h"
|
||||||
|
#endif // USE_I2C
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace esp32_camera {
|
namespace esp32_camera {
|
||||||
@@ -118,6 +122,9 @@ class ESP32Camera : public EntityBase, public Component {
|
|||||||
void set_pixel_clock_pin(uint8_t pin);
|
void set_pixel_clock_pin(uint8_t pin);
|
||||||
void set_external_clock(uint8_t pin, uint32_t frequency);
|
void set_external_clock(uint8_t pin, uint32_t frequency);
|
||||||
void set_i2c_pins(uint8_t sda, uint8_t scl);
|
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_reset_pin(uint8_t pin);
|
||||||
void set_power_down_pin(uint8_t pin);
|
void set_power_down_pin(uint8_t pin);
|
||||||
/* -- image */
|
/* -- image */
|
||||||
@@ -210,6 +217,9 @@ class ESP32Camera : public EntityBase, public Component {
|
|||||||
|
|
||||||
uint32_t last_idle_request_{0};
|
uint32_t last_idle_request_{0};
|
||||||
uint32_t last_update_{0};
|
uint32_t last_update_{0};
|
||||||
|
#ifdef USE_I2C
|
||||||
|
i2c::InternalI2CBus *i2c_bus_{nullptr};
|
||||||
|
#endif // USE_I2C
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
// 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,
|
DEVICE_CLASS_MOTION,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@nohat"]
|
CODEOWNERS = ["@nohat"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -59,6 +59,9 @@ _EVENT_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_EVENT_SCHEMA.add_extra(entity_duplicate_validator("event"))
|
||||||
|
|
||||||
|
|
||||||
def event_schema(
|
def event_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
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]):
|
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, []):
|
for conf in config.get(CONF_ON_EVENT, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
@@ -32,7 +32,7 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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
|
IS_PLATFORM_COMPONENT = True
|
||||||
|
|
||||||
@@ -161,6 +161,9 @@ _FAN_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_FAN_SCHEMA.add_extra(entity_duplicate_validator("fan"))
|
||||||
|
|
||||||
|
|
||||||
def fan_schema(
|
def fan_schema(
|
||||||
class_: cg.Pvariable,
|
class_: cg.Pvariable,
|
||||||
*,
|
*,
|
||||||
@@ -225,7 +228,7 @@ def validate_preset_modes(value):
|
|||||||
|
|
||||||
|
|
||||||
async def setup_fan_core_(var, config):
|
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]))
|
cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
from collections.abc import MutableMapping
|
from collections.abc import MutableMapping
|
||||||
import functools
|
import functools
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from itertools import accumulate
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -468,8 +469,9 @@ class EFont:
|
|||||||
|
|
||||||
|
|
||||||
class GlyphInfo:
|
class GlyphInfo:
|
||||||
def __init__(self, data_len, advance, offset_x, offset_y, width, height):
|
def __init__(self, glyph, data, advance, offset_x, offset_y, width, height):
|
||||||
self.data_len = data_len
|
self.glyph = glyph
|
||||||
|
self.bitmap_data = data
|
||||||
self.advance = advance
|
self.advance = advance
|
||||||
self.offset_x = offset_x
|
self.offset_x = offset_x
|
||||||
self.offset_y = offset_y
|
self.offset_y = offset_y
|
||||||
@@ -477,6 +479,62 @@ class GlyphInfo:
|
|||||||
self.height = height
|
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):
|
async def to_code(config):
|
||||||
"""
|
"""
|
||||||
Collect all glyph codepoints, construct a map from a codepoint to a font file.
|
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 = list(point_set)
|
||||||
codepoints.sort(key=functools.cmp_to_key(glyph_comparator))
|
codepoints.sort(key=functools.cmp_to_key(glyph_comparator))
|
||||||
glyph_args = {}
|
|
||||||
data = []
|
|
||||||
bpp = config[CONF_BPP]
|
bpp = config[CONF_BPP]
|
||||||
scale = 256 // (1 << bpp)
|
|
||||||
size = config[CONF_SIZE]
|
size = config[CONF_SIZE]
|
||||||
# create the data array for all glyphs
|
# create the data array for all glyphs
|
||||||
for codepoint in codepoints:
|
glyph_args = [
|
||||||
font = point_font_map[codepoint]
|
glyph_to_glyphinfo(x, point_font_map[x], size, bpp) for x in codepoints
|
||||||
if not font.is_scalable:
|
]
|
||||||
sizes = [pt_to_px(x.size) for x in font.available_sizes]
|
rhs = [HexInt(x) for x in flatten([x.bitmap_data for x in glyph_args])]
|
||||||
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]
|
|
||||||
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs)
|
||||||
|
|
||||||
# Create the glyph table that points to data in the above array.
|
# Create the glyph table that points to data in the above array.
|
||||||
glyph_initializer = []
|
glyph_initializer = [
|
||||||
for codepoint in codepoints:
|
cg.StructInitializer(
|
||||||
glyph_initializer.append(
|
GlyphData,
|
||||||
cg.StructInitializer(
|
(
|
||||||
GlyphData,
|
"a_char",
|
||||||
(
|
cg.RawExpression(f"(const uint8_t *){cpp_string_escape(x.glyph)}"),
|
||||||
"a_char",
|
),
|
||||||
cg.RawExpression(
|
(
|
||||||
f"(const uint8_t *){cpp_string_escape(codepoint)}"
|
"data",
|
||||||
),
|
cg.RawExpression(f"{str(prog_arr)} + {str(y - len(x.bitmap_data))}"),
|
||||||
),
|
),
|
||||||
(
|
("advance", x.advance),
|
||||||
"data",
|
("offset_x", x.offset_x),
|
||||||
cg.RawExpression(
|
("offset_y", x.offset_y),
|
||||||
f"{str(prog_arr)} + {str(glyph_args[codepoint].data_len)}"
|
("width", x.width),
|
||||||
),
|
("height", x.height),
|
||||||
),
|
|
||||||
("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),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
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)
|
glyphs = cg.static_const_array(config[CONF_RAW_GLYPH_ID], glyph_initializer)
|
||||||
|
|
||||||
font_height = pt_to_px(base_font.size.height)
|
font_height = pt_to_px(base_font.size.height)
|
||||||
ascender = pt_to_px(base_font.size.ascender)
|
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 font_height == 0:
|
||||||
if not base_font.is_scalable:
|
if not base_font.is_scalable:
|
||||||
font_height = size
|
font_height = size
|
||||||
@@ -610,5 +617,8 @@ async def to_code(config):
|
|||||||
len(glyph_initializer),
|
len(glyph_initializer),
|
||||||
ascender,
|
ascender,
|
||||||
font_height,
|
font_height,
|
||||||
|
descender,
|
||||||
|
xheight,
|
||||||
|
capheight,
|
||||||
bpp,
|
bpp,
|
||||||
)
|
)
|
||||||
|
@@ -45,8 +45,15 @@ void Glyph::scan_area(int *x1, int *y1, int *width, int *height) const {
|
|||||||
*height = this->glyph_data_->height;
|
*height = this->glyph_data_->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::Font(const GlyphData *data, int data_nr, int baseline, int height, uint8_t bpp)
|
Font::Font(const GlyphData *data, int data_nr, int baseline, int height, int descender, int xheight, int capheight,
|
||||||
: baseline_(baseline), height_(height), bpp_(bpp) {
|
uint8_t bpp)
|
||||||
|
: baseline_(baseline),
|
||||||
|
height_(height),
|
||||||
|
descender_(descender),
|
||||||
|
linegap_(height - baseline - descender),
|
||||||
|
xheight_(xheight),
|
||||||
|
capheight_(capheight),
|
||||||
|
bpp_(bpp) {
|
||||||
glyphs_.reserve(data_nr);
|
glyphs_.reserve(data_nr);
|
||||||
for (int i = 0; i < data_nr; ++i)
|
for (int i = 0; i < data_nr; ++i)
|
||||||
glyphs_.emplace_back(&data[i]);
|
glyphs_.emplace_back(&data[i]);
|
||||||
|
@@ -50,11 +50,17 @@ class Font
|
|||||||
public:
|
public:
|
||||||
/** Construct the font with the given glyphs.
|
/** 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 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);
|
int match_next_glyph(const uint8_t *str, int *match_length);
|
||||||
|
|
||||||
@@ -65,14 +71,23 @@ class Font
|
|||||||
#endif
|
#endif
|
||||||
inline int get_baseline() { return this->baseline_; }
|
inline int get_baseline() { return this->baseline_; }
|
||||||
inline int get_height() { return this->height_; }
|
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_; }
|
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:
|
protected:
|
||||||
std::vector<Glyph, ExternalRAMAllocator<Glyph>> glyphs_;
|
std::vector<Glyph, RAMAllocator<Glyph>> glyphs_;
|
||||||
int baseline_;
|
int baseline_;
|
||||||
int height_;
|
int height_;
|
||||||
|
int descender_;
|
||||||
|
int linegap_;
|
||||||
|
int xheight_;
|
||||||
|
int capheight_;
|
||||||
uint8_t bpp_; // bits per pixel
|
uint8_t bpp_; // bits per pixel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -41,6 +41,6 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_build_flag("-DUSE_HOST")
|
cg.add_build_flag("-DUSE_HOST")
|
||||||
cg.add_define("USE_ESPHOME_HOST_MAC_ADDRESS", config[CONF_MAC_ADDRESS].parts)
|
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_define("ESPHOME_BOARD", "host")
|
||||||
cg.add_platformio_option("platform", "platformio/native")
|
cg.add_platformio_option("platform", "platformio/native")
|
||||||
|
@@ -239,7 +239,7 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
|
|||||||
|
|
||||||
std::string response_body;
|
std::string response_body;
|
||||||
if (this->capture_response_.value(x...)) {
|
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);
|
uint8_t *buf = allocator.allocate(max_length);
|
||||||
if (buf != nullptr) {
|
if (buf != nullptr) {
|
||||||
size_t read_index = 0;
|
size_t read_index = 0;
|
||||||
|
@@ -54,7 +54,7 @@ void HttpRequestUpdate::update_task(void *params) {
|
|||||||
UPDATE_RETURN;
|
UPDATE_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *data = allocator.allocate(container->content_length);
|
uint8_t *data = allocator.allocate(container->content_length);
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
std::string msg = str_sprintf("Failed to allocate %d bytes for manifest", container->content_length);
|
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"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
i2c_ns = cg.esphome_ns.namespace("i2c")
|
i2c_ns = cg.esphome_ns.namespace("i2c")
|
||||||
I2CBus = i2c_ns.class_("I2CBus")
|
I2CBus = i2c_ns.class_("I2CBus")
|
||||||
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", I2CBus, cg.Component)
|
InternalI2CBus = i2c_ns.class_("InternalI2CBus", I2CBus)
|
||||||
IDFI2CBus = i2c_ns.class_("IDFI2CBus", I2CBus, cg.Component)
|
ArduinoI2CBus = i2c_ns.class_("ArduinoI2CBus", InternalI2CBus, cg.Component)
|
||||||
|
IDFI2CBus = i2c_ns.class_("IDFI2CBus", InternalI2CBus, cg.Component)
|
||||||
I2CDevice = i2c_ns.class_("I2CDevice")
|
I2CDevice = i2c_ns.class_("I2CDevice")
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
@coroutine_with_priority(1.0)
|
@coroutine_with_priority(1.0)
|
||||||
async def to_code(config):
|
async def to_code(config):
|
||||||
cg.add_global(i2c_ns.using)
|
cg.add_global(i2c_ns.using)
|
||||||
|
cg.add_define("USE_I2C")
|
||||||
var = cg.new_Pvariable(config[CONF_ID])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <cstdint>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -108,5 +108,12 @@ class I2CBus {
|
|||||||
bool scan_{false}; ///< Should we scan ? Can be set in the yaml
|
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 i2c
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
#include "i2c_bus_arduino.h"
|
#include "i2c_bus_arduino.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <cstring>
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include <Arduino.h>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -23,6 +23,7 @@ void ArduinoI2CBus::setup() {
|
|||||||
} else {
|
} else {
|
||||||
wire_ = new TwoWire(next_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
wire_ = new TwoWire(next_bus_num); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
this->port_ = next_bus_num;
|
||||||
next_bus_num++;
|
next_bus_num++;
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory)
|
wire_ = new TwoWire(); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
#include "i2c_bus.h"
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
|||||||
RECOVERY_COMPLETED,
|
RECOVERY_COMPLETED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ArduinoI2CBus : public I2CBus, public Component {
|
class ArduinoI2CBus : public InternalI2CBus, public Component {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() 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_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||||
|
|
||||||
|
int get_port() const override { return this->port_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recover_();
|
void recover_();
|
||||||
void set_pins_and_clock_();
|
void set_pins_and_clock_();
|
||||||
RecoveryCode recovery_result_;
|
RecoveryCode recovery_result_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
int8_t port_{-1};
|
||||||
TwoWire *wire_;
|
TwoWire *wire_;
|
||||||
uint8_t sda_pin_;
|
uint8_t sda_pin_;
|
||||||
uint8_t scl_pin_;
|
uint8_t scl_pin_;
|
||||||
|
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
|
|
||||||
#include "i2c_bus.h"
|
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include <driver/i2c.h>
|
#include <driver/i2c.h>
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "i2c_bus.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace i2c {
|
namespace i2c {
|
||||||
@@ -15,7 +15,7 @@ enum RecoveryCode {
|
|||||||
RECOVERY_COMPLETED,
|
RECOVERY_COMPLETED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class IDFI2CBus : public I2CBus, public Component {
|
class IDFI2CBus : public InternalI2CBus, public Component {
|
||||||
public:
|
public:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void dump_config() 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_frequency(uint32_t frequency) { frequency_ = frequency; }
|
||||||
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
void set_timeout(uint32_t timeout) { timeout_ = timeout; }
|
||||||
|
|
||||||
|
int get_port() const override { return static_cast<int>(this->port_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recover_();
|
void recover_();
|
||||||
RecoveryCode recovery_result_;
|
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) {
|
esp_err_t I2SAudioSpeaker::allocate_buffers_(size_t data_buffer_size, size_t ring_buffer_size) {
|
||||||
if (this->data_buffer_ == nullptr) {
|
if (this->data_buffer_ == nullptr) {
|
||||||
// Allocate data buffer for temporarily storing audio from the ring buffer before writing to the I2S bus
|
// 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);
|
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
|
this->audio_ring_buffer_.reset(); // Releases ownership of the shared_ptr
|
||||||
|
|
||||||
if (this->data_buffer_ != nullptr) {
|
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);
|
allocator.deallocate(this->data_buffer_, buffer_size);
|
||||||
this->data_buffer_ = nullptr;
|
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.
|
* Allocate buffers. May be called after setup to re-initialise if e.g. greyscale is changed.
|
||||||
*/
|
*/
|
||||||
void Inkplate6::initialize_() {
|
void Inkplate6::initialize_() {
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
ExternalRAMAllocator<uint32_t> allocator32(ExternalRAMAllocator<uint32_t>::ALLOW_FAILURE);
|
RAMAllocator<uint32_t> allocator32;
|
||||||
uint32_t buffer_size = this->get_buffer_length_();
|
uint32_t buffer_size = this->get_buffer_length_();
|
||||||
if (buffer_size == 0)
|
if (buffer_size == 0)
|
||||||
return;
|
return;
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
#define highbyte(val) (uint8_t)((val) >> 8)
|
#define highbyte(val) (uint8_t)((val) >> 8)
|
||||||
#define lowbyte(val) (uint8_t)((val) &0xff)
|
#define lowbyte(val) (uint8_t)((val) &0xff)
|
||||||
|
|
||||||
@@ -73,9 +75,9 @@ void LD2410Component::dump_config() {
|
|||||||
#endif
|
#endif
|
||||||
this->read_all_info();
|
this->read_all_info();
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
" Throttle_ : %ums\n"
|
" Throttle: %ums\n"
|
||||||
" MAC Address : %s\n"
|
" MAC address: %s\n"
|
||||||
" Firmware Version : %s",
|
" Firmware version: %s",
|
||||||
this->throttle_, const_cast<char *>(this->mac_.c_str()), const_cast<char *>(this->version_.c_str()));
|
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
|
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_)
|
if (current_millis - last_periodic_millis_ < this->throttle_)
|
||||||
return;
|
return;
|
||||||
last_periodic_millis_ = current_millis;
|
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 UNKNOWN_MAC("unknown");
|
||||||
const std::string NO_MAC("08:05:04:03:02:01");
|
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
|
#ifdef USE_NUMBER
|
||||||
std::function<void(void)> set_number_value(number::Number *n, float value) {
|
std::function<void(void)> set_number_value(number::Number *n, float value) {
|
||||||
float normalized_value = value * 1.0;
|
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) {
|
bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
||||||
ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", buffer[COMMAND]);
|
ESP_LOGV(TAG, "Handling ACK DATA for COMMAND %02X", buffer[COMMAND]);
|
||||||
if (len < 10) {
|
if (len < 10) {
|
||||||
ESP_LOGE(TAG, "Error with last command : incorrect length");
|
ESP_LOGE(TAG, "Invalid length");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // check 4 frame start bytes
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (buffer[COMMAND_STATUS] != 0x01) {
|
if (buffer[COMMAND_STATUS] != 0x01) {
|
||||||
ESP_LOGE(TAG, "Error with last command : status != 0x01");
|
ESP_LOGE(TAG, "Invalid status");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this->two_byte_to_int_(buffer[8], buffer[9]) != 0x00) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (buffer[COMMAND]) {
|
switch (buffer[COMMAND]) {
|
||||||
case lowbyte(CMD_ENABLE_CONF):
|
case lowbyte(CMD_ENABLE_CONF):
|
||||||
ESP_LOGV(TAG, "Handled Enable conf command");
|
ESP_LOGV(TAG, "Enable conf");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_DISABLE_CONF):
|
case lowbyte(CMD_DISABLE_CONF):
|
||||||
ESP_LOGV(TAG, "Handled Disabled conf command");
|
ESP_LOGV(TAG, "Disabled conf");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SET_BAUD_RATE):
|
case lowbyte(CMD_SET_BAUD_RATE):
|
||||||
ESP_LOGV(TAG, "Handled baud rate change command");
|
ESP_LOGV(TAG, "Baud rate change");
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->baud_rate_select_ != nullptr) {
|
if (this->baud_rate_select_ != nullptr) {
|
||||||
ESP_LOGE(TAG, "Change baud rate 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
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_VERSION):
|
case lowbyte(CMD_VERSION):
|
||||||
this->version_ = format_version(buffer);
|
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
|
#ifdef USE_TEXT_SENSOR
|
||||||
if (this->version_text_sensor_ != nullptr) {
|
if (this->version_text_sensor_ != nullptr) {
|
||||||
this->version_text_sensor_->publish_state(this->version_);
|
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): {
|
case lowbyte(CMD_QUERY_DISTANCE_RESOLUTION): {
|
||||||
std::string distance_resolution =
|
std::string distance_resolution =
|
||||||
DISTANCE_RESOLUTION_INT_TO_ENUM.at(this->two_byte_to_int_(buffer[10], buffer[11]));
|
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
|
#ifdef USE_SELECT
|
||||||
if (this->distance_resolution_select_ != nullptr &&
|
if (this->distance_resolution_select_ != nullptr &&
|
||||||
this->distance_resolution_select_->state != distance_resolution) {
|
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_function_ = LIGHT_FUNCTION_INT_TO_ENUM.at(buffer[10]);
|
||||||
this->light_threshold_ = buffer[11] * 1.0;
|
this->light_threshold_ = buffer[11] * 1.0;
|
||||||
this->out_pin_level_ = OUT_PIN_LEVEL_INT_TO_ENUM.at(buffer[12]);
|
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 function: %s", const_cast<char *>(this->light_function_.c_str()));
|
||||||
ESP_LOGV(TAG, "Light threshold is: %f", this->light_threshold_);
|
ESP_LOGV(TAG, "Light threshold: %f", this->light_threshold_);
|
||||||
ESP_LOGV(TAG, "Out pin level is: %s", const_cast<char *>(this->out_pin_level_.c_str()));
|
ESP_LOGV(TAG, "Out pin level: %s", const_cast<char *>(this->out_pin_level_.c_str()));
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->light_function_select_ != nullptr && this->light_function_select_->state != this->light_function_) {
|
if (this->light_function_select_ != nullptr && this->light_function_select_->state != this->light_function_) {
|
||||||
this->light_function_select_->publish_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) {
|
if (len < 20) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this->mac_ = format_mac(buffer);
|
this->mac_ = format_mac_address_pretty(&buffer[10]);
|
||||||
ESP_LOGV(TAG, "MAC Address is: %s", const_cast<char *>(this->mac_.c_str()));
|
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
if (this->mac_text_sensor_ != nullptr) {
|
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
|
#endif
|
||||||
#ifdef USE_SWITCH
|
#ifdef USE_SWITCH
|
||||||
@@ -420,19 +407,19 @@ bool LD2410Component::handle_ack_data_(uint8_t *buffer, int len) {
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_GATE_SENS):
|
case lowbyte(CMD_GATE_SENS):
|
||||||
ESP_LOGV(TAG, "Handled sensitivity command");
|
ESP_LOGV(TAG, "Sensitivity");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_BLUETOOTH):
|
case lowbyte(CMD_BLUETOOTH):
|
||||||
ESP_LOGV(TAG, "Handled bluetooth command");
|
ESP_LOGV(TAG, "Bluetooth");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SET_DISTANCE_RESOLUTION):
|
case lowbyte(CMD_SET_DISTANCE_RESOLUTION):
|
||||||
ESP_LOGV(TAG, "Handled set distance resolution command");
|
ESP_LOGV(TAG, "Set distance resolution");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SET_LIGHT_CONTROL):
|
case lowbyte(CMD_SET_LIGHT_CONTROL):
|
||||||
ESP_LOGV(TAG, "Handled set light control command");
|
ESP_LOGV(TAG, "Set light control");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_BT_PASSWORD):
|
case lowbyte(CMD_BT_PASSWORD):
|
||||||
ESP_LOGV(TAG, "Handled set bluetooth password command");
|
ESP_LOGV(TAG, "Set bluetooth password");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_QUERY): // Query parameters response
|
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) {
|
void LD2410Component::set_bluetooth_password(const std::string &password) {
|
||||||
if (password.length() != 6) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
this->set_config_mode_(true);
|
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) {
|
void LD2410Component::set_engineering_mode(bool enable) {
|
||||||
this->set_config_mode_(true);
|
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;
|
uint8_t cmd = enable ? CMD_ENABLE_ENG : CMD_DISABLE_ENG;
|
||||||
this->send_command_(cmd, nullptr, 0);
|
this->send_command_(cmd, nullptr, 0);
|
||||||
this->set_config_mode_(false);
|
this->set_config_mode_(false);
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "ld2420.h"
|
#include "ld2420.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -40,7 +41,7 @@ There are three documented parameters for modes:
|
|||||||
00 04 = Energy output mode
|
00 04 = Energy output mode
|
||||||
This mode outputs detailed signal energy values for each gate and the target distance.
|
This mode outputs detailed signal energy values for each gate and the target distance.
|
||||||
The data format consist of the following.
|
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
|
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
|
F4 F3 F2 F1 23 00 00 00 00 00 00 .. .. .. .. F8 F7 F6 F5
|
||||||
00 00 = debug output mode
|
00 00 = debug output mode
|
||||||
@@ -67,10 +68,10 @@ float LD2420Component::get_setup_priority() const { return setup_priority::BUS;
|
|||||||
void LD2420Component::dump_config() {
|
void LD2420Component::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
"LD2420:\n"
|
"LD2420:\n"
|
||||||
" Firmware Version : %7s\n"
|
" Firmware version: %7s",
|
||||||
"LD2420 Number:",
|
|
||||||
this->ld2420_firmware_ver_);
|
this->ld2420_firmware_ver_);
|
||||||
#ifdef USE_NUMBER
|
#ifdef USE_NUMBER
|
||||||
|
ESP_LOGCONFIG(TAG, "Number:");
|
||||||
LOG_NUMBER(TAG, " Gate Timeout:", this->gate_timeout_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 Max Distance:", this->max_gate_distance_number_);
|
||||||
LOG_NUMBER(TAG, " Gate Min Distance:", this->min_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, " Factory Reset:", this->factory_reset_button_);
|
||||||
LOG_BUTTON(TAG, " Restart Module:", this->restart_module_button_);
|
LOG_BUTTON(TAG, " Restart Module:", this->restart_module_button_);
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGCONFIG(TAG, "LD2420 Select:");
|
ESP_LOGCONFIG(TAG, "Select:");
|
||||||
LOG_SELECT(TAG, " Operating Mode", this->operating_selector_);
|
LOG_SELECT(TAG, " Operating Mode", this->operating_selector_);
|
||||||
if (this->get_firmware_int_(ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
if (LD2420Component::get_firmware_int(this->ld2420_firmware_ver_) < CALIBRATE_VERSION_MIN) {
|
||||||
ESP_LOGW(TAG, "LD2420 Firmware 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_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +103,7 @@ uint8_t LD2420Component::calc_checksum(void *data, size_t size) {
|
|||||||
return checksum;
|
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;
|
std::string version_str = version_string;
|
||||||
if (version_str[0] == 'v') {
|
if (version_str[0] == 'v') {
|
||||||
version_str = version_str.substr(1);
|
version_str = version_str.substr(1);
|
||||||
@@ -115,7 +116,7 @@ int LD2420Component::get_firmware_int_(const char *version_string) {
|
|||||||
void LD2420Component::setup() {
|
void LD2420Component::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Running setup");
|
ESP_LOGCONFIG(TAG, "Running setup");
|
||||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
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();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -127,7 +128,7 @@ void LD2420Component::setup() {
|
|||||||
const char *pfw = this->ld2420_firmware_ver_;
|
const char *pfw = this->ld2420_firmware_ver_;
|
||||||
std::string fw_str(pfw);
|
std::string fw_str(pfw);
|
||||||
|
|
||||||
for (auto &listener : listeners_) {
|
for (auto &listener : this->listeners_) {
|
||||||
listener->on_fw_version(fw_str);
|
listener->on_fw_version(fw_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,11 +138,11 @@ void LD2420Component::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&this->new_config, &this->current_config, sizeof(this->current_config));
|
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->set_operating_mode(OP_SIMPLE_MODE_STRING);
|
||||||
this->operating_selector_->publish_state(OP_SIMPLE_MODE_STRING);
|
this->operating_selector_->publish_state(OP_SIMPLE_MODE_STRING);
|
||||||
this->set_mode_(CMD_SYSTEM_MODE_SIMPLE);
|
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 {
|
} else {
|
||||||
this->set_mode_(CMD_SYSTEM_MODE_ENERGY);
|
this->set_mode_(CMD_SYSTEM_MODE_ENERGY);
|
||||||
this->operating_selector_->publish_state(OP_NORMAL_MODE_STRING);
|
this->operating_selector_->publish_state(OP_NORMAL_MODE_STRING);
|
||||||
@@ -151,18 +152,17 @@ void LD2420Component::setup() {
|
|||||||
#endif
|
#endif
|
||||||
this->set_system_mode(this->system_mode_);
|
this->set_system_mode(this->system_mode_);
|
||||||
this->set_config_mode(false);
|
this->set_config_mode(false);
|
||||||
ESP_LOGCONFIG(TAG, "LD2420 setup complete.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::apply_config_action() {
|
void LD2420Component::apply_config_action() {
|
||||||
const uint8_t checksum = calc_checksum(&this->new_config, sizeof(this->new_config));
|
const uint8_t checksum = calc_checksum(&this->new_config, sizeof(this->new_config));
|
||||||
if (checksum == calc_checksum(&this->current_config, sizeof(this->current_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;
|
return;
|
||||||
}
|
}
|
||||||
ESP_LOGCONFIG(TAG, "Reconfiguring LD2420");
|
ESP_LOGD(TAG, "Reconfiguring");
|
||||||
if (this->set_config_mode(true) == LD2420_ERROR_TIMEOUT) {
|
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();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -178,13 +178,12 @@ void LD2420Component::apply_config_action() {
|
|||||||
this->set_system_mode(this->system_mode_);
|
this->set_system_mode(this->system_mode_);
|
||||||
this->set_config_mode(false); // Disable config mode to save new values in LD2420 nvm
|
this->set_config_mode(false); // Disable config mode to save new values in LD2420 nvm
|
||||||
this->set_operating_mode(OP_NORMAL_MODE_STRING);
|
this->set_operating_mode(OP_NORMAL_MODE_STRING);
|
||||||
ESP_LOGCONFIG(TAG, "LD2420 reconfig complete.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::factory_reset_action() {
|
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) {
|
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();
|
this->mark_failed();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -207,18 +206,16 @@ void LD2420Component::factory_reset_action() {
|
|||||||
this->init_gate_config_numbers();
|
this->init_gate_config_numbers();
|
||||||
this->refresh_gate_config_numbers();
|
this->refresh_gate_config_numbers();
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGCONFIG(TAG, "LD2420 factory reset complete.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::restart_module_action() {
|
void LD2420Component::restart_module_action() {
|
||||||
ESP_LOGCONFIG(TAG, "Restarting LD2420 module");
|
ESP_LOGD(TAG, "Restarting");
|
||||||
this->send_module_restart();
|
this->send_module_restart();
|
||||||
this->set_timeout(250, [this]() {
|
this->set_timeout(250, [this]() {
|
||||||
this->set_config_mode(true);
|
this->set_config_mode(true);
|
||||||
this->set_system_mode(system_mode_);
|
this->set_system_mode(this->system_mode_);
|
||||||
this->set_config_mode(false);
|
this->set_config_mode(false);
|
||||||
});
|
});
|
||||||
ESP_LOGCONFIG(TAG, "LD2420 Restarted.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::revert_config_action() {
|
void LD2420Component::revert_config_action() {
|
||||||
@@ -226,18 +223,18 @@ void LD2420Component::revert_config_action() {
|
|||||||
#ifdef USE_NUMBER
|
#ifdef USE_NUMBER
|
||||||
this->init_gate_config_numbers();
|
this->init_gate_config_numbers();
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGCONFIG(TAG, "Reverted config number edits.");
|
ESP_LOGD(TAG, "Reverted config number edits");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::loop() {
|
void LD2420Component::loop() {
|
||||||
// If there is a active send command do not process it here, the send command call will handle it.
|
// If there is a active send command do not process it here, the send command call will handle it.
|
||||||
if (!get_cmd_active_()) {
|
if (!this->get_cmd_active_()) {
|
||||||
if (!available())
|
if (!this->available())
|
||||||
return;
|
return;
|
||||||
static uint8_t buffer[2048];
|
static uint8_t buffer[2048];
|
||||||
static uint8_t rx_data;
|
static uint8_t rx_data;
|
||||||
while (available()) {
|
while (this->available()) {
|
||||||
rx_data = read();
|
rx_data = this->read();
|
||||||
this->readline_(rx_data, buffer, sizeof(buffer));
|
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) {
|
void LD2420Component::set_operating_mode(const std::string &state) {
|
||||||
// If unsupported firmware ignore mode select
|
// 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);
|
this->current_operating_mode = OP_MODE_TO_UINT.at(state);
|
||||||
// Entering Auto Calibrate we need to clear the privoiuos data collection
|
// Entering Auto Calibrate we need to clear the privoiuos data collection
|
||||||
this->operating_selector_->publish_state(state);
|
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
|
// 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)
|
if (current_millis - this->last_periodic_millis < REFRESH_RATE_MS)
|
||||||
return;
|
return;
|
||||||
this->last_periodic_millis = current_millis;
|
this->last_periodic_millis = current_millis;
|
||||||
for (auto &listener : this->listeners_) {
|
for (auto &listener : this->listeners_) {
|
||||||
listener->on_distance(get_distance_());
|
listener->on_distance(this->get_distance_());
|
||||||
listener->on_presence(get_presence_());
|
listener->on_presence(this->get_presence_());
|
||||||
listener->on_energy(this->gate_energy_, sizeof(this->gate_energy_) / sizeof(this->gate_energy_[0]));
|
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};
|
char outbuf[bufsize]{0};
|
||||||
while (true) {
|
while (true) {
|
||||||
if (inbuf[pos - 2] == 'O' && inbuf[pos - 1] == 'F' && inbuf[pos] == 'F') {
|
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') {
|
} else if (inbuf[pos - 1] == 'O' && inbuf[pos] == 'N') {
|
||||||
set_presence_(true);
|
this->set_presence_(true);
|
||||||
}
|
}
|
||||||
if (inbuf[pos] >= '0' && inbuf[pos] <= '9') {
|
if (inbuf[pos] >= '0' && inbuf[pos] <= '9') {
|
||||||
if (index < bufsize - 1) {
|
if (index < bufsize - 1) {
|
||||||
@@ -411,18 +408,18 @@ void LD2420Component::handle_simple_mode_(const uint8_t *inbuf, int len) {
|
|||||||
}
|
}
|
||||||
outbuf[index] = '\0';
|
outbuf[index] = '\0';
|
||||||
if (index > 1)
|
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
|
// 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)
|
if (current_millis - this->last_normal_periodic_millis < REFRESH_RATE_MS)
|
||||||
return;
|
return;
|
||||||
this->last_normal_periodic_millis = current_millis;
|
this->last_normal_periodic_millis = current_millis;
|
||||||
for (auto &listener : this->listeners_)
|
for (auto &listener : this->listeners_)
|
||||||
listener->on_distance(get_distance_());
|
listener->on_distance(this->get_distance_());
|
||||||
for (auto &listener : this->listeners_)
|
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;
|
uint8_t data_element = 0;
|
||||||
uint16_t data_pos = 0;
|
uint16_t data_pos = 0;
|
||||||
if (this->cmd_reply_.length > CMD_MAX_BYTES) {
|
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;
|
return;
|
||||||
} else if (this->cmd_reply_.length < 2) {
|
} 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;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(&this->cmd_reply_.error, &buffer[CMD_ERROR_WORD], sizeof(this->cmd_reply_.error));
|
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;
|
this->cmd_reply_.ack = true;
|
||||||
switch ((uint16_t) this->cmd_reply_.command) {
|
switch ((uint16_t) this->cmd_reply_.command) {
|
||||||
case (CMD_ENABLE_CONF):
|
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;
|
break;
|
||||||
case (CMD_DISABLE_CONF):
|
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;
|
break;
|
||||||
case (CMD_READ_REGISTER):
|
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
|
// TODO Read/Write register is not implemented yet, this will get flushed out to a proper header file
|
||||||
data_pos = 0x0A;
|
data_pos = 0x0A;
|
||||||
for (uint16_t index = 0; index < (CMD_REG_DATA_REPLY_SIZE * // NOLINT
|
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;
|
break;
|
||||||
case (CMD_WRITE_REGISTER):
|
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;
|
break;
|
||||||
case (CMD_WRITE_ABD_PARAM):
|
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;
|
break;
|
||||||
case (CMD_READ_ABD_PARAM):
|
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;
|
data_pos = CMD_ABD_DATA_REPLY_START;
|
||||||
for (uint16_t index = 0; index < (CMD_ABD_DATA_REPLY_SIZE * // NOLINT
|
for (uint16_t index = 0; index < (CMD_ABD_DATA_REPLY_SIZE * // NOLINT
|
||||||
((buffer[CMD_FRAME_DATA_LENGTH] - 4) / CMD_ABD_DATA_REPLY_SIZE));
|
((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;
|
break;
|
||||||
case (CMD_WRITE_SYS_PARAM):
|
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;
|
break;
|
||||||
case (CMD_READ_VERSION):
|
case (CMD_READ_VERSION):
|
||||||
memcpy(this->ld2420_firmware_ver_, &buffer[12], buffer[10]);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -533,7 +530,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!this->cmd_reply_.ack) {
|
while (!this->cmd_reply_.ack) {
|
||||||
while (available()) {
|
while (this->available()) {
|
||||||
this->readline_(read(), ack_buffer, sizeof(ack_buffer));
|
this->readline_(read(), ack_buffer, sizeof(ack_buffer));
|
||||||
}
|
}
|
||||||
delay_microseconds_safe(1450);
|
delay_microseconds_safe(1450);
|
||||||
@@ -548,7 +545,7 @@ int LD2420Component::send_cmd_from_array(CmdFrameT frame) {
|
|||||||
if (this->cmd_reply_.ack)
|
if (this->cmd_reply_.ack)
|
||||||
retry = 0;
|
retry = 0;
|
||||||
if (this->cmd_reply_.error > 0)
|
if (this->cmd_reply_.error > 0)
|
||||||
handle_cmd_error(error);
|
this->handle_cmd_error(error);
|
||||||
}
|
}
|
||||||
return 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.data_length += sizeof(CMD_PROTOCOL_VER);
|
||||||
}
|
}
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
return this->send_cmd_from_array(cmd_frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,7 +573,7 @@ void LD2420Component::ld2420_restart() {
|
|||||||
cmd_frame.header = CMD_FRAME_HEADER;
|
cmd_frame.header = CMD_FRAME_HEADER;
|
||||||
cmd_frame.command = CMD_RESTART;
|
cmd_frame.command = CMD_RESTART;
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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[1] = reg;
|
||||||
cmd_frame.data_length += 2;
|
cmd_frame.data_length += 2;
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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));
|
memcpy(&cmd_frame.data[cmd_frame.data_length], &value, sizeof(CMD_REG_DATA_REPLY_SIZE));
|
||||||
cmd_frame.data_length += 2;
|
cmd_frame.data_length += 2;
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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) {
|
int LD2420Component::get_gate_threshold_(uint8_t gate) {
|
||||||
uint8_t error;
|
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]));
|
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.data_length += 2;
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
error = this->send_cmd_from_array(cmd_frame);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
this->current_config.move_thresh[gate] = cmd_reply_.data[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
|
sizeof(CMD_TIMEOUT_REG)); // Register: global delay time
|
||||||
cmd_frame.data_length += sizeof(CMD_TIMEOUT_REG);
|
cmd_frame.data_length += sizeof(CMD_TIMEOUT_REG);
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
error = this->send_cmd_from_array(cmd_frame);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
this->current_config.min_gate = (uint16_t) cmd_reply_.data[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));
|
memcpy(&cmd_frame.data[cmd_frame.data_length], &unknown_parm, sizeof(unknown_parm));
|
||||||
cmd_frame.data_length += sizeof(unknown_parm);
|
cmd_frame.data_length += sizeof(unknown_parm);
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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)
|
if (this->send_cmd_from_array(cmd_frame) == 0)
|
||||||
set_mode_(mode);
|
this->set_mode_(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LD2420Component::get_firmware_version_() {
|
void LD2420Component::get_firmware_version_() {
|
||||||
@@ -679,7 +676,7 @@ void LD2420Component::get_firmware_version_() {
|
|||||||
cmd_frame.command = CMD_READ_VERSION;
|
cmd_frame.command = CMD_READ_VERSION;
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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.data_length += sizeof(timeout);
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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]));
|
sizeof(this->new_config.still_thresh[gate]));
|
||||||
cmd_frame.data_length += sizeof(this->new_config.still_thresh[gate]);
|
cmd_frame.data_length += sizeof(this->new_config.still_thresh[gate]);
|
||||||
cmd_frame.footer = CMD_FRAME_FOOTER;
|
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);
|
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 set_operating_mode(const std::string &state);
|
||||||
void auto_calibrate_sensitivity();
|
void auto_calibrate_sensitivity();
|
||||||
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
|
void update_radar_data(uint16_t const *gate_energy, uint8_t sample_number);
|
||||||
uint8_t calc_checksum(void *data, size_t size);
|
static uint8_t calc_checksum(void *data, size_t size);
|
||||||
|
|
||||||
RegConfigT current_config;
|
RegConfigT current_config;
|
||||||
RegConfigT new_config;
|
RegConfigT new_config;
|
||||||
@@ -222,7 +222,7 @@ class LD2420Component : public Component, public uart::UARTDevice {
|
|||||||
volatile bool ack;
|
volatile bool ack;
|
||||||
};
|
};
|
||||||
|
|
||||||
int get_firmware_int_(const char *version_string);
|
static int get_firmware_int(const char *version_string);
|
||||||
void get_firmware_version_();
|
void get_firmware_version_();
|
||||||
int get_gate_threshold_(uint8_t gate);
|
int get_gate_threshold_(uint8_t gate);
|
||||||
void get_reg_value_(uint16_t reg);
|
void get_reg_value_(uint16_t reg);
|
||||||
|
@@ -6,7 +6,9 @@
|
|||||||
#ifdef USE_SENSOR
|
#ifdef USE_SENSOR
|
||||||
#include "esphome/components/sensor/sensor.h"
|
#include "esphome/components/sensor/sensor.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
#define highbyte(val) (uint8_t)((val) >> 8)
|
#define highbyte(val) (uint8_t)((val) >> 8)
|
||||||
#define lowbyte(val) (uint8_t)((val) &0xff)
|
#define lowbyte(val) (uint8_t)((val) &0xff)
|
||||||
@@ -96,11 +98,6 @@ static inline std::string get_direction(int16_t speed) {
|
|||||||
return STATIONARY;
|
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) {
|
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],
|
return str_sprintf("%u.%02X.%02X%02X%02X%02X", buffer[13], buffer[12], buffer[17], buffer[16], buffer[15],
|
||||||
buffer[14]);
|
buffer[14]);
|
||||||
@@ -120,7 +117,7 @@ void LD2450Component::setup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LD2450Component::dump_config() {
|
void LD2450Component::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "HLK-LD2450 Human motion tracking radar module:");
|
ESP_LOGCONFIG(TAG, "LD2450:");
|
||||||
#ifdef USE_BINARY_SENSOR
|
#ifdef USE_BINARY_SENSOR
|
||||||
LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_);
|
LOG_BINARY_SENSOR(" ", "TargetBinarySensor", this->target_binary_sensor_);
|
||||||
LOG_BINARY_SENSOR(" ", "MovingTargetBinarySensor", this->moving_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_);
|
LOG_NUMBER(" ", "PresenceTimeoutNumber", this->presence_timeout_number_);
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGCONFIG(TAG,
|
ESP_LOGCONFIG(TAG,
|
||||||
" Throttle : %ums\n"
|
" Throttle: %ums\n"
|
||||||
" MAC Address : %s\n"
|
" MAC Address: %s\n"
|
||||||
" Firmware version : %s",
|
" Firmware version: %s",
|
||||||
this->throttle_, const_cast<char *>(this->mac_.c_str()), const_cast<char *>(this->version_.c_str()));
|
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) {
|
if (this->timeout_ == 0) {
|
||||||
this->timeout_ = ld2450::convert_seconds_to_ms(DEFAULT_PRESENCE_TIMEOUT);
|
this->timeout_ = ld2450::convert_seconds_to_ms(DEFAULT_PRESENCE_TIMEOUT);
|
||||||
}
|
}
|
||||||
auto current_millis = millis();
|
return App.get_loop_component_start_time() - check_millis >= this->timeout_;
|
||||||
return current_millis - check_millis >= this->timeout_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract, store and publish zone details LD2450 buffer
|
// 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
|
// Header Target 1 Target 2 Target 3 End
|
||||||
void LD2450Component::handle_periodic_data_(uint8_t *buffer, uint8_t len) {
|
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)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (buffer[0] != 0xAA || buffer[1] != 0xFF || buffer[2] != 0x03 || buffer[3] != 0x00) { // header
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (buffer[len - 2] != 0x55 || buffer[len - 1] != 0xCC) { // footer
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto current_millis = millis();
|
if (App.get_loop_component_start_time() - this->last_periodic_millis_ < this->throttle_) {
|
||||||
if (current_millis - this->last_periodic_millis_ < this->throttle_) {
|
|
||||||
ESP_LOGV(TAG, "Throttling: %d", this->throttle_);
|
ESP_LOGV(TAG, "Throttling: %d", this->throttle_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->last_periodic_millis_ = current_millis;
|
this->last_periodic_millis_ = App.get_loop_component_start_time();
|
||||||
|
|
||||||
int16_t target_count = 0;
|
int16_t target_count = 0;
|
||||||
int16_t still_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
|
#ifdef USE_SENSOR
|
||||||
// For presence timeout check
|
// For presence timeout check
|
||||||
if (target_count > 0) {
|
if (target_count > 0) {
|
||||||
this->presence_millis_ = millis();
|
this->presence_millis_ = App.get_loop_component_start_time();
|
||||||
}
|
}
|
||||||
if (moving_target_count > 0) {
|
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) {
|
if (still_target_count > 0) {
|
||||||
this->still_presence_millis_ = millis();
|
this->still_presence_millis_ = App.get_loop_component_start_time();
|
||||||
}
|
}
|
||||||
#endif
|
#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) {
|
bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
||||||
ESP_LOGV(TAG, "Handling ack data for command %02X", buffer[COMMAND]);
|
ESP_LOGV(TAG, "Handling ack data for command %02X", buffer[COMMAND]);
|
||||||
if (len < 10) {
|
if (len < 10) {
|
||||||
ESP_LOGE(TAG, "Ack data: invalid length");
|
ESP_LOGE(TAG, "Invalid ack length");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (buffer[0] != 0xFD || buffer[1] != 0xFC || buffer[2] != 0xFB || buffer[3] != 0xFA) { // frame header
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (buffer[COMMAND_STATUS] != 0x01) {
|
if (buffer[COMMAND_STATUS] != 0x01) {
|
||||||
ESP_LOGE(TAG, "Ack data: invalid status");
|
ESP_LOGE(TAG, "Invalid ack status");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (buffer[8] || buffer[9]) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (buffer[COMMAND]) {
|
switch (buffer[COMMAND]) {
|
||||||
case lowbyte(CMD_ENABLE_CONF):
|
case lowbyte(CMD_ENABLE_CONF):
|
||||||
ESP_LOGV(TAG, "Got enable conf command");
|
ESP_LOGV(TAG, "Enable conf command");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_DISABLE_CONF):
|
case lowbyte(CMD_DISABLE_CONF):
|
||||||
ESP_LOGV(TAG, "Got disable conf command");
|
ESP_LOGV(TAG, "Disable conf command");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SET_BAUD_RATE):
|
case lowbyte(CMD_SET_BAUD_RATE):
|
||||||
ESP_LOGV(TAG, "Got baud rate change command");
|
ESP_LOGV(TAG, "Baud rate change command");
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
if (this->baud_rate_select_ != nullptr) {
|
if (this->baud_rate_select_ != nullptr) {
|
||||||
ESP_LOGV(TAG, "Change baud rate to %s", this->baud_rate_select_->state.c_str());
|
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) {
|
if (len < 20) {
|
||||||
return false;
|
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());
|
ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str());
|
||||||
#ifdef USE_TEXT_SENSOR
|
#ifdef USE_TEXT_SENSOR
|
||||||
if (this->mac_text_sensor_ != nullptr) {
|
if (this->mac_text_sensor_ != nullptr) {
|
||||||
@@ -622,15 +617,15 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
|||||||
#endif
|
#endif
|
||||||
#ifdef USE_SWITCH
|
#ifdef USE_SWITCH
|
||||||
if (this->bluetooth_switch_ != nullptr) {
|
if (this->bluetooth_switch_ != nullptr) {
|
||||||
this->bluetooth_switch_->publish_state(this->mac_ != NO_MAC);
|
this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_BLUETOOTH):
|
case lowbyte(CMD_BLUETOOTH):
|
||||||
ESP_LOGV(TAG, "Got Bluetooth command");
|
ESP_LOGV(TAG, "Bluetooth command");
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SINGLE_TARGET_MODE):
|
case lowbyte(CMD_SINGLE_TARGET_MODE):
|
||||||
ESP_LOGV(TAG, "Got single target conf command");
|
ESP_LOGV(TAG, "Single target conf command");
|
||||||
#ifdef USE_SWITCH
|
#ifdef USE_SWITCH
|
||||||
if (this->multi_target_switch_ != nullptr) {
|
if (this->multi_target_switch_ != nullptr) {
|
||||||
this->multi_target_switch_->publish_state(false);
|
this->multi_target_switch_->publish_state(false);
|
||||||
@@ -638,7 +633,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_MULTI_TARGET_MODE):
|
case lowbyte(CMD_MULTI_TARGET_MODE):
|
||||||
ESP_LOGV(TAG, "Got multi target conf command");
|
ESP_LOGV(TAG, "Multi target conf command");
|
||||||
#ifdef USE_SWITCH
|
#ifdef USE_SWITCH
|
||||||
if (this->multi_target_switch_ != nullptr) {
|
if (this->multi_target_switch_ != nullptr) {
|
||||||
this->multi_target_switch_->publish_state(true);
|
this->multi_target_switch_->publish_state(true);
|
||||||
@@ -646,7 +641,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_QUERY_TARGET_MODE):
|
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
|
#ifdef USE_SWITCH
|
||||||
if (this->multi_target_switch_ != nullptr) {
|
if (this->multi_target_switch_ != nullptr) {
|
||||||
this->multi_target_switch_->publish_state(buffer[10] == 0x02);
|
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
|
#endif
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_QUERY_ZONE):
|
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->zone_type_ = std::stoi(std::to_string(buffer[10]), nullptr, 16);
|
||||||
this->publish_zone_type();
|
this->publish_zone_type();
|
||||||
#ifdef USE_SELECT
|
#ifdef USE_SELECT
|
||||||
@@ -674,7 +669,7 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) {
|
|||||||
this->process_zone_(buffer);
|
this->process_zone_(buffer);
|
||||||
break;
|
break;
|
||||||
case lowbyte(CMD_SET_ZONE):
|
case lowbyte(CMD_SET_ZONE):
|
||||||
ESP_LOGV(TAG, "Got set zone conf command");
|
ESP_LOGV(TAG, "Set zone conf command");
|
||||||
this->query_zone_info();
|
this->query_zone_info();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@@ -38,8 +38,8 @@ from esphome.const import (
|
|||||||
CONF_WHITE,
|
CONF_WHITE,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
from .automation import LIGHT_STATE_SCHEMA
|
from .automation import LIGHT_STATE_SCHEMA
|
||||||
from .effects import (
|
from .effects import (
|
||||||
@@ -110,6 +110,8 @@ LIGHT_SCHEMA = (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LIGHT_SCHEMA.add_extra(entity_duplicate_validator("light"))
|
||||||
|
|
||||||
BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend(
|
BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_EFFECTS): validate_effects(BINARY_EFFECTS),
|
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):
|
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]))
|
cg.add(light_var.set_restore_mode(config[CONF_RESTORE_MODE]))
|
||||||
|
|
||||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -67,6 +67,9 @@ _LOCK_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_LOCK_SCHEMA.add_extra(entity_duplicate_validator("lock"))
|
||||||
|
|
||||||
|
|
||||||
def lock_schema(
|
def lock_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
*,
|
*,
|
||||||
@@ -94,7 +97,7 @@ LOCK_SCHEMA.add_extra(cv.deprecated_schema_constant("lock"))
|
|||||||
|
|
||||||
|
|
||||||
async def _setup_lock_core(var, config):
|
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, []):
|
for conf in config.get(CONF_ON_LOCK, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
|
@@ -184,7 +184,9 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(Logger),
|
cv.GenerateID(): cv.declare_id(Logger),
|
||||||
cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int,
|
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.Optional(CONF_DEASSERT_RTS_DTR, default=False): cv.boolean,
|
||||||
cv.SplitDefault(
|
cv.SplitDefault(
|
||||||
CONF_TASK_LOG_BUFFER_SIZE,
|
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
|
// - Messages are serialized through main loop for proper console output
|
||||||
// - Fallback to emergency console logging only if ring buffer is full
|
// - Fallback to emergency console logging only if ring buffer is full
|
||||||
// - WITHOUT task log buffer: Only emergency console output, no callbacks
|
// - 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))
|
if (level > this->level_for(tag))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -46,8 +46,8 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
|||||||
bool message_sent = false;
|
bool message_sent = false;
|
||||||
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
#ifdef USE_ESPHOME_TASK_LOG_BUFFER
|
||||||
// For non-main tasks, queue the message for callbacks - but only if we have any callbacks registered
|
// 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,
|
message_sent =
|
||||||
static_cast<uint16_t>(line), current_task, format, args);
|
this->log_buffer_->send_message_thread_safe(level, tag, static_cast<uint16_t>(line), current_task, format, args);
|
||||||
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
#endif // USE_ESPHOME_TASK_LOG_BUFFER
|
||||||
|
|
||||||
// Emergency console logging for non-main tasks when ring buffer is full or disabled
|
// 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)
|
// Maximum size for console log messages (includes null terminator)
|
||||||
static const size_t MAX_CONSOLE_LOG_MSG_SIZE = 144;
|
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
|
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,
|
this->format_log_to_buffer_with_terminator_(level, tag, line, format, args, console_buffer, &buffer_at,
|
||||||
MAX_CONSOLE_LOG_MSG_SIZE);
|
MAX_CONSOLE_LOG_MSG_SIZE);
|
||||||
this->write_msg_(console_buffer);
|
this->write_msg_(console_buffer);
|
||||||
@@ -69,7 +69,7 @@ void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Implementation for all other platforms
|
// 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_)
|
if (level > this->level_for(tag) || global_recursion_guard_)
|
||||||
return;
|
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
|
#ifdef USE_STORE_LOG_STR_IN_FLASH
|
||||||
// Implementation for ESP8266 with flash string support.
|
// Implementation for ESP8266 with flash string support.
|
||||||
// Note: USE_STORE_LOG_STR_IN_FLASH is only defined for ESP8266.
|
// 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
|
va_list args) { // NOLINT
|
||||||
if (level > this->level_for(tag) || global_recursion_guard_)
|
if (level > this->level_for(tag) || global_recursion_guard_)
|
||||||
return;
|
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
|
#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);
|
auto it = this->log_levels_.find(tag);
|
||||||
if (it != this->log_levels_.end())
|
if (it != this->log_levels_.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
@@ -195,13 +195,13 @@ void Logger::loop() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Logger::set_baud_rate(uint32_t baud_rate) { this->baud_rate_ = baud_rate; }
|
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)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
||||||
UARTSelection Logger::get_uart() const { return this->uart_; }
|
UARTSelection Logger::get_uart() const { return this->uart_; }
|
||||||
#endif
|
#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));
|
this->log_callback_.add(std::move(callback));
|
||||||
}
|
}
|
||||||
float Logger::get_setup_priority() const { return setup_priority::BUS + 500.0f; }
|
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) {
|
if (level > ESPHOME_LOG_LEVEL) {
|
||||||
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]);
|
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.
|
* Advanced configuration (pin selection, etc) is not supported.
|
||||||
*/
|
*/
|
||||||
enum UARTSelection {
|
enum UARTSelection : uint8_t {
|
||||||
#ifdef USE_LIBRETINY
|
#ifdef USE_LIBRETINY
|
||||||
UART_SELECTION_DEFAULT = 0,
|
UART_SELECTION_DEFAULT = 0,
|
||||||
UART_SELECTION_UART0,
|
UART_SELECTION_UART0,
|
||||||
@@ -129,10 +129,10 @@ class Logger : public Component {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Set the default log level for this logger.
|
/// 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.
|
/// Set the log level of the specified tag.
|
||||||
void set_log_level(const std::string &tag, int log_level);
|
void set_log_level(const std::string &tag, uint8_t log_level);
|
||||||
int get_log_level() { return this->current_level_; }
|
uint8_t get_log_level() { return this->current_level_; }
|
||||||
|
|
||||||
// ========== INTERNAL METHODS ==========
|
// ========== INTERNAL METHODS ==========
|
||||||
// (In most use cases you won't need these)
|
// (In most use cases you won't need these)
|
||||||
@@ -140,19 +140,20 @@ class Logger : public Component {
|
|||||||
void pre_setup();
|
void pre_setup();
|
||||||
void dump_config() override;
|
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
|
/// 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
|
// 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;
|
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
|
#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
|
#endif
|
||||||
|
|
||||||
protected:
|
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
|
// 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)
|
// 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,
|
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, int *buffer_at, int buffer_size) {
|
va_list args, char *buffer, uint16_t *buffer_at,
|
||||||
|
uint16_t buffer_size) {
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||||
this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size);
|
this->write_header_to_buffer_(level, tag, line, this->get_thread_name_(), buffer, buffer_at, buffer_size);
|
||||||
#else
|
#else
|
||||||
@@ -180,7 +182,7 @@ class Logger : public Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper to format and send a log message to both console and callbacks
|
// 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) {
|
va_list args) {
|
||||||
// Format to tx_buffer and prepare for output
|
// Format to tx_buffer and prepare for output
|
||||||
this->tx_buffer_at_ = 0; // Initialize buffer position
|
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
|
// 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
|
// Calculate available space
|
||||||
const int available = buffer_size - *buffer_at;
|
if (*buffer_at >= buffer_size)
|
||||||
if (available <= 0)
|
|
||||||
return;
|
return;
|
||||||
|
const uint16_t available = buffer_size - *buffer_at;
|
||||||
|
|
||||||
// Determine copy length (minimum of remaining capacity and string length)
|
// Determine copy length (minimum of remaining capacity and string length)
|
||||||
const size_t copy_len = (length < static_cast<size_t>(available)) ? length : available;
|
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
|
// 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_list arg;
|
||||||
va_start(arg, format);
|
va_start(arg, format);
|
||||||
this->format_body_to_buffer_(buffer, buffer_at, buffer_size, format, arg);
|
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_();
|
const char *get_uart_selection_();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Group 4-byte aligned members first
|
||||||
uint32_t baud_rate_;
|
uint32_t baud_rate_;
|
||||||
char *tx_buffer_{nullptr};
|
char *tx_buffer_{nullptr};
|
||||||
int tx_buffer_at_{0};
|
#ifdef USE_ARDUINO
|
||||||
int tx_buffer_size_{0};
|
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)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040)
|
||||||
UARTSelection uart_{UART_SELECTION_UART0};
|
UARTSelection uart_{UART_SELECTION_UART0};
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_LIBRETINY
|
#ifdef USE_LIBRETINY
|
||||||
UARTSelection uart_{UART_SELECTION_DEFAULT};
|
UARTSelection uart_{UART_SELECTION_DEFAULT};
|
||||||
#endif
|
#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
|
#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};
|
bool main_task_recursion_guard_{false};
|
||||||
pthread_key_t log_recursion_key_;
|
|
||||||
#else
|
#else
|
||||||
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
bool global_recursion_guard_{false}; // Simple global recursion guard for single-task platforms
|
||||||
#endif
|
#endif
|
||||||
CallbackManager<void(int)> level_callback_{};
|
|
||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||||
void *main_task_ = nullptr; // Only used for thread name identification
|
|
||||||
const char *HOT get_thread_name_() {
|
const char *HOT get_thread_name_() {
|
||||||
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
||||||
if (current_task == main_task_) {
|
if (current_task == main_task_) {
|
||||||
@@ -297,11 +309,10 @@ class Logger : public Component {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void HOT write_header_to_buffer_(int level, const char *tag, int line, const char *thread_name, char *buffer,
|
inline void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name,
|
||||||
int *buffer_at, int buffer_size) {
|
char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
|
||||||
// Format header
|
// Format header
|
||||||
if (level < 0)
|
// uint8_t level is already bounded 0-255, just ensure it's <= 7
|
||||||
level = 0;
|
|
||||||
if (level > 7)
|
if (level > 7)
|
||||||
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);
|
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) {
|
va_list args) {
|
||||||
// Get remaining capacity in the buffer
|
// Get remaining capacity in the buffer
|
||||||
const int remaining = buffer_size - *buffer_at;
|
if (*buffer_at >= buffer_size)
|
||||||
if (remaining <= 0)
|
|
||||||
return;
|
return;
|
||||||
|
const uint16_t remaining = buffer_size - *buffer_at;
|
||||||
|
|
||||||
const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args);
|
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)
|
// 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;
|
*buffer_at += formatted_len;
|
||||||
|
|
||||||
// Remove all trailing newlines right after formatting
|
// 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) {
|
inline void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
|
||||||
static const int RESET_COLOR_LEN = strlen(ESPHOME_LOG_RESET_COLOR);
|
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);
|
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)
|
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:
|
public:
|
||||||
explicit LoggerMessageTrigger(Logger *parent, int level) {
|
explicit LoggerMessageTrigger(Logger *parent, uint8_t level) {
|
||||||
this->level_ = 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_) {
|
if (level <= this->level_) {
|
||||||
this->trigger(level, tag, message);
|
this->trigger(level, tag, message);
|
||||||
}
|
}
|
||||||
@@ -362,7 +373,7 @@ class LoggerMessageTrigger : public Trigger<int, const char *, const char *> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int level_;
|
uint8_t level_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace logger
|
} // namespace logger
|
||||||
|
@@ -454,9 +454,13 @@ def container_validator(schema, widget_type: WidgetType):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def validator(value):
|
def validator(value):
|
||||||
result = schema
|
|
||||||
if w_sch := widget_type.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
|
ltype = df.TYPE_NONE
|
||||||
if value and (layout := value.get(df.CONF_LAYOUT)):
|
if value and (layout := value.get(df.CONF_LAYOUT)):
|
||||||
if not isinstance(layout, dict):
|
if not isinstance(layout, dict):
|
||||||
|
@@ -3,7 +3,6 @@ import esphome.codegen as cg
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_ID
|
from esphome.const import CONF_ID
|
||||||
from esphome.core import ID
|
from esphome.core import ID
|
||||||
from esphome.cpp_generator import MockObj
|
|
||||||
|
|
||||||
from .defines import (
|
from .defines import (
|
||||||
CONF_STYLE_DEFINITIONS,
|
CONF_STYLE_DEFINITIONS,
|
||||||
@@ -13,12 +12,13 @@ from .defines import (
|
|||||||
literal,
|
literal,
|
||||||
)
|
)
|
||||||
from .helpers import add_lv_use
|
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 .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 (
|
from .widgets import (
|
||||||
Widget,
|
Widget,
|
||||||
add_widgets,
|
add_widgets,
|
||||||
|
collect_parts,
|
||||||
set_obj_properties,
|
set_obj_properties,
|
||||||
theme_widget_map,
|
theme_widget_map,
|
||||||
wait_for_widgets,
|
wait_for_widgets,
|
||||||
@@ -37,12 +37,18 @@ async def style_set(svar, style):
|
|||||||
lv.call(f"style_set_{remapped_prop}", svar, literal(value))
|
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):
|
async def styles_to_code(config):
|
||||||
"""Convert styles to C__ code."""
|
"""Convert styles to C__ code."""
|
||||||
for style in config.get(CONF_STYLE_DEFINITIONS, ()):
|
for style in config.get(CONF_STYLE_DEFINITIONS, ()):
|
||||||
svar = cg.new_Pvariable(style[CONF_ID])
|
await create_style(style, style[CONF_ID].id)
|
||||||
lv.style_init(svar)
|
|
||||||
await style_set(svar, style)
|
|
||||||
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
@@ -68,16 +74,18 @@ async def theme_to_code(config):
|
|||||||
if theme := config.get(CONF_THEME):
|
if theme := config.get(CONF_THEME):
|
||||||
add_lv_use(CONF_THEME)
|
add_lv_use(CONF_THEME)
|
||||||
for w_name, style in theme.items():
|
for w_name, style in theme.items():
|
||||||
if not isinstance(style, dict):
|
# Work around Python 3.10 bug with nested async comprehensions
|
||||||
continue
|
# With Python 3.11 this could be simplified
|
||||||
|
styles = {}
|
||||||
lname = "lv_theme_apply_" + w_name
|
for part, states in collect_parts(style).items():
|
||||||
apply = lv_variable(lv_lambda_t, lname)
|
styles[part] = {
|
||||||
theme_widget_map[w_name] = apply
|
state: await create_style(
|
||||||
ow = Widget.create("obj", MockObj(ID("obj")), obj_spec)
|
props,
|
||||||
async with LambdaContext([(lv_obj_t_ptr, "obj")], where=w_name) as context:
|
"_lv_theme_style_" + w_name + "_" + part + "_" + state,
|
||||||
await set_obj_properties(ow, style)
|
)
|
||||||
lv_assign(apply, await context.get_lambda())
|
for state, props in states.items()
|
||||||
|
}
|
||||||
|
theme_widget_map[w_name] = styles
|
||||||
|
|
||||||
|
|
||||||
async def add_top_layer(lv_component, config):
|
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.const import CONF_DEFAULT, CONF_GROUP, CONF_ID, CONF_STATE, CONF_TYPE
|
||||||
from esphome.core import ID, TimePeriod
|
from esphome.core import ID, TimePeriod
|
||||||
from esphome.coroutine import FakeAwaitable
|
from esphome.coroutine import FakeAwaitable
|
||||||
from esphome.cpp_generator import CallExpression, MockObj
|
from esphome.cpp_generator import MockObj
|
||||||
|
|
||||||
from ..defines import (
|
from ..defines import (
|
||||||
CONF_FLEX_ALIGN_CROSS,
|
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)
|
w = Widget.create(wid, var, spec, w_cnfig)
|
||||||
if theme := theme_widget_map.get(w_type):
|
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 set_obj_properties(w, w_cnfig)
|
||||||
await add_widgets(w, w_cnfig)
|
await add_widgets(w, w_cnfig)
|
||||||
await spec.to_code(w, w_cnfig)
|
await spec.to_code(w, w_cnfig)
|
||||||
|
@@ -1,8 +1,15 @@
|
|||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome.const import CONF_MAX_VALUE, CONF_MIN_VALUE, CONF_MODE, CONF_VALUE
|
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 ..defines import (
|
||||||
from ..lv_validation import animated, get_start_value, lv_float
|
BAR_MODES,
|
||||||
|
CONF_ANIMATED,
|
||||||
|
CONF_INDICATOR,
|
||||||
|
CONF_MAIN,
|
||||||
|
CONF_START_VALUE,
|
||||||
|
literal,
|
||||||
|
)
|
||||||
|
from ..lv_validation import animated, lv_int
|
||||||
from ..lvcode import lv
|
from ..lvcode import lv
|
||||||
from ..types import LvNumber, NumberType
|
from ..types import LvNumber, NumberType
|
||||||
from . import Widget
|
from . import Widget
|
||||||
@@ -10,22 +17,30 @@ from . import Widget
|
|||||||
# Note this file cannot be called "bar.py" because that name is disallowed.
|
# Note this file cannot be called "bar.py" because that name is disallowed.
|
||||||
|
|
||||||
CONF_BAR = "bar"
|
CONF_BAR = "bar"
|
||||||
BAR_MODIFY_SCHEMA = cv.Schema(
|
|
||||||
{
|
|
||||||
cv.Optional(CONF_VALUE): lv_float,
|
def validate_bar(config):
|
||||||
cv.Optional(CONF_ANIMATED, default=True): animated,
|
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(
|
BAR_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_VALUE): lv_float,
|
cv.Optional(CONF_VALUE): lv_int,
|
||||||
cv.Optional(CONF_MIN_VALUE, default=0): cv.int_,
|
cv.Optional(CONF_START_VALUE): lv_int,
|
||||||
cv.Optional(CONF_MAX_VALUE, default=100): cv.int_,
|
cv.Optional(CONF_MIN_VALUE): lv_int,
|
||||||
cv.Optional(CONF_MODE, default="NORMAL"): BAR_MODES.one_of,
|
cv.Optional(CONF_MAX_VALUE): lv_int,
|
||||||
|
cv.Optional(CONF_MODE): BAR_MODES.one_of,
|
||||||
cv.Optional(CONF_ANIMATED, default=True): animated,
|
cv.Optional(CONF_ANIMATED, default=True): animated,
|
||||||
}
|
}
|
||||||
)
|
).add_extra(validate_bar)
|
||||||
|
|
||||||
|
|
||||||
class BarType(NumberType):
|
class BarType(NumberType):
|
||||||
@@ -35,17 +50,23 @@ class BarType(NumberType):
|
|||||||
LvNumber("lv_bar_t"),
|
LvNumber("lv_bar_t"),
|
||||||
parts=(CONF_MAIN, CONF_INDICATOR),
|
parts=(CONF_MAIN, CONF_INDICATOR),
|
||||||
schema=BAR_SCHEMA,
|
schema=BAR_SCHEMA,
|
||||||
modify_schema=BAR_MODIFY_SCHEMA,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async def to_code(self, w: Widget, config):
|
async def to_code(self, w: Widget, config):
|
||||||
var = w.obj
|
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:
|
if CONF_MIN_VALUE in config:
|
||||||
lv.bar_set_range(var, config[CONF_MIN_VALUE], config[CONF_MAX_VALUE])
|
lv.bar_set_range(
|
||||||
lv.bar_set_mode(var, literal(config[CONF_MODE]))
|
var,
|
||||||
value = await get_start_value(config)
|
await lv_int.process(config[CONF_MIN_VALUE]),
|
||||||
if value is not None:
|
await lv_int.process(config[CONF_MAX_VALUE]),
|
||||||
lv.bar_set_value(var, value, literal(config[CONF_ANIMATED]))
|
)
|
||||||
|
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
|
@property
|
||||||
def animated(self):
|
def animated(self):
|
||||||
|
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.const import CONF_SIZE, CONF_TEXT
|
from esphome.const import CONF_SIZE, CONF_TEXT
|
||||||
from esphome.cpp_generator import MockObjClass
|
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 ..lv_validation import color, color_retmapper, lv_text
|
||||||
from ..lvcode import LocalVariable, lv, lv_expr
|
from ..lvcode import LocalVariable, lv, lv_expr
|
||||||
from ..schemas import TEXT_SCHEMA
|
from ..schemas import TEXT_SCHEMA
|
||||||
@@ -34,7 +34,7 @@ class QrCodeType(WidgetType):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def get_uses(self):
|
def get_uses(self):
|
||||||
return ("canvas", "img")
|
return ("canvas", "img", "label")
|
||||||
|
|
||||||
def obj_creator(self, parent: MockObjClass, config: dict):
|
def obj_creator(self, parent: MockObjClass, config: dict):
|
||||||
dark_color = color_retmapper(config[CONF_DARK_COLOR])
|
dark_color = color_retmapper(config[CONF_DARK_COLOR])
|
||||||
@@ -45,10 +45,8 @@ class QrCodeType(WidgetType):
|
|||||||
async def to_code(self, w: Widget, config):
|
async def to_code(self, w: Widget, config):
|
||||||
if (value := config.get(CONF_TEXT)) is not None:
|
if (value := config.get(CONF_TEXT)) is not None:
|
||||||
value = await lv_text.process(value)
|
value = await lv_text.process(value)
|
||||||
with LocalVariable(
|
with LocalVariable("qr_text", cg.std_string, value, modifier="") as str_obj:
|
||||||
"qr_text", cg.const_char_ptr, value, modifier=""
|
lv.qrcode_update(w.obj, str_obj.c_str(), str_obj.size())
|
||||||
) as str_obj:
|
|
||||||
lv.qrcode_update(w.obj, str_obj, literal(f"strlen({str_obj})"))
|
|
||||||
|
|
||||||
|
|
||||||
qr_code_spec = QrCodeType()
|
qr_code_spec = QrCodeType()
|
||||||
|
@@ -8,7 +8,7 @@ namespace m5stack_8angle {
|
|||||||
static const char *const TAG = "m5stack_8angle.light";
|
static const char *const TAG = "m5stack_8angle.light";
|
||||||
|
|
||||||
void M5Stack8AngleLightOutput::setup() {
|
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);
|
this->buf_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
|
||||||
if (this->buf_ == nullptr) {
|
if (this->buf_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
|
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,
|
CONF_VOLUME,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE
|
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.coroutine import coroutine_with_priority
|
||||||
from esphome.cpp_generator import MockObjClass
|
from esphome.cpp_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ IsAnnouncingCondition = media_player_ns.class_(
|
|||||||
|
|
||||||
|
|
||||||
async def setup_media_player_core_(var, config):
|
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, []):
|
for conf in config.get(CONF_ON_STATE, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||||
await automation.build_automation(trigger, [], conf)
|
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(
|
def media_player_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
@@ -166,7 +168,6 @@ def media_player_schema(
|
|||||||
MEDIA_PLAYER_SCHEMA = media_player_schema(MediaPlayer)
|
MEDIA_PLAYER_SCHEMA = media_player_schema(MediaPlayer)
|
||||||
MEDIA_PLAYER_SCHEMA.add_extra(cv.deprecated_schema_constant("media_player"))
|
MEDIA_PLAYER_SCHEMA.add_extra(cv.deprecated_schema_constant("media_player"))
|
||||||
|
|
||||||
|
|
||||||
MEDIA_PLAYER_ACTION_SCHEMA = automation.maybe_simple_id(
|
MEDIA_PLAYER_ACTION_SCHEMA = automation.maybe_simple_id(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
|
@@ -27,7 +27,7 @@ void VADModel::log_model_config() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StreamingModel::load_model_() {
|
bool StreamingModel::load_model_() {
|
||||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> arena_allocator;
|
||||||
|
|
||||||
if (this->tensor_arena_ == nullptr) {
|
if (this->tensor_arena_ == nullptr) {
|
||||||
this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_);
|
this->tensor_arena_ = arena_allocator.allocate(this->tensor_arena_size_);
|
||||||
@@ -96,7 +96,7 @@ bool StreamingModel::load_model_() {
|
|||||||
void StreamingModel::unload_model() {
|
void StreamingModel::unload_model() {
|
||||||
this->interpreter_.reset();
|
this->interpreter_.reset();
|
||||||
|
|
||||||
RAMAllocator<uint8_t> arena_allocator(RAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> arena_allocator;
|
||||||
|
|
||||||
if (this->tensor_arena_ != nullptr) {
|
if (this->tensor_arena_ != nullptr) {
|
||||||
arena_allocator.deallocate(this->tensor_arena_, this->tensor_arena_size_);
|
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_))
|
cg.add(var.set_writer(lambda_))
|
||||||
await display.register_display(var, config)
|
await display.register_display(var, config)
|
||||||
await spi.register_spi_device(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);
|
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_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
|
// 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; }
|
bool waiting_for_response() { return parent_->waiting_for_response != 0; }
|
||||||
|
|
||||||
|
@@ -112,6 +112,22 @@ TYPE_REGISTER_MAP = {
|
|||||||
"FP32_R": 2,
|
"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 = modbus_controller_ns.class_(
|
||||||
"ModbusCommandSentTrigger", automation.Trigger.template(cg.int_, cg.int_)
|
"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]))
|
cg.add(var.set_offline_skip_updates(config[CONF_OFFLINE_SKIP_UPDATES]))
|
||||||
if CONF_SERVER_REGISTERS in config:
|
if CONF_SERVER_REGISTERS in config:
|
||||||
for server_register in config[CONF_SERVER_REGISTERS]:
|
for server_register in config[CONF_SERVER_REGISTERS]:
|
||||||
|
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(
|
cg.add(
|
||||||
var.add_server_register(
|
server_register_var.set_read_lambda(
|
||||||
cg.new_Pvariable(
|
cg.TemplateArguments(cpp_type),
|
||||||
server_register[CONF_ID],
|
await cg.process_lambda(
|
||||||
server_register[CONF_ADDRESS],
|
server_register[CONF_READ_LAMBDA],
|
||||||
server_register[CONF_VALUE_TYPE],
|
[(cg.uint16, "address")],
|
||||||
TYPE_REGISTER_MAP[server_register[CONF_VALUE_TYPE]],
|
return_type=cpp_type,
|
||||||
await cg.process_lambda(
|
),
|
||||||
server_register[CONF_READ_LAMBDA],
|
|
||||||
[],
|
|
||||||
return_type=cg.float_,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
cg.add(var.add_server_register(server_register_var))
|
||||||
await register_modbus_device(var, config)
|
await register_modbus_device(var, config)
|
||||||
for conf in config.get(CONF_ON_COMMAND_SENT, []):
|
for conf in config.get(CONF_ON_COMMAND_SENT, []):
|
||||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
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;
|
bool found = false;
|
||||||
for (auto *server_register : this->server_registers_) {
|
for (auto *server_register : this->server_registers_) {
|
||||||
if (server_register->address == current_address) {
|
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.",
|
std::vector<uint16_t> payload;
|
||||||
server_register->address, static_cast<uint8_t>(server_register->value_type),
|
payload.reserve(server_register->register_count * 2);
|
||||||
server_register->register_count, value);
|
number_to_payload(payload, value, server_register->value_type);
|
||||||
std::vector<uint16_t> payload = float_to_payload(value, server_register->value_type);
|
|
||||||
sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend());
|
sixteen_bit_response.insert(sixteen_bit_response.end(), payload.cbegin(), payload.cend());
|
||||||
current_address += server_register->register_count;
|
current_address += server_register->register_count;
|
||||||
found = true;
|
found = true;
|
||||||
@@ -132,11 +137,7 @@ void ModbusController::on_modbus_read_registers(uint8_t function_code, uint16_t
|
|||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
ESP_LOGW(TAG, "Could not match any register to address %02X. Sending exception response.", current_address);
|
ESP_LOGW(TAG, "Could not match any register to address %02X. Sending exception response.", current_address);
|
||||||
std::vector<uint8_t> error_response;
|
send_error(function_code, 0x02);
|
||||||
error_response.push_back(this->address_);
|
|
||||||
error_response.push_back(0x81);
|
|
||||||
error_response.push_back(0x02);
|
|
||||||
this->send_raw(error_response);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,10 @@ enum class SensorValueType : uint8_t {
|
|||||||
FP32_R = 0xD
|
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) {
|
inline ModbusFunctionCode modbus_register_read_function(ModbusRegisterType reg_type) {
|
||||||
switch (reg_type) {
|
switch (reg_type) {
|
||||||
case ModbusRegisterType::COIL:
|
case ModbusRegisterType::COIL:
|
||||||
@@ -253,18 +257,53 @@ class SensorItem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class ServerRegister {
|
class ServerRegister {
|
||||||
|
using ReadLambda = std::function<int64_t()>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count,
|
ServerRegister(uint16_t address, SensorValueType value_type, uint8_t register_count) {
|
||||||
std::function<float()> read_lambda) {
|
|
||||||
this->address = address;
|
this->address = address;
|
||||||
this->value_type = value_type;
|
this->value_type = value_type;
|
||||||
this->register_count = register_count;
|
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};
|
uint16_t address{0};
|
||||||
SensorValueType value_type{SensorValueType::RAW};
|
SensorValueType value_type{SensorValueType::RAW};
|
||||||
uint8_t register_count{0};
|
uint8_t register_count{0};
|
||||||
std::function<float()> read_lambda;
|
ReadLambda read_lambda;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ModbusController::create_register_ranges_ tries to optimize register range
|
// 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;
|
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
||||||
/// called when a modbus error response was received
|
/// called when a modbus error response was received
|
||||||
void on_modbus_error(uint8_t function_code, uint8_t exception_code) override;
|
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;
|
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
|
/// 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);
|
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);
|
int64_t number = payload_to_number(data, item.sensor_value_type, item.offset, item.bitmask);
|
||||||
|
|
||||||
float float_value;
|
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));
|
float_value = bit_cast<float>(static_cast<uint32_t>(number));
|
||||||
} else {
|
} else {
|
||||||
float_value = static_cast<float>(number);
|
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) {
|
inline std::vector<uint16_t> float_to_payload(float value, SensorValueType value_type) {
|
||||||
int64_t val;
|
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);
|
val = bit_cast<uint32_t>(value);
|
||||||
} else {
|
} else {
|
||||||
val = llroundf(value);
|
val = llroundf(value);
|
||||||
|
@@ -68,6 +68,7 @@ def AUTO_LOAD():
|
|||||||
|
|
||||||
CONF_DISCOVER_IP = "discover_ip"
|
CONF_DISCOVER_IP = "discover_ip"
|
||||||
CONF_IDF_SEND_ASYNC = "idf_send_async"
|
CONF_IDF_SEND_ASYNC = "idf_send_async"
|
||||||
|
CONF_WAIT_FOR_CONNECTION = "wait_for_connection"
|
||||||
|
|
||||||
|
|
||||||
def validate_message_just_topic(value):
|
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_PUBLISH_NAN_AS_NONE, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_WAIT_FOR_CONNECTION, default=False): cv.boolean,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
validate_config,
|
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_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(
|
MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
|
@@ -17,7 +17,8 @@ enum class MQTTClientDisconnectReason : int8_t {
|
|||||||
MQTT_MALFORMED_CREDENTIALS = 4,
|
MQTT_MALFORMED_CREDENTIALS = 4,
|
||||||
MQTT_NOT_AUTHORIZED = 5,
|
MQTT_NOT_AUTHORIZED = 5,
|
||||||
ESP8266_NOT_ENOUGH_SPACE = 6,
|
ESP8266_NOT_ENOUGH_SPACE = 6,
|
||||||
TLS_BAD_FINGERPRINT = 7
|
TLS_BAD_FINGERPRINT = 7,
|
||||||
|
DNS_RESOLVE_ERROR = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
/// internal struct for MQTT messages.
|
/// internal struct for MQTT messages.
|
||||||
|
@@ -176,7 +176,8 @@ void MQTTClientComponent::dump_config() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool MQTTClientComponent::can_proceed() {
|
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_() {
|
void MQTTClientComponent::start_dnslookup_() {
|
||||||
@@ -228,6 +229,8 @@ void MQTTClientComponent::check_dnslookup_() {
|
|||||||
if (this->dns_resolve_error_) {
|
if (this->dns_resolve_error_) {
|
||||||
ESP_LOGW(TAG, "Couldn't resolve IP address for '%s'", this->credentials_.address.c_str());
|
ESP_LOGW(TAG, "Couldn't resolve IP address for '%s'", this->credentials_.address.c_str());
|
||||||
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
this->state_ = MQTT_CLIENT_DISCONNECTED;
|
||||||
|
this->disconnect_reason_ = MQTTClientDisconnectReason::DNS_RESOLVE_ERROR;
|
||||||
|
this->on_disconnect_.call(MQTTClientDisconnectReason::DNS_RESOLVE_ERROR);
|
||||||
return;
|
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) {
|
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->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
|
#if ASYNC_TCP_SSL_ENABLED
|
||||||
|
@@ -4,11 +4,12 @@
|
|||||||
|
|
||||||
#ifdef USE_MQTT
|
#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/json/json_util.h"
|
||||||
#include "esphome/components/network/ip_address.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)
|
#if defined(USE_ESP32)
|
||||||
#include "mqtt_backend_esp32.h"
|
#include "mqtt_backend_esp32.h"
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
@@ -267,6 +268,8 @@ class MQTTClientComponent : public Component {
|
|||||||
void set_publish_nan_as_none(bool publish_nan_as_none);
|
void set_publish_nan_as_none(bool publish_nan_as_none);
|
||||||
bool is_publish_nan_as_none() const;
|
bool is_publish_nan_as_none() const;
|
||||||
|
|
||||||
|
void set_wait_for_connection(bool wait_for_connection) { this->wait_for_connection_ = wait_for_connection; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void send_device_info_();
|
void send_device_info_();
|
||||||
|
|
||||||
@@ -332,8 +335,10 @@ class MQTTClientComponent : public Component {
|
|||||||
uint32_t connect_begin_;
|
uint32_t connect_begin_;
|
||||||
uint32_t last_connected_{0};
|
uint32_t last_connected_{0};
|
||||||
optional<MQTTClientDisconnectReason> disconnect_reason_{};
|
optional<MQTTClientDisconnectReason> disconnect_reason_{};
|
||||||
|
CallbackManager<MQTTBackend::on_disconnect_callback_t> on_disconnect_;
|
||||||
|
|
||||||
bool publish_nan_as_none_{false};
|
bool publish_nan_as_none_{false};
|
||||||
|
bool wait_for_connection_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
extern MQTTClientComponent *global_mqtt_client; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
extern MQTTClientComponent *global_mqtt_client; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
#include "nextion.h"
|
#include "nextion.h"
|
||||||
#include "esphome/core/util.h"
|
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/core/application.h"
|
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "esphome/core/util.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace nextion {
|
namespace nextion {
|
||||||
@@ -33,6 +33,7 @@ bool Nextion::send_command_(const std::string &command) {
|
|||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
if (!this->ignore_is_setup_ && !this->command_pacer_.can_send()) {
|
||||||
|
ESP_LOGN(TAG, "Command spacing: delaying command '%s'", command.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // USE_NEXTION_COMMAND_SPACING
|
#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};
|
const uint8_t to_send[3] = {0xFF, 0xFF, 0xFF};
|
||||||
this->write_array(to_send, sizeof(to_send));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,13 +71,13 @@ bool Nextion::check_connect_() {
|
|||||||
}
|
}
|
||||||
this->send_command_("connect");
|
this->send_command_("connect");
|
||||||
|
|
||||||
this->comok_sent_ = millis();
|
this->comok_sent_ = App.get_loop_component_start_time();
|
||||||
this->ignore_is_setup_ = false;
|
this->ignore_is_setup_ = false;
|
||||||
|
|
||||||
return 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;
|
return false;
|
||||||
|
|
||||||
std::string response;
|
std::string response;
|
||||||
@@ -321,15 +318,38 @@ void Nextion::loop() {
|
|||||||
|
|
||||||
if (!this->nextion_reports_is_setup_) {
|
if (!this->nextion_reports_is_setup_) {
|
||||||
if (this->started_ms_ == 0)
|
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");
|
ESP_LOGD(TAG, "Manual ready set");
|
||||||
this->nextion_reports_is_setup_ = true;
|
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) {
|
bool Nextion::remove_from_q_(bool report_empty) {
|
||||||
if (this->nextion_queue_.empty()) {
|
if (this->nextion_queue_.empty()) {
|
||||||
if (report_empty) {
|
if (report_empty) {
|
||||||
@@ -377,12 +397,6 @@ void Nextion::process_nextion_commands_() {
|
|||||||
size_t commands_processed = 0;
|
size_t commands_processed = 0;
|
||||||
#endif // USE_NEXTION_MAX_COMMANDS_PER_LOOP
|
#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;
|
size_t to_process_length = 0;
|
||||||
std::string to_process;
|
std::string to_process;
|
||||||
|
|
||||||
@@ -418,7 +432,7 @@ void Nextion::process_nextion_commands_() {
|
|||||||
case 0x01: // instruction sent by user was successful
|
case 0x01: // instruction sent by user was successful
|
||||||
|
|
||||||
ESP_LOGVV(TAG, "Cmd OK");
|
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_();
|
this->remove_from_q_();
|
||||||
if (!this->is_setup_) {
|
if (!this->is_setup_) {
|
||||||
@@ -430,6 +444,7 @@ void Nextion::process_nextion_commands_() {
|
|||||||
}
|
}
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
this->command_pacer_.mark_sent(); // Here is where we should mark the command as sent
|
||||||
|
ESP_LOGN(TAG, "Command spacing: marked command sent");
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 0x02: // invalid Component ID or name was used
|
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);
|
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) {
|
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++) {
|
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;
|
uint16_t ret = 0;
|
||||||
uint8_t c = 0;
|
uint8_t c = 0;
|
||||||
uint8_t nr_of_ff_bytes = 0;
|
uint8_t nr_of_ff_bytes = 0;
|
||||||
uint64_t start;
|
|
||||||
bool exit_flag = false;
|
bool exit_flag = false;
|
||||||
bool ff_flag = false;
|
bool ff_flag = false;
|
||||||
|
|
||||||
start = millis();
|
const uint32_t start = millis();
|
||||||
|
|
||||||
while ((timeout == 0 && this->available()) || millis() - start <= timeout) {
|
while ((timeout == 0 && this->available()) || millis() - start <= timeout) {
|
||||||
if (!this->available()) {
|
if (!this->available()) {
|
||||||
@@ -1011,7 +1025,7 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
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)) {
|
if (this->send_command_(command)) {
|
||||||
this->add_no_result_to_queue_(variable_name);
|
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,
|
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_))
|
if ((!this->is_setup() && !this->ignore_is_setup_))
|
||||||
@@ -1167,7 +1214,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
ESP_LOGW(TAG, "Queue alloc failed");
|
||||||
@@ -1176,7 +1223,7 @@ void Nextion::add_to_get_queue(NextionComponentBase *component) {
|
|||||||
new (nextion_queue) nextion::NextionQueue();
|
new (nextion_queue) nextion::NextionQueue();
|
||||||
|
|
||||||
nextion_queue->component = component;
|
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());
|
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())
|
if ((!this->is_setup() && !this->ignore_is_setup_) || this->is_sleeping())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ExternalRAMAllocator<nextion::NextionQueue> allocator(ExternalRAMAllocator<nextion::NextionQueue>::ALLOW_FAILURE);
|
RAMAllocator<nextion::NextionQueue> allocator;
|
||||||
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
nextion::NextionQueue *nextion_queue = allocator.allocate(1);
|
||||||
if (nextion_queue == nullptr) {
|
if (nextion_queue == nullptr) {
|
||||||
ESP_LOGW(TAG, "Queue alloc failed");
|
ESP_LOGW(TAG, "Queue alloc failed");
|
||||||
@@ -1208,7 +1255,7 @@ void Nextion::add_addt_command_to_queue(NextionComponentBase *component) {
|
|||||||
new (nextion_queue) nextion::NextionQueue();
|
new (nextion_queue) nextion::NextionQueue();
|
||||||
|
|
||||||
nextion_queue->component = component;
|
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);
|
this->waveform_queue_.push_back(nextion_queue);
|
||||||
if (this->waveform_queue_.size() == 1)
|
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
|
#ifdef USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
size_t max_queue_size_{0};
|
size_t max_queue_size_{0};
|
||||||
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
#endif // USE_NEXTION_MAX_QUEUE_SIZE
|
||||||
|
|
||||||
#ifdef USE_NEXTION_COMMAND_SPACING
|
#ifdef USE_NEXTION_COMMAND_SPACING
|
||||||
NextionCommandPacer command_pacer_{0};
|
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
|
#endif // USE_NEXTION_COMMAND_SPACING
|
||||||
|
|
||||||
std::deque<NextionQueue *> nextion_queue_;
|
std::deque<NextionQueue *> nextion_queue_;
|
||||||
std::deque<NextionQueue *> waveform_queue_;
|
std::deque<NextionQueue *> waveform_queue_;
|
||||||
uint16_t recv_ret_string_(std::string &response, uint32_t timeout, bool recv_flag);
|
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)));
|
__attribute__((format(printf, 3, 4)));
|
||||||
void add_no_result_to_queue_with_command_(const std::string &variable_name, const std::string &command);
|
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, ...)
|
bool add_no_result_to_queue_with_printf_(const std::string &variable_name, const char *format, ...)
|
||||||
__attribute__((format(printf, 3, 4)));
|
__attribute__((format(printf, 3, 4)));
|
||||||
|
|
||||||
|
@@ -25,6 +25,9 @@ class NextionQueue {
|
|||||||
virtual ~NextionQueue() = default;
|
virtual ~NextionQueue() = default;
|
||||||
NextionComponentBase *component;
|
NextionComponentBase *component;
|
||||||
uint32_t queue_time = 0;
|
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 {
|
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_NEXTION_TFT_UPLOAD
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include "esphome/components/network/util.h"
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/util.h"
|
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "esphome/components/network/util.h"
|
#include "esphome/core/util.h"
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
#include <esp_heap_caps.h>
|
#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
|
// Allocate the buffer dynamically
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *buffer = allocator.allocate(4096);
|
uint8_t *buffer = allocator.allocate(4096);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
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);
|
ESP_LOGV(TAG, "Fetch %" PRIu16 " bytes", buffer_size);
|
||||||
uint16_t read_len = 0;
|
uint16_t read_len = 0;
|
||||||
int partial_read_len = 0;
|
int partial_read_len = 0;
|
||||||
const uint32_t start_time = millis();
|
const uint32_t start_time = App.get_loop_component_start_time();
|
||||||
while (read_len < buffer_size && millis() - start_time < 5000) {
|
while (read_len < buffer_size && App.get_loop_component_start_time() - start_time < 5000) {
|
||||||
if (http_client.getStreamPtr()->available() > 0) {
|
if (http_client.getStreamPtr()->available() > 0) {
|
||||||
partial_read_len =
|
partial_read_len =
|
||||||
http_client.getStreamPtr()->readBytes(reinterpret_cast<char *>(buffer) + read_len, buffer_size - 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);
|
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
|
#ifdef USE_ESP8266
|
||||||
WiFiClient *Nextion::get_wifi_client_() {
|
WiFiClient *Nextion::get_wifi_client_() {
|
||||||
if (this->tft_url_.compare(0, 6, "https:") == 0) {
|
if (this->tft_url_.compare(0, 6, "https:") == 0) {
|
||||||
|
@@ -3,14 +3,14 @@
|
|||||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||||
#ifdef USE_ESP_IDF
|
#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_heap_caps.h>
|
||||||
#include <esp_http_client.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 esphome {
|
||||||
namespace nextion {
|
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
|
// Allocate the buffer dynamically
|
||||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
RAMAllocator<uint8_t> allocator;
|
||||||
uint8_t *buffer = allocator.allocate(4096);
|
uint8_t *buffer = allocator.allocate(4096);
|
||||||
if (!buffer) {
|
if (!buffer) {
|
||||||
ESP_LOGE(TAG, "Buffer alloc failed");
|
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);
|
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 nextion
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
|
@@ -76,8 +76,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_WIND_SPEED,
|
DEVICE_CLASS_WIND_SPEED,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
DEVICE_CLASSES = [
|
DEVICE_CLASSES = [
|
||||||
@@ -207,6 +207,9 @@ _NUMBER_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_NUMBER_SCHEMA.add_extra(entity_duplicate_validator("number"))
|
||||||
|
|
||||||
|
|
||||||
def number_schema(
|
def number_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -237,7 +240,7 @@ NUMBER_SCHEMA.add_extra(cv.deprecated_schema_constant("number"))
|
|||||||
async def setup_number_core_(
|
async def setup_number_core_(
|
||||||
var, config, *, min_value: float, max_value: float, step: float
|
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_min_value(min_value))
|
||||||
cg.add(var.traits.set_max_value(max_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_ON_DOWNLOAD_FINISHED = "on_download_finished"
|
||||||
CONF_PLACEHOLDER = "placeholder"
|
CONF_PLACEHOLDER = "placeholder"
|
||||||
|
CONF_UPDATE = "update"
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -167,6 +168,7 @@ SET_URL_SCHEMA = cv.Schema(
|
|||||||
{
|
{
|
||||||
cv.GenerateID(): cv.use_id(OnlineImage),
|
cv.GenerateID(): cv.use_id(OnlineImage),
|
||||||
cv.Required(CONF_URL): cv.templatable(cv.url),
|
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:
|
if CONF_URL in config:
|
||||||
template_ = await cg.templatable(config[CONF_URL], args, cg.std_string)
|
template_ = await cg.templatable(config[CONF_URL], args, cg.std_string)
|
||||||
cg.add(var.set_url(template_))
|
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
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
@@ -201,9 +201,12 @@ template<typename... Ts> class OnlineImageSetUrlAction : public Action<Ts...> {
|
|||||||
public:
|
public:
|
||||||
OnlineImageSetUrlAction(OnlineImage *parent) : parent_(parent) {}
|
OnlineImageSetUrlAction(OnlineImage *parent) : parent_(parent) {}
|
||||||
TEMPLATABLE_VALUE(std::string, url)
|
TEMPLATABLE_VALUE(std::string, url)
|
||||||
|
TEMPLATABLE_VALUE(bool, update)
|
||||||
void play(Ts... x) override {
|
void play(Ts... x) override {
|
||||||
this->parent_->set_url(this->url_.value(x...));
|
this->parent_->set_url(this->url_.value(x...));
|
||||||
this->parent_->update();
|
if (this->update_.value(x...)) {
|
||||||
|
this->parent_->update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -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_PANID", config[CONF_PAN_ID])
|
||||||
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_CHANNEL", config[CONF_CHANNEL])
|
add_idf_sdkconfig_option("CONFIG_OPENTHREAD_NETWORK_CHANNEL", config[CONF_CHANNEL])
|
||||||
add_idf_sdkconfig_option(
|
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):
|
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:
|
if (ext_pan_id := config.get(CONF_EXT_PAN_ID)) is not None:
|
||||||
add_idf_sdkconfig_option(
|
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:
|
if (mesh_local_prefix := config.get(CONF_MESH_LOCAL_PREFIX)) is not None:
|
||||||
add_idf_sdkconfig_option(
|
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:
|
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 CONF_FORCE_DATASET in config:
|
||||||
if config[CONF_FORCE_DATASET]:
|
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_EXT_PAN_ID): cv.hex_int,
|
||||||
cv.Optional(CONF_NETWORK_NAME): cv.string_strict,
|
cv.Optional(CONF_NETWORK_NAME): cv.string_strict,
|
||||||
cv.Optional(CONF_PSKC): cv.hex_int,
|
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
|
// Copy the mdns services to our local instance so that the c_str pointers remain valid for the lifetime of this
|
||||||
// component
|
// component
|
||||||
this->mdns_services_ = this->mdns_->get_services();
|
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_) {
|
for (const auto &service : this->mdns_services_) {
|
||||||
otSrpClientBuffersServiceEntry *entry = otSrpClientBuffersAllocateService(instance);
|
otSrpClientBuffersServiceEntry *entry = otSrpClientBuffersAllocateService(instance);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
@@ -185,11 +185,11 @@ void OpenThreadSrpComponent::setup() {
|
|||||||
if (error != OT_ERROR_NONE) {
|
if (error != OT_ERROR_NONE) {
|
||||||
ESP_LOGW(TAG, "Failed to add service: %s", otThreadErrorToString(error));
|
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);
|
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) {
|
void *OpenThreadSrpComponent::pool_alloc_(size_t size) {
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
# Sourced from https://gist.github.com/agners/0338576e0003318b63ec1ea75adc90f9
|
# Sourced from https://gist.github.com/agners/0338576e0003318b63ec1ea75adc90f9
|
||||||
import binascii
|
import binascii
|
||||||
|
import ipaddress
|
||||||
|
|
||||||
from esphome.const import CONF_CHANNEL
|
from esphome.const import CONF_CHANNEL
|
||||||
|
|
||||||
@@ -37,6 +38,12 @@ def parse_tlv(tlv) -> dict:
|
|||||||
if tag in TLV_TYPES:
|
if tag in TLV_TYPES:
|
||||||
if tag == 3:
|
if tag == 3:
|
||||||
output[TLV_TYPES[tag]] = val.decode("utf-8")
|
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:
|
else:
|
||||||
output[TLV_TYPES[tag]] = int.from_bytes(val)
|
output[TLV_TYPES[tag]] = int.from_bytes(val)
|
||||||
return output
|
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/dma.h>
|
||||||
#include <hardware/irq.h>
|
#include <hardware/irq.h>
|
||||||
#include <hardware/pio.h>
|
#include <hardware/pio.h>
|
||||||
#include <pico/stdlib.h>
|
|
||||||
#include <pico/sem.h>
|
#include <pico/sem.h>
|
||||||
|
#include <pico/stdlib.h>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace rp2040_pio_led_strip {
|
namespace rp2040_pio_led_strip {
|
||||||
@@ -44,7 +44,7 @@ void RP2040PIOLEDStripLightOutput::setup() {
|
|||||||
|
|
||||||
size_t buffer_size = this->get_buffer_size_();
|
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);
|
this->buf_ = allocator.allocate(buffer_size);
|
||||||
if (this->buf_ == nullptr) {
|
if (this->buf_ == nullptr) {
|
||||||
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", buffer_size);
|
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", buffer_size);
|
||||||
|
@@ -17,8 +17,8 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -65,6 +65,9 @@ _SELECT_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_SELECT_SCHEMA.add_extra(entity_duplicate_validator("select"))
|
||||||
|
|
||||||
|
|
||||||
def select_schema(
|
def select_schema(
|
||||||
class_: MockObjClass,
|
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]):
|
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))
|
cg.add(var.traits.set_options(options))
|
||||||
|
|
||||||
|
@@ -101,8 +101,8 @@ from esphome.const import (
|
|||||||
ENTITY_CATEGORY_CONFIG,
|
ENTITY_CATEGORY_CONFIG,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
@@ -318,6 +318,8 @@ _SENSOR_SCHEMA = (
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("sensor"))
|
||||||
|
|
||||||
|
|
||||||
def sensor_schema(
|
def sensor_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
@@ -787,7 +789,7 @@ async def build_filters(config):
|
|||||||
|
|
||||||
|
|
||||||
async def setup_sensor_core_(var, 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:
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||||
cg.add(var.set_device_class(device_class))
|
cg.add(var.set_device_class(device_class))
|
||||||
|
@@ -79,6 +79,7 @@ CONF_SPI_MODE = "spi_mode"
|
|||||||
CONF_FORCE_SW = "force_sw"
|
CONF_FORCE_SW = "force_sw"
|
||||||
CONF_INTERFACE = "interface"
|
CONF_INTERFACE = "interface"
|
||||||
CONF_INTERFACE_INDEX = "interface_index"
|
CONF_INTERFACE_INDEX = "interface_index"
|
||||||
|
CONF_RELEASE_DEVICE = "release_device"
|
||||||
TYPE_SINGLE = "single"
|
TYPE_SINGLE = "single"
|
||||||
TYPE_QUAD = "quad"
|
TYPE_QUAD = "quad"
|
||||||
TYPE_OCTAL = "octal"
|
TYPE_OCTAL = "octal"
|
||||||
@@ -378,6 +379,7 @@ def spi_device_schema(
|
|||||||
cv.Optional(CONF_SPI_MODE, default=default_mode): cv.enum(
|
cv.Optional(CONF_SPI_MODE, default=default_mode): cv.enum(
|
||||||
SPI_MODE_OPTIONS, upper=True
|
SPI_MODE_OPTIONS, upper=True
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_RELEASE_DEVICE): cv.All(cv.boolean, cv.only_with_esp_idf),
|
||||||
}
|
}
|
||||||
if cs_pin_required:
|
if cs_pin_required:
|
||||||
schema[cv.Required(CONF_CS_PIN)] = pins.gpio_output_pin_schema
|
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):
|
async def register_spi_device(var, config):
|
||||||
parent = await cg.get_variable(config[CONF_SPI_ID])
|
parent = await cg.get_variable(config[CONF_SPI_ID])
|
||||||
cg.add(var.set_spi_parent(parent))
|
cg.add(var.set_spi_parent(parent))
|
||||||
if CONF_CS_PIN in config:
|
if cs_pin := config.get(CONF_CS_PIN):
|
||||||
pin = await cg.gpio_pin_expression(config[CONF_CS_PIN])
|
pin = await cg.gpio_pin_expression(cs_pin)
|
||||||
cg.add(var.set_cs_pin(pin))
|
cg.add(var.set_cs_pin(pin))
|
||||||
if CONF_DATA_RATE in config:
|
if data_rate := config.get(CONF_DATA_RATE):
|
||||||
cg.add(var.set_data_rate(config[CONF_DATA_RATE]))
|
cg.add(var.set_data_rate(data_rate))
|
||||||
if CONF_SPI_MODE in config:
|
if spi_mode := config.get(CONF_SPI_MODE):
|
||||||
cg.add(var.set_mode(config[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):
|
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)
|
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,
|
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) {
|
if (this->devices_.count(device) != 0) {
|
||||||
ESP_LOGE(TAG, "Device already registered");
|
ESP_LOGE(TAG, "Device already registered");
|
||||||
return this->devices_[device];
|
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;
|
this->devices_[device] = delegate;
|
||||||
return 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) {}
|
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_);
|
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 {
|
class SPIComponent : public Component {
|
||||||
public:
|
public:
|
||||||
SPIDelegate *register_device(SPIClient *device, SPIMode mode, SPIBitOrder bit_order, uint32_t data_rate,
|
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 unregister_device(SPIClient *device);
|
||||||
|
|
||||||
void set_clk(GPIOPin *clk) { this->clk_pin_ = clk; }
|
void set_clk(GPIOPin *clk) { this->clk_pin_ = clk; }
|
||||||
@@ -390,7 +391,8 @@ class SPIClient {
|
|||||||
|
|
||||||
virtual void spi_setup() {
|
virtual void spi_setup() {
|
||||||
esph_log_d("spi_device", "mode %u, data_rate %ukHz", (unsigned) this->mode_, (unsigned) (this->data_rate_ / 1000));
|
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() {
|
virtual void spi_teardown() {
|
||||||
@@ -399,6 +401,8 @@ class SPIClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool spi_is_ready() { return this->delegate_->is_ready(); }
|
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:
|
protected:
|
||||||
SPIBitOrder bit_order_{BIT_ORDER_MSB_FIRST};
|
SPIBitOrder bit_order_{BIT_ORDER_MSB_FIRST};
|
||||||
@@ -406,6 +410,8 @@ class SPIClient {
|
|||||||
uint32_t data_rate_{1000000};
|
uint32_t data_rate_{1000000};
|
||||||
SPIComponent *parent_{nullptr};
|
SPIComponent *parent_{nullptr};
|
||||||
GPIOPin *cs_{nullptr};
|
GPIOPin *cs_{nullptr};
|
||||||
|
bool release_device_{false};
|
||||||
|
bool write_only_{false};
|
||||||
SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE};
|
SPIDelegate *delegate_{SPIDelegate::NULL_DELEGATE};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -43,10 +43,7 @@ class SPIDelegateHw : public SPIDelegate {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
// avoid overwriting the supplied buffer. Use vector for automatic deallocation
|
this->channel_->transfer(ptr, nullptr, length);
|
||||||
auto rxbuf = std::vector<uint8_t>(length);
|
|
||||||
memcpy(rxbuf.data(), ptr, length);
|
|
||||||
this->channel_->transfer((void *) rxbuf.data(), length);
|
|
||||||
#elif defined(USE_ESP8266)
|
#elif defined(USE_ESP8266)
|
||||||
// ESP8266 SPI library requires the pointer to be word aligned, but the data may not be
|
// 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
|
// so we need to copy the data to a temporary buffer
|
||||||
@@ -89,7 +86,8 @@ class SPIBusHw : public SPIBus {
|
|||||||
#endif
|
#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);
|
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 {
|
class SPIDelegateHw : public SPIDelegate {
|
||||||
public:
|
public:
|
||||||
SPIDelegateHw(SPIInterface channel, uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
SPIDelegateHw(SPIInterface channel, uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||||
bool write_only)
|
bool release_device, bool write_only)
|
||||||
: SPIDelegate(data_rate, bit_order, mode, cs_pin), channel_(channel), write_only_(write_only) {
|
: SPIDelegate(data_rate, bit_order, mode, cs_pin),
|
||||||
spi_device_interface_config_t config = {};
|
channel_(channel),
|
||||||
config.mode = static_cast<uint8_t>(mode);
|
release_device_(release_device),
|
||||||
config.clock_speed_hz = static_cast<int>(data_rate);
|
write_only_(write_only) {
|
||||||
config.spics_io_num = -1;
|
if (!this->release_device_)
|
||||||
config.flags = 0;
|
add_device_();
|
||||||
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 is_ready() override { return this->handle_ != nullptr; }
|
bool is_ready() override { return this->handle_ != nullptr; }
|
||||||
|
|
||||||
void begin_transaction() override {
|
void begin_transaction() override {
|
||||||
|
if (this->release_device_)
|
||||||
|
this->add_device_();
|
||||||
if (this->is_ready()) {
|
if (this->is_ready()) {
|
||||||
if (spi_device_acquire_bus(this->handle_, portMAX_DELAY) != ESP_OK)
|
if (spi_device_acquire_bus(this->handle_, portMAX_DELAY) != ESP_OK)
|
||||||
ESP_LOGE(TAG, "Failed to acquire SPI bus");
|
ESP_LOGE(TAG, "Failed to acquire SPI bus");
|
||||||
SPIDelegate::begin_transaction();
|
SPIDelegate::begin_transaction();
|
||||||
} else {
|
} 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()) {
|
if (this->is_ready()) {
|
||||||
SPIDelegate::end_transaction();
|
SPIDelegate::end_transaction();
|
||||||
spi_device_release_bus(this->handle_);
|
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); }
|
void read_array(uint8_t *ptr, size_t length) override { this->transfer(nullptr, ptr, length); }
|
||||||
|
|
||||||
protected:
|
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_{};
|
SPIInterface channel_{};
|
||||||
spi_device_handle_t handle_{};
|
spi_device_handle_t handle_{};
|
||||||
|
bool release_device_{false};
|
||||||
bool write_only_{false};
|
bool write_only_{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -231,9 +249,10 @@ class SPIBusHw : public SPIBus {
|
|||||||
ESP_LOGE(TAG, "Bus init failed - err %X", err);
|
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 {
|
SPIDelegate *get_delegate(uint32_t data_rate, SPIBitOrder bit_order, SPIMode mode, GPIOPin *cs_pin,
|
||||||
return new SPIDelegateHw(this->channel_, data_rate, bit_order, mode, cs_pin,
|
bool release_device, bool write_only) override {
|
||||||
Utility::get_pin_no(this->sdi_pin_) == -1);
|
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:
|
protected:
|
||||||
|
@@ -5,7 +5,7 @@ namespace spi_led_strip {
|
|||||||
|
|
||||||
SpiLedStrip::SpiLedStrip(uint16_t num_leds) {
|
SpiLedStrip::SpiLedStrip(uint16_t num_leds) {
|
||||||
this->num_leds_ = 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->buffer_size_ = num_leds * 4 + 8;
|
||||||
this->buf_ = allocator.allocate(this->buffer_size_);
|
this->buf_ = allocator.allocate(this->buffer_size_);
|
||||||
if (this->buf_ == nullptr) {
|
if (this->buf_ == nullptr) {
|
||||||
|
@@ -20,8 +20,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_SWITCH,
|
DEVICE_CLASS_SWITCH,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@esphome/core"]
|
CODEOWNERS = ["@esphome/core"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -91,6 +91,9 @@ _SWITCH_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_SWITCH_SCHEMA.add_extra(entity_duplicate_validator("switch"))
|
||||||
|
|
||||||
|
|
||||||
def switch_schema(
|
def switch_schema(
|
||||||
class_: MockObjClass,
|
class_: MockObjClass,
|
||||||
*,
|
*,
|
||||||
@@ -131,7 +134,7 @@ SWITCH_SCHEMA.add_extra(cv.deprecated_schema_constant("switch"))
|
|||||||
|
|
||||||
|
|
||||||
async def setup_switch_core_(var, config):
|
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:
|
if (inverted := config.get(CONF_INVERTED)) is not None:
|
||||||
cg.add(var.set_inverted(inverted))
|
cg.add(var.set_inverted(inverted))
|
||||||
|
@@ -14,8 +14,8 @@ from esphome.const import (
|
|||||||
CONF_WEB_SERVER,
|
CONF_WEB_SERVER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@mauritskorse"]
|
CODEOWNERS = ["@mauritskorse"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -58,6 +58,9 @@ _TEXT_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_TEXT_SCHEMA.add_extra(entity_duplicate_validator("text"))
|
||||||
|
|
||||||
|
|
||||||
def text_schema(
|
def text_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
*,
|
*,
|
||||||
@@ -94,7 +97,7 @@ async def setup_text_core_(
|
|||||||
max_length: int | None,
|
max_length: int | None,
|
||||||
pattern: str | 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_min_length(min_length))
|
||||||
cg.add(var.traits.set_max_length(max_length))
|
cg.add(var.traits.set_max_length(max_length))
|
||||||
|
@@ -21,8 +21,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_TIMESTAMP,
|
DEVICE_CLASS_TIMESTAMP,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
from esphome.util import Registry
|
from esphome.util import Registry
|
||||||
|
|
||||||
DEVICE_CLASSES = [
|
DEVICE_CLASSES = [
|
||||||
@@ -153,6 +153,9 @@ _TEXT_SENSOR_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_TEXT_SENSOR_SCHEMA.add_extra(entity_duplicate_validator("text_sensor"))
|
||||||
|
|
||||||
|
|
||||||
def text_sensor_schema(
|
def text_sensor_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
*,
|
*,
|
||||||
@@ -186,7 +189,7 @@ async def build_filters(config):
|
|||||||
|
|
||||||
|
|
||||||
async def setup_text_sensor_core_(var, 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:
|
if (device_class := config.get(CONF_DEVICE_CLASS)) is not None:
|
||||||
cg.add(var.set_device_class(device_class))
|
cg.add(var.set_device_class(device_class))
|
||||||
|
@@ -15,8 +15,8 @@ from esphome.const import (
|
|||||||
ENTITY_CATEGORY_CONFIG,
|
ENTITY_CATEGORY_CONFIG,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
CODEOWNERS = ["@jesserockz"]
|
CODEOWNERS = ["@jesserockz"]
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
@@ -58,6 +58,9 @@ _UPDATE_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_UPDATE_SCHEMA.add_extra(entity_duplicate_validator("update"))
|
||||||
|
|
||||||
|
|
||||||
def update_schema(
|
def update_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
*,
|
*,
|
||||||
@@ -87,7 +90,7 @@ UPDATE_SCHEMA.add_extra(cv.deprecated_schema_constant("update"))
|
|||||||
|
|
||||||
|
|
||||||
async def setup_update_core_(var, config):
|
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):
|
if device_class_config := config.get(CONF_DEVICE_CLASS):
|
||||||
cg.add(var.set_device_class(device_class_config))
|
cg.add(var.set_device_class(device_class_config))
|
||||||
|
@@ -6,7 +6,7 @@ from esphome.components.esp32 import (
|
|||||||
only_on_variant,
|
only_on_variant,
|
||||||
)
|
)
|
||||||
import esphome.config_validation as cv
|
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
|
from esphome.cpp_types import Component
|
||||||
|
|
||||||
AUTO_LOAD = ["bytebuffer"]
|
AUTO_LOAD = ["bytebuffer"]
|
||||||
@@ -16,9 +16,9 @@ usb_host_ns = cg.esphome_ns.namespace("usb_host")
|
|||||||
USBHost = usb_host_ns.class_("USBHost", Component)
|
USBHost = usb_host_ns.class_("USBHost", Component)
|
||||||
USBClient = usb_host_ns.class_("USBClient", Component)
|
USBClient = usb_host_ns.class_("USBClient", Component)
|
||||||
|
|
||||||
CONF_DEVICES = "devices"
|
|
||||||
CONF_VID = "vid"
|
CONF_VID = "vid"
|
||||||
CONF_PID = "pid"
|
CONF_PID = "pid"
|
||||||
|
CONF_ENABLE_HUBS = "enable_hubs"
|
||||||
|
|
||||||
|
|
||||||
def usb_device_schema(cls=USBClient, vid: int = None, pid: [int] = None) -> cv.Schema:
|
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.COMPONENT_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(USBHost),
|
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()),
|
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):
|
async def to_code(config):
|
||||||
add_idf_sdkconfig_option("CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE", 1024)
|
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])
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
for device in config.get(CONF_DEVICES) or ():
|
for device in config.get(CONF_DEVICES) or ():
|
||||||
|
@@ -22,8 +22,8 @@ from esphome.const import (
|
|||||||
DEVICE_CLASS_WATER,
|
DEVICE_CLASS_WATER,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, coroutine_with_priority
|
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_generator import MockObjClass
|
||||||
from esphome.cpp_helpers import setup_entity
|
|
||||||
|
|
||||||
IS_PLATFORM_COMPONENT = True
|
IS_PLATFORM_COMPONENT = True
|
||||||
|
|
||||||
@@ -103,6 +103,9 @@ _VALVE_SCHEMA = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_VALVE_SCHEMA.add_extra(entity_duplicate_validator("valve"))
|
||||||
|
|
||||||
|
|
||||||
def valve_schema(
|
def valve_schema(
|
||||||
class_: MockObjClass = cv.UNDEFINED,
|
class_: MockObjClass = cv.UNDEFINED,
|
||||||
*,
|
*,
|
||||||
@@ -132,7 +135,7 @@ VALVE_SCHEMA.add_extra(cv.deprecated_schema_constant("valve"))
|
|||||||
|
|
||||||
|
|
||||||
async def _setup_valve_core(var, config):
|
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):
|
if device_class_config := config.get(CONF_DEVICE_CLASS):
|
||||||
cg.add(var.set_device_class(device_class_config))
|
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