[core] Add sum_bytes() and use it for the additive byte checksums components hand-roll (#20507)

This commit is contained in:
J. Nick Koston
2026-10-11 08:48:47 -10:00
committed by GitHub
parent 8e8261c39e
commit 86af0af0e4
36 changed files with 69 additions and 196 deletions
+1 -4
View File
@@ -146,10 +146,7 @@ bool BalluClimate::on_receive(remote_base::RemoteReceiveData data) {
return false;
}
uint8_t checksum = 0;
// Calculate checksum and compare with signal value.
for (uint8_t i = 0; i < BALLU_STATE_LENGTH - 1; i++)
checksum += remote_state[i];
const uint8_t checksum = sum_bytes(remote_state, BALLU_STATE_LENGTH - 1);
if (checksum != remote_state[BALLU_STATE_LENGTH - 1]) {
ESP_LOGVV(TAG, "Checksum fail");
+1 -5
View File
@@ -51,12 +51,8 @@ void BL0939::loop() {
}
bool BL0939::validate_checksum(const DataPacket *data) {
uint8_t checksum = BL0939_READ_COMMAND;
// Whole package but checksum
for (uint32_t i = 0; i < sizeof(data->raw) - 1; i++) {
checksum += data->raw[i];
}
checksum ^= 0xFF;
const uint8_t checksum = sum_bytes(data->raw, sizeof(data->raw) - 1, BL0939_READ_COMMAND) ^ 0xFF;
if (checksum != data->checksum) {
ESP_LOGW(TAG, "BL0939 invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
}
+2 -6
View File
@@ -44,13 +44,9 @@ void BL0940::loop() {
}
bool BL0940::validate_checksum_(DataPacket *data) {
uint8_t checksum = this->read_command_;
// Whole package but checksum
uint8_t *raw = (uint8_t *) data;
for (uint32_t i = 0; i < sizeof(*data) - 1; i++) {
checksum += raw[i];
}
checksum ^= 0xFF;
const uint8_t checksum =
sum_bytes(reinterpret_cast<const uint8_t *>(data), sizeof(*data) - 1, this->read_command_) ^ 0xFF;
if (checksum != data->checksum) {
ESP_LOGW(TAG, "Invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
}
+3 -6
View File
@@ -70,13 +70,10 @@ void BL0942::loop() {
}
bool BL0942::validate_checksum_(DataPacket *data) {
uint8_t checksum = BL0942_READ_COMMAND | this->address_;
// Whole package but checksum
uint8_t *raw = (uint8_t *) data;
for (uint32_t i = 0; i < sizeof(*data) - 1; i++) {
checksum += raw[i];
}
checksum ^= 0xFF;
const uint8_t checksum =
sum_bytes(reinterpret_cast<const uint8_t *>(data), sizeof(*data) - 1, BL0942_READ_COMMAND | this->address_) ^
0xFF;
if (checksum != data->checksum) {
ESP_LOGW(TAG, "BL0942 invalid checksum! 0x%02X != 0x%02X", checksum, data->checksum);
}
+4 -12
View File
@@ -81,11 +81,7 @@ void CSE7761Component::write_(uint8_t reg, uint16_t data) {
buffer[3] = data & 0xFF;
len = 4;
}
uint8_t crc = 0;
for (uint32_t i = 0; i < len; i++) {
crc += buffer[i];
}
buffer[len] = ~crc;
buffer[len] = ~sum_bytes(buffer, len);
len++;
}
@@ -115,16 +111,12 @@ bool CSE7761Component::read_once_(uint8_t reg, uint8_t size, uint32_t *value) {
}
rcvd--;
if (static_cast<uint8_t>(~sum_bytes(buffer, rcvd, 0xA5 + reg)) != buffer[rcvd]) {
return false;
}
uint32_t result = 0;
// CRC check
uint8_t crc = 0xA5 + reg;
for (uint32_t i = 0; i < rcvd; i++) {
result = (result << 8) | buffer[i];
crc += buffer[i];
}
crc = ~crc;
if (crc != buffer[rcvd]) {
return false;
}
*value = result;
+1 -4
View File
@@ -67,10 +67,7 @@ bool CSE7766Component::check_byte_() {
}
if (index == CSE7766_RAW_DATA_SIZE - 1) {
uint8_t checksum = 0;
for (uint8_t i = 2; i < CSE7766_RAW_DATA_SIZE - 1; i++) {
checksum += this->raw_data_[i];
}
const uint8_t checksum = sum_bytes(this->raw_data_ + 2, CSE7766_RAW_DATA_SIZE - 3);
if (checksum != this->raw_data_[CSE7766_RAW_DATA_SIZE - 1]) {
ESP_LOGW(TAG, "Invalid checksum from CSE7766: 0x%02X != 0x%02X", checksum,
+1 -8
View File
@@ -1,6 +1,7 @@
#include "daikin.h"
#include "esphome/components/remote_base/remote_base.h"
#include "esphome/core/application.h"
#include "esphome/core/helpers.h"
namespace esphome::daikin {
@@ -8,14 +9,6 @@ ESPHOME_LOG_TAG(TAG, "daikin.climate");
static constexpr uint32_t BOOST_TIMEOUT_ID = 0;
static uint8_t sum_bytes(const uint8_t *data, size_t len) {
uint8_t sum = 0;
for (size_t i = 0; i < len; i++) {
sum += data[i];
}
return sum;
}
void DaikinClimate::setup() {
climate_ir::ClimateIR::setup();
// A boost preset restored from flash gets its timer too
+1 -4
View File
@@ -246,10 +246,7 @@ climate::ClimateTraits DaikinArcClimate::traits() {
}
bool DaikinArcClimate::parse_state_frame_(const uint8_t frame[]) {
uint8_t checksum = 0;
for (int i = 0; i < (DAIKIN_STATE_FRAME_SIZE - 1); i++) {
checksum += frame[i];
}
const uint8_t checksum = sum_bytes(frame, DAIKIN_STATE_FRAME_SIZE - 1);
if (frame[DAIKIN_STATE_FRAME_SIZE - 1] != checksum) {
ESP_LOGI(TAG, "checksum error");
return false;
+2 -4
View File
@@ -1,5 +1,6 @@
#include "daikin_brc.h"
#include "esphome/components/remote_base/remote_base.h"
#include "esphome/core/helpers.h"
namespace esphome::daikin_brc {
@@ -160,10 +161,7 @@ uint8_t DaikinBrcClimate::temperature_() {
}
bool DaikinBrcClimate::parse_state_frame_(const uint8_t frame[]) {
uint8_t checksum = 0;
for (int i = 0; i < (DAIKIN_BRC_STATE_FRAME_SIZE - 1); i++) {
checksum += frame[i];
}
const uint8_t checksum = sum_bytes(frame, DAIKIN_BRC_STATE_FRAME_SIZE - 1);
if (frame[DAIKIN_BRC_STATE_FRAME_SIZE - 1] != checksum) {
ESP_LOGCONFIG(TAG, "Bad CheckSum %x", checksum);
return false;
+1 -6
View File
@@ -129,12 +129,7 @@ void DalyBmsComponent::decode_data_(std::vector<uint8_t> data) {
while ((it = std::find(it, data.end(), 0xA5)) != data.end()) {
if (data.end() - it >= DALY_FRAME_SIZE && it[1] == 0x01) {
uint8_t checksum;
int sum = 0;
for (int i = 0; i < 12; i++) {
sum += it[i];
}
checksum = sum;
const uint8_t checksum = sum_bytes(&*it, 12);
if (checksum == it[12]) {
switch (it[2]) {
+2 -4
View File
@@ -1,5 +1,6 @@
#include "delonghi.h"
#include "esphome/components/remote_base/remote_base.h"
#include "esphome/core/helpers.h"
namespace esphome::delonghi {
@@ -102,10 +103,7 @@ uint8_t DelonghiClimate::temperature_() {
}
bool DelonghiClimate::parse_state_frame_(const uint8_t frame[]) {
uint8_t checksum = 0;
for (int i = 0; i < (DELONGHI_STATE_FRAME_SIZE - 1); i++) {
checksum += frame[i];
}
const uint8_t checksum = sum_bytes(frame, DELONGHI_STATE_FRAME_SIZE - 1);
if (frame[DELONGHI_STATE_FRAME_SIZE - 1] != checksum) {
return false;
}
+1 -6
View File
@@ -42,12 +42,7 @@ void FS3000Component::update() {
}
// checksum passes if the modulo 256 sum of the five bytes is 0
uint8_t checksum = 0;
for (uint8_t i : data) {
checksum += i;
}
if (checksum != 0) {
if (sum_bytes(data, sizeof(data)) != 0) {
this->status_set_warning();
ESP_LOGW(TAG, "Checksum failure when reading from FS3000");
return;
@@ -224,11 +224,7 @@ void FujitsuGeneralClimate::transmit_(uint8_t const *message, uint8_t length) {
}
uint8_t FujitsuGeneralClimate::checksum_state_(uint8_t const *message) {
uint8_t checksum = 0;
for (uint8_t i = 7; i < FUJITSU_GENERAL_STATE_MESSAGE_LENGTH - 1; ++i) {
checksum += message[i];
}
return 256 - checksum;
return -sum_bytes(message + 7, FUJITSU_GENERAL_STATE_MESSAGE_LENGTH - 8);
}
uint8_t FujitsuGeneralClimate::checksum_util_(uint8_t const *message) { return 255 - message[5]; }
+1 -8
View File
@@ -80,14 +80,7 @@ void HM3301Component::update() {
this->status_clear_warning();
}
bool HM3301Component::validate_checksum_(const uint8_t *data) {
uint8_t sum = 0;
for (int i = 0; i < 28; i++) {
sum += data[i];
}
return sum == data[28];
}
bool HM3301Component::validate_checksum_(const uint8_t *data) { return sum_bytes(data, 28) == data[28]; }
uint16_t HM3301Component::get_sensor_value_(const uint8_t *data, uint8_t i) {
return (uint16_t) data[i * 2] << 8 | data[i * 2 + 1];
@@ -95,16 +95,9 @@ void ImprovSerialComponent::write_data_(const uint8_t *data, const size_t size)
const uint8_t header_checksum_len = there_is_data ? TX_BUFFER_SIZE - 3 : TX_BUFFER_SIZE - 2;
// Only transmit the full buffer length if there is no data (only state/error byte is provided in this case)
const uint8_t header_tx_len = there_is_data ? TX_BUFFER_SIZE - 3 : TX_BUFFER_SIZE;
// Calculate checksum for message
uint8_t checksum = 0;
for (uint8_t i = 0; i < header_checksum_len; i++) {
checksum += this->tx_header_[i];
}
uint8_t checksum = sum_bytes(this->tx_header_, header_checksum_len);
if (there_is_data) {
// Include data in checksum
for (size_t i = 0; i < size; i++) {
checksum += data[i];
}
checksum = sum_bytes(data, size, checksum);
}
this->tx_header_[TX_CHECKSUM_IDX] = checksum;
+1 -7
View File
@@ -31,13 +31,7 @@ static const LogString *detection_range_to_log_string(MHZ19DetectionRange range)
}
#endif
uint8_t mhz19_checksum(const uint8_t *command) {
uint8_t sum = 0;
for (uint8_t i = 1; i < MHZ19_REQUEST_LENGTH; i++) {
sum += command[i];
}
return 0xFF - sum + 0x01;
}
uint8_t mhz19_checksum(const uint8_t *command) { return -sum_bytes(command + 1, MHZ19_REQUEST_LENGTH - 1); }
void MHZ19Component::setup() {
if (this->abc_boot_logic_ == MHZ19_ABC_ENABLED) {
+1 -3
View File
@@ -242,9 +242,7 @@ void MitsubishiClimate::transmit_state() {
}
// Checksum
for (int i = 0; i < 17; i++) {
remote_state[17] += remote_state[i];
}
remote_state[17] = sum_bytes(remote_state, 17);
ESP_LOGD(TAG, "sending: %02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X",
remote_state[0], remote_state[1], remote_state[2], remote_state[3], remote_state[4], remote_state[5],
@@ -3,7 +3,6 @@
#include <algorithm>
#include <array>
#include <cmath>
#include <numeric>
#include "mitsubishi_cn105_properties.h"
namespace esphome::mitsubishi_cn105 {
@@ -31,7 +30,7 @@ static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_REQUEST = 0x41;
static constexpr uint8_t PACKET_TYPE_WRITE_SETTINGS_RESPONSE = 0x61;
static constexpr uint8_t checksum(const uint8_t *bytes, size_t length) {
return static_cast<uint8_t>(0xFC - std::accumulate(bytes, bytes + length, uint8_t{0}));
return static_cast<uint8_t>(0xFC - sum_bytes(bytes, length));
}
template<std::size_t PayloadSize>
@@ -36,14 +36,7 @@ static size_t get_field(char *dest, const char *buf_start, const char *buf_end,
// Calculates the CRC (checksum) for a given group of characters.
uint8_t Mk2PVRouter::calculate_crc_(const char *grp, size_t grp_len) {
uint8_t crc_tmp{0};
const auto effective_len = grp_len - CRC_SUFFIX_LEN;
for (size_t i = 0; i < effective_len; i++) {
crc_tmp += grp[i];
}
crc_tmp &= CRC_MASK;
crc_tmp += CRC_OFFSET;
return crc_tmp;
return (sum_bytes(reinterpret_cast<const uint8_t *>(grp), grp_len - CRC_SUFFIX_LEN) & CRC_MASK) + CRC_OFFSET;
}
// Verifies the CRC of a group against its trailing CRC byte.
+1 -5
View File
@@ -43,11 +43,7 @@ void PM1006Component::loop() {
}
uint8_t PM1006Component::pm1006_checksum_(const uint8_t *command_data, uint8_t length) const {
uint8_t sum = 0;
for (uint8_t i = 0; i < length; i++) {
sum += command_data[i];
}
return sum;
return sum_bytes(command_data, length);
}
optional<bool> PM1006Component::check_byte_() const {
+1 -5
View File
@@ -71,11 +71,7 @@ bool PN532I2C::read_response(uint8_t command, pn532::PN532Frame &data) {
// frame: status, preamble, start code (2), LEN, LCS, TFI, command response code, data, DCS, postamble
constexpr size_t tfi_offset = 6;
uint8_t checksum = 0;
for (size_t i = 0; i < len + 1U; i++) {
checksum += data[tfi_offset + i];
}
checksum = ~checksum + 1;
const uint8_t checksum = -sum_bytes(data.data() + tfi_offset, len + 1U);
if (data[tfi_offset + len + 1] != checksum) {
ESP_LOGV(TAG, "read data invalid checksum! %02X != %02X", data[tfi_offset + len + 1], checksum);
+2 -6
View File
@@ -127,12 +127,8 @@ bool PN532Spi::read_response(uint8_t command, pn532::PN532Frame &data) {
ESP_LOGV(TAG, "Response data: %s", format_hex_pretty_to(hex_buf, sizeof(hex_buf), data.data(), data.size()));
uint8_t checksum = header[5] + header[6]; // TFI + Command response code
for (int i = 0; i < len - 1; i++) {
uint8_t dat = data[i];
checksum += dat;
}
checksum = ~checksum + 1;
// TFI + Command response code + data
const uint8_t checksum = -sum_bytes(data.data(), len - 1, header[5] + header[6]);
if (data[len - 1] != checksum) {
ESP_LOGV(TAG, "read data invalid checksum! %02X != %02X", data[len - 1], checksum);
+1 -3
View File
@@ -34,9 +34,7 @@ void PZEM004T::loop() {
// 1-5: data
// 6: checksum (sum of other bytes)
// see https://github.com/olehs/PZEM004T
uint8_t sum = 0;
for (int i = 0; i < 6; i++)
sum += resp[i];
const uint8_t sum = sum_bytes(resp.data(), 6);
if (sum != resp[6]) {
ESP_LOGV(TAG, "PZEM004T invalid checksum! 0x%02X != 0x%02X", sum, resp[6]);
+1 -5
View File
@@ -115,11 +115,7 @@ void SDS011Component::sds011_write_command_(const uint8_t *command_data) {
}
uint8_t SDS011Component::sds011_checksum_(const uint8_t *command_data, uint8_t length) const {
uint8_t sum = 0;
for (uint8_t i = 0; i < length; i++) {
sum += command_data[i];
}
return sum;
return sum_bytes(command_data, length);
}
optional<bool> SDS011Component::check_byte_() const {
@@ -251,17 +251,11 @@ void MR24HPC1Component::loop() {
}
}
// Calculate CRC check digit
static uint8_t get_frame_crc_sum(const uint8_t *data, int len) {
unsigned int crc_sum = 0;
for (int i = 0; i < len - 3; i++) {
crc_sum += data[i];
}
return crc_sum & 0xff;
}
// Frames are at least 10 bytes, so the three trailing bytes can always be left out
static uint8_t get_frame_crc_sum(const uint8_t *data, size_t len) { return sum_bytes(data, len - 3); }
// Check that the check digit is correct
static int get_frame_check_status(uint8_t *data, int len) {
static int get_frame_check_status(const uint8_t *data, size_t len) {
uint8_t crc_sum = get_frame_crc_sum(data, len);
uint8_t verified = data[len - 3];
return (verified == crc_sum) ? 1 : 0;
+1 -7
View File
@@ -83,13 +83,7 @@ void SM300D2Sensor::update() {
this->humidity_sensor_->publish_state(humidity);
}
uint16_t SM300D2Sensor::sm300d2_checksum_(uint8_t *ptr) {
uint8_t sum = 0;
for (int i = 0; i < (SM300D2_RESPONSE_LENGTH - 1); i++) {
sum += *ptr++;
}
return sum;
}
uint16_t SM300D2Sensor::sm300d2_checksum_(uint8_t *ptr) { return sum_bytes(ptr, SM300D2_RESPONSE_LENGTH - 1); }
void SM300D2Sensor::dump_config() {
ESP_LOGCONFIG(TAG, "SM300D2:");
+1 -7
View File
@@ -52,13 +52,7 @@ ESPHOME_LOG_TAG(TAG, "sonoff_d1");
static constexpr size_t SONOFF_D1_ACK_SIZE = 7;
static constexpr size_t SONOFF_D1_MAX_CMD_SIZE = 17;
uint8_t SonoffD1Output::calc_checksum_(const uint8_t *cmd, const size_t len) {
uint8_t crc = 0;
for (size_t i = 2; i < len - 1; i++) {
crc += cmd[i];
}
return crc;
}
uint8_t SonoffD1Output::calc_checksum_(const uint8_t *cmd, const size_t len) { return sum_bytes(cmd + 2, len - 3); }
void SonoffD1Output::populate_checksum_(uint8_t *cmd, const size_t len) {
// Update the checksum
+1 -6
View File
@@ -10,12 +10,7 @@ ESPHOME_LOG_TAG(TAG, "systa_bus");
void SystaBus::dump_config() { ESP_LOGCONFIG(TAG, "SystaBus:"); }
static bool checksum(std::span<const uint8_t> data) {
uint8_t csum = 0;
for (uint8_t i : data)
csum += i;
return csum == 0;
}
static bool checksum(std::span<const uint8_t> data) { return sum_bytes(data.data(), data.size()) == 0; }
void SystaBus::loop() {
uint8_t c;
+1 -3
View File
@@ -168,11 +168,9 @@ bool Tcl112Climate::on_receive(remote_base::RemoteReceiveData data) {
return false;
}
uint8_t checksum = 0;
// Calculate & set the checksum for the current internal state of the remote.
// Stored the checksum value in the last byte.
for (uint8_t checksum_byte = 0; checksum_byte < TCL112_STATE_LENGTH - 1; checksum_byte++)
checksum += remote_state[checksum_byte];
const uint8_t checksum = sum_bytes(remote_state, TCL112_STATE_LENGTH - 1);
if (checksum != remote_state[TCL112_STATE_LENGTH - 1]) {
ESP_LOGVV(TAG, "Checksum fail");
return false;
+5 -5
View File
@@ -24,12 +24,12 @@ static int get_field(char *dest, char *buf_start, char *buf_end, int sep, int ma
/* TeleInfo methods */
bool TeleInfo::check_crc_(const char *grp, const char *grp_end) {
int grp_len = grp_end - grp;
if (grp_len < this->checksum_area_end_) {
ESP_LOGE(TAG, "Empty or too short group");
return false;
}
uint8_t raw_crc = grp[grp_len - 1];
uint8_t crc_tmp = 0;
int i;
for (i = 0; i < grp_len - checksum_area_end_; i++)
crc_tmp += grp[i];
uint8_t crc_tmp = sum_bytes(reinterpret_cast<const uint8_t *>(grp), grp_len - this->checksum_area_end_);
crc_tmp &= 0x3F;
crc_tmp += 0x20;
+1 -6
View File
@@ -1052,8 +1052,6 @@ bool ToshibaClimate::compare_rac_pt1411hwru_packets_(const uint8_t *message1, co
}
bool ToshibaClimate::is_valid_rac_pt1411hwru_message_(const uint8_t *message) {
uint8_t checksum = 0;
switch (this->is_valid_rac_pt1411hwru_header_(message)) {
case RAC_PT1411HWRU_MESSAGE_HEADER0:
case RAC_PT1411HWRU_CS_HEADER:
@@ -1065,10 +1063,7 @@ bool ToshibaClimate::is_valid_rac_pt1411hwru_message_(const uint8_t *message) {
break;
case RAC_PT1411HWRU_MESSAGE_HEADER1:
for (uint8_t i = 0; i < RAC_PT1411HWRU_MESSAGE_LENGTH - 1; i++) {
checksum += message[i];
}
if (checksum == message[RAC_PT1411HWRU_MESSAGE_LENGTH - 1]) {
if (sum_bytes(message, RAC_PT1411HWRU_MESSAGE_LENGTH - 1) == message[RAC_PT1411HWRU_MESSAGE_LENGTH - 1]) {
return true;
}
break;
+3 -7
View File
@@ -152,9 +152,7 @@ bool Tuya::validate_message_() {
// Byte 6+LEN: CHECKSUM - sum of all bytes (including header) modulo 256
uint8_t rx_checksum = new_byte;
uint8_t calc_checksum = 0;
for (uint32_t i = 0; i < 6 + length; i++)
calc_checksum += data[i];
const uint8_t calc_checksum = sum_bytes(data, 6 + length);
if (rx_checksum != calc_checksum) {
ESP_LOGW(TAG, "Tuya Received invalid message checksum %02X!=%02X", rx_checksum, calc_checksum);
@@ -531,10 +529,8 @@ void Tuya::send_raw_command_(TuyaCommand command) {
if (!command.payload.empty())
this->write_array(command.payload.data(), command.payload.size());
uint8_t checksum = 0x55 + 0xAA + (uint8_t) command.cmd + len_hi + len_lo;
for (auto &data : command.payload)
checksum += data;
this->write_byte(checksum);
const uint8_t header_sum = 0x55 + 0xAA + (uint8_t) command.cmd + len_hi + len_lo;
this->write_byte(sum_bytes(command.payload.data(), command.payload.size(), header_sum));
}
void Tuya::process_command_queue_() {
+2 -7
View File
@@ -68,9 +68,7 @@ static bool check_byte(const uint8_t data[FRAME_SIZE], size_t index, uint8_t exp
}
static bool validate_active_frame(const uint8_t data[FRAME_SIZE]) {
uint8_t sum = 0;
for (size_t i = 0; i < FRAME_CHECKSUM_INDEX; ++i)
sum += data[i];
const uint8_t sum = sum_bytes(data, FRAME_CHECKSUM_INDEX);
return check_byte(data, 0, FRAME_START_BYTE_1, "start byte 1") &&
check_byte(data, 1, FRAME_START_BYTE_2, "start byte 2") &&
check_byte(data, FRAME_INDEX_INSTANT_FLOW_FLAG, FRAME_FLAG_INSTANT_FLOW, "instant flow flag") &&
@@ -83,10 +81,7 @@ static bool validate_active_frame(const uint8_t data[FRAME_SIZE]) {
static bool validate_passive_frame(const uint8_t data[PASSIVE_FRAME_SIZE]) {
if (data[0] != FRAME_START_BYTE_1 || data[1] != PASSIVE_START_BYTE_2 || data[22] != FRAME_STOP_BYTE)
return false;
uint8_t sum = 0;
for (size_t i = 0; i < 21; ++i)
sum += data[i];
return data[21] == (sum & 0xFF);
return data[21] == sum_bytes(data, 21);
}
static void passive_no_id_to_active_frame(const uint8_t passive[PASSIVE_FRAME_SIZE], uint8_t active[FRAME_SIZE]) {
+1 -4
View File
@@ -58,10 +58,7 @@ void WTS01Sensor::process_packet_() {
// Based on Tasmota implementation
// Format: 55 01 01 04 01 11 16 12 95
// header T Td Ck - T = Temperature, Td = Temperature decimal, Ck = Checksum
uint8_t calculated_checksum = 0;
for (uint8_t i = 0; i < PACKET_SIZE - 1; i++) {
calculated_checksum += this->buffer_[i];
}
const uint8_t calculated_checksum = sum_bytes(this->buffer_, PACKET_SIZE - 1);
uint8_t received_checksum = this->buffer_[PACKET_SIZE - 1];
if (calculated_checksum != received_checksum) {
+8
View File
@@ -15,6 +15,7 @@
#include <limits>
#include <memory>
#include <new>
#include <numeric>
#include <span>
#include <string>
#include <type_traits>
@@ -879,6 +880,13 @@ template<typename T, typename U> T remap(U value, U min, U max, T min_out, T max
return (value - min) * (max_out - min_out) / (max - min) + min_out;
}
/// Add up the bytes of \p data with size \p len, truncated to 8 bits: the checksum many serial and IR
/// protocols use. Prefer this over a bare std::accumulate, whose result type follows the seed, so a plain 0
/// sums in int and compares wrong against a checksum byte.
constexpr uint8_t sum_bytes(const uint8_t *data, size_t len, uint8_t sum = 0) {
return std::accumulate(data, data + len, sum);
}
/// Calculate a CRC-8 checksum of \p data with size \p len.
uint8_t crc8(const uint8_t *data, uint8_t len, uint8_t crc = 0x00, uint8_t poly = 0x8C, bool msb_first = false);
+8
View File
@@ -55,6 +55,14 @@ TEST(HelpersTest, Ilog10RoundTripMatchesLog10) {
}
}
TEST(HelpersTest, SumBytes) {
static constexpr uint8_t FRAME[] = {0x11, 0xDA, 0x27, 0x00, 0xC5, 0x00, 0x10};
EXPECT_EQ(sum_bytes(FRAME, sizeof(FRAME)), 0xE7); // the Daikin comfort frame checksum
EXPECT_EQ(sum_bytes(FRAME, 0), 0);
EXPECT_EQ(sum_bytes(FRAME, sizeof(FRAME), 0x19), 0x00); // wraps at 8 bits
static_assert(sum_bytes(FRAME, 2) == 0xEB, "usable in constant expressions");
}
TEST(StaticVectorTest, ConvertingConstructorFromSmaller) {
StaticVector<uint8_t, 5> small{0x03, 0x00, 0x10, 0x00, 0x01};
StaticVector<uint8_t, 253> big = small;