ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
hdlc_reliability.h
Go to the documentation of this file.
1#pragma once
2
4#ifdef USE_PACKET_INTERFACE_HDLC
5#include <array>
6
7#include "packet_interface.h"
8
10
23 public:
25 static constexpr uint8_t MAX_WINDOW = 7;
27 static constexpr size_t FRAME_OVERHEAD = 3;
28
29 explicit HdlcReliability(PacketInterface *lower);
30
31 void setup() override;
32 void loop() override;
33 void dump_config() override;
34 bool send_to_interface(const PacketBuffer &data, const PacketMetaData &meta_data) override;
36 size_t get_send_capacity() const override {
37 return this->tx_slots_ == nullptr ? 0 : this->max_queue_length_ - this->outstanding_();
38 }
39
40 void set_ack_timeout(uint32_t timeout_ms) { this->timeout_ms_ = timeout_ms; }
41 void set_ack_delay(uint32_t ack_delay_ms) { this->ack_delay_ms_ = ack_delay_ms; }
43 void set_max_retries(uint8_t retries) { this->max_retries_ = retries; }
44
45 bool is_connected() const { return this->state_ == LinkState::LINK_STATE_CONNECTED; }
46
47 protected:
48 enum class LinkState : uint8_t {
49 LINK_STATE_RESET_PENDING, // SABM to be sent from loop()
50 LINK_STATE_RESETTING, // SABM sent, waiting for UA
52 };
53
54 void receive_(const PacketBuffer &data, const PacketMetaData &meta_data);
55 void receive_info_(uint8_t control, const uint8_t *payload, size_t length, const PacketMetaData &meta_data);
56 bool send_frame_(uint8_t control, const uint8_t *payload, size_t length);
57 bool send_supervisory_(uint8_t type);
58 bool send_pending_();
60 void retry_send_();
62 void owe_ack_(bool now);
63 void ack_sent_();
64 void process_ack_(uint8_t nr);
65 void on_timeout_();
66 void start_reset_();
67 void link_up_();
68 void start_timer_();
69 void request_loop_();
70 uint8_t outstanding_() const { return (this->vs_ - this->va_) & 7; }
71 uint8_t slot_index_(uint8_t seq) const { return (this->head_ + ((seq - this->va_) & 7)) % this->max_queue_length_; }
72 uint8_t *slot_(uint8_t seq) { return this->tx_slots_ + this->slot_index_(seq) * this->max_packet_size_; }
73
75 // max_queue_length_ slots of max_packet_size_ bytes, a ring starting at head_ which holds frame va_; allocated in
76 // setup() and never freed
77 uint8_t *tx_slots_{nullptr};
78 std::array<uint16_t, MAX_WINDOW> tx_lengths_{}; // indexed like the slots
82 uint8_t max_retries_{5};
83 uint8_t retries_{0};
84 uint8_t head_{0};
85 uint8_t vs_{0}; // sequence number of the next new frame
86 uint8_t vn_{0}; // next frame to send; frames from va_ up to it have been sent
87 uint8_t va_{0}; // oldest unacknowledged frame
88 uint8_t vr_{0}; // next frame expected from the peer
90 bool ack_pending_{false}; // an RR is owed
91 bool ack_due_{false}; // and should be sent now
92 bool rej_sent_{false};
93 bool peer_frame_seen_{false}; // a numbered frame has arrived since the link came up
94 bool oversize_warned_{false};
95 bool reset_wait_logged_{false}; // the queue filled while waiting for this reset to be answered
96};
97
98} // namespace esphome::packet_interface
99#endif
A reliability layer that delivers packets in order, without loss or duplicates, between two peers.
void owe_ack_(bool now)
An RR is owed: at once, or after the ack delay unless an I-frame carries it first.
size_t get_send_capacity() const override
No room while the layer has no send queue: before setup(), or when setup() failed.
void set_ack_delay(uint32_t ack_delay_ms)
std::array< uint16_t, MAX_WINDOW > tx_lengths_
void receive_info_(uint8_t control, const uint8_t *payload, size_t length, const PacketMetaData &meta_data)
bool send_frame_(uint8_t control, const uint8_t *payload, size_t length)
static constexpr uint8_t MAX_WINDOW
Most frames that can be unacknowledged at once, set by the 3 bit sequence numbers.
bool send_to_interface(const PacketBuffer &data, const PacketMetaData &meta_data) override
void receive_(const PacketBuffer &data, const PacketMetaData &meta_data)
static constexpr size_t FRAME_OVERHEAD
Control byte plus CRC-16.
A buffer class that efficiently represents a composite buffer with three sections:
A class that will transport data to and from an abstract channel.
A struct to hold metadata about a packet.
uint8_t type
static void uint32_t
uint16_t seq