mirror of
https://github.com/esphome/esphome.git
synced 2026-10-14 02:02:51 +00:00
[core] Add sum_bytes() and use it for the additive byte checksums components hand-roll (#20507)
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]; }
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_() {
|
||||
|
||||
@@ -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]) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user