1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-30 06:33:51 +00:00

Merge branch 'device_id_state' into integration

This commit is contained in:
J. Nick Koston
2025-07-03 12:17:48 -05:00
36 changed files with 5854 additions and 4646 deletions

View File

@@ -311,6 +311,7 @@ message BinarySensorStateResponse {
// If the binary sensor does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
// ==================== COVER ====================
@@ -360,6 +361,7 @@ message CoverStateResponse {
float position = 3;
float tilt = 4;
CoverOperation current_operation = 5;
uint32 device_id = 6;
}
enum LegacyCoverCommand {
@@ -432,6 +434,7 @@ message FanStateResponse {
FanDirection direction = 5;
int32 speed_level = 6;
string preset_mode = 7;
uint32 device_id = 8;
}
message FanCommandRequest {
option (id) = 31;
@@ -513,6 +516,7 @@ message LightStateResponse {
float cold_white = 12;
float warm_white = 13;
string effect = 9;
uint32 device_id = 14;
}
message LightCommandRequest {
option (id) = 32;
@@ -598,6 +602,7 @@ message SensorStateResponse {
// If the sensor does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
// ==================== SWITCH ====================
@@ -628,6 +633,7 @@ message SwitchStateResponse {
fixed32 key = 1;
bool state = 2;
uint32 device_id = 3;
}
message SwitchCommandRequest {
option (id) = 33;
@@ -669,6 +675,7 @@ message TextSensorStateResponse {
// If the text sensor does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
// ==================== SUBSCRIBE LOGS ====================
@@ -966,6 +973,7 @@ message ClimateStateResponse {
string custom_preset = 13;
float current_humidity = 14;
float target_humidity = 15;
uint32 device_id = 16;
}
message ClimateCommandRequest {
option (id) = 48;
@@ -1039,6 +1047,7 @@ message NumberStateResponse {
// If the number does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
message NumberCommandRequest {
option (id) = 51;
@@ -1080,6 +1089,7 @@ message SelectStateResponse {
// If the select does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
message SelectCommandRequest {
option (id) = 54;
@@ -1120,6 +1130,7 @@ message SirenStateResponse {
fixed32 key = 1;
bool state = 2;
uint32 device_id = 3;
}
message SirenCommandRequest {
option (id) = 57;
@@ -1183,6 +1194,7 @@ message LockStateResponse {
option (no_delay) = true;
fixed32 key = 1;
LockState state = 2;
uint32 device_id = 3;
}
message LockCommandRequest {
option (id) = 60;
@@ -1282,6 +1294,7 @@ message MediaPlayerStateResponse {
MediaPlayerState state = 2;
float volume = 3;
bool muted = 4;
uint32 device_id = 5;
}
message MediaPlayerCommandRequest {
option (id) = 65;
@@ -1822,6 +1835,7 @@ message AlarmControlPanelStateResponse {
option (no_delay) = true;
fixed32 key = 1;
AlarmControlPanelState state = 2;
uint32 device_id = 3;
}
message AlarmControlPanelCommandRequest {
@@ -1871,6 +1885,7 @@ message TextStateResponse {
// If the Text does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
uint32 device_id = 4;
}
message TextCommandRequest {
option (id) = 99;
@@ -1914,6 +1929,7 @@ message DateStateResponse {
uint32 year = 3;
uint32 month = 4;
uint32 day = 5;
uint32 device_id = 6;
}
message DateCommandRequest {
option (id) = 102;
@@ -1958,6 +1974,7 @@ message TimeStateResponse {
uint32 hour = 3;
uint32 minute = 4;
uint32 second = 5;
uint32 device_id = 6;
}
message TimeCommandRequest {
option (id) = 105;
@@ -1999,6 +2016,7 @@ message EventResponse {
fixed32 key = 1;
string event_type = 2;
uint32 device_id = 3;
}
// ==================== VALVE ====================
@@ -2039,6 +2057,7 @@ message ValveStateResponse {
fixed32 key = 1;
float position = 2;
ValveOperation current_operation = 3;
uint32 device_id = 4;
}
message ValveCommandRequest {
@@ -2082,6 +2101,7 @@ message DateTimeStateResponse {
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 2;
fixed32 epoch_seconds = 3;
uint32 device_id = 4;
}
message DateTimeCommandRequest {
option (id) = 114;
@@ -2128,6 +2148,7 @@ message UpdateStateResponse {
string title = 8;
string release_summary = 9;
string release_url = 10;
uint32 device_id = 11;
}
enum UpdateCommand {
UPDATE_COMMAND_NONE = 0;

View File

@@ -90,19 +90,6 @@ APIConnection::~APIConnection() {
#endif
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void APIConnection::log_batch_item_(const DeferredBatch::BatchItem &item) {
// Set log-only mode
this->flags_.log_only_mode = true;
// Call the creator - it will create the message and log it via encode_message_to_buffer
item.creator(item.entity, this, std::numeric_limits<uint16_t>::max(), true, item.message_type);
// Clear log-only mode
this->flags_.log_only_mode = false;
}
#endif
void APIConnection::loop() {
if (this->flags_.next_close) {
// requested a disconnect
@@ -154,15 +141,25 @@ void APIConnection::loop() {
}
}
// Process deferred batch if scheduled
// Process deferred batch if scheduled and timer has expired
if (this->flags_.batch_scheduled && now - this->deferred_batch_.batch_start_time >= this->get_batch_delay_ms_()) {
this->process_batch_();
}
if (!this->list_entities_iterator_.completed()) {
this->list_entities_iterator_.advance();
this->process_iterator_batch_(this->list_entities_iterator_);
} else if (!this->initial_state_iterator_.completed()) {
this->initial_state_iterator_.advance();
this->process_iterator_batch_(this->initial_state_iterator_);
// If we've completed initial states, process any remaining and clear the flag
if (this->initial_state_iterator_.completed()) {
// Process any remaining batched messages immediately
if (!this->deferred_batch_.empty()) {
this->process_batch_();
}
// Now that everything is sent, enable immediate sending for future state changes
this->flags_.should_try_send_immediately = true;
}
}
if (this->flags_.sent_ping) {
@@ -300,8 +297,8 @@ uint16_t APIConnection::encode_message_to_buffer(ProtoMessage &msg, uint16_t mes
#ifdef USE_BINARY_SENSOR
bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary_sensor) {
return this->schedule_message_(binary_sensor, &APIConnection::try_send_binary_sensor_state,
BinarySensorStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(binary_sensor, &APIConnection::try_send_binary_sensor_state,
BinarySensorStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -328,7 +325,7 @@ uint16_t APIConnection::try_send_binary_sensor_info(EntityBase *entity, APIConne
#ifdef USE_COVER
bool APIConnection::send_cover_state(cover::Cover *cover) {
return this->schedule_message_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(cover, &APIConnection::try_send_cover_state, CoverStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_cover_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -389,7 +386,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
#ifdef USE_FAN
bool APIConnection::send_fan_state(fan::Fan *fan) {
return this->schedule_message_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(fan, &APIConnection::try_send_fan_state, FanStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_fan_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -448,7 +445,7 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
#ifdef USE_LIGHT
bool APIConnection::send_light_state(light::LightState *light) {
return this->schedule_message_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(light, &APIConnection::try_send_light_state, LightStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_light_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -540,7 +537,7 @@ void APIConnection::light_command(const LightCommandRequest &msg) {
#ifdef USE_SENSOR
bool APIConnection::send_sensor_state(sensor::Sensor *sensor) {
return this->schedule_message_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(sensor, &APIConnection::try_send_sensor_state, SensorStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -572,7 +569,7 @@ uint16_t APIConnection::try_send_sensor_info(EntityBase *entity, APIConnection *
#ifdef USE_SWITCH
bool APIConnection::send_switch_state(switch_::Switch *a_switch) {
return this->schedule_message_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(a_switch, &APIConnection::try_send_switch_state, SwitchStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_switch_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -609,8 +606,8 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
#ifdef USE_TEXT_SENSOR
bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor) {
return this->schedule_message_(text_sensor, &APIConnection::try_send_text_sensor_state,
TextSensorStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(text_sensor, &APIConnection::try_send_text_sensor_state,
TextSensorStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_text_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -637,7 +634,7 @@ uint16_t APIConnection::try_send_text_sensor_info(EntityBase *entity, APIConnect
#ifdef USE_CLIMATE
bool APIConnection::send_climate_state(climate::Climate *climate) {
return this->schedule_message_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(climate, &APIConnection::try_send_climate_state, ClimateStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_climate_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -737,7 +734,7 @@ void APIConnection::climate_command(const ClimateCommandRequest &msg) {
#ifdef USE_NUMBER
bool APIConnection::send_number_state(number::Number *number) {
return this->schedule_message_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(number, &APIConnection::try_send_number_state, NumberStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_number_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -777,7 +774,7 @@ void APIConnection::number_command(const NumberCommandRequest &msg) {
#ifdef USE_DATETIME_DATE
bool APIConnection::send_date_state(datetime::DateEntity *date) {
return this->schedule_message_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(date, &APIConnection::try_send_date_state, DateStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_date_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -811,7 +808,7 @@ void APIConnection::date_command(const DateCommandRequest &msg) {
#ifdef USE_DATETIME_TIME
bool APIConnection::send_time_state(datetime::TimeEntity *time) {
return this->schedule_message_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(time, &APIConnection::try_send_time_state, TimeStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_time_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -845,8 +842,8 @@ void APIConnection::time_command(const TimeCommandRequest &msg) {
#ifdef USE_DATETIME_DATETIME
bool APIConnection::send_datetime_state(datetime::DateTimeEntity *datetime) {
return this->schedule_message_(datetime, &APIConnection::try_send_datetime_state,
DateTimeStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(datetime, &APIConnection::try_send_datetime_state,
DateTimeStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_datetime_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -881,7 +878,7 @@ void APIConnection::datetime_command(const DateTimeCommandRequest &msg) {
#ifdef USE_TEXT
bool APIConnection::send_text_state(text::Text *text) {
return this->schedule_message_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(text, &APIConnection::try_send_text_state, TextStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_text_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -919,7 +916,7 @@ void APIConnection::text_command(const TextCommandRequest &msg) {
#ifdef USE_SELECT
bool APIConnection::send_select_state(select::Select *select) {
return this->schedule_message_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(select, &APIConnection::try_send_select_state, SelectStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_select_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -974,7 +971,7 @@ void esphome::api::APIConnection::button_command(const ButtonCommandRequest &msg
#ifdef USE_LOCK
bool APIConnection::send_lock_state(lock::Lock *a_lock) {
return this->schedule_message_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(a_lock, &APIConnection::try_send_lock_state, LockStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_lock_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
@@ -1018,7 +1015,7 @@ void APIConnection::lock_command(const LockCommandRequest &msg) {
#ifdef USE_VALVE
bool APIConnection::send_valve_state(valve::Valve *valve) {
return this->schedule_message_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(valve, &APIConnection::try_send_valve_state, ValveStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_valve_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -1058,8 +1055,8 @@ void APIConnection::valve_command(const ValveCommandRequest &msg) {
#ifdef USE_MEDIA_PLAYER
bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
return this->schedule_message_(media_player, &APIConnection::try_send_media_player_state,
MediaPlayerStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(media_player, &APIConnection::try_send_media_player_state,
MediaPlayerStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_media_player_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -1320,8 +1317,8 @@ void APIConnection::voice_assistant_set_configuration(const VoiceAssistantSetCon
#ifdef USE_ALARM_CONTROL_PANEL
bool APIConnection::send_alarm_control_panel_state(alarm_control_panel::AlarmControlPanel *a_alarm_control_panel) {
return this->schedule_message_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state,
AlarmControlPanelStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(a_alarm_control_panel, &APIConnection::try_send_alarm_control_panel_state,
AlarmControlPanelStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_alarm_control_panel_state(EntityBase *entity, APIConnection *conn,
uint32_t remaining_size, bool is_single) {
@@ -1404,7 +1401,7 @@ uint16_t APIConnection::try_send_event_info(EntityBase *entity, APIConnection *c
#ifdef USE_UPDATE
bool APIConnection::send_update_state(update::UpdateEntity *update) {
return this->schedule_message_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE);
return this->send_message_smart_(update, &APIConnection::try_send_update_state, UpdateStateResponse::MESSAGE_TYPE);
}
uint16_t APIConnection::try_send_update_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single) {
@@ -1751,11 +1748,16 @@ void APIConnection::process_batch_() {
if (payload_size > 0 &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, item.message_type)) {
this->deferred_batch_.clear();
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log messages after send attempt for VV debugging
// It's safe to use the buffer for logging at this point regardless of send result
this->log_batch_item_(item);
#endif
this->clear_batch_();
} else if (payload_size == 0) {
// Message too large
ESP_LOGW(TAG, "Message too large to send: type=%u", item.message_type);
this->deferred_batch_.clear();
this->clear_batch_();
}
return;
}
@@ -1864,7 +1866,7 @@ void APIConnection::process_batch_() {
this->schedule_batch_();
} else {
// All items processed
this->deferred_batch_.clear();
this->clear_batch_();
}
}

View File

@@ -18,6 +18,8 @@ namespace api {
// Keepalive timeout in milliseconds
static constexpr uint32_t KEEPALIVE_TIMEOUT_MS = 60000;
// Maximum number of entities to process in a single batch during initial state/info sending
static constexpr size_t MAX_INITIAL_PER_BATCH = 20;
class APIConnection : public APIServerConnection {
public:
@@ -290,12 +292,29 @@ class APIConnection : public APIServerConnection {
// Helper function to fill common entity state fields
static void fill_entity_state_base(esphome::EntityBase *entity, StateResponseProtoMessage &response) {
response.key = entity->get_object_id_hash();
#ifdef USE_DEVICES
response.device_id = entity->get_device_id();
#endif
}
// Non-template helper to encode any ProtoMessage
static uint16_t encode_message_to_buffer(ProtoMessage &msg, uint16_t message_type, APIConnection *conn,
uint32_t remaining_size, bool is_single);
// Helper method to process multiple entities from an iterator in a batch
template<typename Iterator> void process_iterator_batch_(Iterator &iterator) {
size_t initial_size = this->deferred_batch_.size();
while (!iterator.completed() && (this->deferred_batch_.size() - initial_size) < MAX_INITIAL_PER_BATCH) {
iterator.advance();
}
// If the batch is full, process it immediately
// Note: iterator.advance() already calls schedule_batch_() via schedule_message_()
if (this->deferred_batch_.size() >= MAX_INITIAL_PER_BATCH) {
this->process_batch_();
}
}
#ifdef USE_BINARY_SENSOR
static uint16_t try_send_binary_sensor_state(EntityBase *entity, APIConnection *conn, uint32_t remaining_size,
bool is_single);
@@ -582,7 +601,8 @@ class APIConnection : public APIServerConnection {
uint8_t service_call_subscription : 1;
uint8_t next_close : 1;
uint8_t batch_scheduled : 1;
uint8_t batch_first_message : 1; // For batch buffer allocation
uint8_t batch_first_message : 1; // For batch buffer allocation
uint8_t should_try_send_immediately : 1; // True after initial states are sent
#ifdef HAS_PROTO_MESSAGE_DUMP
uint8_t log_only_mode : 1;
#endif
@@ -609,11 +629,50 @@ class APIConnection : public APIServerConnection {
bool schedule_batch_();
void process_batch_();
void clear_batch_() {
this->deferred_batch_.clear();
this->flags_.batch_scheduled = false;
}
#ifdef HAS_PROTO_MESSAGE_DUMP
void log_batch_item_(const DeferredBatch::BatchItem &item);
// Helper to log a proto message from a MessageCreator object
void log_proto_message_(EntityBase *entity, const MessageCreator &creator, uint16_t message_type) {
this->flags_.log_only_mode = true;
creator(entity, this, MAX_PACKET_SIZE, true, message_type);
this->flags_.log_only_mode = false;
}
void log_batch_item_(const DeferredBatch::BatchItem &item) {
// Use the helper to log the message
this->log_proto_message_(item.entity, item.creator, item.message_type);
}
#endif
// Helper method to send a message either immediately or via batching
bool send_message_smart_(EntityBase *entity, MessageCreatorPtr creator, uint16_t message_type) {
// Try to send immediately if:
// 1. We should try to send immediately (should_try_send_immediately = true)
// 2. Batch delay is 0 (user has opted in to immediate sending)
// 3. Buffer has space available
if (this->flags_.should_try_send_immediately && this->get_batch_delay_ms_() == 0 &&
this->helper_->can_write_without_blocking()) {
// Now actually encode and send
if (creator(entity, this, MAX_PACKET_SIZE, true) &&
this->send_buffer(ProtoWriteBuffer{&this->parent_->get_shared_buffer_ref()}, message_type)) {
#ifdef HAS_PROTO_MESSAGE_DUMP
// Log the message in verbose mode
this->log_proto_message_(entity, MessageCreator(creator), message_type);
#endif
return true;
}
// If immediate send failed, fall through to batching
}
// Fall back to scheduled batching
return this->schedule_message_(entity, creator, message_type);
}
// Helper function to schedule a deferred message with known message type
bool schedule_message_(EntityBase *entity, MessageCreator creator, uint16_t message_type) {
this->deferred_batch_.add_item(entity, std::move(creator), message_type);

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,8 @@
// See script/api_protobuf/api_protobuf.py
#pragma once
#include "esphome/core/defines.h"
#include "proto.h"
#include "api_pb2_size.h"
@@ -15,6 +17,7 @@ enum EntityCategory : uint32_t {
ENTITY_CATEGORY_CONFIG = 1,
ENTITY_CATEGORY_DIAGNOSTIC = 2,
};
#ifdef USE_COVER
enum LegacyCoverState : uint32_t {
LEGACY_COVER_STATE_OPEN = 0,
LEGACY_COVER_STATE_CLOSED = 1,
@@ -29,6 +32,8 @@ enum LegacyCoverCommand : uint32_t {
LEGACY_COVER_COMMAND_CLOSE = 1,
LEGACY_COVER_COMMAND_STOP = 2,
};
#endif
#ifdef USE_FAN
enum FanSpeed : uint32_t {
FAN_SPEED_LOW = 0,
FAN_SPEED_MEDIUM = 1,
@@ -38,6 +43,8 @@ enum FanDirection : uint32_t {
FAN_DIRECTION_FORWARD = 0,
FAN_DIRECTION_REVERSE = 1,
};
#endif
#ifdef USE_LIGHT
enum ColorMode : uint32_t {
COLOR_MODE_UNKNOWN = 0,
COLOR_MODE_ON_OFF = 1,
@@ -51,6 +58,8 @@ enum ColorMode : uint32_t {
COLOR_MODE_RGB_COLOR_TEMPERATURE = 47,
COLOR_MODE_RGB_COLD_WARM_WHITE = 51,
};
#endif
#ifdef USE_SENSOR
enum SensorStateClass : uint32_t {
STATE_CLASS_NONE = 0,
STATE_CLASS_MEASUREMENT = 1,
@@ -62,6 +71,7 @@ enum SensorLastResetType : uint32_t {
LAST_RESET_NEVER = 1,
LAST_RESET_AUTO = 2,
};
#endif
enum LogLevel : uint32_t {
LOG_LEVEL_NONE = 0,
LOG_LEVEL_ERROR = 1,
@@ -82,6 +92,7 @@ enum ServiceArgType : uint32_t {
SERVICE_ARG_TYPE_FLOAT_ARRAY = 6,
SERVICE_ARG_TYPE_STRING_ARRAY = 7,
};
#ifdef USE_CLIMATE
enum ClimateMode : uint32_t {
CLIMATE_MODE_OFF = 0,
CLIMATE_MODE_HEAT_COOL = 1,
@@ -127,11 +138,15 @@ enum ClimatePreset : uint32_t {
CLIMATE_PRESET_SLEEP = 6,
CLIMATE_PRESET_ACTIVITY = 7,
};
#endif
#ifdef USE_NUMBER
enum NumberMode : uint32_t {
NUMBER_MODE_AUTO = 0,
NUMBER_MODE_BOX = 1,
NUMBER_MODE_SLIDER = 2,
};
#endif
#ifdef USE_LOCK
enum LockState : uint32_t {
LOCK_STATE_NONE = 0,
LOCK_STATE_LOCKED = 1,
@@ -145,6 +160,8 @@ enum LockCommand : uint32_t {
LOCK_LOCK = 1,
LOCK_OPEN = 2,
};
#endif
#ifdef USE_MEDIA_PLAYER
enum MediaPlayerState : uint32_t {
MEDIA_PLAYER_STATE_NONE = 0,
MEDIA_PLAYER_STATE_IDLE = 1,
@@ -162,6 +179,8 @@ enum MediaPlayerFormatPurpose : uint32_t {
MEDIA_PLAYER_FORMAT_PURPOSE_DEFAULT = 0,
MEDIA_PLAYER_FORMAT_PURPOSE_ANNOUNCEMENT = 1,
};
#endif
#ifdef USE_BLUETOOTH_PROXY
enum BluetoothDeviceRequestType : uint32_t {
BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0,
BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1,
@@ -183,6 +202,7 @@ enum BluetoothScannerMode : uint32_t {
BLUETOOTH_SCANNER_MODE_PASSIVE = 0,
BLUETOOTH_SCANNER_MODE_ACTIVE = 1,
};
#endif
enum VoiceAssistantSubscribeFlag : uint32_t {
VOICE_ASSISTANT_SUBSCRIBE_NONE = 0,
VOICE_ASSISTANT_SUBSCRIBE_API_AUDIO = 1,
@@ -192,6 +212,7 @@ enum VoiceAssistantRequestFlag : uint32_t {
VOICE_ASSISTANT_REQUEST_USE_VAD = 1,
VOICE_ASSISTANT_REQUEST_USE_WAKE_WORD = 2,
};
#ifdef USE_VOICE_ASSISTANT
enum VoiceAssistantEvent : uint32_t {
VOICE_ASSISTANT_ERROR = 0,
VOICE_ASSISTANT_RUN_START = 1,
@@ -216,6 +237,8 @@ enum VoiceAssistantTimerEvent : uint32_t {
VOICE_ASSISTANT_TIMER_CANCELLED = 2,
VOICE_ASSISTANT_TIMER_FINISHED = 3,
};
#endif
#ifdef USE_ALARM_CONTROL_PANEL
enum AlarmControlPanelState : uint32_t {
ALARM_STATE_DISARMED = 0,
ALARM_STATE_ARMED_HOME = 1,
@@ -237,20 +260,27 @@ enum AlarmControlPanelStateCommand : uint32_t {
ALARM_CONTROL_PANEL_ARM_CUSTOM_BYPASS = 5,
ALARM_CONTROL_PANEL_TRIGGER = 6,
};
#endif
#ifdef USE_TEXT
enum TextMode : uint32_t {
TEXT_MODE_TEXT = 0,
TEXT_MODE_PASSWORD = 1,
};
#endif
#ifdef USE_VALVE
enum ValveOperation : uint32_t {
VALVE_OPERATION_IDLE = 0,
VALVE_OPERATION_IS_OPENING = 1,
VALVE_OPERATION_IS_CLOSING = 2,
};
#endif
#ifdef USE_UPDATE
enum UpdateCommand : uint32_t {
UPDATE_COMMAND_NONE = 0,
UPDATE_COMMAND_UPDATE = 1,
UPDATE_COMMAND_CHECK = 2,
};
#endif
} // namespace enums
@@ -273,6 +303,7 @@ class StateResponseProtoMessage : public ProtoMessage {
public:
~StateResponseProtoMessage() override = default;
uint32_t key{0};
uint32_t device_id{0};
protected:
};
@@ -523,6 +554,7 @@ class SubscribeStatesRequest : public ProtoMessage {
protected:
};
#ifdef USE_BINARY_SENSOR
class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 12;
@@ -546,7 +578,7 @@ class ListEntitiesBinarySensorResponse : public InfoResponseProtoMessage {
class BinarySensorStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 21;
static constexpr uint16_t ESTIMATED_SIZE = 9;
static constexpr uint16_t ESTIMATED_SIZE = 13;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "binary_sensor_state_response"; }
#endif
@@ -562,6 +594,8 @@ class BinarySensorStateResponse : public StateResponseProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_COVER
class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 13;
@@ -588,7 +622,7 @@ class ListEntitiesCoverResponse : public InfoResponseProtoMessage {
class CoverStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 22;
static constexpr uint16_t ESTIMATED_SIZE = 19;
static constexpr uint16_t ESTIMATED_SIZE = 23;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "cover_state_response"; }
#endif
@@ -631,6 +665,8 @@ class CoverCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_FAN
class ListEntitiesFanResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 14;
@@ -657,7 +693,7 @@ class ListEntitiesFanResponse : public InfoResponseProtoMessage {
class FanStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 23;
static constexpr uint16_t ESTIMATED_SIZE = 26;
static constexpr uint16_t ESTIMATED_SIZE = 30;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "fan_state_response"; }
#endif
@@ -709,6 +745,8 @@ class FanCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_LIGHT
class ListEntitiesLightResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 15;
@@ -738,7 +776,7 @@ class ListEntitiesLightResponse : public InfoResponseProtoMessage {
class LightStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 24;
static constexpr uint16_t ESTIMATED_SIZE = 63;
static constexpr uint16_t ESTIMATED_SIZE = 67;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "light_state_response"; }
#endif
@@ -810,6 +848,8 @@ class LightCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_SENSOR
class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 16;
@@ -837,7 +877,7 @@ class ListEntitiesSensorResponse : public InfoResponseProtoMessage {
class SensorStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 25;
static constexpr uint16_t ESTIMATED_SIZE = 12;
static constexpr uint16_t ESTIMATED_SIZE = 16;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "sensor_state_response"; }
#endif
@@ -853,6 +893,8 @@ class SensorStateResponse : public StateResponseProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_SWITCH
class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 17;
@@ -876,7 +918,7 @@ class ListEntitiesSwitchResponse : public InfoResponseProtoMessage {
class SwitchStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 26;
static constexpr uint16_t ESTIMATED_SIZE = 7;
static constexpr uint16_t ESTIMATED_SIZE = 11;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "switch_state_response"; }
#endif
@@ -910,6 +952,8 @@ class SwitchCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_TEXT_SENSOR
class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 18;
@@ -932,7 +976,7 @@ class ListEntitiesTextSensorResponse : public InfoResponseProtoMessage {
class TextSensorStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 27;
static constexpr uint16_t ESTIMATED_SIZE = 16;
static constexpr uint16_t ESTIMATED_SIZE = 20;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "text_sensor_state_response"; }
#endif
@@ -949,6 +993,7 @@ class TextSensorStateResponse : public StateResponseProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
class SubscribeLogsRequest : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 28;
@@ -987,6 +1032,7 @@ class SubscribeLogsResponse : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#ifdef USE_API_NOISE
class NoiseEncryptionSetKeyRequest : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 124;
@@ -1021,6 +1067,7 @@ class NoiseEncryptionSetKeyResponse : public ProtoMessage {
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
class SubscribeHomeassistantServicesRequest : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 34;
@@ -1226,6 +1273,7 @@ class ExecuteServiceRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
#ifdef USE_ESP32_CAMERA
class ListEntitiesCameraResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 43;
@@ -1283,6 +1331,8 @@ class CameraImageRequest : public ProtoMessage {
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_CLIMATE
class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 46;
@@ -1322,7 +1372,7 @@ class ListEntitiesClimateResponse : public InfoResponseProtoMessage {
class ClimateStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 47;
static constexpr uint16_t ESTIMATED_SIZE = 65;
static constexpr uint16_t ESTIMATED_SIZE = 70;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "climate_state_response"; }
#endif
@@ -1392,6 +1442,8 @@ class ClimateCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_NUMBER
class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 49;
@@ -1419,7 +1471,7 @@ class ListEntitiesNumberResponse : public InfoResponseProtoMessage {
class NumberStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 50;
static constexpr uint16_t ESTIMATED_SIZE = 12;
static constexpr uint16_t ESTIMATED_SIZE = 16;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "number_state_response"; }
#endif
@@ -1453,6 +1505,8 @@ class NumberCommandRequest : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
};
#endif
#ifdef USE_SELECT
class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 52;
@@ -1475,7 +1529,7 @@ class ListEntitiesSelectResponse : public InfoResponseProtoMessage {
class SelectStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 53;
static constexpr uint16_t ESTIMATED_SIZE = 16;
static constexpr uint16_t ESTIMATED_SIZE = 20;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "select_state_response"; }
#endif
@@ -1511,6 +1565,8 @@ class SelectCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
#endif
#ifdef USE_SIREN
class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 55;
@@ -1535,7 +1591,7 @@ class ListEntitiesSirenResponse : public InfoResponseProtoMessage {
class SirenStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 56;
static constexpr uint16_t ESTIMATED_SIZE = 7;
static constexpr uint16_t ESTIMATED_SIZE = 11;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "siren_state_response"; }
#endif
@@ -1577,6 +1633,8 @@ class SirenCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_LOCK
class ListEntitiesLockResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 58;
@@ -1602,7 +1660,7 @@ class ListEntitiesLockResponse : public InfoResponseProtoMessage {
class LockStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 59;
static constexpr uint16_t ESTIMATED_SIZE = 7;
static constexpr uint16_t ESTIMATED_SIZE = 11;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "lock_state_response"; }
#endif
@@ -1639,6 +1697,8 @@ class LockCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_BUTTON
class ListEntitiesButtonResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 61;
@@ -1675,6 +1735,8 @@ class ButtonCommandRequest : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
};
#endif
#ifdef USE_MEDIA_PLAYER
class MediaPlayerSupportedFormat : public ProtoMessage {
public:
std::string format{};
@@ -1715,7 +1777,7 @@ class ListEntitiesMediaPlayerResponse : public InfoResponseProtoMessage {
class MediaPlayerStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 64;
static constexpr uint16_t ESTIMATED_SIZE = 14;
static constexpr uint16_t ESTIMATED_SIZE = 18;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "media_player_state_response"; }
#endif
@@ -1759,6 +1821,8 @@ class MediaPlayerCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_BLUETOOTH_PROXY
class SubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 66;
@@ -2313,6 +2377,8 @@ class BluetoothScannerSetModeRequest : public ProtoMessage {
protected:
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_VOICE_ASSISTANT
class SubscribeVoiceAssistantRequest : public ProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 89;
@@ -2562,6 +2628,8 @@ class VoiceAssistantSetConfiguration : public ProtoMessage {
protected:
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
#endif
#ifdef USE_ALARM_CONTROL_PANEL
class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 94;
@@ -2586,7 +2654,7 @@ class ListEntitiesAlarmControlPanelResponse : public InfoResponseProtoMessage {
class AlarmControlPanelStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 95;
static constexpr uint16_t ESTIMATED_SIZE = 7;
static constexpr uint16_t ESTIMATED_SIZE = 11;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "alarm_control_panel_state_response"; }
#endif
@@ -2622,6 +2690,8 @@ class AlarmControlPanelCommandRequest : public ProtoMessage {
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_TEXT
class ListEntitiesTextResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 97;
@@ -2647,7 +2717,7 @@ class ListEntitiesTextResponse : public InfoResponseProtoMessage {
class TextStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 98;
static constexpr uint16_t ESTIMATED_SIZE = 16;
static constexpr uint16_t ESTIMATED_SIZE = 20;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "text_state_response"; }
#endif
@@ -2683,6 +2753,8 @@ class TextCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
};
#endif
#ifdef USE_DATETIME_DATE
class ListEntitiesDateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 100;
@@ -2704,7 +2776,7 @@ class ListEntitiesDateResponse : public InfoResponseProtoMessage {
class DateStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 101;
static constexpr uint16_t ESTIMATED_SIZE = 19;
static constexpr uint16_t ESTIMATED_SIZE = 23;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "date_state_response"; }
#endif
@@ -2743,6 +2815,8 @@ class DateCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_DATETIME_TIME
class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 103;
@@ -2764,7 +2838,7 @@ class ListEntitiesTimeResponse : public InfoResponseProtoMessage {
class TimeStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 104;
static constexpr uint16_t ESTIMATED_SIZE = 19;
static constexpr uint16_t ESTIMATED_SIZE = 23;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "time_state_response"; }
#endif
@@ -2803,6 +2877,8 @@ class TimeCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_EVENT
class ListEntitiesEventResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 107;
@@ -2826,7 +2902,7 @@ class ListEntitiesEventResponse : public InfoResponseProtoMessage {
class EventResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 108;
static constexpr uint16_t ESTIMATED_SIZE = 14;
static constexpr uint16_t ESTIMATED_SIZE = 18;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "event_response"; }
#endif
@@ -2840,7 +2916,10 @@ class EventResponse : public StateResponseProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_VALVE
class ListEntitiesValveResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 109;
@@ -2866,7 +2945,7 @@ class ListEntitiesValveResponse : public InfoResponseProtoMessage {
class ValveStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 110;
static constexpr uint16_t ESTIMATED_SIZE = 12;
static constexpr uint16_t ESTIMATED_SIZE = 16;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "valve_state_response"; }
#endif
@@ -2903,6 +2982,8 @@ class ValveCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
#ifdef USE_DATETIME_DATETIME
class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 112;
@@ -2924,7 +3005,7 @@ class ListEntitiesDateTimeResponse : public InfoResponseProtoMessage {
class DateTimeStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 113;
static constexpr uint16_t ESTIMATED_SIZE = 12;
static constexpr uint16_t ESTIMATED_SIZE = 16;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "date_time_state_response"; }
#endif
@@ -2958,6 +3039,8 @@ class DateTimeCommandRequest : public ProtoMessage {
protected:
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
};
#endif
#ifdef USE_UPDATE
class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 116;
@@ -2980,7 +3063,7 @@ class ListEntitiesUpdateResponse : public InfoResponseProtoMessage {
class UpdateStateResponse : public StateResponseProtoMessage {
public:
static constexpr uint16_t MESSAGE_TYPE = 117;
static constexpr uint16_t ESTIMATED_SIZE = 61;
static constexpr uint16_t ESTIMATED_SIZE = 65;
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "update_state_response"; }
#endif
@@ -3023,6 +3106,7 @@ class UpdateCommandRequest : public ProtoMessage {
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
};
#endif
} // namespace api
} // namespace esphome

File diff suppressed because it is too large Load Diff

View File

@@ -2,9 +2,10 @@
// See script/api_protobuf/api_protobuf.py
#pragma once
#include "api_pb2.h"
#include "esphome/core/defines.h"
#include "api_pb2.h"
namespace esphome {
namespace api {

View File

@@ -0,0 +1 @@
CODEOWNERS = ["@mrk-its"]

View File

@@ -0,0 +1,209 @@
#include "ds2484.h"
namespace esphome {
namespace ds2484 {
static const char *const TAG = "ds2484.onewire";
void DS2484OneWireBus::setup() {
ESP_LOGCONFIG(TAG, "Running setup");
this->reset_device();
this->search();
}
void DS2484OneWireBus::dump_config() {
ESP_LOGCONFIG(TAG, "1-wire bus:");
this->dump_devices_(TAG);
}
bool DS2484OneWireBus::read_status_(uint8_t *status) {
for (uint8_t retry_nr = 0; retry_nr < 10; retry_nr++) {
if (this->read(status, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "read status error");
return false;
}
ESP_LOGVV(TAG, "status: %02x", *status);
if (!(*status & 1)) {
return true;
}
}
ESP_LOGE(TAG, "read status error: too many retries");
return false;
}
bool DS2484OneWireBus::wait_for_completion_() {
uint8_t status;
return this->read_status_(&status);
}
bool DS2484OneWireBus::reset_device() {
ESP_LOGVV(TAG, "reset_device");
uint8_t device_reset_cmd = 0xf0;
uint8_t response;
if (this->write(&device_reset_cmd, 1) != i2c::ERROR_OK) {
return false;
}
if (!this->wait_for_completion_()) {
ESP_LOGE(TAG, "reset_device: can't complete");
return false;
}
uint8_t config = (this->active_pullup_ ? 1 : 0) | (this->strong_pullup_ ? 4 : 0);
uint8_t write_config[2] = {0xd2, (uint8_t) (config | (~config << 4))};
if (this->write(write_config, 2) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "reset_device: can't write config");
return false;
}
if (this->read(&response, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "can't read read8 response");
return false;
}
if (response != (write_config[1] & 0xf)) {
ESP_LOGE(TAG, "configuration didn't update");
return false;
}
return true;
};
int DS2484OneWireBus::reset_int() {
ESP_LOGVV(TAG, "reset");
uint8_t reset_cmd = 0xb4;
if (this->write(&reset_cmd, 1) != i2c::ERROR_OK) {
return -1;
}
return this->wait_for_completion_() ? 1 : 0;
};
void DS2484OneWireBus::write8_(uint8_t value) {
uint8_t buffer[2] = {0xa5, value};
this->write(buffer, 2);
this->wait_for_completion_();
};
void DS2484OneWireBus::write8(uint8_t value) {
ESP_LOGVV(TAG, "write8: %02x", value);
this->write8_(value);
};
void DS2484OneWireBus::write64(uint64_t value) {
ESP_LOGVV(TAG, "write64: %llx", value);
for (uint8_t i = 0; i < 8; i++) {
this->write8_((value >> (i * 8)) & 0xff);
}
}
uint8_t DS2484OneWireBus::read8() {
uint8_t read8_cmd = 0x96;
uint8_t set_read_reg_cmd[2] = {0xe1, 0xe1};
uint8_t response = 0;
if (this->write(&read8_cmd, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "can't write read8 cmd");
return 0;
}
this->wait_for_completion_();
if (this->write(set_read_reg_cmd, 2) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "can't set read data reg");
return 0;
}
if (this->read(&response, 1) != i2c::ERROR_OK) {
ESP_LOGE(TAG, "can't read read8 response");
return 0;
}
return response;
}
uint64_t DS2484OneWireBus::read64() {
uint8_t response = 0;
for (uint8_t i = 0; i < 8; i++) {
response |= (this->read8() << (i * 8));
}
return response;
}
void DS2484OneWireBus::reset_search() {
this->last_discrepancy_ = 0;
this->last_device_flag_ = false;
this->address_ = 0;
}
bool DS2484OneWireBus::one_wire_triple_(bool *branch, bool *id_bit, bool *cmp_id_bit) {
uint8_t buffer[2] = {(uint8_t) 0x78, (uint8_t) (*branch ? 0x80u : 0)};
uint8_t status;
if (!this->read_status_(&status)) {
ESP_LOGE(TAG, "one_wire_triple start: read status error");
return false;
}
if (this->write(buffer, 2) != i2c::ERROR_OK) {
ESP_LOGV(TAG, "one_wire_triple: can't write cmd");
return false;
}
if (!this->read_status_(&status)) {
ESP_LOGE(TAG, "one_wire_triple: read status error");
return false;
}
*id_bit = bool(status & 0x20);
*cmp_id_bit = bool(status & 0x40);
*branch = bool(status & 0x80);
return true;
}
uint64_t IRAM_ATTR DS2484OneWireBus::search_int() {
ESP_LOGVV(TAG, "search_int");
if (this->last_device_flag_) {
ESP_LOGVV(TAG, "last device flag set, quitting");
return 0u;
}
uint8_t last_zero = 0;
uint64_t bit_mask = 1;
uint64_t address = this->address_;
// Initiate search
for (uint8_t bit_number = 1; bit_number <= 64; bit_number++, bit_mask <<= 1) {
bool branch;
// compute branch value for the case when there is a discrepancy
// (there are devices with both 0s and 1s at this bit)
if (bit_number < this->last_discrepancy_) {
branch = (address & bit_mask) > 0;
} else {
branch = bit_number == this->last_discrepancy_;
}
bool id_bit, cmp_id_bit;
bool branch_before = branch;
if (!this->one_wire_triple_(&branch, &id_bit, &cmp_id_bit)) {
ESP_LOGW(TAG, "one wire triple error, quitting");
return 0;
}
if (id_bit && cmp_id_bit) {
ESP_LOGW(TAG, "no devices on the bus, quitting");
// No devices participating in search
return 0;
}
if (!id_bit && !cmp_id_bit && !branch) {
last_zero = bit_number;
}
ESP_LOGVV(TAG, "%d %d branch: %d %d", id_bit, cmp_id_bit, branch_before, branch);
if (branch) {
address |= bit_mask;
} else {
address &= ~bit_mask;
}
}
ESP_LOGVV(TAG, "last_discepancy: %d", last_zero);
ESP_LOGVV(TAG, "address: %llx", address);
this->last_discrepancy_ = last_zero;
if (this->last_discrepancy_ == 0) {
// we're at root and have no choices left, so this was the last one.
this->last_device_flag_ = true;
}
this->address_ = address;
return address;
}
} // namespace ds2484
} // namespace esphome

View File

@@ -0,0 +1,43 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/core/preferences.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/one_wire/one_wire.h"
namespace esphome {
namespace ds2484 {
class DS2484OneWireBus : public one_wire::OneWireBus, public i2c::I2CDevice, public Component {
public:
void setup() override;
void dump_config() override;
float get_setup_priority() const override { return setup_priority::BUS - 1.0; }
bool reset_device();
int reset_int() override;
void write8(uint8_t) override;
void write64(uint64_t) override;
uint8_t read8() override;
uint64_t read64() override;
void set_active_pullup(bool value) { this->active_pullup_ = value; }
void set_strong_pullup(bool value) { this->strong_pullup_ = value; }
protected:
void reset_search() override;
uint64_t search_int() override;
bool read_status_(uint8_t *);
bool wait_for_completion_();
void write8_(uint8_t);
bool one_wire_triple_(bool *branch, bool *id_bit, bool *cmp_id_bit);
uint64_t address_;
uint8_t last_discrepancy_{0};
bool last_device_flag_{false};
bool active_pullup_{false};
bool strong_pullup_{false};
};
} // namespace ds2484
} // namespace esphome

View File

@@ -0,0 +1,37 @@
import esphome.codegen as cg
from esphome.components import i2c
from esphome.components.one_wire import OneWireBus
import esphome.config_validation as cv
from esphome.const import CONF_ID
ds2484_ns = cg.esphome_ns.namespace("ds2484")
CONF_ACTIVE_PULLUP = "active_pullup"
CONF_STRONG_PULLUP = "strong_pullup"
CODEOWNERS = ["@mrk-its"]
DEPENDENCIES = ["i2c"]
DS2484OneWireBus = ds2484_ns.class_(
"DS2484OneWireBus", OneWireBus, i2c.I2CDevice, cg.Component
)
CONFIG_SCHEMA = (
cv.Schema(
{
cv.GenerateID(): cv.declare_id(DS2484OneWireBus),
cv.Optional(CONF_ACTIVE_PULLUP, default=False): cv.boolean,
cv.Optional(CONF_STRONG_PULLUP, default=False): cv.boolean,
}
)
.extend(cv.COMPONENT_SCHEMA)
.extend(i2c.i2c_device_schema(0x18))
)
async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
await i2c.register_i2c_device(var, config)
await cg.register_component(var, config)
cg.add(var.set_active_pullup(config[CONF_ACTIVE_PULLUP]))
cg.add(var.set_strong_pullup(config[CONF_STRONG_PULLUP]))

View File

@@ -63,6 +63,7 @@ BASE_SCHEMA = cv.All(
cv.Schema(
{
cv.Required(CONF_URL): cv.url,
cv.Optional(CONF_PATH): cv.string,
cv.Optional(CONF_USERNAME): cv.string,
cv.Optional(CONF_PASSWORD): cv.string,
cv.Exclusive(CONF_FILE, CONF_FILES): validate_yaml_filename,
@@ -116,6 +117,9 @@ def _process_base_package(config: dict) -> dict:
)
files = []
if base_path := config.get(CONF_PATH):
repo_dir = repo_dir / base_path
for file in config[CONF_FILES]:
if isinstance(file, str):
files.append({CONF_PATH: file, CONF_VARS: {}})

View File

@@ -1,19 +1,76 @@
import esphome.codegen as cg
from esphome.components import binary_sensor
from esphome.const import CONF_ID
import esphome.config_validation as cv
from esphome.const import (
CONF_DATA,
CONF_ID,
CONF_NAME,
CONF_STATUS,
CONF_TYPE,
DEVICE_CLASS_CONNECTIVITY,
ENTITY_CATEGORY_DIAGNOSTIC,
)
import esphome.final_validate as fv
from . import (
CONF_ENCRYPTION,
CONF_PING_PONG_ENABLE,
CONF_PROVIDER,
CONF_PROVIDERS,
CONF_REMOTE_ID,
CONF_TRANSPORT_ID,
PacketTransport,
packet_transport_sensor_schema,
provider_name_validate,
)
CONFIG_SCHEMA = packet_transport_sensor_schema(binary_sensor.binary_sensor_schema())
STATUS_SENSOR_SCHEMA = binary_sensor.binary_sensor_schema(
device_class=DEVICE_CLASS_CONNECTIVITY,
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
).extend(
{
cv.GenerateID(CONF_TRANSPORT_ID): cv.use_id(PacketTransport),
cv.Required(CONF_PROVIDER): provider_name_validate,
}
)
CONFIG_SCHEMA = cv.typed_schema(
{
CONF_DATA: packet_transport_sensor_schema(binary_sensor.binary_sensor_schema()),
CONF_STATUS: STATUS_SENSOR_SCHEMA,
},
key=CONF_TYPE,
default_type=CONF_DATA,
)
def _final_validate(config):
if config[CONF_TYPE] != CONF_STATUS:
# Only run this validation if a status sensor is being configured
return config
full_config = fv.full_config.get()
transport_path = full_config.get_path_for_id(config[CONF_TRANSPORT_ID])[:-1]
transport_config = full_config.get_config_for_path(transport_path)
if transport_config[CONF_PING_PONG_ENABLE] and any(
CONF_ENCRYPTION in p
for p in transport_config[CONF_PROVIDERS]
if p[CONF_NAME] == config[CONF_PROVIDER]
):
return config
raise cv.Invalid(
"Status sensor requires ping-pong to be enabled and the nominated provider to use encryption."
)
FINAL_VALIDATE_SCHEMA = _final_validate
async def to_code(config):
var = await binary_sensor.new_binary_sensor(config)
comp = await cg.get_variable(config[CONF_TRANSPORT_ID])
remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID))
cg.add(comp.add_remote_binary_sensor(config[CONF_PROVIDER], remote_id, var))
if config[CONF_TYPE] == CONF_STATUS:
cg.add(comp.set_provider_status_sensor(config[CONF_PROVIDER], var))
cg.add_define("USE_STATUS_SENSOR")
else: # CONF_DATA is default
remote_id = str(config.get(CONF_REMOTE_ID) or config.get(CONF_ID))
cg.add(comp.add_remote_binary_sensor(config[CONF_PROVIDER], remote_id, var))

View File

@@ -317,8 +317,37 @@ void PacketTransport::update() {
auto now = millis() / 1000;
if (this->last_key_time_ + this->ping_pong_recyle_time_ < now) {
this->resend_ping_key_ = this->ping_pong_enable_;
ESP_LOGV(TAG, "Ping request, age %u", now - this->last_key_time_);
this->last_key_time_ = now;
}
for (const auto &provider : this->providers_) {
uint32_t key_response_age = now - provider.second.last_key_response_time;
if (key_response_age > (this->ping_pong_recyle_time_ * 2u)) {
#ifdef USE_STATUS_SENSOR
if (provider.second.status_sensor != nullptr && provider.second.status_sensor->state) {
ESP_LOGI(TAG, "Ping status for %s timeout at %u with age %u", provider.first.c_str(), now, key_response_age);
provider.second.status_sensor->publish_state(false);
}
#endif
#ifdef USE_SENSOR
for (auto &sensor : this->remote_sensors_[provider.first]) {
sensor.second->publish_state(NAN);
}
#endif
#ifdef USE_BINARY_SENSOR
for (auto &sensor : this->remote_binary_sensors_[provider.first]) {
sensor.second->invalidate_state();
}
#endif
} else {
#ifdef USE_STATUS_SENSOR
if (provider.second.status_sensor != nullptr && !provider.second.status_sensor->state) {
ESP_LOGI(TAG, "Ping status for %s restored at %u with age %u", provider.first.c_str(), now, key_response_age);
provider.second.status_sensor->publish_state(true);
}
#endif
}
}
}
void PacketTransport::add_key_(const char *name, uint32_t key) {
@@ -437,7 +466,8 @@ void PacketTransport::process_(const std::vector<uint8_t> &data) {
if (decoder.decode(PING_KEY, key) == DECODE_OK) {
if (key == this->ping_key_) {
ping_key_seen = true;
ESP_LOGV(TAG, "Found good ping key %X", (unsigned) key);
provider.last_key_response_time = millis() / 1000;
ESP_LOGV(TAG, "Found good ping key %X at timestamp %" PRIu32, (unsigned) key, provider.last_key_response_time);
} else {
ESP_LOGV(TAG, "Unknown ping key %X", (unsigned) key);
}

View File

@@ -8,7 +8,7 @@
#ifdef USE_BINARY_SENSOR
#include "esphome/components/binary_sensor/binary_sensor.h"
#endif
#
#include <vector>
#include <map>
@@ -27,6 +27,10 @@ struct Provider {
std::vector<uint8_t> encryption_key;
const char *name;
uint32_t last_code[2];
uint32_t last_key_response_time;
#ifdef USE_STATUS_SENSOR
binary_sensor::BinarySensor *status_sensor{nullptr};
#endif
};
#ifdef USE_SENSOR
@@ -75,10 +79,7 @@ class PacketTransport : public PollingComponent {
void add_provider(const char *hostname) {
if (this->providers_.count(hostname) == 0) {
Provider provider;
provider.encryption_key = std::vector<uint8_t>{};
provider.last_code[0] = 0;
provider.last_code[1] = 0;
Provider provider{};
provider.name = hostname;
this->providers_[hostname] = provider;
#ifdef USE_SENSOR
@@ -97,6 +98,11 @@ class PacketTransport : public PollingComponent {
void set_provider_encryption(const char *name, std::vector<uint8_t> key) {
this->providers_[name].encryption_key = std::move(key);
}
#ifdef USE_STATUS_SENSOR
void set_provider_status_sensor(const char *name, binary_sensor::BinarySensor *sensor) {
this->providers_[name].status_sensor = sensor;
}
#endif
void set_platform_name(const char *name) { this->platform_name_ = name; }
protected:

View File

@@ -86,6 +86,7 @@
#define USE_SELECT
#define USE_SENSOR
#define USE_STATUS_LED
#define USE_STATUS_SENSOR
#define USE_SWITCH
#define USE_TEXT
#define USE_TEXT_SENSOR