7#include "esphome/core/log.h"
16constexpr const char *
const TAG =
"home_io_control.oneway_seq";
19constexpr uint32_t FNV1_OFFSET_BASIS = 2166136261U;
20constexpr uint32_t FNV1_PRIME = 16777619U;
28uint32_t preference_key(
const uint8_t node_id[
NODE_ID_SIZE]) {
31 uint32_t hash = FNV1_OFFSET_BASIS;
32 hash = (hash ^
static_cast<uint8_t
>(
'1')) * FNV1_PRIME;
33 hash = (hash ^
static_cast<uint8_t
>(
'W')) * FNV1_PRIME;
35 hash = (hash ^ node_id[i]) * FNV1_PRIME;
43bool persist(ESPPreferenceObject &pref, uint16_t value) {
44 if (!pref.save(&value))
46 return global_preferences->sync();
52 if (this->find_(node_id) !=
nullptr)
57 counter.pref = global_preferences->make_preference<uint16_t>(preference_key(node_id));
59 uint16_t persisted = 0;
60 if (counter.pref.load(&persisted)) {
66 counter.next = persisted > initial_sequence ? persisted : initial_sequence;
68 counter.next = initial_sequence;
71 counter.reserved = counter.next;
73 this->counters_.push_back(counter);
77 Counter *counter = this->find_(node_id);
78 if (counter ==
nullptr)
81 if (counter->next == counter->reserved) {
85 if (!persist(counter->pref, new_reservation)) {
88 ESP_LOGE(
TAG,
"Could not persist a 1W sequence reservation; refusing to transmit");
91 counter->reserved = new_reservation;
95 counter->next =
static_cast<uint16_t
>(counter->next + 1);
100 Counter *counter = this->find_(node_id);
101 if (counter ==
nullptr)
104 if (!persist(counter->pref, value))
106 counter->next = value;
108 counter->reserved = value;
113 const Counter *counter = this->find_(node_id);
114 if (counter ==
nullptr)
120OneWaySequenceStore::Counter *OneWaySequenceStore::find_(
const uint8_t node_id[
NODE_ID_SIZE]) {
121 for (
auto &counter : this->counters_) {
122 if (memcmp(counter.node_id, node_id,
NODE_ID_SIZE) == 0)
128const OneWaySequenceStore::Counter *OneWaySequenceStore::find_(
const uint8_t node_id[
NODE_ID_SIZE])
const {
129 for (
const auto &counter : this->counters_) {
130 if (memcmp(counter.node_id, node_id,
NODE_ID_SIZE) == 0)
bool seed(const uint8_t node_id[NODE_ID_SIZE], uint16_t value)
Force an identity's counter to a specific value and persist it immediately.
void add_identity(const uint8_t node_id[NODE_ID_SIZE], uint16_t initial_sequence)
Register a controller identity and load its persisted counter.
bool next(const uint8_t node_id[NODE_ID_SIZE], uint16_t &out)
Reserve and return the next sequence for an identity.
bool peek(const uint8_t node_id[NODE_ID_SIZE], uint16_t &out) const
The next sequence this identity would hand out, without reserving it.
static constexpr uint8_t NODE_ID_SIZE
Device/node addresses are 3 bytes (e.g., "123ABC").
static constexpr const char * TAG
static constexpr uint16_t ONEWAY_SEQUENCE_STRIDE
How many sequences one flash write reserves.
Persistent rolling-sequence counters for one-way (1W) transmit.