diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 94921e1d088..72bd3a0c6ba 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -887,6 +887,16 @@ constexpr uint8_t sum_bytes(const uint8_t *data, size_t len, uint8_t sum = 0) { return std::accumulate(data, data + len, sum); } +/// Add up the bytes of \p data with size \p len, truncated to 16 bits. +constexpr uint16_t sum16_bytes(const uint8_t *data, size_t len, uint16_t sum = 0) { + return std::accumulate(data, data + len, sum); +} + +/// XOR the bytes of \p data with size \p len, starting from \p init. +constexpr uint8_t xor_bytes(const uint8_t *data, size_t len, uint8_t init = 0) { + return std::accumulate(data, data + len, init, std::bit_xor<>()); +} + /// 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); diff --git a/tests/components/core/helpers_test.cpp b/tests/components/core/helpers_test.cpp index 92a7f841830..499aea5a8ad 100644 --- a/tests/components/core/helpers_test.cpp +++ b/tests/components/core/helpers_test.cpp @@ -78,6 +78,24 @@ TEST(HelpersTest, SumBytes) { static_assert(sum_bytes(FRAME, 2) == 0xEB, "usable in constant expressions"); } +TEST(HelpersTest, Sum16Bytes) { + static constexpr uint8_t FRAME[] = {0x42, 0x4D, 0xE1, 0x00, 0x01}; + EXPECT_EQ(sum16_bytes(FRAME, sizeof(FRAME)), 0x0171); // the PMSx003 active mode command checksum + EXPECT_EQ(sum16_bytes(FRAME, 0), 0); + EXPECT_EQ(sum16_bytes(FRAME, sizeof(FRAME), 0x1234), 0x13A5); + EXPECT_EQ(sum16_bytes(FRAME, sizeof(FRAME), 0xFFFF), 0x0170); // wraps at 16 bits + static_assert(sum16_bytes(FRAME, 2) == 0x8F, "usable in constant expressions"); +} + +TEST(HelpersTest, XorBytes) { + static constexpr uint8_t FRAME[] = {0x01, 0x03, 0x00, 0x15, 0x00}; + EXPECT_EQ(xor_bytes(FRAME + 1, 3, 0xFF), 0xE9); // the Z-Wave GetVersion frame checksum + EXPECT_EQ(xor_bytes(FRAME, 0), 0); + EXPECT_EQ(xor_bytes(FRAME, 0, 0x5A), 0x5A); + EXPECT_EQ(xor_bytes(FRAME, sizeof(FRAME)), 0x17); + static_assert(xor_bytes(FRAME, 2) == 0x02, "usable in constant expressions"); +} + TEST(StaticVectorTest, ConvertingConstructorFromSmaller) { StaticVector small{0x03, 0x00, 0x10, 0x00, 0x01}; StaticVector big = small;