ESPHome 2026.6.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
51/*
52Can Frame describes a normative CAN Frame
53The RTR = Remote Transmission Request is implemented in every CAN controller but rarely used
54So currently the flag is passed to and from the hardware but currently ignored to the user application.
55*/
56struct CanFrame {
57 bool use_extended_id = false;
59 uint32_t can_id; /* 29 or 11 bit CAN_ID */
60 uint8_t can_data_length_code; /* frame payload length in byte (0 .. CAN_MAX_DATA_LENGTH) */
61 uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)));
62};
63
64class Canbus : public Component {
65 public:
66 Canbus(){};
67 void setup() override;
68 void dump_config() override;
69 float get_setup_priority() const override { return setup_priority::HARDWARE; }
70 void loop() override;
71
72 canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request,
73 const std::vector<uint8_t> &data);
74 canbus::Error send_data(uint32_t can_id, bool use_extended_id, const std::vector<uint8_t> &data) {
75 // for backwards compatibility only
76 return this->send_data(can_id, use_extended_id, false, data);
77 }
78 void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
79 void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
80 void set_bitrate(CanSpeed bit_rate) { this->bit_rate_ = bit_rate; }
81
82 void add_trigger(CanbusTrigger *trigger);
93 template<typename F> void add_callback(F &&callback) { this->callback_manager_.add(std::forward<F>(callback)); }
94
95 protected:
96 template<typename... Ts> friend class CanbusSendAction;
97 std::vector<CanbusTrigger *> triggers_{};
101 CallbackManager<void(uint32_t can_id, bool extended_id, bool rtr, const std::vector<uint8_t> &data)>
103
104 virtual bool setup_internal() = 0;
105 virtual Error send_message(struct CanFrame *frame) = 0;
106 virtual Error read_message(struct CanFrame *frame) = 0;
107};
108
109template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public Parented<Canbus> {
110 public:
111 void set_data_template(std::vector<uint8_t> (*func)(Ts...)) {
112 // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers
113 this->data_.func = func;
114 this->len_ = -1; // Sentinel value indicates template mode
115 }
116
117 // Store pointer to static data in flash (no RAM copy)
118 void set_data_static(const uint8_t *data, size_t len) {
119 this->data_.data = data;
120 this->len_ = len; // Length >= 0 indicates static mode
121 }
122
123 void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
124
125 void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
126
127 void set_remote_transmission_request(bool remote_transmission_request) {
128 this->remote_transmission_request_ = remote_transmission_request;
129 }
130
131 void play(const Ts &...x) override {
132 auto can_id = this->can_id_.has_value() ? *this->can_id_ : this->parent_->can_id_;
133 auto use_extended_id =
134 this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_;
135 std::vector<uint8_t> data;
136 if (this->len_ >= 0) {
137 // Static mode: copy from flash to vector
138 data.assign(this->data_.data, this->data_.data + this->len_);
139 } else {
140 // Template mode: call function
141 data = this->data_.func(x...);
142 }
143 this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, data);
144 }
145
146 protected:
147 optional<uint32_t> can_id_{};
148 optional<bool> use_extended_id_{};
150 ssize_t len_{-1}; // -1 = template mode, >=0 = static mode with length
151 union Data {
152 std::vector<uint8_t> (*func)(Ts...); // Function pointer (stateless lambdas)
153 const uint8_t *data; // Pointer to static data in flash
155};
156
157class CanbusTrigger : public Trigger<std::vector<uint8_t>, uint32_t, bool>, public Component {
158 friend class Canbus;
159
160 public:
161 explicit CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask,
162 const bool use_extended_id)
163 : parent_(parent), can_id_(can_id), can_id_mask_(can_id_mask), use_extended_id_(use_extended_id){};
164
165 void set_remote_transmission_request(bool remote_transmission_request) {
166 this->remote_transmission_request_ = remote_transmission_request;
167 }
168
169 void setup() override { this->parent_->add_trigger(this); }
170
171 protected:
177};
178
179} // namespace esphome::canbus
Helper class to easily give an object a parent of type T.
Definition helpers.h:1861
CallbackManager< void(uint32_t can_id, bool extended_id, bool rtr, const std::vector< uint8_t > &data)> callback_manager_
Definition canbus.h:102
void loop() override
Definition canbus.cpp:68
void set_use_extended_id(bool use_extended_id)
Definition canbus.h:79
canbus::Error send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request, const std::vector< uint8_t > &data)
Definition canbus.cpp:24
void add_callback(F &&callback)
Add a callback to be called when a CAN message is received.
Definition canbus.h:93
void setup() override
Definition canbus.cpp:9
void add_trigger(CanbusTrigger *trigger)
Definition canbus.cpp:59
canbus::Error send_data(uint32_t can_id, bool use_extended_id, const std::vector< uint8_t > &data)
Definition canbus.h:74
void set_bitrate(CanSpeed bit_rate)
Definition canbus.h:80
void set_can_id(uint32_t can_id)
Definition canbus.h:78
float get_setup_priority() const override
Definition canbus.h:69
void dump_config() override
Definition canbus.cpp:16
virtual Error send_message(struct CanFrame *frame)=0
virtual bool setup_internal()=0
std::vector< CanbusTrigger * > triggers_
Definition canbus.h:97
virtual Error read_message(struct CanFrame *frame)=0
void set_data_template(std::vector< uint8_t >(*func)(Ts...))
Definition canbus.h:111
void set_remote_transmission_request(bool remote_transmission_request)
Definition canbus.h:127
void set_data_static(const uint8_t *data, size_t len)
Definition canbus.h:118
optional< uint32_t > can_id_
Definition canbus.h:147
void play(const Ts &...x) override
Definition canbus.h:131
void set_use_extended_id(bool use_extended_id)
Definition canbus.h:125
optional< bool > use_extended_id_
Definition canbus.h:148
void set_can_id(uint32_t can_id)
Definition canbus.h:123
union esphome::canbus::CanbusSendAction::Data data_
optional< bool > remote_transmission_request_
Definition canbus.h:176
CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask, const bool use_extended_id)
Definition canbus.h:161
void set_remote_transmission_request(bool remote_transmission_request)
Definition canbus.h:165
__int64 ssize_t
Definition httplib.h:178
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.h:41
const void size_t len
Definition hal.h:64
static void uint32_t
uint8_t can_data_length_code
Definition canbus.h:60
uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)))
uint16_t x
Definition tt21100.cpp:5
std::vector< uint8_t >(* func)(Ts...)
Definition canbus.h:152