mirror of
https://github.com/esphome/esphome.git
synced 2026-09-03 19:46:02 +00:00
Merge remote-tracking branch 'upstream/dev' into protect_entity_setters
# Conflicts: # esphome/core/entity_base.cpp # esphome/core/entity_base.h # esphome/core/entity_helpers.py # tests/component_tests/sensor/test_sensor.py # tests/component_tests/text_sensor/test_text_sensor.py
This commit is contained in:
@@ -47,7 +47,7 @@ runs:
|
||||
|
||||
- name: Build and push to ghcr by digest
|
||||
id: build-ghcr
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
@@ -73,7 +73,7 @@ runs:
|
||||
|
||||
- name: Build and push to dockerhub by digest
|
||||
id: build-dockerhub
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
|
||||
env:
|
||||
DOCKER_BUILD_SUMMARY: false
|
||||
DOCKER_BUILD_RECORD_UPLOAD: false
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
|
||||
uses: github/codeql-action/init@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
@@ -86,6 +86,6 @@ jobs:
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@c793b717bc78562f491db7b0e93a3a178b099162 # v4.32.5
|
||||
uses: github/codeql-action/analyze@0d579ffd059c29b07949a3cce3983f0780820c98 # v4.32.6
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -11,7 +11,7 @@ ci:
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.15.3
|
||||
rev: v0.15.5
|
||||
hooks:
|
||||
# Run the linter.
|
||||
- id: ruff
|
||||
|
||||
@@ -121,7 +121,7 @@ void ADE7880::update() {
|
||||
this->update_sensor_from_s32_register16_(chan->forward_active_energy, AFWATTHR, [&chan](float val) {
|
||||
return chan->forward_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, AFWATTHR, [&chan](float val) {
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, ARWATTHR, [&chan](float val) {
|
||||
return chan->reverse_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
}
|
||||
@@ -137,7 +137,7 @@ void ADE7880::update() {
|
||||
this->update_sensor_from_s32_register16_(chan->forward_active_energy, BFWATTHR, [&chan](float val) {
|
||||
return chan->forward_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, BFWATTHR, [&chan](float val) {
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, BRWATTHR, [&chan](float val) {
|
||||
return chan->reverse_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
}
|
||||
@@ -153,7 +153,7 @@ void ADE7880::update() {
|
||||
this->update_sensor_from_s32_register16_(chan->forward_active_energy, CFWATTHR, [&chan](float val) {
|
||||
return chan->forward_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, CFWATTHR, [&chan](float val) {
|
||||
this->update_sensor_from_s32_register16_(chan->reverse_active_energy, CRWATTHR, [&chan](float val) {
|
||||
return chan->reverse_active_energy_total += val / 14400.0f;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ constexpr uint16_t CWATTHR = 0xE402;
|
||||
constexpr uint16_t AFWATTHR = 0xE403;
|
||||
constexpr uint16_t BFWATTHR = 0xE404;
|
||||
constexpr uint16_t CFWATTHR = 0xE405;
|
||||
constexpr uint16_t ARWATTHR = 0xE406;
|
||||
constexpr uint16_t BRWATTHR = 0xE407;
|
||||
constexpr uint16_t CRWATTHR = 0xE408;
|
||||
constexpr uint16_t AFVARHR = 0xE409;
|
||||
constexpr uint16_t BFVARHR = 0xE40A;
|
||||
constexpr uint16_t CFVARHR = 0xE40B;
|
||||
|
||||
@@ -58,6 +58,7 @@ service APIConnection {
|
||||
rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {}
|
||||
rpc unsubscribe_bluetooth_le_advertisements(UnsubscribeBluetoothLEAdvertisementsRequest) returns (void) {}
|
||||
rpc bluetooth_scanner_set_mode(BluetoothScannerSetModeRequest) returns (void) {}
|
||||
rpc bluetooth_set_connection_params(BluetoothSetConnectionParamsRequest) returns (BluetoothSetConnectionParamsResponse) {}
|
||||
|
||||
rpc subscribe_voice_assistant(SubscribeVoiceAssistantRequest) returns (void) {}
|
||||
rpc voice_assistant_get_configuration(VoiceAssistantConfigurationRequest) returns (VoiceAssistantConfigurationResponse) {}
|
||||
@@ -69,6 +70,12 @@ service APIConnection {
|
||||
rpc zwave_proxy_request(ZWaveProxyRequest) returns (void) {}
|
||||
|
||||
rpc infrared_rf_transmit_raw_timings(InfraredRFTransmitRawTimingsRequest) returns (void) {}
|
||||
|
||||
rpc serial_proxy_configure(SerialProxyConfigureRequest) returns (void) {}
|
||||
rpc serial_proxy_write(SerialProxyWriteRequest) returns (void) {}
|
||||
rpc serial_proxy_set_modem_pins(SerialProxySetModemPinsRequest) returns (void) {}
|
||||
rpc serial_proxy_get_modem_pins(SerialProxyGetModemPinsRequest) returns (void) {}
|
||||
rpc serial_proxy_request(SerialProxyRequest) returns (void) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,6 +205,17 @@ message DeviceInfo {
|
||||
uint32 area_id = 3;
|
||||
}
|
||||
|
||||
enum SerialProxyPortType {
|
||||
SERIAL_PROXY_PORT_TYPE_TTL = 0;
|
||||
SERIAL_PROXY_PORT_TYPE_RS232 = 1;
|
||||
SERIAL_PROXY_PORT_TYPE_RS485 = 2;
|
||||
}
|
||||
|
||||
message SerialProxyInfo {
|
||||
string name = 1; // Human-readable port name
|
||||
SerialProxyPortType port_type = 2; // Port type (RS232, RS485)
|
||||
}
|
||||
|
||||
message DeviceInfoResponse {
|
||||
option (id) = 10;
|
||||
option (source) = SOURCE_SERVER;
|
||||
@@ -260,6 +278,9 @@ message DeviceInfoResponse {
|
||||
// Indicates if Z-Wave proxy support is available and features supported
|
||||
uint32 zwave_proxy_feature_flags = 23 [(field_ifdef) = "USE_ZWAVE_PROXY"];
|
||||
uint32 zwave_home_id = 24 [(field_ifdef) = "USE_ZWAVE_PROXY"];
|
||||
|
||||
// Serial proxy instance metadata
|
||||
repeated SerialProxyInfo serial_proxies = 25 [(field_ifdef) = "USE_SERIAL_PROXY", (fixed_array_size_define) = "SERIAL_PROXY_COUNT"];
|
||||
}
|
||||
|
||||
message ListEntitiesRequest {
|
||||
@@ -2517,3 +2538,114 @@ message InfraredRFReceiveEvent {
|
||||
fixed32 key = 2; // Key identifying the receiver instance
|
||||
repeated sint32 timings = 3 [packed = true, (container_pointer_no_template) = "std::vector<int32_t>"]; // Raw timings in microseconds (zigzag-encoded): alternating mark/space periods
|
||||
}
|
||||
|
||||
// ==================== SERIAL PROXY ====================
|
||||
|
||||
enum SerialProxyParity {
|
||||
SERIAL_PROXY_PARITY_NONE = 0;
|
||||
SERIAL_PROXY_PARITY_EVEN = 1;
|
||||
SERIAL_PROXY_PARITY_ODD = 2;
|
||||
}
|
||||
|
||||
// Configure UART parameters for a serial proxy instance
|
||||
message SerialProxyConfigureRequest {
|
||||
option (id) = 138;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
uint32 baudrate = 2; // Baud rate in bits per second
|
||||
bool flow_control = 3; // Enable hardware flow control
|
||||
SerialProxyParity parity = 4; // Parity setting
|
||||
uint32 stop_bits = 5; // Number of stop bits (1 or 2)
|
||||
uint32 data_size = 6; // Number of data bits (5-8)
|
||||
}
|
||||
|
||||
// Data received from a serial device, forwarded to clients
|
||||
message SerialProxyDataReceived {
|
||||
option (id) = 139;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
option (no_delay) = true;
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bytes data = 2; // Raw data received from the serial device
|
||||
}
|
||||
|
||||
// Write data to a serial device
|
||||
message SerialProxyWriteRequest {
|
||||
option (id) = 140;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
option (no_delay) = true;
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
bytes data = 2; // Raw data to write to the serial device
|
||||
}
|
||||
|
||||
// Set modem control pin states (RTS and DTR)
|
||||
message SerialProxySetModemPinsRequest {
|
||||
option (id) = 141;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
uint32 line_states = 2; // Bitmask of SerialProxyLineStateFlags
|
||||
}
|
||||
|
||||
// Request current modem control pin states
|
||||
message SerialProxyGetModemPinsRequest {
|
||||
option (id) = 142;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
}
|
||||
|
||||
// Response with current modem control pin states
|
||||
message SerialProxyGetModemPinsResponse {
|
||||
option (id) = 143;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
uint32 line_states = 2; // Bitmask of SerialProxyLineStateFlags
|
||||
}
|
||||
|
||||
enum SerialProxyRequestType {
|
||||
SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE = 0; // Subscribe to receive data from this serial proxy instance
|
||||
SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE = 1; // Unsubscribe from this serial proxy instance
|
||||
SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2; // Flush the serial port (block until all TX data is sent)
|
||||
}
|
||||
|
||||
// Generic request message for simple serial proxy operations
|
||||
message SerialProxyRequest {
|
||||
option (id) = 144;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_SERIAL_PROXY";
|
||||
|
||||
uint32 instance = 1; // Instance index (0-based)
|
||||
SerialProxyRequestType type = 2; // Request type
|
||||
}
|
||||
|
||||
// ==================== BLUETOOTH CONNECTION PARAMS ====================
|
||||
message BluetoothSetConnectionParamsRequest {
|
||||
option (id) = 145;
|
||||
option (source) = SOURCE_CLIENT;
|
||||
option (ifdef) = "USE_BLUETOOTH_PROXY";
|
||||
|
||||
uint64 address = 1;
|
||||
uint32 min_interval = 2; // units of 1.25ms
|
||||
uint32 max_interval = 3; // units of 1.25ms
|
||||
uint32 latency = 4;
|
||||
uint32 timeout = 5; // units of 10ms
|
||||
}
|
||||
|
||||
message BluetoothSetConnectionParamsResponse {
|
||||
option (id) = 146;
|
||||
option (source) = SOURCE_SERVER;
|
||||
option (ifdef) = "USE_BLUETOOTH_PROXY";
|
||||
|
||||
uint64 address = 1;
|
||||
int32 error = 2;
|
||||
}
|
||||
|
||||
@@ -1188,6 +1188,9 @@ void APIConnection::on_bluetooth_scanner_set_mode_request(const BluetoothScanner
|
||||
bluetooth_proxy::global_bluetooth_proxy->bluetooth_scanner_set_mode(
|
||||
msg.mode == enums::BluetoothScannerMode::BLUETOOTH_SCANNER_MODE_ACTIVE);
|
||||
}
|
||||
void APIConnection::on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg) {
|
||||
bluetooth_proxy::global_bluetooth_proxy->bluetooth_set_connection_params(msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
|
||||
@@ -148,6 +148,7 @@ class APIConnection final : public APIServerConnectionBase {
|
||||
void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override;
|
||||
void on_subscribe_bluetooth_connections_free_request() override;
|
||||
void on_bluetooth_scanner_set_mode_request(const BluetoothScannerSetModeRequest &msg) override;
|
||||
void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &msg) override;
|
||||
|
||||
#endif
|
||||
#ifdef USE_HOMEASSISTANT_TIME
|
||||
|
||||
@@ -71,6 +71,18 @@ uint32_t DeviceInfo::calculate_size() const {
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
void SerialProxyInfo::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_string(1, this->name);
|
||||
buffer.encode_uint32(2, static_cast<uint32_t>(this->port_type));
|
||||
}
|
||||
uint32_t SerialProxyInfo::calculate_size() const {
|
||||
uint32_t size = 0;
|
||||
size += ProtoSize::calc_length(1, this->name.size());
|
||||
size += ProtoSize::calc_uint32(1, static_cast<uint32_t>(this->port_type));
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_string(2, this->name);
|
||||
buffer.encode_string(3, this->mac_address);
|
||||
@@ -108,16 +120,16 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
#endif
|
||||
#ifdef USE_DEVICES
|
||||
for (const auto &it : this->devices) {
|
||||
buffer.encode_message(20, it);
|
||||
buffer.encode_sub_message(20, it);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AREAS
|
||||
for (const auto &it : this->areas) {
|
||||
buffer.encode_message(21, it);
|
||||
buffer.encode_sub_message(21, it);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_AREAS
|
||||
buffer.encode_message(22, this->area, false);
|
||||
buffer.encode_optional_sub_message(22, this->area);
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
buffer.encode_uint32(23, this->zwave_proxy_feature_flags);
|
||||
@@ -125,6 +137,11 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
buffer.encode_uint32(24, this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
buffer.encode_message(25, it);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
uint32_t DeviceInfoResponse::calculate_size() const {
|
||||
uint32_t size = 0;
|
||||
@@ -180,6 +197,11 @@ uint32_t DeviceInfoResponse::calculate_size() const {
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
size += ProtoSize::calc_uint32(2, this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
size += ProtoSize::calc_message_force(2, it.calculate_size());
|
||||
}
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
@@ -898,13 +920,13 @@ uint32_t HomeassistantServiceMap::calculate_size() const {
|
||||
void HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_string(1, this->service);
|
||||
for (auto &it : this->data) {
|
||||
buffer.encode_message(2, it);
|
||||
buffer.encode_sub_message(2, it);
|
||||
}
|
||||
for (auto &it : this->data_template) {
|
||||
buffer.encode_message(3, it);
|
||||
buffer.encode_sub_message(3, it);
|
||||
}
|
||||
for (auto &it : this->variables) {
|
||||
buffer.encode_message(4, it);
|
||||
buffer.encode_sub_message(4, it);
|
||||
}
|
||||
buffer.encode_bool(5, this->is_event);
|
||||
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
|
||||
@@ -1104,7 +1126,7 @@ void ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_string(1, this->name);
|
||||
buffer.encode_fixed32(2, this->key);
|
||||
for (auto &it : this->args) {
|
||||
buffer.encode_message(3, it);
|
||||
buffer.encode_sub_message(3, it);
|
||||
}
|
||||
buffer.encode_uint32(4, static_cast<uint32_t>(this->supports_response));
|
||||
}
|
||||
@@ -2111,7 +2133,7 @@ void ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint32(7, static_cast<uint32_t>(this->entity_category));
|
||||
buffer.encode_bool(8, this->supports_pause);
|
||||
for (auto &it : this->supported_formats) {
|
||||
buffer.encode_message(9, it);
|
||||
buffer.encode_sub_message(9, it);
|
||||
}
|
||||
#ifdef USE_DEVICES
|
||||
buffer.encode_uint32(10, this->device_id);
|
||||
@@ -2242,7 +2264,7 @@ uint32_t BluetoothLERawAdvertisement::calculate_size() const {
|
||||
}
|
||||
void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
for (uint16_t i = 0; i < this->advertisements_len; i++) {
|
||||
buffer.encode_message(1, this->advertisements[i]);
|
||||
buffer.encode_sub_message(1, this->advertisements[i]);
|
||||
}
|
||||
}
|
||||
uint32_t BluetoothLERawAdvertisementsResponse::calculate_size() const {
|
||||
@@ -2321,7 +2343,7 @@ void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
buffer.encode_uint32(3, this->properties);
|
||||
for (auto &it : this->descriptors) {
|
||||
buffer.encode_message(4, it);
|
||||
buffer.encode_sub_message(4, it);
|
||||
}
|
||||
buffer.encode_uint32(5, this->short_uuid);
|
||||
}
|
||||
@@ -2348,7 +2370,7 @@ void BluetoothGATTService::encode(ProtoWriteBuffer &buffer) const {
|
||||
}
|
||||
buffer.encode_uint32(2, this->handle);
|
||||
for (auto &it : this->characteristics) {
|
||||
buffer.encode_message(3, it);
|
||||
buffer.encode_sub_message(3, it);
|
||||
}
|
||||
buffer.encode_uint32(4, this->short_uuid);
|
||||
}
|
||||
@@ -2370,7 +2392,7 @@ uint32_t BluetoothGATTService::calculate_size() const {
|
||||
void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
for (auto &it : this->services) {
|
||||
buffer.encode_message(2, it);
|
||||
buffer.encode_sub_message(2, it);
|
||||
}
|
||||
}
|
||||
uint32_t BluetoothGATTGetServicesResponse::calculate_size() const {
|
||||
@@ -2651,7 +2673,7 @@ void VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_bool(1, this->start);
|
||||
buffer.encode_string(2, this->conversation_id);
|
||||
buffer.encode_uint32(3, this->flags);
|
||||
buffer.encode_message(4, this->audio_settings, false);
|
||||
buffer.encode_optional_sub_message(4, this->audio_settings);
|
||||
buffer.encode_string(5, this->wake_word_phrase);
|
||||
}
|
||||
uint32_t VoiceAssistantRequest::calculate_size() const {
|
||||
@@ -2884,7 +2906,7 @@ bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoL
|
||||
}
|
||||
void VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
for (auto &it : this->available_wake_words) {
|
||||
buffer.encode_message(1, it);
|
||||
buffer.encode_sub_message(1, it);
|
||||
}
|
||||
for (const auto &it : *this->active_wake_words) {
|
||||
buffer.encode_string(2, it, true);
|
||||
@@ -3714,5 +3736,144 @@ uint32_t InfraredRFReceiveEvent::calculate_size() const {
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->baudrate = value.as_uint32();
|
||||
break;
|
||||
case 3:
|
||||
this->flow_control = value.as_bool();
|
||||
break;
|
||||
case 4:
|
||||
this->parity = static_cast<enums::SerialProxyParity>(value.as_uint32());
|
||||
break;
|
||||
case 5:
|
||||
this->stop_bits = value.as_uint32();
|
||||
break;
|
||||
case 6:
|
||||
this->data_size = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void SerialProxyDataReceived::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint32(1, this->instance);
|
||||
buffer.encode_bytes(2, this->data_ptr_, this->data_len_);
|
||||
}
|
||||
uint32_t SerialProxyDataReceived::calculate_size() const {
|
||||
uint32_t size = 0;
|
||||
size += ProtoSize::calc_uint32(1, this->instance);
|
||||
size += ProtoSize::calc_length(1, this->data_len_);
|
||||
return size;
|
||||
}
|
||||
bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxyWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->data = value.data();
|
||||
this->data_len = value.size();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->line_states = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint32(1, this->instance);
|
||||
buffer.encode_uint32(2, this->line_states);
|
||||
}
|
||||
uint32_t SerialProxyGetModemPinsResponse::calculate_size() const {
|
||||
uint32_t size = 0;
|
||||
size += ProtoSize::calc_uint32(1, this->instance);
|
||||
size += ProtoSize::calc_uint32(1, this->line_states);
|
||||
return size;
|
||||
}
|
||||
bool SerialProxyRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->instance = value.as_uint32();
|
||||
break;
|
||||
case 2:
|
||||
this->type = static_cast<enums::SerialProxyRequestType>(value.as_uint32());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1:
|
||||
this->address = value.as_uint64();
|
||||
break;
|
||||
case 2:
|
||||
this->min_interval = value.as_uint32();
|
||||
break;
|
||||
case 3:
|
||||
this->max_interval = value.as_uint32();
|
||||
break;
|
||||
case 4:
|
||||
this->latency = value.as_uint32();
|
||||
break;
|
||||
case 5:
|
||||
this->timeout = value.as_uint32();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void BluetoothSetConnectionParamsResponse::encode(ProtoWriteBuffer &buffer) const {
|
||||
buffer.encode_uint64(1, this->address);
|
||||
buffer.encode_int32(2, this->error);
|
||||
}
|
||||
uint32_t BluetoothSetConnectionParamsResponse::calculate_size() const {
|
||||
uint32_t size = 0;
|
||||
size += ProtoSize::calc_uint64(1, this->address);
|
||||
size += ProtoSize::calc_int32(1, this->error);
|
||||
return size;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
@@ -11,6 +11,11 @@ namespace esphome::api {
|
||||
|
||||
namespace enums {
|
||||
|
||||
enum SerialProxyPortType : uint32_t {
|
||||
SERIAL_PROXY_PORT_TYPE_TTL = 0,
|
||||
SERIAL_PROXY_PORT_TYPE_RS232 = 1,
|
||||
SERIAL_PROXY_PORT_TYPE_RS485 = 2,
|
||||
};
|
||||
enum EntityCategory : uint32_t {
|
||||
ENTITY_CATEGORY_NONE = 0,
|
||||
ENTITY_CATEGORY_CONFIG = 1,
|
||||
@@ -317,6 +322,18 @@ enum ZWaveProxyRequestType : uint32_t {
|
||||
ZWAVE_PROXY_REQUEST_TYPE_HOME_ID_CHANGE = 2,
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
enum SerialProxyParity : uint32_t {
|
||||
SERIAL_PROXY_PARITY_NONE = 0,
|
||||
SERIAL_PROXY_PARITY_EVEN = 1,
|
||||
SERIAL_PROXY_PARITY_ODD = 2,
|
||||
};
|
||||
enum SerialProxyRequestType : uint32_t {
|
||||
SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE = 0,
|
||||
SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE = 1,
|
||||
SERIAL_PROXY_REQUEST_TYPE_FLUSH = 2,
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace enums
|
||||
|
||||
@@ -477,10 +494,24 @@ class DeviceInfo final : public ProtoMessage {
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
class SerialProxyInfo final : public ProtoMessage {
|
||||
public:
|
||||
StringRef name{};
|
||||
enums::SerialProxyPortType port_type{};
|
||||
void encode(ProtoWriteBuffer &buffer) const;
|
||||
uint32_t calculate_size() const;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
class DeviceInfoResponse final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 10;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 255;
|
||||
static constexpr uint16_t ESTIMATED_SIZE = 309;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "device_info_response"; }
|
||||
#endif
|
||||
@@ -532,6 +563,9 @@ class DeviceInfoResponse final : public ProtoMessage {
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
uint32_t zwave_home_id{0};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
std::array<SerialProxyInfo, SERIAL_PROXY_COUNT> serial_proxies{};
|
||||
#endif
|
||||
void encode(ProtoWriteBuffer &buffer) const;
|
||||
uint32_t calculate_size() const;
|
||||
@@ -3061,5 +3095,169 @@ class InfraredRFReceiveEvent final : public ProtoMessage {
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
class SerialProxyConfigureRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 138;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 20;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_configure_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
uint32_t baudrate{0};
|
||||
bool flow_control{false};
|
||||
enums::SerialProxyParity parity{};
|
||||
uint32_t stop_bits{0};
|
||||
uint32_t data_size{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyDataReceived final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 139;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 23;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_data_received"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
const uint8_t *data_ptr_{nullptr};
|
||||
size_t data_len_{0};
|
||||
void set_data(const uint8_t *data, size_t len) {
|
||||
this->data_ptr_ = data;
|
||||
this->data_len_ = len;
|
||||
}
|
||||
void encode(ProtoWriteBuffer &buffer) const;
|
||||
uint32_t calculate_size() const;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
class SerialProxyWriteRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 140;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 23;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_write_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
const uint8_t *data{nullptr};
|
||||
uint16_t data_len{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &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 SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 141;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 8;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_set_modem_pins_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
uint32_t line_states{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 142;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 4;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_get_modem_pins_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsResponse final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 143;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 8;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_get_modem_pins_response"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
uint32_t line_states{0};
|
||||
void encode(ProtoWriteBuffer &buffer) const;
|
||||
uint32_t calculate_size() const;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
class SerialProxyRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 144;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 6;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "serial_proxy_request"; }
|
||||
#endif
|
||||
uint32_t instance{0};
|
||||
enums::SerialProxyRequestType type{};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 145;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 20;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "bluetooth_set_connection_params_request"; }
|
||||
#endif
|
||||
uint64_t address{0};
|
||||
uint32_t min_interval{0};
|
||||
uint32_t max_interval{0};
|
||||
uint32_t latency{0};
|
||||
uint32_t timeout{0};
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class BluetoothSetConnectionParamsResponse final : public ProtoMessage {
|
||||
public:
|
||||
static constexpr uint8_t MESSAGE_TYPE = 146;
|
||||
static constexpr uint8_t ESTIMATED_SIZE = 8;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *message_name() const override { return "bluetooth_set_connection_params_response"; }
|
||||
#endif
|
||||
uint64_t address{0};
|
||||
int32_t error{0};
|
||||
void encode(ProtoWriteBuffer &buffer) const;
|
||||
uint32_t calculate_size() const;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
const char *dump_to(DumpBuffer &out) const override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
@@ -100,6 +100,18 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
|
||||
out.append(hex_buf).append("\n");
|
||||
}
|
||||
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyPortType>(enums::SerialProxyPortType value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_TTL:
|
||||
return "SERIAL_PROXY_PORT_TYPE_TTL";
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_RS232:
|
||||
return "SERIAL_PROXY_PORT_TYPE_RS232";
|
||||
case enums::SERIAL_PROXY_PORT_TYPE_RS485:
|
||||
return "SERIAL_PROXY_PORT_TYPE_RS485";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<enums::EntityCategory>(enums::EntityCategory value) {
|
||||
switch (value) {
|
||||
case enums::ENTITY_CATEGORY_NONE:
|
||||
@@ -752,6 +764,32 @@ template<> const char *proto_enum_to_string<enums::ZWaveProxyRequestType>(enums:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyParity>(enums::SerialProxyParity value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_PARITY_NONE:
|
||||
return "SERIAL_PROXY_PARITY_NONE";
|
||||
case enums::SERIAL_PROXY_PARITY_EVEN:
|
||||
return "SERIAL_PROXY_PARITY_EVEN";
|
||||
case enums::SERIAL_PROXY_PARITY_ODD:
|
||||
return "SERIAL_PROXY_PARITY_ODD";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<enums::SerialProxyRequestType>(enums::SerialProxyRequestType value) {
|
||||
switch (value) {
|
||||
case enums::SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE:
|
||||
return "SERIAL_PROXY_REQUEST_TYPE_SUBSCRIBE";
|
||||
case enums::SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE:
|
||||
return "SERIAL_PROXY_REQUEST_TYPE_UNSUBSCRIBE";
|
||||
case enums::SERIAL_PROXY_REQUEST_TYPE_FLUSH:
|
||||
return "SERIAL_PROXY_REQUEST_TYPE_FLUSH";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *HelloRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "HelloRequest");
|
||||
@@ -801,6 +839,14 @@ const char *DeviceInfo::dump_to(DumpBuffer &out) const {
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
const char *SerialProxyInfo::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyInfo");
|
||||
dump_field(out, "name", this->name);
|
||||
dump_field(out, "port_type", static_cast<enums::SerialProxyPortType>(this->port_type));
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "DeviceInfoResponse");
|
||||
dump_field(out, "name", this->name);
|
||||
@@ -861,6 +907,13 @@ const char *DeviceInfoResponse::dump_to(DumpBuffer &out) const {
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
dump_field(out, "zwave_home_id", this->zwave_home_id);
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
for (const auto &it : this->serial_proxies) {
|
||||
out.append(" serial_proxies: ");
|
||||
it.dump_to(out);
|
||||
out.append("\n");
|
||||
}
|
||||
#endif
|
||||
return out.c_str();
|
||||
}
|
||||
@@ -2510,6 +2563,70 @@ const char *InfraredRFReceiveEvent::dump_to(DumpBuffer &out) const {
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
const char *SerialProxyConfigureRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyConfigureRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "baudrate", this->baudrate);
|
||||
dump_field(out, "flow_control", this->flow_control);
|
||||
dump_field(out, "parity", static_cast<enums::SerialProxyParity>(this->parity));
|
||||
dump_field(out, "stop_bits", this->stop_bits);
|
||||
dump_field(out, "data_size", this->data_size);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyDataReceived::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyDataReceived");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_bytes_field(out, "data", this->data_ptr_, this->data_len_);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyWriteRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyWriteRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_bytes_field(out, "data", this->data, this->data_len);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxySetModemPinsRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxySetModemPinsRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "line_states", this->line_states);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyGetModemPinsRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyGetModemPinsRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyGetModemPinsResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyGetModemPinsResponse");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "line_states", this->line_states);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *SerialProxyRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "SerialProxyRequest");
|
||||
dump_field(out, "instance", this->instance);
|
||||
dump_field(out, "type", static_cast<enums::SerialProxyRequestType>(this->type));
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
const char *BluetoothSetConnectionParamsRequest::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "BluetoothSetConnectionParamsRequest");
|
||||
dump_field(out, "address", this->address);
|
||||
dump_field(out, "min_interval", this->min_interval);
|
||||
dump_field(out, "max_interval", this->max_interval);
|
||||
dump_field(out, "latency", this->latency);
|
||||
dump_field(out, "timeout", this->timeout);
|
||||
return out.c_str();
|
||||
}
|
||||
const char *BluetoothSetConnectionParamsResponse::dump_to(DumpBuffer &out) const {
|
||||
MessageDumpHelper helper(out, "BluetoothSetConnectionParamsResponse");
|
||||
dump_field(out, "address", this->address);
|
||||
dump_field(out, "error", this->error);
|
||||
return out.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace esphome::api
|
||||
|
||||
|
||||
@@ -634,6 +634,72 @@ void APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
|
||||
this->on_infrared_rf_transmit_raw_timings_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyConfigureRequest::MESSAGE_TYPE: {
|
||||
SerialProxyConfigureRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_configure_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_configure_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyWriteRequest::MESSAGE_TYPE: {
|
||||
SerialProxyWriteRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_write_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_write_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxySetModemPinsRequest::MESSAGE_TYPE: {
|
||||
SerialProxySetModemPinsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_set_modem_pins_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_set_modem_pins_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyGetModemPinsRequest::MESSAGE_TYPE: {
|
||||
SerialProxyGetModemPinsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_get_modem_pins_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_get_modem_pins_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
case SerialProxyRequest::MESSAGE_TYPE: {
|
||||
SerialProxyRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_serial_proxy_request"), msg);
|
||||
#endif
|
||||
this->on_serial_proxy_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
case BluetoothSetConnectionParamsRequest::MESSAGE_TYPE: {
|
||||
BluetoothSetConnectionParamsRequest msg;
|
||||
msg.decode(msg_data, msg_size);
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
this->log_receive_message_(LOG_STR("on_bluetooth_set_connection_params_request"), msg);
|
||||
#endif
|
||||
this->on_bluetooth_set_connection_params_request(msg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -216,6 +216,27 @@ class APIServerConnectionBase : public ProtoService {
|
||||
virtual void on_infrared_rf_transmit_raw_timings_request(const InfraredRFTransmitRawTimingsRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_configure_request(const SerialProxyConfigureRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_write_request(const SerialProxyWriteRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_set_modem_pins_request(const SerialProxySetModemPinsRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_get_modem_pins_request(const SerialProxyGetModemPinsRequest &value){};
|
||||
#endif
|
||||
|
||||
#ifdef USE_SERIAL_PROXY
|
||||
virtual void on_serial_proxy_request(const SerialProxyRequest &value){};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
virtual void on_bluetooth_set_connection_params_request(const BluetoothSetConnectionParamsRequest &value){};
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) override;
|
||||
};
|
||||
|
||||
@@ -582,11 +582,7 @@ void APIServer::request_time() {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool APIServer::is_connected(bool state_subscription_only) const {
|
||||
if (!state_subscription_only) {
|
||||
return !this->clients_.empty();
|
||||
}
|
||||
|
||||
bool APIServer::is_connected_with_state_subscription() const {
|
||||
for (const auto &client : this->clients_) {
|
||||
if (client->flags_.state_subscription) {
|
||||
return true;
|
||||
|
||||
@@ -185,7 +185,8 @@ class APIServer : public Component,
|
||||
void send_infrared_rf_receive_event(uint32_t device_id, uint32_t key, const std::vector<int32_t> *timings);
|
||||
#endif
|
||||
|
||||
bool is_connected(bool state_subscription_only = false) const;
|
||||
bool is_connected() const { return !this->clients_.empty(); }
|
||||
bool is_connected_with_state_subscription() const;
|
||||
|
||||
#ifdef USE_API_HOMEASSISTANT_STATES
|
||||
struct HomeAssistantStateSubscription {
|
||||
@@ -323,7 +324,10 @@ template<typename... Ts> class APIConnectedCondition : public Condition<Ts...> {
|
||||
TEMPLATABLE_VALUE(bool, state_subscription_only)
|
||||
public:
|
||||
bool check(const Ts &...x) override {
|
||||
return global_api_server->is_connected(this->state_subscription_only_.value(x...));
|
||||
if (this->state_subscription_only_.value(x...)) {
|
||||
return global_api_server->is_connected_with_state_subscription();
|
||||
}
|
||||
return global_api_server->is_connected();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "proto.h"
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -87,6 +88,76 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size
|
||||
return count;
|
||||
}
|
||||
|
||||
// Single-pass encode for repeated submessage elements (non-template core).
|
||||
// Writes field tag, reserves 1 byte for length varint, encodes the submessage body,
|
||||
// then backpatches the actual length. For the common case (body < 128 bytes), this is
|
||||
// just a single byte write with no memmove — all current repeated submessage types
|
||||
// (BLE advertisements at ~47B, GATT descriptors at ~24B, service args, etc.) take
|
||||
// this fast path.
|
||||
//
|
||||
// The memmove fallback for body >= 128 bytes exists only for correctness (e.g., a GATT
|
||||
// characteristic with many descriptors). It is safe because calculate_size() already
|
||||
// reserved space for the full multi-byte varint — the shift fills that reserved space:
|
||||
//
|
||||
// calculate_size() allocates per element: tag + varint_size(body) + body_size
|
||||
//
|
||||
// After encode, before memmove (1 byte reserved, body written):
|
||||
// [tag][__][body ..... body][??]
|
||||
// ^ ^-- unused byte (v2 space from calculate_size)
|
||||
// len_pos
|
||||
//
|
||||
// After memmove(body_start+1, body_start, body_size):
|
||||
// [tag][__][__][body ..... body]
|
||||
// ^ ^-- body shifted forward, fills v2 space exactly
|
||||
// len_pos
|
||||
//
|
||||
// After writing 2-byte varint at len_pos:
|
||||
// [tag][v1][v2][body ..... body]
|
||||
// ^-- pos_ = element end, within buffer
|
||||
void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const void *value,
|
||||
void (*encode_fn)(const void *, ProtoWriteBuffer &)) {
|
||||
this->encode_field_raw(field_id, 2);
|
||||
// Reserve 1 byte for length varint (optimistic: submessage < 128 bytes)
|
||||
uint8_t *len_pos = this->pos_;
|
||||
this->debug_check_bounds_(1);
|
||||
this->pos_++;
|
||||
uint8_t *body_start = this->pos_;
|
||||
encode_fn(value, *this);
|
||||
uint32_t body_size = static_cast<uint32_t>(this->pos_ - body_start);
|
||||
if (body_size < 128) [[likely]] {
|
||||
// Common case: 1-byte varint, just backpatch
|
||||
*len_pos = static_cast<uint8_t>(body_size);
|
||||
return;
|
||||
}
|
||||
// Compute extra bytes needed for varint beyond the 1 already reserved
|
||||
uint8_t extra = ProtoSize::varint(body_size) - 1;
|
||||
// Shift body forward to make room for the extra varint bytes
|
||||
this->debug_check_bounds_(extra);
|
||||
std::memmove(body_start + extra, body_start, body_size);
|
||||
uint8_t *end = this->pos_ + extra;
|
||||
// Write the full varint at len_pos
|
||||
this->pos_ = len_pos;
|
||||
this->encode_varint_raw(body_size);
|
||||
this->pos_ = end;
|
||||
}
|
||||
|
||||
// Non-template core for encode_optional_sub_message.
|
||||
void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value,
|
||||
void (*encode_fn)(const void *, ProtoWriteBuffer &)) {
|
||||
if (nested_size == 0)
|
||||
return;
|
||||
this->encode_field_raw(field_id, 2);
|
||||
this->encode_varint_raw(nested_size);
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
uint8_t *start = this->pos_;
|
||||
encode_fn(value, *this);
|
||||
if (static_cast<uint32_t>(this->pos_ - start) != nested_size)
|
||||
this->debug_check_encode_size_(field_id, nested_size, this->pos_ - start);
|
||||
#else
|
||||
encode_fn(value, *this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
void ProtoWriteBuffer::debug_check_bounds_(size_t bytes, const char *caller) {
|
||||
if (this->pos_ + bytes > this->buffer_->data() + this->buffer_->size()) {
|
||||
|
||||
@@ -185,7 +185,7 @@ class ProtoVarInt {
|
||||
#endif
|
||||
};
|
||||
|
||||
// Forward declarations for decode_to_message, encode_message and encode_packed_sint32
|
||||
// Forward declarations for decode_to_message and related encoding helpers
|
||||
class ProtoDecodableMessage;
|
||||
class ProtoMessage;
|
||||
class ProtoSize;
|
||||
@@ -363,12 +363,18 @@ class ProtoWriteBuffer {
|
||||
}
|
||||
/// Encode a packed repeated sint32 field (zero-copy from vector)
|
||||
void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values);
|
||||
/// Encode a nested message field (force=true for repeated, false for singular)
|
||||
/// Templated so concrete message type is preserved for direct encode/calculate_size calls.
|
||||
template<typename T> void encode_message(uint32_t field_id, const T &value, bool force = true);
|
||||
// Non-template core for encode_message — all buffer work happens here
|
||||
void encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value,
|
||||
void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force);
|
||||
/// Single-pass encode for repeated submessage elements.
|
||||
/// Thin template wrapper; all buffer work is in the non-template core.
|
||||
template<typename T> void encode_sub_message(uint32_t field_id, const T &value);
|
||||
/// Encode an optional singular submessage field — skips if empty.
|
||||
/// Thin template wrapper; all buffer work is in the non-template core.
|
||||
template<typename T> void encode_optional_sub_message(uint32_t field_id, const T &value);
|
||||
|
||||
// Non-template core for encode_sub_message — backpatch approach.
|
||||
void encode_sub_message(uint32_t field_id, const void *value, void (*encode_fn)(const void *, ProtoWriteBuffer &));
|
||||
// Non-template core for encode_optional_sub_message.
|
||||
void encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value,
|
||||
void (*encode_fn)(const void *, ProtoWriteBuffer &));
|
||||
std::vector<uint8_t> *get_buffer() const { return buffer_; }
|
||||
|
||||
protected:
|
||||
@@ -690,26 +696,14 @@ template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &bu
|
||||
static_cast<const T *>(msg)->encode(buf);
|
||||
}
|
||||
|
||||
// Implementation of encode_message - must be after ProtoMessage is defined
|
||||
template<typename T> inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const T &value, bool force) {
|
||||
this->encode_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>, force);
|
||||
// Thin template wrapper; delegates to non-template core in proto.cpp.
|
||||
template<typename T> inline void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const T &value) {
|
||||
this->encode_sub_message(field_id, &value, &proto_encode_msg<T>);
|
||||
}
|
||||
|
||||
// Non-template core for encode_message
|
||||
inline void ProtoWriteBuffer::encode_message(uint32_t field_id, uint32_t msg_length_bytes, const void *value,
|
||||
void (*encode_fn)(const void *, ProtoWriteBuffer &), bool force) {
|
||||
if (msg_length_bytes == 0 && !force)
|
||||
return;
|
||||
this->encode_field_raw(field_id, 2);
|
||||
this->encode_varint_raw(msg_length_bytes);
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
uint8_t *start = this->pos_;
|
||||
encode_fn(value, *this);
|
||||
if (static_cast<uint32_t>(this->pos_ - start) != msg_length_bytes)
|
||||
this->debug_check_encode_size_(field_id, msg_length_bytes, this->pos_ - start);
|
||||
#else
|
||||
encode_fn(value, *this);
|
||||
#endif
|
||||
// Thin template wrapper; delegates to non-template core.
|
||||
template<typename T> inline void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, const T &value) {
|
||||
this->encode_optional_sub_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>);
|
||||
}
|
||||
|
||||
// Implementation of decode_to_message - must be after ProtoDecodableMessage is defined
|
||||
|
||||
@@ -78,7 +78,7 @@ static void spi_set_clock(uint32_t max_hz) {
|
||||
int source_clk = 0;
|
||||
int spi_clk = 0;
|
||||
int div = 0;
|
||||
uint32_t param;
|
||||
uint32_t param = PWD_SPI_CLK_BIT;
|
||||
if (max_hz > 4333000) {
|
||||
if (max_hz > 30000000) {
|
||||
spi_clk = 30000000;
|
||||
|
||||
@@ -10,7 +10,9 @@ static const char *const TAG = "bl0906";
|
||||
|
||||
constexpr uint32_t to_uint32_t(ube24_t input) { return input.h << 16 | input.m << 8 | input.l; }
|
||||
|
||||
constexpr int32_t to_int32_t(sbe24_t input) { return input.h << 16 | input.m << 8 | input.l; }
|
||||
constexpr int32_t to_int32_t(sbe24_t input) {
|
||||
return static_cast<int32_t>(encode_uint32((uint8_t) input.h, input.m, input.l, 0)) >> 8;
|
||||
}
|
||||
|
||||
// The SUM byte is (Addr+Data_L+Data_M+Data_H)&0xFF negated;
|
||||
constexpr uint8_t bl0906_checksum(const uint8_t address, const DataPacket *data) {
|
||||
|
||||
@@ -24,6 +24,10 @@ class BluetoothConnection final : public esp32_ble_client::BLEClientBase {
|
||||
|
||||
esp_err_t notify_characteristic(uint16_t handle, bool enable);
|
||||
|
||||
esp_err_t update_connection_params(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout) {
|
||||
return this->update_conn_params_(min_interval, max_interval, latency, timeout, "custom");
|
||||
}
|
||||
|
||||
void set_address(uint64_t address) override;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/macros.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
@@ -361,6 +363,33 @@ void BluetoothProxy::bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest
|
||||
}
|
||||
}
|
||||
|
||||
void BluetoothProxy::bluetooth_set_connection_params(const api::BluetoothSetConnectionParamsRequest &msg) {
|
||||
if (this->api_connection_ == nullptr)
|
||||
return;
|
||||
|
||||
auto *connection = this->get_connection_(msg.address, false);
|
||||
api::BluetoothSetConnectionParamsResponse resp;
|
||||
resp.address = msg.address;
|
||||
|
||||
if (connection == nullptr || !connection->connected()) {
|
||||
ESP_LOGW(TAG, "[%d] [%s] Cannot set connection params, not connected",
|
||||
connection ? static_cast<int>(connection->connection_index_) : -1,
|
||||
connection ? connection->address_str() : "unknown");
|
||||
resp.error = ESP_GATT_NOT_CONNECTED;
|
||||
this->api_connection_->send_message(resp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Protobuf fields are uint32_t to future-proof the API if BLE ever supports wider values;
|
||||
// clamp to uint16_t since the current BLE spec defines these as 16-bit.
|
||||
constexpr uint32_t max_val = std::numeric_limits<uint16_t>::max();
|
||||
resp.error = connection->update_connection_params(static_cast<uint16_t>(std::min(msg.min_interval, max_val)),
|
||||
static_cast<uint16_t>(std::min(msg.max_interval, max_val)),
|
||||
static_cast<uint16_t>(std::min(msg.latency, max_val)),
|
||||
static_cast<uint16_t>(std::min(msg.timeout, max_val)));
|
||||
this->api_connection_->send_message(resp);
|
||||
}
|
||||
|
||||
void BluetoothProxy::subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags) {
|
||||
if (this->api_connection_ != nullptr) {
|
||||
ESP_LOGE(TAG, "Only one API subscription is allowed at a time");
|
||||
|
||||
@@ -46,6 +46,7 @@ enum BluetoothProxyFeature : uint32_t {
|
||||
FEATURE_CACHE_CLEARING = 1 << 4,
|
||||
FEATURE_RAW_ADVERTISEMENTS = 1 << 5,
|
||||
FEATURE_STATE_AND_MODE = 1 << 6,
|
||||
FEATURE_CONNECTION_PARAMS_SETTING = 1 << 7,
|
||||
};
|
||||
|
||||
enum BluetoothProxySubscriptionFlag : uint32_t {
|
||||
@@ -82,6 +83,7 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener,
|
||||
void bluetooth_gatt_write_descriptor(const api::BluetoothGATTWriteDescriptorRequest &msg);
|
||||
void bluetooth_gatt_send_services(const api::BluetoothGATTGetServicesRequest &msg);
|
||||
void bluetooth_gatt_notify(const api::BluetoothGATTNotifyRequest &msg);
|
||||
void bluetooth_set_connection_params(const api::BluetoothSetConnectionParamsRequest &msg);
|
||||
|
||||
void subscribe_api_connection(api::APIConnection *api_connection, uint32_t flags);
|
||||
void unsubscribe_api_connection(api::APIConnection *api_connection);
|
||||
@@ -130,6 +132,7 @@ class BluetoothProxy final : public esp32_ble_tracker::ESPBTDeviceListener,
|
||||
flags |= BluetoothProxyFeature::FEATURE_REMOTE_CACHING;
|
||||
flags |= BluetoothProxyFeature::FEATURE_PAIRING;
|
||||
flags |= BluetoothProxyFeature::FEATURE_CACHE_CLEARING;
|
||||
flags |= BluetoothProxyFeature::FEATURE_CONNECTION_PARAMS_SETTING;
|
||||
}
|
||||
|
||||
return flags;
|
||||
|
||||
@@ -429,7 +429,7 @@ bool BMP581Component::read_temperature_(float &temperature) {
|
||||
}
|
||||
|
||||
// temperature MSB is in data[2], LSB is in data[1], XLSB in data[0]
|
||||
int32_t raw_temp = (int32_t) data[2] << 16 | (int32_t) data[1] << 8 | (int32_t) data[0];
|
||||
int32_t raw_temp = static_cast<int32_t>(encode_uint32(data[2], data[1], data[0], 0)) >> 8;
|
||||
temperature = (float) (raw_temp / 65536.0); // convert measurement to degrees Celsius (page 22 of datasheet)
|
||||
|
||||
return true;
|
||||
@@ -458,7 +458,7 @@ bool BMP581Component::read_temperature_and_pressure_(float &temperature, float &
|
||||
}
|
||||
|
||||
// temperature MSB is in data[2], LSB is in data[1], XLSB in data[0]
|
||||
int32_t raw_temp = (int32_t) data[2] << 16 | (int32_t) data[1] << 8 | (int32_t) data[0];
|
||||
int32_t raw_temp = static_cast<int32_t>(encode_uint32(data[2], data[1], data[0], 0)) >> 8;
|
||||
temperature = (float) (raw_temp / 65536.0); // convert measurement to degrees Celsius (page 22 of datasheet)
|
||||
|
||||
// pressure MSB is in data[5], LSB is in data[4], XLSB in data[3]
|
||||
|
||||
@@ -263,7 +263,7 @@ class ByteBuffer {
|
||||
|
||||
void put_uint8(uint8_t value, size_t offset) { this->data_[offset] = value; }
|
||||
void put_uint16(uint16_t value, size_t offset) { this->put(value, offset); }
|
||||
void put_uint24(uint32_t value, size_t offset) { this->put(value, offset); }
|
||||
void put_uint24(uint32_t value, size_t offset) { this->put_uint32_(value, offset, 3); }
|
||||
void put_uint32(uint32_t value, size_t offset) { this->put(value, offset); }
|
||||
void put_uint64(uint64_t value, size_t offset) { this->put(value, offset); }
|
||||
// Signed versions of the put functions
|
||||
|
||||
@@ -92,7 +92,7 @@ void CAP1188Component::loop() {
|
||||
this->read_register(CAP1188_MAIN, &data, 1);
|
||||
data = data & ~CAP1188_MAIN_INT;
|
||||
|
||||
this->write_register(CAP1188_MAIN, &data, 2);
|
||||
this->write_register(CAP1188_MAIN, &data, 1);
|
||||
}
|
||||
|
||||
for (auto *channel : this->channels_) {
|
||||
|
||||
@@ -13,6 +13,7 @@ from esphome.const import (
|
||||
PLATFORM_ESP32,
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_LN882X,
|
||||
PLATFORM_RP2040,
|
||||
PLATFORM_RTL87XX,
|
||||
PlatformFramework,
|
||||
)
|
||||
@@ -53,6 +54,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
PLATFORM_ESP8266,
|
||||
PLATFORM_BK72XX,
|
||||
PLATFORM_LN882X,
|
||||
PLATFORM_RP2040,
|
||||
PLATFORM_RTL87XX,
|
||||
]
|
||||
),
|
||||
@@ -103,11 +105,8 @@ async def to_code(config):
|
||||
if config[CONF_COMPRESSION] == "gzip":
|
||||
cg.add_define("USE_CAPTIVE_PORTAL_GZIP")
|
||||
|
||||
if CORE.using_arduino:
|
||||
if CORE.is_esp8266:
|
||||
cg.add_library("DNSServer", None)
|
||||
if CORE.is_libretiny:
|
||||
cg.add_library("DNSServer", None)
|
||||
if CORE.using_arduino and (CORE.is_esp8266 or CORE.is_libretiny or CORE.is_rp2040):
|
||||
cg.add_library("DNSServer", None)
|
||||
|
||||
|
||||
# Only compile the ESP-IDF DNS server when using ESP-IDF framework
|
||||
|
||||
@@ -8,6 +8,7 @@ from esphome.const import (
|
||||
CONF_AWAY_COMMAND_TOPIC,
|
||||
CONF_AWAY_STATE_TOPIC,
|
||||
CONF_CURRENT_HUMIDITY_STATE_TOPIC,
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
CONF_CURRENT_TEMPERATURE_STATE_TOPIC,
|
||||
CONF_CUSTOM_FAN_MODE,
|
||||
CONF_CUSTOM_PRESET,
|
||||
@@ -112,7 +113,6 @@ CLIMATE_SWING_MODES = {
|
||||
|
||||
validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True)
|
||||
|
||||
CONF_CURRENT_TEMPERATURE = "current_temperature"
|
||||
CONF_MIN_HUMIDITY = "min_humidity"
|
||||
CONF_MAX_HUMIDITY = "max_humidity"
|
||||
CONF_TARGET_HUMIDITY = "target_humidity"
|
||||
|
||||
@@ -236,8 +236,8 @@ void BLEClientBase::log_warning_(const char *message) {
|
||||
ESP_LOGW(TAG, "[%d] [%s] %s", this->connection_index_, this->address_str_, message);
|
||||
}
|
||||
|
||||
void BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
|
||||
uint16_t timeout, const char *param_type) {
|
||||
esp_err_t BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency,
|
||||
uint16_t timeout, const char *param_type) {
|
||||
esp_ble_conn_update_params_t conn_params = {{0}};
|
||||
memcpy(conn_params.bda, this->remote_bda_, sizeof(esp_bd_addr_t));
|
||||
conn_params.min_int = min_interval;
|
||||
@@ -249,6 +249,7 @@ void BLEClientBase::update_conn_params_(uint16_t min_interval, uint16_t max_inte
|
||||
if (err != ESP_OK) {
|
||||
this->log_gattc_warning_("esp_ble_gap_update_conn_params", err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void BLEClientBase::set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout,
|
||||
|
||||
@@ -129,8 +129,8 @@ class BLEClientBase : public espbt::ESPBTClient, public Component {
|
||||
void log_event_(const char *name);
|
||||
void log_gattc_lifecycle_event_(const char *name);
|
||||
void log_gattc_data_event_(const char *name);
|
||||
void update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout,
|
||||
const char *param_type);
|
||||
esp_err_t update_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout,
|
||||
const char *param_type);
|
||||
void set_conn_params_(uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t timeout,
|
||||
const char *param_type);
|
||||
void log_gattc_warning_(const char *operation, esp_gatt_status_t status);
|
||||
|
||||
@@ -310,8 +310,8 @@ void BLECharacteristic::gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt
|
||||
(*this->on_write_callback_)(this->value_, param->exec_write.conn_id);
|
||||
}
|
||||
}
|
||||
esp_err_t err =
|
||||
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, nullptr);
|
||||
esp_err_t err = esp_ble_gatts_send_response(gatts_if, param->exec_write.conn_id, param->exec_write.trans_id,
|
||||
ESP_GATT_OK, nullptr);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_ble_gatts_send_response failed: %d", err);
|
||||
}
|
||||
|
||||
@@ -3,15 +3,11 @@ import logging
|
||||
from esphome import automation
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import climate, logger, uart
|
||||
from esphome.components.climate import (
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
ClimateMode,
|
||||
ClimatePreset,
|
||||
ClimateSwingMode,
|
||||
)
|
||||
from esphome.components.climate import ClimateMode, ClimatePreset, ClimateSwingMode
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_BEEPER,
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
CONF_DISPLAY,
|
||||
CONF_ID,
|
||||
CONF_LEVEL,
|
||||
|
||||
@@ -49,7 +49,7 @@ void HTE501Component::update() {
|
||||
this->set_timeout(50, [this]() {
|
||||
uint8_t i2c_response[6];
|
||||
this->read(i2c_response, 6);
|
||||
if (i2c_response[2] != crc8(i2c_response, 2, 0xFF, 0x31, true) &&
|
||||
if (i2c_response[2] != crc8(i2c_response, 2, 0xFF, 0x31, true) ||
|
||||
i2c_response[5] != crc8(i2c_response + 3, 2, 0xFF, 0x31, true)) {
|
||||
this->error_code_ = CRC_CHECK_FAILED;
|
||||
this->status_set_warning();
|
||||
|
||||
@@ -50,6 +50,8 @@ CONF_FOLLOW_REDIRECTS = "follow_redirects"
|
||||
CONF_REDIRECT_LIMIT = "redirect_limit"
|
||||
CONF_BUFFER_SIZE_RX = "buffer_size_rx"
|
||||
CONF_BUFFER_SIZE_TX = "buffer_size_tx"
|
||||
CONF_TLS_BUFFER_SIZE_RX = "tls_buffer_size_rx"
|
||||
CONF_TLS_BUFFER_SIZE_TX = "tls_buffer_size_tx"
|
||||
CONF_CA_CERTIFICATE_PATH = "ca_certificate_path"
|
||||
|
||||
CONF_MAX_RESPONSE_BUFFER_SIZE = "max_response_buffer_size"
|
||||
@@ -124,6 +126,12 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.SplitDefault(CONF_BUFFER_SIZE_TX, esp32=512): cv.All(
|
||||
cv.uint16_t, cv.only_on_esp32
|
||||
),
|
||||
cv.SplitDefault(CONF_TLS_BUFFER_SIZE_RX, esp8266=512): cv.All(
|
||||
cv.uint16_t, cv.only_on_esp8266
|
||||
),
|
||||
cv.SplitDefault(CONF_TLS_BUFFER_SIZE_TX, esp8266=512): cv.All(
|
||||
cv.uint16_t, cv.only_on_esp8266
|
||||
),
|
||||
cv.Optional(CONF_CA_CERTIFICATE_PATH): cv.All(
|
||||
cv.file_,
|
||||
cv.Any(cv.only_on(PLATFORM_HOST), cv.only_on_esp32),
|
||||
@@ -150,6 +158,8 @@ async def to_code(config):
|
||||
|
||||
if CORE.is_esp8266 and not config[CONF_ESP8266_DISABLE_SSL_SUPPORT]:
|
||||
cg.add_define("USE_HTTP_REQUEST_ESP8266_HTTPS")
|
||||
cg.add(var.set_tls_buffer_size_rx(config[CONF_TLS_BUFFER_SIZE_RX]))
|
||||
cg.add(var.set_tls_buffer_size_tx(config[CONF_TLS_BUFFER_SIZE_TX]))
|
||||
|
||||
if timeout_ms := config.get(CONF_WATCHDOG_TIMEOUT):
|
||||
cg.add(var.set_watchdog_timeout(timeout_ms))
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace esphome::http_request {
|
||||
|
||||
static const char *const TAG = "http_request.arduino";
|
||||
#ifdef USE_ESP8266
|
||||
static constexpr int RX_BUFFER_SIZE = 512;
|
||||
static constexpr int TX_BUFFER_SIZE = 512;
|
||||
// ESP8266 Arduino core (WiFiClientSecureBearSSL.cpp) returns -1000 on OOM
|
||||
static constexpr int ESP8266_SSL_ERR_OOM = -1000;
|
||||
#endif
|
||||
@@ -58,7 +56,7 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur
|
||||
ESP_LOGV(TAG, "ESP8266 HTTPS connection with WiFiClientSecure");
|
||||
stream_ptr = std::make_unique<WiFiClientSecure>();
|
||||
WiFiClientSecure *secure_client = static_cast<WiFiClientSecure *>(stream_ptr.get());
|
||||
secure_client->setBufferSizes(RX_BUFFER_SIZE, TX_BUFFER_SIZE);
|
||||
secure_client->setBufferSizes(this->tls_buffer_size_rx_, this->tls_buffer_size_tx_);
|
||||
secure_client->setInsecure();
|
||||
} else {
|
||||
stream_ptr = std::make_unique<WiFiClient>();
|
||||
@@ -138,8 +136,8 @@ std::shared_ptr<HttpContainer> HttpRequestArduino::perform(const std::string &ur
|
||||
}
|
||||
ESP_LOGW(TAG, "SSL failure: %s (Code: %d)", LOG_STR_ARG(error_msg), last_error);
|
||||
if (last_error == ESP8266_SSL_ERR_OOM) {
|
||||
ESP_LOGW(TAG, "Heap free: %u bytes, configured buffer sizes: %u bytes", ESP.getFreeHeap(),
|
||||
static_cast<unsigned int>(RX_BUFFER_SIZE + TX_BUFFER_SIZE));
|
||||
ESP_LOGW(TAG, "Configured TLS buffer sizes: %u/%u bytes, check max free heap block using the debug component",
|
||||
(unsigned int) this->tls_buffer_size_rx_, (unsigned int) this->tls_buffer_size_tx_);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Connection failure with no error code");
|
||||
|
||||
@@ -47,10 +47,20 @@ class HttpContainerArduino : public HttpContainer {
|
||||
};
|
||||
|
||||
class HttpRequestArduino : public HttpRequestComponent {
|
||||
public:
|
||||
#ifdef USE_ESP8266
|
||||
void set_tls_buffer_size_rx(uint16_t size) { this->tls_buffer_size_rx_ = size; }
|
||||
void set_tls_buffer_size_tx(uint16_t size) { this->tls_buffer_size_tx_ = size; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
std::shared_ptr<HttpContainer> perform(const std::string &url, const std::string &method, const std::string &body,
|
||||
const std::vector<Header> &request_headers,
|
||||
const std::vector<std::string> &lower_case_collect_headers) override;
|
||||
#ifdef USE_ESP8266
|
||||
uint16_t tls_buffer_size_rx_{512};
|
||||
uint16_t tls_buffer_size_tx_{512};
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace esphome::http_request
|
||||
|
||||
@@ -10,11 +10,13 @@ static const char *const TAG = "iaqcore";
|
||||
|
||||
enum IAQCoreErrorCode : uint8_t { ERROR_OK = 0, ERROR_RUNIN = 0x10, ERROR_BUSY = 0x01, ERROR_ERROR = 0x80 };
|
||||
|
||||
static constexpr size_t SENSOR_DATA_LENGTH = 9;
|
||||
|
||||
struct SensorData {
|
||||
uint16_t co2;
|
||||
IAQCoreErrorCode status;
|
||||
int32_t resistance;
|
||||
uint16_t co2;
|
||||
uint16_t tvoc;
|
||||
IAQCoreErrorCode status;
|
||||
|
||||
SensorData(const uint8_t *buffer) {
|
||||
this->co2 = encode_uint16(buffer[0], buffer[1]);
|
||||
@@ -33,9 +35,9 @@ void IAQCore::setup() {
|
||||
}
|
||||
|
||||
void IAQCore::update() {
|
||||
uint8_t buffer[sizeof(SensorData)];
|
||||
uint8_t buffer[SENSOR_DATA_LENGTH];
|
||||
|
||||
if (this->read_register(0xB5, buffer, sizeof(buffer)) != i2c::ERROR_OK) {
|
||||
if (this->read_register(0xB5, buffer, SENSOR_DATA_LENGTH) != i2c::ERROR_OK) {
|
||||
ESP_LOGD(TAG, "Read failed");
|
||||
this->status_set_warning();
|
||||
this->publish_nans_();
|
||||
|
||||
@@ -599,11 +599,7 @@ bool INA2XX::read_unsigned_16_(uint8_t reg, uint16_t &out) {
|
||||
}
|
||||
|
||||
int64_t INA2XX::two_complement_(uint64_t value, uint8_t bits) {
|
||||
if (value > (1ULL << (bits - 1))) {
|
||||
return (int64_t) (value - (1ULL << bits));
|
||||
} else {
|
||||
return (int64_t) value;
|
||||
}
|
||||
return (int64_t) (value << (64 - bits)) >> (64 - bits);
|
||||
}
|
||||
} // namespace ina2xx_base
|
||||
} // namespace esphome
|
||||
|
||||
@@ -407,7 +407,7 @@ void Inkplate::display1b_() {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t clock = (1 << this->cl_pin_->get_pin());
|
||||
uint32_t clock = (1UL << this->cl_pin_->get_pin());
|
||||
uint32_t data_mask = this->get_data_pin_mask_();
|
||||
ESP_LOGV(TAG, "Display1b start loops (%ums)", millis() - start_time);
|
||||
|
||||
@@ -575,7 +575,7 @@ void Inkplate::display3b_() {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t clock = (1 << this->cl_pin_->get_pin());
|
||||
uint32_t clock = (1UL << this->cl_pin_->get_pin());
|
||||
uint32_t data_mask = this->get_data_pin_mask_();
|
||||
uint32_t pos;
|
||||
uint32_t data;
|
||||
@@ -646,7 +646,7 @@ bool Inkplate::partial_update_() {
|
||||
int rep = (this->model_ == INKPLATE_6_V2) ? 6 : 5;
|
||||
|
||||
eink_on_();
|
||||
uint32_t clock = (1 << this->cl_pin_->get_pin());
|
||||
uint32_t clock = (1UL << this->cl_pin_->get_pin());
|
||||
uint32_t data_mask = this->get_data_pin_mask_();
|
||||
for (int k = 0; k < rep; k++) {
|
||||
vscan_start_();
|
||||
@@ -704,7 +704,7 @@ void Inkplate::vscan_start_() {
|
||||
}
|
||||
|
||||
void Inkplate::hscan_start_(uint32_t d) {
|
||||
uint8_t clock = (1 << this->cl_pin_->get_pin());
|
||||
uint32_t clock = (1UL << this->cl_pin_->get_pin());
|
||||
this->sph_pin_->digital_write(false);
|
||||
GPIO.out_w1ts = d | clock;
|
||||
GPIO.out_w1tc = this->get_data_pin_mask_() | clock;
|
||||
@@ -751,7 +751,7 @@ void Inkplate::clean_fast_(uint8_t c, uint8_t rep) {
|
||||
|
||||
uint32_t send = ((data & 0b00000011) << 4) | (((data & 0b00001100) >> 2) << 18) | (((data & 0b00010000) >> 4) << 23) |
|
||||
(((data & 0b11100000) >> 5) << 25);
|
||||
uint32_t clock = (1 << this->cl_pin_->get_pin());
|
||||
uint32_t clock = (1UL << this->cl_pin_->get_pin());
|
||||
|
||||
for (int k = 0; k < rep; k++) {
|
||||
vscan_start_();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "LwRx.h"
|
||||
#include <cstring>
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace lightwaverf {
|
||||
@@ -185,13 +186,20 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) {
|
||||
bool ret = true;
|
||||
int16_t j = 0; // int
|
||||
if (this->rx_msgcomplete && len <= RX_MSGLEN) {
|
||||
// Copy message under interrupt lock to prevent ISR overwriting rx_msg mid-read
|
||||
uint8_t msg_copy[RX_MSGLEN];
|
||||
{
|
||||
InterruptLock lock;
|
||||
memcpy(msg_copy, this->rx_msg, RX_MSGLEN);
|
||||
this->rx_msgcomplete = false;
|
||||
}
|
||||
for (uint8_t i = 0; ret && i < RX_MSGLEN; i++) {
|
||||
if (this->rx_translate || (len != RX_MSGLEN)) {
|
||||
j = this->rx_find_nibble_(this->rx_msg[i]);
|
||||
j = this->rx_find_nibble_(msg_copy[i]);
|
||||
if (j < 0)
|
||||
ret = false;
|
||||
} else {
|
||||
j = this->rx_msg[i];
|
||||
j = msg_copy[i];
|
||||
}
|
||||
switch (len) {
|
||||
case 4:
|
||||
@@ -199,6 +207,7 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) {
|
||||
buf[2] = j;
|
||||
if (i == 2)
|
||||
buf[3] = j;
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
if (i == 3)
|
||||
buf[0] = j;
|
||||
@@ -212,7 +221,6 @@ bool LwRx::lwrx_getmessage(uint8_t *buf, uint8_t len) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
this->rx_msgcomplete = false;
|
||||
} else {
|
||||
ret = false;
|
||||
}
|
||||
|
||||
@@ -105,8 +105,8 @@ class LwRx {
|
||||
|
||||
uint32_t rx_prev; // time of previous interrupt in microseconds
|
||||
|
||||
bool rx_msgcomplete = false; // set high when message available
|
||||
bool rx_translate = true; // Set false to get raw data
|
||||
volatile bool rx_msgcomplete = false; // set high when message available
|
||||
bool rx_translate = true; // Set false to get raw data
|
||||
|
||||
uint8_t rx_state = 0;
|
||||
|
||||
|
||||
@@ -192,7 +192,8 @@ void LwTx::lwtx_set_gap_multiplier(uint8_t gap_multiplier) { this->tx_gap_multip
|
||||
void LwTx::lw_timer_start() {
|
||||
{
|
||||
InterruptLock lock;
|
||||
static LwTx *arg = this; // NOLINT
|
||||
static LwTx *arg;
|
||||
arg = this;
|
||||
timer1_attachInterrupt([] { isr_t_xtimer(arg); });
|
||||
timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
|
||||
timer1_write(this->espPeriod);
|
||||
|
||||
@@ -62,8 +62,8 @@ class LwTx {
|
||||
uint8_t tx_repeats = 12; // Number of repeats of message sent
|
||||
uint8_t txon = 1;
|
||||
uint8_t txoff = 0;
|
||||
bool tx_msg_active = false; // set true to activate message sending
|
||||
bool tx_translate = true; // Set false to send raw data
|
||||
volatile bool tx_msg_active = false; // set true to activate message sending
|
||||
bool tx_translate = true; // Set false to send raw data
|
||||
|
||||
uint8_t tx_buf[TX_MSGLEN]; // the message buffer during reception
|
||||
uint8_t tx_repeat = 0; // counter for repeats
|
||||
|
||||
@@ -146,7 +146,6 @@ void LTRAlsPs501Component::update() {
|
||||
|
||||
void LTRAlsPs501Component::loop() {
|
||||
ErrorCode err = i2c::ERROR_OK;
|
||||
static uint8_t tries{0};
|
||||
|
||||
switch (this->state_) {
|
||||
case State::DELAYED_SETUP:
|
||||
@@ -175,20 +174,20 @@ void LTRAlsPs501Component::loop() {
|
||||
|
||||
case State::WAITING_FOR_DATA:
|
||||
if (this->is_als_data_ready_(this->als_readings_) == LtrDataAvail::LTR_DATA_OK) {
|
||||
tries = 0;
|
||||
this->tries_ = 0;
|
||||
ESP_LOGV(TAG, "Reading sensor data assuming gain = %.0fx, time = %d ms",
|
||||
get_gain_coeff(this->als_readings_.gain), get_itime_ms(this->als_readings_.integration_time));
|
||||
this->read_sensor_data_(this->als_readings_);
|
||||
this->apply_lux_calculation_(this->als_readings_);
|
||||
this->state_ = State::DATA_COLLECTED;
|
||||
} else if (tries >= MAX_TRIES) {
|
||||
} else if (this->tries_ >= MAX_TRIES) {
|
||||
ESP_LOGW(TAG, "Can't get data after several tries. Aborting.");
|
||||
tries = 0;
|
||||
this->tries_ = 0;
|
||||
this->status_set_warning();
|
||||
this->state_ = State::IDLE;
|
||||
return;
|
||||
} else {
|
||||
tries++;
|
||||
this->tries_++;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -230,21 +229,21 @@ void LTRAlsPs501Component::loop() {
|
||||
}
|
||||
|
||||
void LTRAlsPs501Component::check_and_trigger_ps_() {
|
||||
static uint32_t last_high_trigger_time{0};
|
||||
static uint32_t last_low_trigger_time{0};
|
||||
uint16_t ps_data = this->read_ps_data_();
|
||||
uint32_t now = millis();
|
||||
|
||||
if (ps_data != this->ps_readings_) {
|
||||
this->ps_readings_ = ps_data;
|
||||
// Higher values - object is closer to sensor
|
||||
if (ps_data > this->ps_threshold_high_ && now - last_high_trigger_time >= this->ps_cooldown_time_s_ * 1000) {
|
||||
last_high_trigger_time = now;
|
||||
if (ps_data > this->ps_threshold_high_ &&
|
||||
now - this->last_ps_high_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) {
|
||||
this->last_ps_high_trigger_time_ = now;
|
||||
ESP_LOGD(TAG, "Proximity high threshold triggered. Value = %d, Trigger level = %d", ps_data,
|
||||
this->ps_threshold_high_);
|
||||
this->on_ps_high_trigger_callback_.call();
|
||||
} else if (ps_data < this->ps_threshold_low_ && now - last_low_trigger_time >= this->ps_cooldown_time_s_ * 1000) {
|
||||
last_low_trigger_time = now;
|
||||
} else if (ps_data < this->ps_threshold_low_ &&
|
||||
now - this->last_ps_low_trigger_time_ >= this->ps_cooldown_time_s_ * 1000) {
|
||||
this->last_ps_low_trigger_time_ = now;
|
||||
ESP_LOGD(TAG, "Proximity low threshold triggered. Value = %d, Trigger level = %d", ps_data,
|
||||
this->ps_threshold_low_);
|
||||
this->on_ps_low_trigger_callback_.call();
|
||||
|
||||
@@ -74,6 +74,7 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice {
|
||||
READY_TO_PUBLISH,
|
||||
KEEP_PUBLISHING
|
||||
} state_{State::NOT_INITIALIZED};
|
||||
uint8_t tries_{0};
|
||||
|
||||
LtrType ltr_type_{LtrType::LTR_TYPE_ALS_ONLY};
|
||||
|
||||
@@ -130,6 +131,8 @@ class LTRAlsPs501Component : public PollingComponent, public i2c::I2CDevice {
|
||||
PsGain501 ps_gain_{PsGain501::PS_GAIN_1};
|
||||
uint16_t ps_threshold_high_{0xffff};
|
||||
uint16_t ps_threshold_low_{0x0000};
|
||||
uint32_t last_ps_high_trigger_time_{0};
|
||||
uint32_t last_ps_low_trigger_time_{0};
|
||||
|
||||
//
|
||||
// Sensors for publishing data
|
||||
|
||||
@@ -422,6 +422,9 @@ void LvglComponent::write_random_() {
|
||||
auto row = random_uint32() % this->disp_drv_.ver_res;
|
||||
row = row / this->draw_rounding * this->draw_rounding;
|
||||
auto size = ((random_uint32() % 32) / this->draw_rounding + 2) * this->draw_rounding - 1;
|
||||
// clamp size so the square fits within the draw buffer
|
||||
if ((size + 1) * (size + 1) > this->draw_buf_.size)
|
||||
size = static_cast<decltype(size)>(sqrtf(this->draw_buf_.size)) - 1;
|
||||
lv_area_t area;
|
||||
area.x1 = col;
|
||||
area.y1 = row;
|
||||
|
||||
@@ -288,9 +288,7 @@ void MipiRgb::draw_pixel_at(int x, int y, Color color) {
|
||||
if (!this->check_buffer_())
|
||||
return;
|
||||
size_t pos = (y * this->width_) + x;
|
||||
uint8_t hi_byte = static_cast<uint8_t>(color.r & 0xF8) | (color.g >> 5);
|
||||
uint8_t lo_byte = static_cast<uint8_t>((color.g & 0x1C) << 3) | (color.b >> 3);
|
||||
uint16_t new_color = hi_byte | (lo_byte << 8); // big endian
|
||||
uint16_t new_color = convert_big_endian(display::ColorUtil::color_to_565(color));
|
||||
if (this->buffer_[pos] == new_color)
|
||||
return;
|
||||
this->buffer_[pos] = new_color;
|
||||
@@ -315,10 +313,12 @@ void MipiRgb::fill(Color color) {
|
||||
}
|
||||
|
||||
auto *ptr_16 = reinterpret_cast<uint16_t *>(this->buffer_);
|
||||
uint8_t hi_byte = static_cast<uint8_t>(color.r & 0xF8) | (color.g >> 5);
|
||||
uint8_t lo_byte = static_cast<uint8_t>((color.g & 0x1C) << 3) | (color.b >> 3);
|
||||
uint16_t new_color = lo_byte | (hi_byte << 8); // little endian
|
||||
uint16_t new_color = convert_big_endian(display::ColorUtil::color_to_565(color));
|
||||
std::fill_n(ptr_16, this->width_ * this->height_, new_color);
|
||||
this->x_low_ = 0;
|
||||
this->y_low_ = 0;
|
||||
this->x_high_ = this->width_ - 1;
|
||||
this->y_high_ = this->height_ - 1;
|
||||
}
|
||||
|
||||
int MipiRgb::get_width() {
|
||||
|
||||
@@ -364,11 +364,7 @@ void MSA3xxComponent::setup_offset_(float offset_x, float offset_y, float offset
|
||||
}
|
||||
|
||||
int64_t MSA3xxComponent::twos_complement_(uint64_t value, uint8_t bits) {
|
||||
if (value > (1ULL << (bits - 1))) {
|
||||
return (int64_t) (value - (1ULL << bits));
|
||||
} else {
|
||||
return (int64_t) value;
|
||||
}
|
||||
return (int64_t) (value << (64 - bits)) >> (64 - bits);
|
||||
}
|
||||
|
||||
void binary_event_debounce(bool state, bool old_state, uint32_t now, uint32_t &last_ms, Trigger<> &trigger,
|
||||
|
||||
@@ -88,7 +88,7 @@ void NextionComponent::update_component_settings(bool force_update) {
|
||||
this->send_state_to_nextion();
|
||||
}
|
||||
|
||||
if (this->component_flags_.bco_needs_update || (force_update && this->component_flags_.bco2_is_set)) {
|
||||
if (this->component_flags_.bco_needs_update || (force_update && this->component_flags_.bco_is_set)) {
|
||||
this->nextion_->set_component_background_color(this->variable_name_.c_str(), this->bco_);
|
||||
this->component_flags_.bco_needs_update = false;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@ NdefRecordText::NdefRecordText(const std::vector<uint8_t> &payload) {
|
||||
|
||||
uint8_t language_code_length = payload[0] & 0b00111111; // Todo, make use of encoding bit?
|
||||
|
||||
if (1 + language_code_length > payload.size()) {
|
||||
ESP_LOGE(TAG, "Record payload too short for language code");
|
||||
return;
|
||||
}
|
||||
|
||||
this->language_code_ = std::string(payload.begin() + 1, payload.begin() + 1 + language_code_length);
|
||||
|
||||
this->text_ = std::string(payload.begin() + 1 + language_code_length, payload.end());
|
||||
|
||||
@@ -35,7 +35,7 @@ uint8_t guess_tag_type(uint8_t uid_length) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) {
|
||||
int8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) {
|
||||
for (uint8_t i = 0; i < MIFARE_CLASSIC_BLOCK_SIZE; i++) {
|
||||
if (data[i] == 0x00) {
|
||||
// Do nothing, skip
|
||||
@@ -49,17 +49,25 @@ uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data) {
|
||||
}
|
||||
|
||||
bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index) {
|
||||
if (data.size() < MIFARE_CLASSIC_BLOCK_SIZE) {
|
||||
ESP_LOGE(TAG, "Error, data too short for NDEF detection.");
|
||||
return false;
|
||||
}
|
||||
auto i = get_mifare_classic_ndef_start_index(data);
|
||||
if (data[i] != 0x03) {
|
||||
if (i < 0 || data[i] != 0x03) {
|
||||
ESP_LOGE(TAG, "Error, Can't decode message length.");
|
||||
return false;
|
||||
}
|
||||
if (data[i + 1] == 0xFF) {
|
||||
message_length = ((0xFF & data[i + 2]) << 8) | (0xFF & data[i + 3]);
|
||||
message_start_index = i + MIFARE_CLASSIC_LONG_TLV_SIZE;
|
||||
uint8_t idx = static_cast<uint8_t>(i);
|
||||
if (idx + 4 <= data.size() && data[idx + 1] == 0xFF) {
|
||||
message_length = ((0xFF & data[idx + 2]) << 8) | (0xFF & data[idx + 3]);
|
||||
message_start_index = idx + MIFARE_CLASSIC_LONG_TLV_SIZE;
|
||||
} else if (idx + 2 <= data.size()) {
|
||||
message_length = data[idx + 1];
|
||||
message_start_index = idx + MIFARE_CLASSIC_SHORT_TLV_SIZE;
|
||||
} else {
|
||||
message_length = data[i + 1];
|
||||
message_start_index = i + MIFARE_CLASSIC_SHORT_TLV_SIZE;
|
||||
ESP_LOGE(TAG, "Error, TLV data too short.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ ESPDEPRECATED("Use format_bytes_to() with stack buffer instead. Removed in 2026.
|
||||
std::string format_bytes(std::span<const uint8_t> bytes);
|
||||
|
||||
uint8_t guess_tag_type(uint8_t uid_length);
|
||||
uint8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data);
|
||||
int8_t get_mifare_classic_ndef_start_index(std::vector<uint8_t> &data);
|
||||
bool decode_mifare_classic_tlv(std::vector<uint8_t> &data, uint32_t &message_length, uint8_t &message_start_index);
|
||||
uint32_t get_mifare_classic_buffer_size(uint32_t message_length);
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@ from esphome.components.zephyr import (
|
||||
)
|
||||
from esphome.components.zephyr.const import (
|
||||
BOOTLOADER_MCUBOOT,
|
||||
CONF_CDC_ACM,
|
||||
KEY_BOOTLOADER,
|
||||
KEY_ZEPHYR,
|
||||
CdcAcm,
|
||||
)
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
@@ -159,6 +161,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Required(CONF_VERSION): cv.string_strict,
|
||||
}
|
||||
),
|
||||
cv.GenerateID(CONF_CDC_ACM): cv.declare_id(CdcAcm),
|
||||
}
|
||||
),
|
||||
set_framework,
|
||||
|
||||
@@ -2,42 +2,27 @@
|
||||
|
||||
#ifdef USE_NRF52_DFU
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/drivers/uart/cdc_acm.h>
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/zephyr/cdc_acm.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace nrf52 {
|
||||
|
||||
static const char *const TAG = "dfu";
|
||||
|
||||
volatile bool goto_dfu = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
static const uint32_t DFU_DBL_RESET_MAGIC = 0x5A1AD5; // SALADS
|
||||
|
||||
#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
|
||||
|
||||
static void cdc_dte_rate_callback(const struct device * /*unused*/, uint32_t rate) {
|
||||
if (rate == 1200) {
|
||||
goto_dfu = true;
|
||||
}
|
||||
}
|
||||
void DeviceFirmwareUpdate::setup() {
|
||||
this->reset_pin_->setup();
|
||||
const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)};
|
||||
for (auto &idx : cdc_dev) {
|
||||
cdc_acm_dte_rate_callback_set(idx, cdc_dte_rate_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceFirmwareUpdate::loop() {
|
||||
if (goto_dfu) {
|
||||
goto_dfu = false;
|
||||
volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C;
|
||||
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
|
||||
this->reset_pin_->digital_write(true);
|
||||
}
|
||||
#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT)
|
||||
zephyr::global_cdc_acm->add_on_rate_callback([this](const device *, uint32_t rate) {
|
||||
if (rate == 1200) {
|
||||
volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C;
|
||||
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
|
||||
this->reset_pin_->digital_write(true);
|
||||
}
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
void DeviceFirmwareUpdate::dump_config() {
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace nrf52 {
|
||||
class DeviceFirmwareUpdate : public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void loop() override;
|
||||
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
|
||||
void dump_config() override;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_OPENTHREAD
|
||||
#include "openthread.h"
|
||||
#include "esp_openthread.h"
|
||||
|
||||
#include <freertos/portmacro.h>
|
||||
|
||||
@@ -51,7 +50,7 @@ void OpenThreadComponent::on_state_changed_(otChangedFlags flags, void *context)
|
||||
auto *self = static_cast<OpenThreadComponent *>(context);
|
||||
// This runs on the OpenThread task thread with the OT lock held,
|
||||
// so we can safely call otThreadGetDeviceRole directly.
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
otInstance *instance = self->get_openthread_instance_();
|
||||
otDeviceRole role = otThreadGetDeviceRole(instance);
|
||||
self->connected_ = role >= OT_DEVICE_ROLE_CHILD;
|
||||
}
|
||||
@@ -233,16 +232,12 @@ bool OpenThreadComponent::teardown() {
|
||||
otSrpClientClearHostAndServices(instance);
|
||||
otSrpClientBuffersFreeAllServices(instance);
|
||||
global_openthread_component = nullptr;
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 0)
|
||||
ESP_LOGD(TAG, "Exit main loop ");
|
||||
int error = esp_openthread_mainloop_exit();
|
||||
int error = this->openthread_stop_();
|
||||
if (error != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Failed attempt to stop main loop %d", error);
|
||||
this->teardown_complete_ = true;
|
||||
}
|
||||
#else
|
||||
this->teardown_complete_ = true;
|
||||
#endif
|
||||
}
|
||||
return this->teardown_complete_;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ class OpenThreadComponent : public Component {
|
||||
protected:
|
||||
std::optional<otIp6Address> get_omr_address_(InstanceLock &lock);
|
||||
static void on_state_changed_(otChangedFlags flags, void *context);
|
||||
otInstance *get_openthread_instance_();
|
||||
int openthread_stop_();
|
||||
std::function<void()> factory_reset_external_callback_;
|
||||
#if CONFIG_OPENTHREAD_MTD
|
||||
uint32_t poll_period_{0};
|
||||
|
||||
@@ -190,6 +190,8 @@ void OpenThreadComponent::ot_main() {
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
int OpenThreadComponent::openthread_stop_() { return esp_openthread_mainloop_exit(); }
|
||||
|
||||
network::IPAddresses OpenThreadComponent::get_ip_addresses() {
|
||||
network::IPAddresses addresses;
|
||||
struct esp_ip6_addr if_ip6s[CONFIG_LWIP_IPV6_NUM_ADDRESSES];
|
||||
@@ -204,6 +206,9 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
// not thread safe, only use in read-only use cases
|
||||
otInstance *OpenThreadComponent::get_openthread_instance_() { return esp_openthread_get_instance(); }
|
||||
|
||||
std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
|
||||
if (esp_openthread_lock_acquire(delay)) {
|
||||
return InstanceLock();
|
||||
|
||||
@@ -137,6 +137,8 @@ class PacketDecoder {
|
||||
return DECODE_EMPTY;
|
||||
if (this->buffer_[this->position_] != key)
|
||||
return DECODE_UNMATCHED;
|
||||
if (this->position_ + 1 + sizeof(T) > this->len_)
|
||||
return DECODE_ERROR;
|
||||
this->position_++;
|
||||
T value = 0;
|
||||
for (size_t i = 0; i != sizeof(T); ++i) {
|
||||
|
||||
@@ -97,7 +97,7 @@ PIDAutotuner::PIDAutotuneResult PIDAutotuner::update(float setpoint, float proce
|
||||
}
|
||||
|
||||
bool zc_symmetrical = this->frequency_detector_.is_increase_decrease_symmetrical();
|
||||
bool amplitude_convergent = this->frequency_detector_.is_increase_decrease_symmetrical();
|
||||
bool amplitude_convergent = this->amplitude_detector_.is_amplitude_convergent();
|
||||
if (!zc_symmetrical || !amplitude_convergent) {
|
||||
// The frequency/amplitude is not fully accurate yet, try to wait
|
||||
// until the fault clears, or terminate after a while anyway
|
||||
@@ -362,7 +362,7 @@ bool PIDAutotuner::OscillationAmplitudeDetector::is_amplitude_convergent() const
|
||||
for (auto v : this->phase_mins)
|
||||
global_min = std::min(global_min, v);
|
||||
for (auto v : this->phase_maxs)
|
||||
global_max = std::min(global_max, v);
|
||||
global_max = std::max(global_max, v);
|
||||
float global_amplitude = (global_max - global_min) / 2.0f;
|
||||
float mean_amplitude = this->get_mean_oscillation_amplitude();
|
||||
return (mean_amplitude - global_amplitude) / (global_amplitude) < 0.05f;
|
||||
|
||||
@@ -647,6 +647,7 @@ void Pipsolar::handle_qpiws_(const char *message) {
|
||||
case 34:
|
||||
this->publish_binary_sensor_(enabled, this->warning_high_ac_input_during_bus_soft_start_);
|
||||
value_warnings_present |= enabled.value_or(false);
|
||||
break;
|
||||
case 35:
|
||||
this->publish_binary_sensor_(enabled, this->warning_battery_equalization_);
|
||||
value_warnings_present |= enabled.value_or(false);
|
||||
|
||||
@@ -49,7 +49,7 @@ bool PN532I2C::read_response(uint8_t command, std::vector<uint8_t> &data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data[1] != 0x00 && data[2] != 0x00 && data[3] != 0xFF) {
|
||||
if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) {
|
||||
// invalid packet
|
||||
ESP_LOGV(TAG, "read data invalid preamble!");
|
||||
return false;
|
||||
@@ -95,7 +95,7 @@ uint8_t PN532I2C::read_response_length_() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data[1] != 0x00 && data[2] != 0x00 && data[3] != 0xFF) {
|
||||
if (data[1] != 0x00 || data[2] != 0x00 || data[3] != 0xFF) {
|
||||
// invalid packet
|
||||
ESP_LOGV(TAG, "read data invalid preamble!");
|
||||
return 0;
|
||||
|
||||
@@ -66,12 +66,11 @@ optional<ParseResult> PVVXMiThermometer::parse_header_(const esp32_ble_tracker::
|
||||
return {};
|
||||
}
|
||||
|
||||
static uint8_t last_frame_count = 0;
|
||||
if (last_frame_count == raw[13]) {
|
||||
ESP_LOGVV(TAG, "parse_header(): duplicate data packet received (%hhu).", last_frame_count);
|
||||
if (this->last_frame_count_ == raw[13]) {
|
||||
ESP_LOGVV(TAG, "parse_header(): duplicate data packet received (%hhu).", this->last_frame_count_);
|
||||
return {};
|
||||
}
|
||||
last_frame_count = raw[13];
|
||||
this->last_frame_count_ = raw[13];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ class PVVXMiThermometer : public Component, public esp32_ble_tracker::ESPBTDevic
|
||||
sensor::Sensor *battery_voltage_{nullptr};
|
||||
sensor::Sensor *signal_strength_{nullptr};
|
||||
|
||||
uint8_t last_frame_count_{0};
|
||||
|
||||
optional<ParseResult> parse_header_(const esp32_ble_tracker::ServiceData &service_data);
|
||||
bool parse_message_(const std::vector<uint8_t> &message, ParseResult &result);
|
||||
bool report_results_(const optional<ParseResult> &result, const char *address);
|
||||
|
||||
@@ -222,7 +222,7 @@ bool SCD30Component::force_recalibration_with_reference(uint16_t co2_reference)
|
||||
}
|
||||
|
||||
uint16_t SCD30Component::get_forced_calibration_reference() {
|
||||
uint16_t forced_calibration_reference;
|
||||
uint16_t forced_calibration_reference = 0;
|
||||
// Get current CO2 calibration
|
||||
if (!this->get_register(SCD30_CMD_FORCED_CALIBRATION, forced_calibration_reference)) {
|
||||
ESP_LOGE(TAG, "Unable to read forced calibration reference.");
|
||||
|
||||
@@ -149,28 +149,25 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) {
|
||||
switch (this->current_frame_locate_) {
|
||||
case LOCATE_FRAME_HEADER: // starting buffer
|
||||
if (buffer == FRAME_HEADER_BUFFER) {
|
||||
this->current_frame_len_ = 1;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_len_ = 0;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
}
|
||||
break;
|
||||
case LOCATE_ID_FRAME1:
|
||||
this->current_frame_id_ = buffer << 8;
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
break;
|
||||
case LOCATE_ID_FRAME2:
|
||||
this->current_frame_id_ += buffer;
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
break;
|
||||
case LOCATE_LENGTH_FRAME_H:
|
||||
this->current_data_frame_len_ = buffer << 8;
|
||||
if (this->current_data_frame_len_ == 0x00) {
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
if (this->current_data_frame_len_ == 0) {
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
} else {
|
||||
this->current_frame_locate_ = LOCATE_FRAME_HEADER;
|
||||
@@ -181,15 +178,13 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) {
|
||||
if (this->current_data_frame_len_ > DATA_BUF_MAX_SIZE) {
|
||||
this->current_frame_locate_ = LOCATE_FRAME_HEADER;
|
||||
} else {
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
}
|
||||
break;
|
||||
case LOCATE_TYPE_FRAME1:
|
||||
this->current_frame_type_ = buffer << 8;
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
break;
|
||||
case LOCATE_TYPE_FRAME2:
|
||||
@@ -198,8 +193,7 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) {
|
||||
(this->current_frame_type_ == PEOPLE_EXIST_TYPE_BUFFER) ||
|
||||
(this->current_frame_type_ == RESULT_INSTALL_HEIGHT) || (this->current_frame_type_ == RESULT_PARAMETERS) ||
|
||||
(this->current_frame_type_ == RESULT_HEIGHT_THRESHOLD) || (this->current_frame_type_ == RESULT_SENSITIVITY)) {
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
} else {
|
||||
this->current_frame_locate_ = LOCATE_FRAME_HEADER;
|
||||
@@ -207,8 +201,7 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) {
|
||||
break;
|
||||
case LOCATE_HEAD_CKSUM_FRAME:
|
||||
if (validate_checksum(this->current_frame_buf_, this->current_frame_len_, buffer)) {
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "HEAD_CKSUM_FRAME ERROR: 0x%02x", buffer);
|
||||
@@ -223,21 +216,20 @@ void MR60FDA2Component::split_frame_(uint8_t buffer) {
|
||||
}
|
||||
break;
|
||||
case LOCATE_DATA_FRAME:
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_data_buf_[this->current_frame_len_ - LEN_TO_DATA_FRAME] = buffer;
|
||||
if (this->current_frame_len_ - LEN_TO_HEAD_CKSUM == this->current_data_frame_len_) {
|
||||
this->current_frame_locate_++;
|
||||
}
|
||||
if (this->current_frame_len_ > FRAME_BUF_MAX_SIZE) {
|
||||
if (this->current_frame_len_ >= FRAME_BUF_MAX_SIZE) {
|
||||
ESP_LOGD(TAG, "PRACTICE_DATA_FRAME_LEN ERROR: %d", this->current_frame_len_ - LEN_TO_HEAD_CKSUM);
|
||||
this->current_frame_locate_ = LOCATE_FRAME_HEADER;
|
||||
break;
|
||||
}
|
||||
this->current_data_buf_[this->current_frame_len_ - LEN_TO_DATA_FRAME + 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
if (this->current_frame_len_ - LEN_TO_HEAD_CKSUM == this->current_data_frame_len_) {
|
||||
this->current_frame_locate_++;
|
||||
}
|
||||
break;
|
||||
case LOCATE_DATA_CKSUM_FRAME:
|
||||
if (validate_checksum(this->current_data_buf_, this->current_data_frame_len_, buffer)) {
|
||||
this->current_frame_len_++;
|
||||
this->current_frame_buf_[this->current_frame_len_ - 1] = buffer;
|
||||
this->current_frame_buf_[this->current_frame_len_++] = buffer;
|
||||
this->current_frame_locate_++;
|
||||
this->process_frame_();
|
||||
} else {
|
||||
|
||||
@@ -20,7 +20,12 @@ void Sen21231Sensor::dump_config() {
|
||||
|
||||
void Sen21231Sensor::read_data_() {
|
||||
person_sensor_results_t results;
|
||||
this->read_bytes(PERSON_SENSOR_I2C_ADDRESS, (uint8_t *) &results, sizeof(results));
|
||||
if (!this->read_bytes(PERSON_SENSOR_I2C_ADDRESS, (uint8_t *) &results, sizeof(results))) {
|
||||
ESP_LOGW(TAG, "Failed to read data from SEN21231");
|
||||
this->status_set_warning();
|
||||
return;
|
||||
}
|
||||
this->status_clear_warning();
|
||||
ESP_LOGD(TAG, "SEN21231: %d faces detected", results.num_faces);
|
||||
this->publish_state(results.num_faces);
|
||||
if (results.num_faces == 1) {
|
||||
|
||||
@@ -188,8 +188,8 @@ bool ShellyDimmer::upgrade_firmware_() {
|
||||
break;
|
||||
}
|
||||
|
||||
std::memcpy(buffer, p, BUFFER_SIZE);
|
||||
p += BUFFER_SIZE;
|
||||
std::memcpy(buffer, p, len);
|
||||
p += len;
|
||||
|
||||
if (stm32_write_memory(stm32, addr, buffer, len) != STM32_ERR_OK) {
|
||||
ESP_LOGW(TAG, "Failed to write to STM32 flash memory");
|
||||
|
||||
@@ -12,10 +12,9 @@ void SMT100Component::update() {
|
||||
}
|
||||
|
||||
void SMT100Component::loop() {
|
||||
static char buffer[MAX_LINE_LENGTH];
|
||||
while (this->available() != 0) {
|
||||
if (readline_(read(), buffer, MAX_LINE_LENGTH) > 0) {
|
||||
int counts = (int) strtol((strtok(buffer, ",")), nullptr, 10);
|
||||
if (this->readline_(this->read(), this->readline_buffer_, MAX_LINE_LENGTH) > 0) {
|
||||
int counts = (int) strtol((strtok(this->readline_buffer_, ",")), nullptr, 10);
|
||||
float permittivity = (float) strtod((strtok(nullptr, ",")), nullptr);
|
||||
float moisture = (float) strtod((strtok(nullptr, ",")), nullptr);
|
||||
float temperature = (float) strtod((strtok(nullptr, ",")), nullptr);
|
||||
@@ -56,7 +55,6 @@ void SMT100Component::dump_config() {
|
||||
}
|
||||
|
||||
int SMT100Component::readline_(int readch, char *buffer, int len) {
|
||||
static int pos = 0;
|
||||
int rpos;
|
||||
|
||||
if (readch > 0) {
|
||||
@@ -64,13 +62,13 @@ int SMT100Component::readline_(int readch, char *buffer, int len) {
|
||||
case '\n': // Ignore new-lines
|
||||
break;
|
||||
case '\r': // Return on CR
|
||||
rpos = pos;
|
||||
pos = 0; // Reset position index ready for next time
|
||||
rpos = this->readline_pos_;
|
||||
this->readline_pos_ = 0; // Reset position index ready for next time
|
||||
return rpos;
|
||||
default:
|
||||
if (pos < len - 1) {
|
||||
buffer[pos++] = readch;
|
||||
buffer[pos] = 0;
|
||||
if (this->readline_pos_ < len - 1) {
|
||||
buffer[this->readline_pos_++] = readch;
|
||||
buffer[this->readline_pos_] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ class SMT100Component : public PollingComponent, public uart::UARTDevice {
|
||||
protected:
|
||||
int readline_(int readch, char *buffer, int len);
|
||||
|
||||
char readline_buffer_[MAX_LINE_LENGTH]{};
|
||||
int readline_pos_{0};
|
||||
|
||||
sensor::Sensor *counts_sensor_{nullptr};
|
||||
sensor::Sensor *permittivity_sensor_{nullptr};
|
||||
sensor::Sensor *moisture_sensor_{nullptr};
|
||||
|
||||
@@ -52,7 +52,11 @@ template<uint8_t SZ> class TextSaver : public TemplateTextSaverBase {
|
||||
bool hasdata = this->pref_.load(&temp);
|
||||
|
||||
if (hasdata) {
|
||||
value.assign(temp + 1, (size_t) temp[0]);
|
||||
size_t len = static_cast<uint8_t>(temp[0]);
|
||||
if (len > SZ) {
|
||||
len = SZ;
|
||||
}
|
||||
value.assign(temp + 1, len);
|
||||
}
|
||||
|
||||
this->prev_.assign(value);
|
||||
|
||||
@@ -4,6 +4,7 @@ from esphome.components import water_heater
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_AWAY,
|
||||
CONF_CURRENT_TEMPERATURE,
|
||||
CONF_ID,
|
||||
CONF_MODE,
|
||||
CONF_OPTIMISTIC,
|
||||
@@ -18,7 +19,6 @@ from esphome.types import ConfigType
|
||||
|
||||
from .. import template_ns
|
||||
|
||||
CONF_CURRENT_TEMPERATURE = "current_temperature"
|
||||
CONF_IS_ON = "is_on"
|
||||
|
||||
TemplateWaterHeater = template_ns.class_(
|
||||
|
||||
@@ -124,17 +124,10 @@ void HostUartComponent::setup() {
|
||||
fcntl(this->file_descriptor_, F_SETFL, 0);
|
||||
struct termios options;
|
||||
tcgetattr(this->file_descriptor_, &options);
|
||||
cfmakeraw(&options);
|
||||
options.c_cflag &= ~CRTSCTS;
|
||||
options.c_cflag |= CREAD | CLOCAL;
|
||||
options.c_lflag &= ~ICANON;
|
||||
options.c_lflag &= ~ECHO;
|
||||
options.c_lflag &= ~ECHOE;
|
||||
options.c_lflag &= ~ECHONL;
|
||||
options.c_lflag &= ~ISIG;
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY);
|
||||
options.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL);
|
||||
options.c_oflag &= ~OPOST;
|
||||
options.c_oflag &= ~ONLCR;
|
||||
options.c_iflag &= ~(IXOFF | IXANY);
|
||||
// Set data bits
|
||||
options.c_cflag &= ~CSIZE; // Mask the character size bits
|
||||
switch (this->data_bits_) {
|
||||
|
||||
@@ -110,7 +110,7 @@ void LibreTinyUARTComponent::setup() {
|
||||
#if LT_HW_UART2
|
||||
ESP_LOGE(TAG, " TX=%u, RX=%u", PIN_SERIAL2_TX, PIN_SERIAL2_RX);
|
||||
#endif
|
||||
this->mark_failed();
|
||||
this->mark_failed(LOG_STR("SoftwareSerial is not implemented for this chip."));
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -445,6 +445,7 @@ void WeikaiChannel::flush() {
|
||||
}
|
||||
|
||||
size_t WeikaiChannel::xfer_fifo_to_buffer_() {
|
||||
size_t total = 0;
|
||||
size_t to_transfer;
|
||||
size_t free;
|
||||
while ((to_transfer = this->rx_in_fifo_()) && (free = this->receive_buffer_.free())) {
|
||||
@@ -458,9 +459,10 @@ size_t WeikaiChannel::xfer_fifo_to_buffer_() {
|
||||
this->reg(0).read_fifo(data, to_transfer);
|
||||
for (size_t i = 0; i < to_transfer; i++)
|
||||
this->receive_buffer_.push(data[i]);
|
||||
total += to_transfer;
|
||||
}
|
||||
} // while work to do
|
||||
return to_transfer;
|
||||
return total;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
@@ -5,11 +5,13 @@ from typing import TypedDict
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import CONF_BOARD, KEY_CORE, KEY_FRAMEWORK_VERSION
|
||||
from esphome.core import CORE
|
||||
from esphome.core import CORE, CoroPriority, coroutine_with_priority
|
||||
from esphome.helpers import copy_file_if_changed, write_file_if_changed
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .const import (
|
||||
BOOTLOADER_MCUBOOT,
|
||||
CONF_CDC_ACM,
|
||||
KEY_BOARD,
|
||||
KEY_BOOTLOADER,
|
||||
KEY_EXTRA_BUILD_FILES,
|
||||
@@ -54,7 +56,7 @@ class ZephyrData(TypedDict):
|
||||
user: dict[str, list[str]]
|
||||
|
||||
|
||||
def zephyr_set_core_data(config):
|
||||
def zephyr_set_core_data(config: ConfigType) -> None:
|
||||
CORE.data[KEY_ZEPHYR] = ZephyrData(
|
||||
board=config[CONF_BOARD],
|
||||
bootloader=config[KEY_BOOTLOADER],
|
||||
@@ -64,7 +66,6 @@ def zephyr_set_core_data(config):
|
||||
pm_static=[],
|
||||
user={},
|
||||
)
|
||||
return config
|
||||
|
||||
|
||||
def zephyr_data() -> ZephyrData:
|
||||
@@ -110,7 +111,7 @@ def add_extra_script(stage: str, filename: str, path: Path) -> None:
|
||||
cg.add_platformio_option("extra_scripts", [key])
|
||||
|
||||
|
||||
def zephyr_to_code(config):
|
||||
def zephyr_to_code(config: ConfigType) -> None:
|
||||
cg.add_build_flag("-DUSE_ZEPHYR")
|
||||
cg.add_define("USE_NATIVE_64BIT_TIME")
|
||||
cg.set_cpp_standard("gnu++20")
|
||||
@@ -132,6 +133,15 @@ def zephyr_to_code(config):
|
||||
Path(__file__).parent / "pre_build.py.script",
|
||||
)
|
||||
|
||||
CORE.add_job(_cdc_acm_to_code, config)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _cdc_acm_to_code(config: ConfigType) -> None:
|
||||
if "CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT" in zephyr_data()[KEY_PRJ_CONF]:
|
||||
var = cg.new_Pvariable(config[CONF_CDC_ACM])
|
||||
await cg.register_component(var, {})
|
||||
|
||||
|
||||
def zephyr_setup_preferences():
|
||||
cg.add(zephyr_ns.setup_preferences())
|
||||
@@ -151,7 +161,7 @@ def _format_prj_conf_val(value: PrjConfValueType) -> str:
|
||||
raise ValueError
|
||||
|
||||
|
||||
def zephyr_add_cdc_acm(config, id):
|
||||
def zephyr_add_cdc_acm(config: ConfigType, id: int) -> None:
|
||||
framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
|
||||
if CORE.is_nrf52 and framework_ver >= cv.Version(3, 2, 0):
|
||||
zephyr_add_prj_conf("CONFIG_USB_DEVICE_STACK_NEXT", False)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT)
|
||||
#include "cdc_acm.h"
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/drivers/uart/cdc_acm.h>
|
||||
|
||||
#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
|
||||
|
||||
namespace esphome::zephyr {
|
||||
|
||||
CdcAcm::CdcAcm() { global_cdc_acm = this; }
|
||||
|
||||
void CdcAcm::setup() {
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart)
|
||||
const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)};
|
||||
for (auto &idx : cdc_dev) {
|
||||
// only one global callback can be registered
|
||||
cdc_acm_dte_rate_callback_set(idx, CdcAcm::cdc_dte_rate_callback_);
|
||||
}
|
||||
#endif // DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart)
|
||||
}
|
||||
|
||||
void CdcAcm::cdc_dte_rate_callback_(const struct device *device, uint32_t rate) {
|
||||
global_cdc_acm->defer([device, rate]() { global_cdc_acm->rate_callbacks_.call(device, rate); });
|
||||
}
|
||||
|
||||
CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome::zephyr
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT)
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include <zephyr/device.h>
|
||||
|
||||
namespace esphome::zephyr {
|
||||
|
||||
class CdcAcm : public Component {
|
||||
public:
|
||||
CdcAcm();
|
||||
void setup() override;
|
||||
void add_on_rate_callback(std::function<void(const device *, uint32_t)> &&callback) {
|
||||
this->rate_callbacks_.add(std::move(callback));
|
||||
}
|
||||
|
||||
protected:
|
||||
static void cdc_dte_rate_callback_(const device *device, uint32_t rate);
|
||||
CallbackManager<void(const device *, uint32_t)> rate_callbacks_;
|
||||
};
|
||||
|
||||
extern CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
} // namespace esphome::zephyr
|
||||
|
||||
#endif
|
||||
@@ -14,3 +14,5 @@ KEY_BOARD: Final = "board"
|
||||
KEY_USER: Final = "user"
|
||||
|
||||
zephyr_ns = cg.esphome_ns.namespace("zephyr")
|
||||
CdcAcm = zephyr_ns.class_("CdcAcm", cg.Component)
|
||||
CONF_CDC_ACM = "cdc_acm"
|
||||
|
||||
@@ -274,6 +274,7 @@ CONF_CURRENT = "current"
|
||||
CONF_CURRENT_HUMIDITY_STATE_TOPIC = "current_humidity_state_topic"
|
||||
CONF_CURRENT_OPERATION = "current_operation"
|
||||
CONF_CURRENT_RESISTOR = "current_resistor"
|
||||
CONF_CURRENT_TEMPERATURE = "current_temperature"
|
||||
CONF_CURRENT_TEMPERATURE_STATE_TOPIC = "current_temperature_state_topic"
|
||||
CONF_CUSTOM = "custom"
|
||||
CONF_CUSTOM_FAN_MODE = "custom_fan_mode"
|
||||
|
||||
@@ -422,15 +422,11 @@ void Component::status_set_error(const LogString *message) {
|
||||
store_component_error_message(this, LOG_STR_ARG(message), true);
|
||||
}
|
||||
}
|
||||
void Component::status_clear_warning() {
|
||||
if ((this->component_state_ & STATUS_LED_WARNING) == 0)
|
||||
return;
|
||||
void Component::status_clear_warning_slow_path_() {
|
||||
this->component_state_ &= ~STATUS_LED_WARNING;
|
||||
ESP_LOGW(TAG, "%s cleared Warning flag", LOG_STR_ARG(this->get_component_log_str()));
|
||||
}
|
||||
void Component::status_clear_error() {
|
||||
if ((this->component_state_ & STATUS_LED_ERROR) == 0)
|
||||
return;
|
||||
void Component::status_clear_error_slow_path_() {
|
||||
this->component_state_ &= ~STATUS_LED_ERROR;
|
||||
ESP_LOGE(TAG, "%s cleared Error flag", LOG_STR_ARG(this->get_component_log_str()));
|
||||
}
|
||||
|
||||
@@ -251,9 +251,17 @@ class Component {
|
||||
void status_set_error(const char *message);
|
||||
void status_set_error(const LogString *message);
|
||||
|
||||
void status_clear_warning();
|
||||
void status_clear_warning() {
|
||||
if ((this->component_state_ & STATUS_LED_WARNING) == 0)
|
||||
return;
|
||||
this->status_clear_warning_slow_path_();
|
||||
}
|
||||
|
||||
void status_clear_error();
|
||||
void status_clear_error() {
|
||||
if ((this->component_state_ & STATUS_LED_ERROR) == 0)
|
||||
return;
|
||||
this->status_clear_error_slow_path_();
|
||||
}
|
||||
|
||||
/** Set warning status flag and automatically clear it after a timeout.
|
||||
*
|
||||
@@ -505,6 +513,9 @@ class Component {
|
||||
bool cancel_defer(const char *name); // NOLINT
|
||||
bool cancel_defer(uint32_t id); // NOLINT
|
||||
|
||||
void status_clear_warning_slow_path_();
|
||||
void status_clear_error_slow_path_();
|
||||
|
||||
// Ordered for optimal packing on 32-bit systems
|
||||
const LogString *component_source_{nullptr};
|
||||
uint16_t warn_if_blocking_over_{WARN_IF_BLOCKING_OVER_MS}; ///< Warn if blocked for this many ms (max 65.5s)
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ platformio==6.1.19
|
||||
esptool==5.2.0
|
||||
click==8.3.1
|
||||
esphome-dashboard==20260210.0
|
||||
aioesphomeapi==44.2.0
|
||||
aioesphomeapi==44.3.1
|
||||
zeroconf==0.148.0
|
||||
puremagic==1.30
|
||||
ruamel.yaml==0.19.1 # dashboard_import
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pylint==4.0.5
|
||||
flake8==7.3.0 # also change in .pre-commit-config.yaml when updating
|
||||
ruff==0.15.4 # also change in .pre-commit-config.yaml when updating
|
||||
ruff==0.15.5 # also change in .pre-commit-config.yaml when updating
|
||||
pyupgrade==3.21.2 # also change in .pre-commit-config.yaml when updating
|
||||
pre-commit
|
||||
|
||||
|
||||
@@ -690,15 +690,12 @@ class MessageType(TypeInfo):
|
||||
|
||||
@property
|
||||
def encode_func(self) -> str:
|
||||
return "encode_message"
|
||||
return "encode_optional_sub_message"
|
||||
|
||||
@property
|
||||
def encode_content(self) -> str:
|
||||
# Singular message fields pass force=false (skip empty messages)
|
||||
# The default for encode_nested_message is force=true (for repeated fields)
|
||||
return (
|
||||
f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, false);"
|
||||
)
|
||||
# Singular message fields skip encoding when empty
|
||||
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});"
|
||||
|
||||
@property
|
||||
def decode_length(self) -> str:
|
||||
@@ -1322,9 +1319,9 @@ class FixedArrayRepeatedType(TypeInfo):
|
||||
"""Helper to generate encode statement for a single element."""
|
||||
if isinstance(self._ti, EnumType):
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);"
|
||||
# MessageType.encode_message doesn't have a force parameter
|
||||
# Repeated message elements use encode_sub_message (force=true is default)
|
||||
if isinstance(self._ti, MessageType):
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, {element});"
|
||||
return f"buffer.encode_sub_message({self.number}, {element});"
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);"
|
||||
|
||||
@property
|
||||
@@ -1650,9 +1647,9 @@ class RepeatedTypeInfo(TypeInfo):
|
||||
"""Helper to generate encode call for a single element."""
|
||||
if isinstance(self._ti, EnumType):
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, static_cast<uint32_t>({element}), true);"
|
||||
# MessageType.encode_message doesn't have a force parameter
|
||||
# Repeated message elements use encode_sub_message (force=true is default)
|
||||
if isinstance(self._ti, MessageType):
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, {element});"
|
||||
return f"buffer.encode_sub_message({self.number}, {element});"
|
||||
return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);"
|
||||
|
||||
@property
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<<: !include common.yaml
|
||||
@@ -1,4 +1,6 @@
|
||||
substitutions:
|
||||
verify_ssl: "false"
|
||||
|
||||
<<: !include common.yaml
|
||||
|
||||
http_request:
|
||||
verify_ssl: false
|
||||
tls_buffer_size_rx: 16384
|
||||
tls_buffer_size_tx: 512
|
||||
|
||||
Reference in New Issue
Block a user