mirror of
https://github.com/esphome/esphome.git
synced 2026-09-15 09:08:41 +00:00
Merge branch 'inline-varint-parse-fast-path' into integration
This commit is contained in:
@@ -58,7 +58,10 @@ void HOT AddressableLightDisplay::draw_absolute_pixel_internal(int x, int y, Col
|
||||
|
||||
if (this->pixel_mapper_f_.has_value()) {
|
||||
// Params are passed by reference, so they may be modified in call.
|
||||
this->addressable_light_buffer_[(*this->pixel_mapper_f_)(x, y)] = color;
|
||||
int index = (*this->pixel_mapper_f_)(x, y);
|
||||
if (index < 0 || static_cast<size_t>(index) >= this->addressable_light_buffer_.size())
|
||||
return;
|
||||
this->addressable_light_buffer_[index] = color;
|
||||
} else {
|
||||
this->addressable_light_buffer_[y * this->get_width_internal() + x] = color;
|
||||
}
|
||||
|
||||
@@ -128,37 +128,37 @@ APIError APIPlaintextFrameHelper::try_read_frame_() {
|
||||
|
||||
// Skip indicator byte at position 0
|
||||
uint8_t varint_pos = 1;
|
||||
uint32_t consumed = 0;
|
||||
|
||||
auto msg_size_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos, &consumed);
|
||||
// rx_header_buf_pos_ >= 3 and varint_pos == 1, so len >= 2
|
||||
auto msg_size_varint = ProtoVarInt::parse_non_empty(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos);
|
||||
if (!msg_size_varint.has_value()) {
|
||||
// not enough data there yet
|
||||
continue;
|
||||
}
|
||||
|
||||
if (msg_size_varint->as_uint32() > MAX_MESSAGE_SIZE) {
|
||||
if (msg_size_varint.value > MAX_MESSAGE_SIZE) {
|
||||
state_ = State::FAILED;
|
||||
HELPER_LOG("Bad packet: message size %" PRIu32 " exceeds maximum %u", msg_size_varint->as_uint32(),
|
||||
MAX_MESSAGE_SIZE);
|
||||
HELPER_LOG("Bad packet: message size %" PRIu32 " exceeds maximum %u",
|
||||
static_cast<uint32_t>(msg_size_varint.value), MAX_MESSAGE_SIZE);
|
||||
return APIError::BAD_DATA_PACKET;
|
||||
}
|
||||
rx_header_parsed_len_ = msg_size_varint->as_uint16();
|
||||
rx_header_parsed_len_ = static_cast<uint16_t>(msg_size_varint.value);
|
||||
|
||||
// Move to next varint position
|
||||
varint_pos += consumed;
|
||||
varint_pos += msg_size_varint.consumed;
|
||||
|
||||
auto msg_type_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos, &consumed);
|
||||
auto msg_type_varint = ProtoVarInt::parse(&rx_header_buf_[varint_pos], rx_header_buf_pos_ - varint_pos);
|
||||
if (!msg_type_varint.has_value()) {
|
||||
// not enough data there yet
|
||||
continue;
|
||||
}
|
||||
if (msg_type_varint->as_uint32() > std::numeric_limits<uint16_t>::max()) {
|
||||
if (msg_type_varint.value > std::numeric_limits<uint16_t>::max()) {
|
||||
state_ = State::FAILED;
|
||||
HELPER_LOG("Bad packet: message type %" PRIu32 " exceeds maximum %u", msg_type_varint->as_uint32(),
|
||||
std::numeric_limits<uint16_t>::max());
|
||||
HELPER_LOG("Bad packet: message type %" PRIu32 " exceeds maximum %u",
|
||||
static_cast<uint32_t>(msg_type_varint.value), std::numeric_limits<uint16_t>::max());
|
||||
return APIError::BAD_DATA_PACKET;
|
||||
}
|
||||
rx_header_parsed_type_ = msg_type_varint->as_uint16();
|
||||
rx_header_parsed_type_ = static_cast<uint16_t>(msg_type_varint.value);
|
||||
rx_header_parsed_ = true;
|
||||
}
|
||||
// header reading done
|
||||
|
||||
+215
-215
File diff suppressed because it is too large
Load Diff
@@ -399,7 +399,7 @@ class HelloRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class HelloResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -688,7 +688,7 @@ class CoverCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_FAN
|
||||
@@ -756,7 +756,7 @@ class FanCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_LIGHT
|
||||
@@ -846,7 +846,7 @@ class LightCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
@@ -936,7 +936,7 @@ class SwitchCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
@@ -988,7 +988,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SubscribeLogsResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -1110,7 +1110,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_API_HOMEASSISTANT_STATES
|
||||
@@ -1176,7 +1176,7 @@ class DSTRule final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class ParsedTimezone final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -1190,7 +1190,7 @@ class ParsedTimezone final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class GetTimeResponse final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -1260,7 +1260,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class ExecuteServiceRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -1285,7 +1285,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
|
||||
@@ -1364,7 +1364,7 @@ class CameraImageRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_CLIMATE
|
||||
@@ -1463,7 +1463,7 @@ class ClimateCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_WATER_HEATER
|
||||
@@ -1527,7 +1527,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_NUMBER
|
||||
@@ -1583,7 +1583,7 @@ class NumberCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SELECT
|
||||
@@ -1635,7 +1635,7 @@ class SelectCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_SIREN
|
||||
@@ -1695,7 +1695,7 @@ class SirenCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_LOCK
|
||||
@@ -1751,7 +1751,7 @@ class LockCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_BUTTON
|
||||
@@ -1784,7 +1784,7 @@ class ButtonCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
@@ -1861,7 +1861,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_BLUETOOTH_PROXY
|
||||
@@ -1878,7 +1878,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothLERawAdvertisement final : public ProtoMessage {
|
||||
public:
|
||||
@@ -1928,7 +1928,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothDeviceConnectionResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -1962,7 +1962,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTDescriptor final : public ProtoMessage {
|
||||
public:
|
||||
@@ -2053,7 +2053,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTReadResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -2096,7 +2096,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2112,7 +2112,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2131,7 +2131,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2148,7 +2148,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothGATTNotifyDataResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -2328,7 +2328,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_VOICE_ASSISTANT
|
||||
@@ -2346,7 +2346,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantAudioSettings final : public ProtoMessage {
|
||||
public:
|
||||
@@ -2395,7 +2395,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantEventData final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2423,7 +2423,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantAudio final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2443,7 +2443,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2464,7 +2464,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2483,7 +2483,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantAnnounceFinished final : public ProtoMessage {
|
||||
public:
|
||||
@@ -2529,7 +2529,7 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -2631,7 +2631,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_TEXT
|
||||
@@ -2686,7 +2686,7 @@ class TextCommandRequest final : public CommandProtoMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATE
|
||||
@@ -2740,7 +2740,7 @@ class DateCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_TIME
|
||||
@@ -2794,7 +2794,7 @@ class TimeCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_EVENT
|
||||
@@ -2885,7 +2885,7 @@ class ValveCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_DATETIME_DATETIME
|
||||
@@ -2935,7 +2935,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_UPDATE
|
||||
@@ -2993,7 +2993,7 @@ class UpdateCommandRequest final : public CommandProtoMessage {
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_ZWAVE_PROXY
|
||||
@@ -3033,7 +3033,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
#endif
|
||||
#ifdef USE_INFRARED
|
||||
@@ -3078,7 +3078,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage {
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class InfraredRFReceiveEvent final : public ProtoMessage {
|
||||
public:
|
||||
@@ -3120,7 +3120,7 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SerialProxyDataReceived final : public ProtoMessage {
|
||||
public:
|
||||
@@ -3160,7 +3160,7 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage {
|
||||
|
||||
protected:
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -3176,7 +3176,7 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
public:
|
||||
@@ -3191,7 +3191,7 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SerialProxyGetModemPinsResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -3224,7 +3224,7 @@ class SerialProxyRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class SerialProxyRequestResponse final : public ProtoMessage {
|
||||
public:
|
||||
@@ -3264,7 +3264,7 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;
|
||||
};
|
||||
class BluetoothSetConnectionParamsResponse final : public ProtoMessage {
|
||||
public:
|
||||
|
||||
@@ -20,20 +20,40 @@ void ProtoWriteBuffer::encode_varint_raw_slow_(uint32_t value) {
|
||||
*this->pos_++ = static_cast<uint8_t>(value);
|
||||
}
|
||||
|
||||
ProtoVarIntResult ProtoVarInt::parse_slow(const uint8_t *buffer, uint32_t len) {
|
||||
// Multi-byte varint: first byte already checked to have high bit set
|
||||
uint32_t result32 = buffer[0] & 0x7F;
|
||||
#ifdef USE_API_VARINT64
|
||||
optional<ProtoVarInt> ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed,
|
||||
uint32_t result32) {
|
||||
uint32_t limit = std::min(len, uint32_t(4));
|
||||
#else
|
||||
uint32_t limit = std::min(len, uint32_t(5));
|
||||
#endif
|
||||
for (uint32_t i = 1; i < limit; i++) {
|
||||
uint8_t val = buffer[i];
|
||||
result32 |= uint32_t(val & 0x7F) << (i * 7);
|
||||
if ((val & 0x80) == 0) {
|
||||
return {result32, i + 1};
|
||||
}
|
||||
}
|
||||
#ifdef USE_API_VARINT64
|
||||
return parse_wide(buffer, len, result32);
|
||||
#else
|
||||
return {0, 0};
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_API_VARINT64
|
||||
ProtoVarIntResult ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) {
|
||||
uint64_t result64 = result32;
|
||||
uint32_t limit = std::min(len, uint32_t(10));
|
||||
for (uint32_t i = 4; i < limit; i++) {
|
||||
uint8_t val = buffer[i];
|
||||
result64 |= uint64_t(val & 0x7F) << (i * 7);
|
||||
if ((val & 0x80) == 0) {
|
||||
*consumed = i + 1;
|
||||
return ProtoVarInt(result64);
|
||||
return {result64, i + 1};
|
||||
}
|
||||
}
|
||||
return {};
|
||||
return {0, 0};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -43,18 +63,16 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size
|
||||
const uint8_t *end = buffer + length;
|
||||
|
||||
while (ptr < end) {
|
||||
uint32_t consumed;
|
||||
|
||||
// Parse field header (tag)
|
||||
auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
// Parse field header (tag) - ptr < end guarantees len >= 1
|
||||
auto res = ProtoVarInt::parse_non_empty(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
break; // Invalid data, stop counting
|
||||
}
|
||||
|
||||
uint32_t tag = res->as_uint32();
|
||||
uint32_t tag = static_cast<uint32_t>(res.value);
|
||||
uint32_t field_type = tag & WIRE_TYPE_MASK;
|
||||
uint32_t field_id = tag >> 3;
|
||||
ptr += consumed;
|
||||
ptr += res.consumed;
|
||||
|
||||
// Count if this is the target field
|
||||
if (field_id == target_field_id) {
|
||||
@@ -64,20 +82,20 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size
|
||||
// Skip field data based on wire type
|
||||
switch (field_type) {
|
||||
case WIRE_TYPE_VARINT: { // VarInt - parse and skip
|
||||
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
res = ProtoVarInt::parse(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
return count; // Invalid data, return what we have
|
||||
}
|
||||
ptr += consumed;
|
||||
ptr += res.consumed;
|
||||
break;
|
||||
}
|
||||
case WIRE_TYPE_LENGTH_DELIMITED: { // Length-delimited - parse length and skip data
|
||||
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
res = ProtoVarInt::parse(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
return count;
|
||||
}
|
||||
uint32_t field_length = res->as_uint32();
|
||||
ptr += consumed;
|
||||
uint32_t field_length = static_cast<uint32_t>(res.value);
|
||||
ptr += res.consumed;
|
||||
if (field_length > static_cast<size_t>(end - ptr)) {
|
||||
return count; // Out of bounds
|
||||
}
|
||||
@@ -190,41 +208,40 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
|
||||
const uint8_t *end = buffer + length;
|
||||
|
||||
while (ptr < end) {
|
||||
uint32_t consumed;
|
||||
|
||||
// Parse field header
|
||||
auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
// Parse field header - ptr < end guarantees len >= 1
|
||||
auto res = ProtoVarInt::parse_non_empty(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
ESP_LOGV(TAG, "Invalid field start at offset %ld", (long) (ptr - buffer));
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t tag = res->as_uint32();
|
||||
uint32_t tag = static_cast<uint32_t>(res.value);
|
||||
uint32_t field_type = tag & WIRE_TYPE_MASK;
|
||||
uint32_t field_id = tag >> 3;
|
||||
ptr += consumed;
|
||||
ptr += res.consumed;
|
||||
|
||||
switch (field_type) {
|
||||
case WIRE_TYPE_VARINT: { // VarInt
|
||||
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
res = ProtoVarInt::parse(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer));
|
||||
return;
|
||||
}
|
||||
if (!this->decode_varint(field_id, *res)) {
|
||||
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
|
||||
if (!this->decode_varint(field_id, res.value)) {
|
||||
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu64 "!", field_id,
|
||||
static_cast<uint64_t>(res.value));
|
||||
}
|
||||
ptr += consumed;
|
||||
ptr += res.consumed;
|
||||
break;
|
||||
}
|
||||
case WIRE_TYPE_LENGTH_DELIMITED: { // Length-delimited
|
||||
res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
|
||||
res = ProtoVarInt::parse(ptr, end - ptr);
|
||||
if (!res.has_value()) {
|
||||
ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer));
|
||||
return;
|
||||
}
|
||||
uint32_t field_length = res->as_uint32();
|
||||
ptr += consumed;
|
||||
uint32_t field_length = static_cast<uint32_t>(res.value);
|
||||
ptr += res.consumed;
|
||||
if (field_length > static_cast<size_t>(end - ptr)) {
|
||||
ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer));
|
||||
return;
|
||||
|
||||
@@ -99,90 +99,56 @@ inline void encode_varint_to_buffer(uint32_t val, uint8_t *buffer) {
|
||||
* within the same function scope where temporaries are created.
|
||||
*/
|
||||
|
||||
/// Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit
|
||||
/// Type used for decoded varint values - uint64_t when BLE needs 64-bit addresses, uint32_t otherwise
|
||||
#ifdef USE_API_VARINT64
|
||||
using proto_varint_value_t = uint64_t;
|
||||
#else
|
||||
using proto_varint_value_t = uint32_t;
|
||||
#endif
|
||||
|
||||
/// Sentinel value for consumed field indicating parse failure
|
||||
inline constexpr uint32_t PROTO_VARINT_PARSE_FAILED = 0;
|
||||
|
||||
/// Result of parsing a varint: value + number of bytes consumed.
|
||||
/// consumed == PROTO_VARINT_PARSE_FAILED indicates parse failure (not enough data or invalid).
|
||||
struct ProtoVarIntResult {
|
||||
proto_varint_value_t value;
|
||||
uint32_t consumed; // PROTO_VARINT_PARSE_FAILED = parse failed
|
||||
|
||||
constexpr bool has_value() const { return this->consumed != PROTO_VARINT_PARSE_FAILED; }
|
||||
};
|
||||
|
||||
/// Static varint parsing methods for the protobuf wire format.
|
||||
class ProtoVarInt {
|
||||
public:
|
||||
ProtoVarInt() : value_(0) {}
|
||||
explicit ProtoVarInt(uint64_t value) : value_(value) {}
|
||||
|
||||
/// Parse a varint from buffer. consumed must be a valid pointer (not null).
|
||||
static optional<ProtoVarInt> parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed) {
|
||||
/// Parse a varint from buffer. Caller must ensure len >= 1.
|
||||
/// Returns result with consumed=0 on failure (truncated multi-byte varint).
|
||||
static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse_non_empty(const uint8_t *buffer, uint32_t len) {
|
||||
#ifdef ESPHOME_DEBUG_API
|
||||
assert(consumed != nullptr);
|
||||
assert(len > 0);
|
||||
#endif
|
||||
if (len == 0)
|
||||
return {};
|
||||
// Fast path: single-byte varints (0-127) are the most common case
|
||||
// (booleans, small enums, field tags). Avoid loop overhead entirely.
|
||||
if ((buffer[0] & 0x80) == 0) {
|
||||
*consumed = 1;
|
||||
return ProtoVarInt(buffer[0]);
|
||||
}
|
||||
// 32-bit phase: process remaining bytes with native 32-bit shifts.
|
||||
// Without USE_API_VARINT64: cover bytes 1-4 (shifts 7, 14, 21, 28) — the uint32_t
|
||||
// shift at byte 4 (shift by 28) may lose bits 32-34, but those are always zero for valid uint32 values.
|
||||
// With USE_API_VARINT64: cover bytes 1-3 (shifts 7, 14, 21) so parse_wide handles
|
||||
// byte 4+ with full 64-bit arithmetic (avoids truncating values > UINT32_MAX).
|
||||
uint32_t result32 = buffer[0] & 0x7F;
|
||||
#ifdef USE_API_VARINT64
|
||||
uint32_t limit = std::min(len, uint32_t(4));
|
||||
#else
|
||||
uint32_t limit = std::min(len, uint32_t(5));
|
||||
#endif
|
||||
for (uint32_t i = 1; i < limit; i++) {
|
||||
uint8_t val = buffer[i];
|
||||
result32 |= uint32_t(val & 0x7F) << (i * 7);
|
||||
if ((val & 0x80) == 0) {
|
||||
*consumed = i + 1;
|
||||
return ProtoVarInt(result32);
|
||||
}
|
||||
}
|
||||
// 64-bit phase for remaining bytes (BLE addresses etc.)
|
||||
#ifdef USE_API_VARINT64
|
||||
return parse_wide(buffer, len, consumed, result32);
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
// (booleans, small enums, field tags, small message sizes/types).
|
||||
if ((buffer[0] & 0x80) == 0) [[likely]]
|
||||
return {buffer[0], 1};
|
||||
return parse_slow(buffer, len);
|
||||
}
|
||||
|
||||
/// Parse a varint from buffer (safe for empty buffers).
|
||||
/// Returns result with consumed=0 on failure (empty buffer or truncated varint).
|
||||
static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len) {
|
||||
if (len == 0)
|
||||
return {0, PROTO_VARINT_PARSE_FAILED};
|
||||
return parse_non_empty(buffer, len);
|
||||
}
|
||||
|
||||
#ifdef USE_API_VARINT64
|
||||
protected:
|
||||
// Slow path for multi-byte varints (>= 128), outlined to keep fast path small
|
||||
static ProtoVarIntResult parse_slow(const uint8_t *buffer, uint32_t len) __attribute__((noinline));
|
||||
|
||||
#ifdef USE_API_VARINT64
|
||||
/// Continue parsing varint bytes 4-9 with 64-bit arithmetic.
|
||||
/// Separated to keep 64-bit shift code (__ashldi3 on 32-bit platforms) out of the common path.
|
||||
static optional<ProtoVarInt> parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, uint32_t result32)
|
||||
__attribute__((noinline));
|
||||
|
||||
public:
|
||||
#endif
|
||||
|
||||
constexpr uint16_t as_uint16() const { return this->value_; }
|
||||
constexpr uint32_t as_uint32() const { return this->value_; }
|
||||
constexpr bool as_bool() const { return this->value_; }
|
||||
constexpr int32_t as_int32() const {
|
||||
// Not ZigZag encoded
|
||||
return static_cast<int32_t>(this->value_);
|
||||
}
|
||||
constexpr int32_t as_sint32() const {
|
||||
// with ZigZag encoding
|
||||
return decode_zigzag32(static_cast<uint32_t>(this->value_));
|
||||
}
|
||||
#ifdef USE_API_VARINT64
|
||||
constexpr uint64_t as_uint64() const { return this->value_; }
|
||||
constexpr int64_t as_int64() const {
|
||||
// Not ZigZag encoded
|
||||
return static_cast<int64_t>(this->value_);
|
||||
}
|
||||
constexpr int64_t as_sint64() const {
|
||||
// with ZigZag encoding
|
||||
return decode_zigzag64(this->value_);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
#ifdef USE_API_VARINT64
|
||||
uint64_t value_;
|
||||
#else
|
||||
uint32_t value_;
|
||||
static ProtoVarIntResult parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) __attribute__((noinline));
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -499,7 +465,7 @@ class ProtoDecodableMessage : public ProtoMessage {
|
||||
|
||||
protected:
|
||||
~ProtoDecodableMessage() = default;
|
||||
virtual bool decode_varint(uint32_t field_id, ProtoVarInt value) { return false; }
|
||||
virtual bool decode_varint(uint32_t field_id, proto_varint_value_t value) { return false; }
|
||||
virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; }
|
||||
virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; }
|
||||
// NOTE: decode_64bit removed - wire type 1 not supported
|
||||
|
||||
@@ -173,7 +173,7 @@ void BL0942::received_package_(DataPacket *data) {
|
||||
float i_rms = (uint24_t) data->i_rms / current_reference_;
|
||||
float watt = (int24_t) data->watt / power_reference_;
|
||||
float total_energy_consumption = cf_cnt / energy_reference_;
|
||||
float frequency = 1000000.0f / data->frequency;
|
||||
float frequency = data->frequency != 0 ? 1000000.0f / data->frequency : NAN;
|
||||
|
||||
if (voltage_sensor_ != nullptr) {
|
||||
voltage_sensor_->publish_state(v_rms);
|
||||
|
||||
@@ -383,7 +383,7 @@ void BME680BSECComponent::publish_(const bsec_output_t *outputs, uint8_t num_out
|
||||
switch (outputs[i].sensor_id) {
|
||||
case BSEC_OUTPUT_IAQ:
|
||||
case BSEC_OUTPUT_STATIC_IAQ: {
|
||||
uint8_t accuracy = outputs[i].accuracy;
|
||||
uint8_t accuracy = std::min<uint8_t>(outputs[i].accuracy, std::size(IAQ_ACCURACY_STATES) - 1);
|
||||
this->queue_push_([this, signal]() { this->publish_sensor_(this->iaq_sensor_, signal); });
|
||||
this->queue_push_([this, accuracy]() {
|
||||
this->publish_sensor_(this->iaq_accuracy_text_sensor_, IAQ_ACCURACY_STATES[accuracy]);
|
||||
|
||||
@@ -438,6 +438,7 @@ void BME68xBSEC2Component::publish_(const bsec_output_t *outputs, uint8_t num_ou
|
||||
}
|
||||
}
|
||||
if (update_accuracy) {
|
||||
max_accuracy = std::min<uint8_t>(max_accuracy, std::size(IAQ_ACCURACY_STATES) - 1);
|
||||
#ifdef USE_SENSOR
|
||||
this->queue_push_(
|
||||
[this, max_accuracy]() { this->publish_sensor_(this->iaq_accuracy_sensor_, max_accuracy, true); });
|
||||
|
||||
@@ -163,7 +163,7 @@ void MeanCombinationComponent::handle_new_value(float value) {
|
||||
return;
|
||||
|
||||
float sum = 0.0;
|
||||
size_t count = 0.0;
|
||||
size_t count = 0;
|
||||
|
||||
for (const auto &sensor : this->sensors_) {
|
||||
if (std::isfinite(sensor->state)) {
|
||||
@@ -172,6 +172,10 @@ void MeanCombinationComponent::handle_new_value(float value) {
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
this->publish_state(NAN);
|
||||
return;
|
||||
}
|
||||
float mean = sum / count;
|
||||
|
||||
this->publish_state(mean);
|
||||
@@ -238,6 +242,11 @@ void RangeCombinationComponent::handle_new_value(float value) {
|
||||
}
|
||||
}
|
||||
|
||||
if (sensor_states.empty()) {
|
||||
this->publish_state(NAN);
|
||||
return;
|
||||
}
|
||||
|
||||
sort(sensor_states.begin(), sensor_states.end());
|
||||
|
||||
float range = sensor_states.back() - sensor_states.front();
|
||||
|
||||
@@ -62,6 +62,8 @@ void DAC7678Output::register_channel(DAC7678Channel *channel) {
|
||||
}
|
||||
|
||||
void DAC7678Output::set_channel_value_(uint8_t channel, uint16_t value) {
|
||||
if (channel >= std::size(this->dac_input_reg_))
|
||||
return;
|
||||
if (this->dac_input_reg_[channel] != value) {
|
||||
ESP_LOGV(TAG, "Channel %01u: input_reg=%04u ", channel, value);
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ void Graph::draw(Display *buff, uint16_t x_offset, uint16_t y_offset, Color colo
|
||||
bool prev_b = false;
|
||||
int16_t prev_y = 0;
|
||||
for (uint32_t i = 0; i < this->width_; i++) {
|
||||
float v = (trace->get_tracedata()->get_value(i) - ymin) / yrange;
|
||||
float v = yrange != 0 ? (trace->get_tracedata()->get_value(i) - ymin) / yrange : NAN;
|
||||
if (!std::isnan(v) && (thick > 0)) {
|
||||
int16_t x = this->width_ - 1 - i + x_offset;
|
||||
uint8_t bit = 1 << ((i % (thick * LineType::PATTERN_LENGTH)) / thick);
|
||||
|
||||
@@ -59,6 +59,12 @@ void MICS4514Component::update() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->red_calibration_ == 0 || this->ox_calibration_ == 0) {
|
||||
ESP_LOGW(TAG, "Calibration values are zero, retrying");
|
||||
this->status_set_warning();
|
||||
this->initial_ = true;
|
||||
return;
|
||||
}
|
||||
float red_f = (float) (power - red) / this->red_calibration_;
|
||||
float ox_f = (float) (power - ox) / this->ox_calibration_;
|
||||
|
||||
|
||||
@@ -452,7 +452,8 @@ void MR24HPC1Component::r24_frame_parse_open_underlying_information_(uint8_t *da
|
||||
}
|
||||
break;
|
||||
case 0x83:
|
||||
if (this->custom_presence_of_detection_sensor_ != nullptr) {
|
||||
if (this->custom_presence_of_detection_sensor_ != nullptr &&
|
||||
data[FRAME_DATA_INDEX] < std::size(S_PRESENCE_OF_DETECTION_RANGE_STR)) {
|
||||
this->custom_presence_of_detection_sensor_->publish_state(
|
||||
S_PRESENCE_OF_DETECTION_RANGE_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
@@ -646,7 +647,7 @@ void MR24HPC1Component::r24_frame_parse_human_information_(uint8_t *data) {
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
case 0x01:
|
||||
case 0x81:
|
||||
if (this->has_target_binary_sensor_ != nullptr) {
|
||||
if (this->has_target_binary_sensor_ != nullptr && data[FRAME_DATA_INDEX] < std::size(S_SOMEONE_EXISTS_STR)) {
|
||||
this->has_target_binary_sensor_->publish_state(S_SOMEONE_EXISTS_STR[data[FRAME_DATA_INDEX]]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -334,6 +334,8 @@ void MR60FDA2Component::process_frame_() {
|
||||
|
||||
// Send Heartbeat Packet Command
|
||||
void MR60FDA2Component::set_install_height(uint8_t index) {
|
||||
if (index >= std::size(INSTALL_HEIGHT))
|
||||
return;
|
||||
uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x04, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
float_to_bytes(INSTALL_HEIGHT[index], &send_data[8]);
|
||||
send_data[12] = calculate_checksum(send_data + 8, 4);
|
||||
@@ -345,6 +347,8 @@ void MR60FDA2Component::set_install_height(uint8_t index) {
|
||||
}
|
||||
|
||||
void MR60FDA2Component::set_height_threshold(uint8_t index) {
|
||||
if (index >= std::size(HEIGHT_THRESHOLD))
|
||||
return;
|
||||
uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x08, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
float_to_bytes(HEIGHT_THRESHOLD[index], &send_data[8]);
|
||||
send_data[12] = calculate_checksum(send_data + 8, 4);
|
||||
@@ -356,6 +360,8 @@ void MR60FDA2Component::set_height_threshold(uint8_t index) {
|
||||
}
|
||||
|
||||
void MR60FDA2Component::set_sensitivity(uint8_t index) {
|
||||
if (index >= std::size(SENSITIVITY))
|
||||
return;
|
||||
uint8_t send_data[13] = {0x01, 0x00, 0x00, 0x00, 0x04, 0x0E, 0x0A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
int_to_bytes(SENSITIVITY[index], &send_data[8]);
|
||||
|
||||
@@ -70,6 +70,10 @@ float TSL2561Sensor::calculate_lx_(uint16_t ch0, uint16_t ch1) {
|
||||
return NAN;
|
||||
}
|
||||
|
||||
if (ch0 == 0) {
|
||||
ESP_LOGVV(TAG, "No light detected");
|
||||
return 0.0f;
|
||||
}
|
||||
float d0 = ch0, d1 = ch1;
|
||||
float ratio = d1 / d0;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "esphome/core/log.h"
|
||||
#include "ufire_ec.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace esphome {
|
||||
namespace ufire_ec {
|
||||
@@ -60,9 +61,15 @@ float UFireECComponent::measure_temperature_() { return this->read_data_(REGISTE
|
||||
|
||||
float UFireECComponent::measure_ms_() { return this->read_data_(REGISTER_MS); }
|
||||
|
||||
void UFireECComponent::set_solution_(float solution, float temperature) {
|
||||
solution /= (1 - (this->temperature_coefficient_ * (temperature - 25)));
|
||||
bool UFireECComponent::set_solution_(float solution, float temperature) {
|
||||
float denom = 1 - (this->temperature_coefficient_ * (temperature - 25));
|
||||
if (std::abs(denom) < 1e-6f) {
|
||||
ESP_LOGE(TAG, "Temperature compensation denominator is zero");
|
||||
return false;
|
||||
}
|
||||
solution /= denom;
|
||||
this->write_data_(REGISTER_SOLUTION, solution);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UFireECComponent::set_compensation_(float temperature) { this->write_data_(REGISTER_COMPENSATION, temperature); }
|
||||
@@ -72,7 +79,8 @@ void UFireECComponent::set_coefficient_(float coefficient) { this->write_data_(R
|
||||
void UFireECComponent::set_temperature_(float temperature) { this->write_data_(REGISTER_TEMP, temperature); }
|
||||
|
||||
void UFireECComponent::calibrate_probe(float solution, float temperature) {
|
||||
this->set_solution_(solution, temperature);
|
||||
if (!this->set_solution_(solution, temperature))
|
||||
return;
|
||||
this->write_byte(REGISTER_TASK, COMMAND_CALIBRATE_PROBE);
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class UFireECComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
protected:
|
||||
float measure_temperature_();
|
||||
float measure_ms_();
|
||||
void set_solution_(float solution, float temperature);
|
||||
bool set_solution_(float solution, float temperature);
|
||||
void set_compensation_(float temperature);
|
||||
void set_coefficient_(float coefficient);
|
||||
void set_temperature_(float temperature);
|
||||
|
||||
@@ -7,6 +7,8 @@ static const uint32_t DELTA = 0x9e3779b9;
|
||||
#define MX ((((z >> 5) ^ (y << 2)) + ((y >> 3) ^ (z << 4))) ^ ((sum ^ y) + (k[(p ^ e) & 7] ^ z)))
|
||||
|
||||
void encrypt(uint32_t *v, size_t n, const uint32_t *k) {
|
||||
if (n == 0)
|
||||
return;
|
||||
uint32_t z, y, sum, e;
|
||||
size_t p;
|
||||
size_t q = 6 + 52 / n;
|
||||
@@ -25,6 +27,8 @@ void encrypt(uint32_t *v, size_t n, const uint32_t *k) {
|
||||
}
|
||||
|
||||
void decrypt(uint32_t *v, size_t n, const uint32_t *k) {
|
||||
if (n == 0)
|
||||
return;
|
||||
uint32_t z, y, sum, e;
|
||||
size_t p;
|
||||
size_t q = 6 + 52 / n;
|
||||
|
||||
@@ -461,7 +461,7 @@ class FloatType(TypeInfo):
|
||||
class Int64Type(TypeInfo):
|
||||
cpp_type = "int64_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_int64()"
|
||||
decode_varint = "static_cast<int64_t>(value)"
|
||||
encode_func = "encode_int64"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -481,7 +481,7 @@ class Int64Type(TypeInfo):
|
||||
class UInt64Type(TypeInfo):
|
||||
cpp_type = "uint64_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_uint64()"
|
||||
decode_varint = "value"
|
||||
encode_func = "encode_uint64"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -501,7 +501,7 @@ class UInt64Type(TypeInfo):
|
||||
class Int32Type(TypeInfo):
|
||||
cpp_type = "int32_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_int32()"
|
||||
decode_varint = "static_cast<int32_t>(value)"
|
||||
encode_func = "encode_int32"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -573,7 +573,7 @@ class Fixed32Type(TypeInfo):
|
||||
class BoolType(TypeInfo):
|
||||
cpp_type = "bool"
|
||||
default_value = "false"
|
||||
decode_varint = "value.as_bool()"
|
||||
decode_varint = "value != 0"
|
||||
encode_func = "encode_bool"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -1151,7 +1151,7 @@ class FixedArrayBytesType(TypeInfo):
|
||||
class UInt32Type(TypeInfo):
|
||||
cpp_type = "uint32_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_uint32()"
|
||||
decode_varint = "value"
|
||||
encode_func = "encode_uint32"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -1175,7 +1175,7 @@ class EnumType(TypeInfo):
|
||||
|
||||
@property
|
||||
def decode_varint(self) -> str:
|
||||
return f"static_cast<{self.cpp_type}>(value.as_uint32())"
|
||||
return f"static_cast<{self.cpp_type}>(value)"
|
||||
|
||||
default_value = ""
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
@@ -1262,7 +1262,7 @@ class SFixed64Type(TypeInfo):
|
||||
class SInt32Type(TypeInfo):
|
||||
cpp_type = "int32_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_sint32()"
|
||||
decode_varint = "decode_zigzag32(value)"
|
||||
encode_func = "encode_sint32"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -1282,7 +1282,7 @@ class SInt32Type(TypeInfo):
|
||||
class SInt64Type(TypeInfo):
|
||||
cpp_type = "int64_t"
|
||||
default_value = "0"
|
||||
decode_varint = "value.as_sint64()"
|
||||
decode_varint = "decode_zigzag64(value)"
|
||||
encode_func = "encode_sint64"
|
||||
wire_type = WireType.VARINT # Uses wire type 0
|
||||
|
||||
@@ -2205,7 +2205,7 @@ def build_message_type(
|
||||
|
||||
cpp = ""
|
||||
if decode_varint:
|
||||
o = f"bool {desc.name}::decode_varint(uint32_t field_id, ProtoVarInt value) {{\n"
|
||||
o = f"bool {desc.name}::decode_varint(uint32_t field_id, proto_varint_value_t value) {{\n"
|
||||
o += " switch (field_id) {\n"
|
||||
o += indent("\n".join(decode_varint), " ") + "\n"
|
||||
o += " default: return false;\n"
|
||||
@@ -2213,7 +2213,7 @@ def build_message_type(
|
||||
o += " return true;\n"
|
||||
o += "}\n"
|
||||
cpp += o
|
||||
prot = "bool decode_varint(uint32_t field_id, ProtoVarInt value) override;"
|
||||
prot = "bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;"
|
||||
protected_content.insert(0, prot)
|
||||
if decode_length:
|
||||
o = f"bool {desc.name}::decode_length(uint32_t field_id, ProtoLengthDelimited value) {{\n"
|
||||
|
||||
+1
-1
@@ -519,7 +519,7 @@ def lint_constants_usage():
|
||||
continue
|
||||
errs.append(
|
||||
f"Constant {highlight(constant)} is defined in {len(uses)} files. Please move all definitions of the "
|
||||
f"constant to const.py (Uses: {', '.join(str(u) for u in uses)}) in a separate PR. "
|
||||
f"constant to esphome/components/const/__init__.py (Uses: {', '.join(str(u) for u in uses)}) in a separate PR. "
|
||||
"See https://developers.esphome.io/contributing/code/#python"
|
||||
)
|
||||
return errs
|
||||
|
||||
@@ -160,6 +160,76 @@ def format_change(before: int, after: int, threshold: float | None = None) -> st
|
||||
return f"{emoji} {delta_str} ({pct_str})"
|
||||
|
||||
|
||||
def _sig_base(sym: str) -> str:
|
||||
"""Strip argument types from a symbol name for fuzzy matching.
|
||||
|
||||
Removes the entire outermost parenthesized argument list (including
|
||||
the parentheses) from the symbol string.
|
||||
|
||||
This makes, for example, "foo(int)::nested" and "foo(float)::nested"
|
||||
share the same key "foo::nested", while "foo(int)" maps to "foo" and
|
||||
therefore does NOT collide with "foo(int)::nested".
|
||||
"""
|
||||
start = sym.find("(")
|
||||
if start == -1:
|
||||
return sym
|
||||
end = sym.rfind(")")
|
||||
if end == -1:
|
||||
return sym
|
||||
return sym[:start] + sym[end + 1 :]
|
||||
|
||||
|
||||
_AMBIGUOUS = object()
|
||||
|
||||
|
||||
def _match_signature_changes(
|
||||
changed_symbols: list[tuple[str, int, int, int]],
|
||||
new_symbols: list[tuple[str, int]],
|
||||
removed_symbols: list[tuple[str, int]],
|
||||
) -> tuple[
|
||||
list[tuple[str, int, int, int]],
|
||||
list[tuple[str, int]],
|
||||
list[tuple[str, int]],
|
||||
]:
|
||||
"""Match new/removed symbol pairs that only differ in argument types.
|
||||
|
||||
When a function's argument types change (e.g. foo(vector<>&) -> foo(Buffer&)),
|
||||
it appears as a new + removed symbol. This matches them by base name and moves
|
||||
them to changed_symbols. Only matches unambiguous 1:1 pairs.
|
||||
"""
|
||||
if not new_symbols or not removed_symbols:
|
||||
return changed_symbols, new_symbols, removed_symbols
|
||||
|
||||
# Build base -> entry maps; mark ambiguous bases with sentinel
|
||||
new_by_base: dict[str, tuple[str, int] | object] = {}
|
||||
for entry in new_symbols:
|
||||
base = _sig_base(entry[0])
|
||||
new_by_base[base] = _AMBIGUOUS if base in new_by_base else entry
|
||||
removed_by_base: dict[str, tuple[str, int] | object] = {}
|
||||
for entry in removed_symbols:
|
||||
base = _sig_base(entry[0])
|
||||
removed_by_base[base] = _AMBIGUOUS if base in removed_by_base else entry
|
||||
|
||||
matched: set[str] = set() # matched base keys
|
||||
for base, new_entry in new_by_base.items():
|
||||
if new_entry is _AMBIGUOUS:
|
||||
continue
|
||||
rem_entry = removed_by_base.get(base)
|
||||
if rem_entry is None or rem_entry is _AMBIGUOUS:
|
||||
continue
|
||||
pr_sym, pr_size = new_entry
|
||||
_rm_sym, target_size = rem_entry
|
||||
delta = pr_size - target_size
|
||||
if delta != 0:
|
||||
changed_symbols.append((pr_sym, target_size, pr_size, delta))
|
||||
matched.add(base)
|
||||
|
||||
if matched:
|
||||
new_symbols = [e for e in new_symbols if _sig_base(e[0]) not in matched]
|
||||
removed_symbols = [e for e in removed_symbols if _sig_base(e[0]) not in matched]
|
||||
return changed_symbols, new_symbols, removed_symbols
|
||||
|
||||
|
||||
def prepare_symbol_changes_data(
|
||||
target_symbols: dict | None, pr_symbols: dict | None
|
||||
) -> dict | None:
|
||||
@@ -200,6 +270,11 @@ def prepare_symbol_changes_data(
|
||||
delta = pr_size - target_size
|
||||
changed_symbols.append((symbol, target_size, pr_size, delta))
|
||||
|
||||
# Match new/removed symbols that only differ in argument types
|
||||
changed_symbols, new_symbols, removed_symbols = _match_signature_changes(
|
||||
changed_symbols, new_symbols, removed_symbols
|
||||
)
|
||||
|
||||
if not changed_symbols and not new_symbols and not removed_symbols:
|
||||
return None
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
"""Tests for script/ci_memory_impact_comment.py symbol matching."""
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
# Add script directory to path so we can import the module
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "script"))
|
||||
|
||||
from ci_memory_impact_comment import prepare_symbol_changes_data # noqa: E402
|
||||
|
||||
|
||||
def test_prepare_symbol_changes_signature_match() -> None:
|
||||
"""Symbols with same base name but different args are matched as changed."""
|
||||
target = {
|
||||
"Foo::bar(std::vector<unsigned char>&, int)": 300,
|
||||
"unchanged()": 50,
|
||||
}
|
||||
pr = {
|
||||
"Foo::bar(ProtoByteBuffer&, int)": 320,
|
||||
"unchanged()": 50,
|
||||
}
|
||||
result = prepare_symbol_changes_data(target, pr)
|
||||
assert result is not None
|
||||
assert len(result["changed_symbols"]) == 1
|
||||
assert len(result["new_symbols"]) == 0
|
||||
assert len(result["removed_symbols"]) == 0
|
||||
sym, t_size, p_size, delta = result["changed_symbols"][0]
|
||||
assert sym == "Foo::bar(ProtoByteBuffer&, int)"
|
||||
assert t_size == 300
|
||||
assert p_size == 320
|
||||
assert delta == 20
|
||||
|
||||
|
||||
def test_prepare_symbol_changes_ambiguous_overloads_not_matched() -> None:
|
||||
"""Multiple overloads with same base name stay as new/removed."""
|
||||
target = {
|
||||
"Foo::bar(int)": 100,
|
||||
"Foo::bar(float)": 200,
|
||||
}
|
||||
pr = {
|
||||
"Foo::bar(double)": 150,
|
||||
"Foo::bar(long)": 250,
|
||||
}
|
||||
result = prepare_symbol_changes_data(target, pr)
|
||||
assert result is not None
|
||||
assert len(result["changed_symbols"]) == 0
|
||||
assert len(result["new_symbols"]) == 2
|
||||
assert len(result["removed_symbols"]) == 2
|
||||
|
||||
|
||||
def test_prepare_symbol_changes_no_parens_not_matched() -> None:
|
||||
"""Symbols without parens (variables) are not fuzzy-matched."""
|
||||
target = {"my_global_var": 100}
|
||||
pr = {"my_global_var_v2": 120}
|
||||
result = prepare_symbol_changes_data(target, pr)
|
||||
assert result is not None
|
||||
assert len(result["changed_symbols"]) == 0
|
||||
assert len(result["new_symbols"]) == 1
|
||||
assert len(result["removed_symbols"]) == 1
|
||||
|
||||
|
||||
def test_prepare_symbol_changes_nested_symbols_matched_separately() -> None:
|
||||
"""Nested symbols like ::__pstr__ don't collide with parent function."""
|
||||
target = {
|
||||
"Foo::bar(std::vector<unsigned char>&, int)": 300,
|
||||
"Foo::bar(std::vector<unsigned char>&, int)::__pstr__": 19,
|
||||
}
|
||||
pr = {
|
||||
"Foo::bar(ProtoByteBuffer&, int)": 320,
|
||||
"Foo::bar(ProtoByteBuffer&, int)::__pstr__": 19,
|
||||
}
|
||||
result = prepare_symbol_changes_data(target, pr)
|
||||
assert result is not None
|
||||
# Both the function and its nested __pstr__ should be matched (not new/removed)
|
||||
assert len(result["new_symbols"]) == 0
|
||||
assert len(result["removed_symbols"]) == 0
|
||||
# __pstr__ has delta=0 so it's silently dropped, only the function shows
|
||||
assert len(result["changed_symbols"]) == 1
|
||||
sym, t_size, p_size, delta = result["changed_symbols"][0]
|
||||
assert sym == "Foo::bar(ProtoByteBuffer&, int)"
|
||||
assert delta == 20
|
||||
|
||||
|
||||
def test_prepare_symbol_changes_exact_match_preferred() -> None:
|
||||
"""Exact name matches are found before fuzzy matching runs."""
|
||||
target = {
|
||||
"Foo::bar(int)": 100,
|
||||
}
|
||||
pr = {
|
||||
"Foo::bar(int)": 120,
|
||||
}
|
||||
result = prepare_symbol_changes_data(target, pr)
|
||||
assert result is not None
|
||||
assert len(result["changed_symbols"]) == 1
|
||||
assert len(result["new_symbols"]) == 0
|
||||
assert len(result["removed_symbols"]) == 0
|
||||
sym, t_size, p_size, delta = result["changed_symbols"][0]
|
||||
assert sym == "Foo::bar(int)"
|
||||
assert delta == 20
|
||||
Reference in New Issue
Block a user