[components] Use xor_bytes and sum16_bytes for checksums (#20922)

This commit is contained in:
J. Nick Koston
2026-10-17 09:18:24 -04:00
committed by GitHub
parent 1b4721d445
commit c0a693dfce
11 changed files with 21 additions and 86 deletions
+2 -11
View File
@@ -28,15 +28,6 @@ static constexpr uint32_t APC1_NO_DATA_TIMEOUT_MS = 15000;
// Drop a partial frame when the bytes stop mid-way
static constexpr uint32_t APC1_RX_IDLE_TIMEOUT_MS = 200;
// Frames and commands end with the 16-bit sum of every byte before it
static uint16_t apc1_checksum(const uint8_t *data, size_t len) {
uint16_t sum = 0;
for (size_t i = 0; i < len; i++) {
sum += data[i];
}
return sum;
}
void APC1Component::setup() {
if (this->set_pin_ != nullptr) {
this->set_pin_->setup();
@@ -157,7 +148,7 @@ void APC1Component::loop() {
void APC1Component::parse_frame_(uint16_t total_len) {
uint16_t expected_checksum = encode_uint16(this->rx_buffer_[total_len - 2], this->rx_buffer_[total_len - 1]);
uint16_t calculated_checksum = apc1_checksum(this->rx_buffer_.data(), total_len - 2);
uint16_t calculated_checksum = sum16_bytes(this->rx_buffer_.data(), total_len - 2);
if (expected_checksum != calculated_checksum) {
ESP_LOGW(TAG, "APC1 checksum mismatch: calculated 0x%04X != expected 0x%04X", calculated_checksum,
expected_checksum);
@@ -343,7 +334,7 @@ void APC1Component::send_command_(APC1Command cmd, uint16_t data) {
0,
0,
};
uint16_t checksum = apc1_checksum(buf.data(), 5);
uint16_t checksum = sum16_bytes(buf.data(), 5);
buf[5] = static_cast<uint8_t>((checksum >> 8) & 0xFF);
buf[6] = static_cast<uint8_t>(checksum & 0xFF);
this->write_array(buf);
+1 -4
View File
@@ -124,10 +124,7 @@ void DFPlayer::play_folder(uint16_t folder, uint16_t file) {
void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) {
uint8_t buffer[10]{0x7e, 0xff, 0x06, cmd, 0x01, (uint8_t) (argument >> 8), (uint8_t) argument, 0x00, 0x00, 0xef};
uint16_t checksum = 0;
for (uint8_t i = 1; i < 7; i++)
checksum += buffer[i];
checksum = -checksum;
const uint16_t checksum = static_cast<uint16_t>(-sum16_bytes(buffer + 1, 6));
buffer[7] = checksum >> 8;
buffer[8] = (uint8_t) checksum;
+2 -7
View File
@@ -161,13 +161,8 @@ template<size_t N> uint8_t find_uint8(const StringToUint8 (&arr)[N], const std::
return 0xFF; // Not found
}
static uint8_t calc_checksum(void *data, size_t size) {
uint8_t checksum = 0;
uint8_t *data_bytes = (uint8_t *) data;
for (size_t i = 0; i < size; i++) {
checksum ^= data_bytes[i]; // XOR operation
}
return checksum;
static uint8_t calc_checksum(const void *data, size_t size) {
return xor_bytes(static_cast<const uint8_t *>(data), size);
}
static int32_t get_firmware_int(const char *version_string) {
+2 -6
View File
@@ -1256,12 +1256,8 @@ void LD6002BComponent::write_frame_(uint16_t type, const uint8_t *data, uint8_t
this->write_byte(static_cast<uint8_t>(~header_xor));
if (len > 0 && data != nullptr) {
uint8_t data_xor = 0;
for (uint8_t i = 0; i < len; i++) {
this->write_byte(data[i]);
data_xor ^= data[i];
}
this->write_byte(static_cast<uint8_t>(~data_xor));
this->write_array(data, len);
this->write_byte(static_cast<uint8_t>(~xor_bytes(data, len)));
}
const uint32_t now = millis();
if (track) {
+1 -4
View File
@@ -124,10 +124,7 @@ bool PMSA003IComponent::read_data_(PM25AQIData *data) {
}
// Calculate checksum
uint16_t checksum = 0;
for (uint8_t i = 0; i < CHECKSUM_START_INDEX; i++) {
checksum += buffer[i];
}
const uint16_t checksum = sum16_bytes(buffer, CHECKSUM_START_INDEX);
const uint16_t check = encode_uint16(buffer[CHECKSUM_START_INDEX], buffer[CHECKSUM_START_INDEX + 1]);
if (checksum != check) {
+2 -8
View File
@@ -159,10 +159,7 @@ optional<bool> PMSX003Component::check_byte_() {
}
// checksum is without checksum bytes
uint16_t checksum = 0;
for (uint16_t i = 0; i < total_size - 2; i++) {
checksum += this->data_[i];
}
const uint16_t checksum = sum16_bytes(this->data_, total_size - 2);
const uint16_t check = this->get_16_bit_uint_(total_size - 2);
if (checksum != check) {
@@ -207,10 +204,7 @@ void PMSX003Component::send_command_(Command cmd, uint16_t data) {
};
// Calculate checksum
uint16_t checksum = 0;
for (uint8_t i = 0; i < 5; i++) {
checksum += send_data[i];
}
const uint16_t checksum = sum16_bytes(send_data, 5);
send_data[5] = (checksum >> 8) & 0xFF; // Verify Byte 1
send_data[6] = (checksum >> 0) & 0xFF; // Verify Byte 2
+1 -3
View File
@@ -39,9 +39,7 @@ void rdm6300::RDM6300Component::loop() {
ESP_LOGW(TAG, "Invalid end byte from RDM6300!");
this->read_state_ = RDM6300_STATE_WAITING_FOR_START;
} else {
uint8_t checksum = 0;
for (uint8_t i = 0; i < 5; i++)
checksum ^= this->buffer_[i];
const uint8_t checksum = xor_bytes(this->buffer_, 5);
this->read_state_ = RDM6300_STATE_WAITING_FOR_START;
if (checksum != this->buffer_[5]) {
ESP_LOGW(TAG, "Checksum from RDM6300 doesn't match! (0x%02X!=0x%02X)", checksum, this->buffer_[5]);
@@ -62,24 +62,8 @@ void MR60FDA2Component::loop() {
}
}
/**
* @brief Calculate the checksum for a byte array.
*
* This function calculates the checksum for the provided byte array using an
* XOR-based checksum algorithm.
*
* @param data The byte array to calculate the checksum for.
* @param len The length of the byte array.
* @return The calculated checksum.
*/
static uint8_t calculate_checksum(const uint8_t *data, size_t len) {
uint8_t checksum = 0;
for (size_t i = 0; i < len; i++) {
checksum ^= data[i];
}
checksum = ~checksum;
return checksum;
}
// The checksum is the inverted XOR of the bytes
static uint8_t calculate_checksum(const uint8_t *data, size_t len) { return ~xor_bytes(data, len); }
/**
* @brief Validate the checksum of a byte array.
@@ -27,6 +27,7 @@
#include "debug.h"
#include "dev_table.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include <algorithm>
@@ -725,20 +726,13 @@ stm32_err_t stm32_write_memory(const stm32_unique_ptr &stm, uint32_t address, co
return STM32_ERR_UNKNOWN;
const unsigned int aligned_len = (len + 3) & ~3;
uint8_t cs = aligned_len - 1;
uint8_t buf[256 + 2];
buf[0] = aligned_len - 1;
for (unsigned int i = 0; i < len; i++) {
cs ^= data[i];
buf[i + 1] = data[i];
}
memcpy(&buf[1], data, len);
/* padding data */
for (auto i = len; i < aligned_len; i++) {
cs ^= 0xFF;
buf[i + 1] = 0xFF;
}
buf[aligned_len + 1] = cs;
memset(&buf[1 + len], 0xFF, aligned_len - len);
buf[aligned_len + 1] = xor_bytes(buf, aligned_len + 1);
stream->write_array(buf, aligned_len + 2);
stream->flush();
+2 -7
View File
@@ -544,9 +544,7 @@ void ToshibaClimate::transmit_generic_() {
}
// The last byte is the xor of all bytes from [4]
for (uint8_t i = 4; i < message_length - 1; i++) {
message[message_length - 1] ^= message[i];
}
message[message_length - 1] = xor_bytes(message + 4, message_length - 5);
// Transmit
auto transmit = this->transmitter_->transmit();
@@ -1335,13 +1333,10 @@ bool ToshibaClimate::on_receive(remote_base::RemoteReceiveData data) {
break;
// Generic (old) Toshiba packet
default:
uint8_t checksum = 0;
// Add back the length of the header (we pruned it above)
message_length += TOSHIBA_HEADER_LENGTH;
// Validate the second checksum before trusting any more of the message
for (uint8_t i = TOSHIBA_HEADER_LENGTH; i < message_length - 1; i++) {
checksum ^= message[i];
}
const uint8_t checksum = xor_bytes(message + TOSHIBA_HEADER_LENGTH, message_length - 1 - TOSHIBA_HEADER_LENGTH);
// Did our computed checksum and the provided checksum match?
if (checksum != message[message_length - 1]) {
return false;
@@ -34,15 +34,9 @@ static constexpr bool is_bootloader_menu_byte(uint8_t byte) {
return byte == 0 || byte == '\r' || byte == '\n' || (byte >= 0x20 && byte <= 0x7E);
}
static uint8_t calculate_frame_checksum(const uint8_t *data, uint8_t length) {
// Calculate Z-Wave frame checksum
// XOR all bytes between SOF and checksum position (exclusive)
static uint8_t calculate_frame_checksum(const uint8_t *data, size_t length) {
// Initial value is 0xFF per Z-Wave protocol specification
uint8_t checksum = 0xFF;
for (uint8_t i = 1; i < length - 1; i++) {
checksum ^= data[i];
}
return checksum;
return xor_bytes(data + 1, length - 2, 0xFF);
}
ZWaveProxy::ZWaveProxy() { global_zwave_proxy = this; }