ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
canbus.h
Go to the documentation of this file.
1#pragma once
2
6
7#include <cinttypes>
8#include <vector>
9
10namespace esphome::canbus {
11
20
44
45class CanbusTrigger;
46template<typename... Ts> class CanbusSendAction;
47
48/* CAN payload length definitions according to ISO 11898-1 */
49static const uint8_t CAN_MAX_DATA_LENGTH = 8;
50
51static const uint8_t CAN_ERROR_PASSIVE_THRESHOLD = 128;
52
53/*
54Can Frame describes a normative CAN Frame
55The RTR = Remote Transmission Request is implemented in every CAN controller but rarely used
56So currently the flag is passed to and from the hardware but currently ignored to the user application.
57*/
58struct CanFrame {
59 bool use_extended_id = false;
61 uint32_t can_id; /* 29 or 11 bit CAN_ID */
62 uint8_t can_data_length_code; /* frame payload length in byte (0 .. CAN_MAX_DATA_LENGTH) */
63 uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)));
64};
65
72
73static constexpr uint32_t CAN_STATUS_UNSET = UINT32_MAX;
74
75struct CanStatus {
76 bool bus_off{false};
77 uint8_t rx_error_counter{0};
78 uint8_t tx_error_counter{0};
79 uint32_t tx_failed_count{CAN_STATUS_UNSET};
80 uint32_t rx_missed_count{CAN_STATUS_UNSET};
81 uint32_t rx_overrun_count{CAN_STATUS_UNSET};
82 uint32_t arb_lost_count{CAN_STATUS_UNSET};
83 uint32_t bus_error_count{CAN_STATUS_UNSET};
84};
85
86class Canbus : public Component {
87 public:
88 Canbus() {};
89 void setup() override;
90 void dump_config() override;
91 float get_setup_priority() const override { return setup_priority::HARDWARE; }
92 void loop() override;
93
94 canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request, const uint8_t *data,
95 size_t len);
96 canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request,
97 const std::vector<uint8_t> &data) {
98 return this->send_data(can_id, use_extended_id, remote_transmission_request, data.data(), data.size());
99 }
100 canbus::Error send_data(uint32_t can_id, bool use_extended_id, const std::vector<uint8_t> &data) {
101 // for backwards compatibility only
102 return this->send_data(can_id, use_extended_id, false, data);
103 }
104 void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
105 void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
106 void set_bitrate(CanSpeed bit_rate) { this->bit_rate_ = bit_rate; }
107 void set_max_frames_per_loop(uint32_t max_frames_per_loop) { this->max_frames_per_loop_ = max_frames_per_loop; }
108 virtual CanStatus get_status() { return {}; }
109
110 void add_trigger(CanbusTrigger *trigger);
121 template<typename F> void add_callback(F &&callback) { this->callback_manager_.add(std::forward<F>(callback)); }
122
123 protected:
124 template<typename... Ts> friend class CanbusSendAction;
125 std::vector<CanbusTrigger *> triggers_{};
127 uint32_t max_frames_per_loop_{50}; // Keep in sync with DEFAULT_MAX_FRAMES_PER_LOOP in __init__.py
128 CanSpeed bit_rate_{CAN_125KBPS}; // Keep in sync with DEFAULT_BIT_RATE in __init__.py
129 bool use_extended_id_{false};
130 uint8_t events_to_log_{0};
131 bool bus_off_{false};
132 CallbackManager<void(uint32_t can_id, bool extended_id, bool rtr, const std::vector<uint8_t> &data)>
134
135 // interval in which to check for new can bus events (bus-off, passive, active)
136 static constexpr uint32_t EVENT_CHECK_INTERVAL_MS = 100;
138
139 // time to wait after logging an event before logging the next event(s)
140 static constexpr uint32_t EVENT_LOG_THROTTLE_MS = 1000;
142
143 // time span without bus-off events before the bus is declared recovered
144 static constexpr uint32_t EVENT_LOG_BUS_OFF_HOLDOFF_MS = 1000;
146
147#ifdef ESPHOME_LOG_HAS_VERBOSE
148 static constexpr uint32_t STATE_LOG_INTERVAL_MS = 1000;
150#endif
151
152 void log_events_(CanEventFlags events, uint32_t now);
153 virtual bool setup_internal() = 0;
154 virtual Error send_message(struct CanFrame *frame) = 0;
155 virtual Error read_message(struct CanFrame *frame) = 0;
156 virtual CanEventFlags get_events() { return CanEventFlags{}; }
157};
158
159template<typename... Ts> class CanbusSendAction final : public Action<Ts...>, public Parented<Canbus> {
160 TEMPLATABLE_BYTES(data)
161
162 void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
163
164 void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
165
166 void set_remote_transmission_request(bool remote_transmission_request) {
167 this->remote_transmission_request_ = remote_transmission_request;
168 }
169
170 void play(const Ts &...x) override {
171 auto can_id = this->can_id_.has_value() ? *this->can_id_ : this->parent_->can_id_;
172 auto use_extended_id =
173 this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_;
174 this->data_.template visit<CAN_MAX_DATA_LENGTH>(
175 [&](const uint8_t *data, size_t len) {
176 this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, data, len);
177 },
178 x...);
179 }
180
181 protected:
182 optional<uint32_t> can_id_{};
183 optional<bool> use_extended_id_{};
185};
186
187class CanbusTrigger final : public Trigger<std::vector<uint8_t>, uint32_t, bool>, public Component {
188 friend class Canbus;
189
190 public:
191 explicit CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask,
192 const bool use_extended_id)
193 : parent_(parent), can_id_(can_id), can_id_mask_(can_id_mask), use_extended_id_(use_extended_id) {};
194
195 void set_remote_transmission_request(bool remote_transmission_request) {
196 this->remote_transmission_request_ = remote_transmission_request;
197 }
198
199 void setup() override { this->parent_->add_trigger(this); }
200
201 protected:
207};
208
209} // namespace esphome::canbus
Helper class to easily give an object a parent of type T.
Definition helpers.h:2073
virtual CanStatus get_status()
Definition canbus.h:108
CallbackManager< void(uint32_t can_id, bool extended_id, bool rtr, const std::vector< uint8_t > &data)> callback_manager_
Definition canbus.h:133
void loop() override
Definition canbus.cpp:68
static constexpr uint32_t EVENT_CHECK_INTERVAL_MS
Definition canbus.h:136
void log_events_(CanEventFlags events, uint32_t now)
Definition canbus.cpp:119
void set_max_frames_per_loop(uint32_t max_frames_per_loop)
Definition canbus.h:107
void set_use_extended_id(bool use_extended_id)
Definition canbus.h:105
canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request, const std::vector< uint8_t > &data)
Definition canbus.h:96
void add_callback(F &&callback)
Add a callback to be called when a CAN message is received.
Definition canbus.h:121
static constexpr uint32_t STATE_LOG_INTERVAL_MS
Definition canbus.h:148
canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request, const uint8_t *data, size_t len)
Definition canbus.cpp:25
void setup() override
Definition canbus.cpp:10
void add_trigger(CanbusTrigger *trigger)
Definition canbus.cpp:59
virtual CanEventFlags get_events()
Definition canbus.h:156
uint32_t last_state_log_time_
Definition canbus.h:149
uint32_t max_frames_per_loop_
Definition canbus.h:127
canbus::Error send_data(uint32_t can_id, bool use_extended_id, const std::vector< uint8_t > &data)
Definition canbus.h:100
uint32_t last_event_log_time_
Definition canbus.h:141
void set_bitrate(CanSpeed bit_rate)
Definition canbus.h:106
void set_can_id(uint32_t can_id)
Definition canbus.h:104
float get_setup_priority() const override
Definition canbus.h:91
static constexpr uint32_t EVENT_LOG_THROTTLE_MS
Definition canbus.h:140
void dump_config() override
Definition canbus.cpp:17
static constexpr uint32_t EVENT_LOG_BUS_OFF_HOLDOFF_MS
Definition canbus.h:144
virtual Error send_message(struct CanFrame *frame)=0
uint32_t last_bus_off_time_
Definition canbus.h:145
virtual bool setup_internal()=0
std::vector< CanbusTrigger * > triggers_
Definition canbus.h:125
uint32_t last_event_check_time_
Definition canbus.h:137
virtual Error read_message(struct CanFrame *frame)=0
optional< uint32_t > can_id_
Definition canbus.h:182
optional< bool > use_extended_id_
Definition canbus.h:183
optional< bool > remote_transmission_request_
Definition canbus.h:206
CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask, const bool use_extended_id)
Definition canbus.h:191
void set_remote_transmission_request(bool remote_transmission_request)
Definition canbus.h:195
@ CAN_EVENT_PASSIVE
Definition canbus.h:67
@ CAN_EVENT_BUS_OFF
Definition canbus.h:69
@ CAN_EVENT_RX_QUEUE_FULL
Definition canbus.h:70
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.h:43
const void size_t len
Definition hal.h:68
static void uint32_t
uint8_t can_data_length_code
Definition canbus.h:62
uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)))
uint16_t x
Definition tt21100.cpp:5