ESPHome  2022.12.8
canbus.h
Go to the documentation of this file.
1 #pragma once
2 
6 
7 #include <vector>
8 
9 namespace esphome {
10 namespace canbus {
11 
12 enum Error : uint8_t {
13  ERROR_OK = 0,
19 };
20 
21 enum CanSpeed : uint8_t {
38 };
39 
40 class CanbusTrigger;
41 template<typename... Ts> class CanbusSendAction;
42 
43 /* CAN payload length definitions according to ISO 11898-1 */
44 static const uint8_t CAN_MAX_DATA_LENGTH = 8;
45 
46 /*
47 Can Frame describes a normative CAN Frame
48 The RTR = Remote Transmission Request is implemented in every CAN controller but rarely used
49 So currently the flag is passed to and from the hardware but currently ignored to the user application.
50 */
51 struct CanFrame {
52  bool use_extended_id = false;
54  uint32_t can_id; /* 29 or 11 bit CAN_ID */
55  uint8_t can_data_length_code; /* frame payload length in byte (0 .. CAN_MAX_DATA_LENGTH) */
56  uint8_t data[CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)));
57 };
58 
59 class Canbus : public Component {
60  public:
61  Canbus(){};
62  void setup() override;
63  void dump_config() override;
64  float get_setup_priority() const override { return setup_priority::HARDWARE; }
65  void loop() override;
66 
67  void send_data(uint32_t can_id, bool use_extended_id, bool remote_transmission_request,
68  const std::vector<uint8_t> &data);
69  void send_data(uint32_t can_id, bool use_extended_id, const std::vector<uint8_t> &data) {
70  // for backwards compatibility only
71  this->send_data(can_id, use_extended_id, false, data);
72  }
73  void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
74  void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
75  void set_bitrate(CanSpeed bit_rate) { this->bit_rate_ = bit_rate; }
76 
77  void add_trigger(CanbusTrigger *trigger);
78 
79  protected:
80  template<typename... Ts> friend class CanbusSendAction;
81  std::vector<CanbusTrigger *> triggers_{};
82  uint32_t can_id_;
85 
86  virtual bool setup_internal();
87  virtual Error send_message(struct CanFrame *frame);
88  virtual Error read_message(struct CanFrame *frame);
89 };
90 
91 template<typename... Ts> class CanbusSendAction : public Action<Ts...>, public Parented<Canbus> {
92  public:
93  void set_data_template(const std::function<std::vector<uint8_t>(Ts...)> func) {
94  this->data_func_ = func;
95  this->static_ = false;
96  }
97  void set_data_static(const std::vector<uint8_t> &data) {
98  this->data_static_ = data;
99  this->static_ = true;
100  }
101 
102  void set_can_id(uint32_t can_id) { this->can_id_ = can_id; }
103 
104  void set_use_extended_id(bool use_extended_id) { this->use_extended_id_ = use_extended_id; }
105 
106  void set_remote_transmission_request(bool remote_transmission_request) {
107  this->remote_transmission_request_ = remote_transmission_request;
108  }
109 
110  void play(Ts... x) override {
111  auto can_id = this->can_id_.has_value() ? *this->can_id_ : this->parent_->can_id_;
112  auto use_extended_id =
113  this->use_extended_id_.has_value() ? *this->use_extended_id_ : this->parent_->use_extended_id_;
114  if (this->static_) {
115  this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, this->data_static_);
116  } else {
117  auto val = this->data_func_(x...);
118  this->parent_->send_data(can_id, use_extended_id, this->remote_transmission_request_, val);
119  }
120  }
121 
122  protected:
124  optional<bool> use_extended_id_{};
125  bool remote_transmission_request_{false};
126  bool static_{false};
127  std::function<std::vector<uint8_t>(Ts...)> data_func_{};
128  std::vector<uint8_t> data_static_{};
129 };
130 
131 class CanbusTrigger : public Trigger<std::vector<uint8_t>, uint32_t, bool>, public Component {
132  friend class Canbus;
133 
134  public:
135  explicit CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask,
136  const bool use_extended_id)
137  : parent_(parent), can_id_(can_id), can_id_mask_(can_id_mask), use_extended_id_(use_extended_id){};
138 
139  void set_remote_transmission_request(bool remote_transmission_request) {
140  this->remote_transmission_request_ = remote_transmission_request;
141  }
142 
143  void setup() override { this->parent_->add_trigger(this); }
144 
145  protected:
147  uint32_t can_id_;
148  uint32_t can_id_mask_;
150  optional<bool> remote_transmission_request_{};
151 };
152 
153 } // namespace canbus
154 } // namespace esphome
void setup()
void send_data(uint32_t can_id, bool use_extended_id, const std::vector< uint8_t > &data)
Definition: canbus.h:69
void loop()
void set_data_static(const std::vector< uint8_t > &data)
Definition: canbus.h:97
float get_setup_priority() const override
Definition: canbus.h:64
uint8_t can_data_length_code
Definition: canbus.h:55
void set_bitrate(CanSpeed bit_rate)
Definition: canbus.h:75
CanbusTrigger(Canbus *parent, const std::uint32_t can_id, const std::uint32_t can_id_mask, const bool use_extended_id)
Definition: canbus.h:135
void set_can_id(uint32_t can_id)
Definition: canbus.h:102
CanSpeed bit_rate_
Definition: canbus.h:84
void setup() override
Definition: canbus.h:143
bool remote_transmission_request
Definition: canbus.h:53
void set_use_extended_id(bool use_extended_id)
Definition: canbus.h:104
void set_data_template(const std::function< std::vector< uint8_t >(Ts...)> func)
Definition: canbus.h:93
void set_remote_transmission_request(bool remote_transmission_request)
Definition: canbus.h:139
void set_use_extended_id(bool use_extended_id)
Definition: canbus.h:74
void play(Ts... x) override
Definition: canbus.h:110
uint8_t data [CAN_MAX_DATA_LENGTH] __attribute__((aligned(8)))
const float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition: component.cpp:17
void set_can_id(uint32_t can_id)
Definition: canbus.h:73
Definition: a4988.cpp:4
uint32_t val
Definition: datatypes.h:85
Helper class to easily give an object a parent of type T.
Definition: helpers.h:500
void set_remote_transmission_request(bool remote_transmission_request)
Definition: canbus.h:106