canopen.h
Go to the documentation of this file.
1 #ifndef H_CANOPEN
2 #define H_CANOPEN
3 
7 #include "exceptions.h"
8 #include "layer.h"
9 #include "objdict.h"
10 #include "timer.h"
11 #include <stdexcept>
12 #include <boost/thread/condition_variable.hpp>
13 #include <boost/chrono/system_clocks.hpp>
14 #include <boost/lexical_cast.hpp>
15 
16 namespace canopen{
17 
19 typedef boost::chrono::high_resolution_clock::duration time_duration;
20 inline time_point get_abs_time(const time_duration& timeout) { return boost::chrono::high_resolution_clock::now() + timeout; }
21 inline time_point get_abs_time() { return boost::chrono::high_resolution_clock::now(); }
22 
23 
24 template<typename T> struct FrameOverlay: public can::Frame{
25  T &data;
26  FrameOverlay(const Header &h) : can::Frame(h,sizeof(T)), data(* (T*) can::Frame::c_array()) {
27  can::Frame::data.fill(0);
28  }
29  FrameOverlay(const can::Frame &f) : can::Frame(f), data(* (T*) can::Frame::c_array()) { }
30 };
31 
32 class SDOClient{
33 
35 
36  boost::timed_mutex mutex;
37 
39  bool processFrame(const can::Frame & msg);
40 
42  size_t offset;
43  size_t total;
44  bool done;
47 
48  void transmitAndWait(const canopen::ObjectDict::Entry &entry, const String &data, String *result);
49  void abort(uint32_t reason);
50 
52 protected:
53  void read(const canopen::ObjectDict::Entry &entry, String &data);
54  void write(const canopen::ObjectDict::Entry &entry, const String &data);
55 public:
57 
58  void init();
59 
60  SDOClient(const can::CommInterfaceSharedPtr interface, const ObjectDictSharedPtr dict, uint8_t node_id)
61  : interface_(interface),
62  storage_(std::make_shared<ObjectStorage>(dict, node_id,
63  std::bind(&SDOClient::read, this, std::placeholders::_1, std::placeholders::_2),
64  std::bind(&SDOClient::write, this, std::placeholders::_1, std::placeholders::_2))
65  ),
66  reader_(false, 1)
67  {
68  }
69 };
70 
71 class PDOMapper{
72  boost::mutex mutex_;
73 
74  class Buffer{
75  public:
76  bool read(uint8_t* b, const size_t len);
77  void write(const uint8_t* b, const size_t len);
78  void read(const canopen::ObjectDict::Entry &entry, String &data);
79  void write(const canopen::ObjectDict::Entry &, const String &data);
80  void clean() { dirty = false; }
81  const size_t size;
82  Buffer(const size_t sz) : size(sz), dirty(false), empty(true), buffer(sz) {}
83 
84  private:
85  boost::mutex mutex;
86  bool dirty;
87  bool empty;
88  std::vector<char> buffer;
89  };
90  typedef std::shared_ptr<Buffer> BufferSharedPtr;
91 
92  class PDO {
93  protected:
94  void parse_and_set_mapping(const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index, const bool &read, const bool &write);
97  std::vector<BufferSharedPtr>buffers;
98  };
99 
100  struct TPDO: public PDO{
101  typedef std::shared_ptr<TPDO> TPDOSharedPtr;
102  void sync();
103  static TPDOSharedPtr create(const can::CommInterfaceSharedPtr interface, const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index){
104  TPDOSharedPtr tpdo(new TPDO(interface));
105  if(!tpdo->init(storage, com_index, map_index))
106  tpdo.reset();
107  return tpdo;
108  }
109  private:
110  TPDO(const can::CommInterfaceSharedPtr interface) : interface_(interface){}
111  bool init(const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index);
113  boost::mutex mutex;
114  };
115 
116  struct RPDO : public PDO{
117  void sync(LayerStatus &status);
118  typedef std::shared_ptr<RPDO> RPDOSharedPtr;
119  static RPDOSharedPtr create(const can::CommInterfaceSharedPtr interface, const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index){
120  RPDOSharedPtr rpdo(new RPDO(interface));
121  if(!rpdo->init(storage, com_index, map_index))
122  rpdo.reset();
123  return rpdo;
124  }
125  private:
126  bool init(const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index);
127  RPDO(const can::CommInterfaceSharedPtr interface) : interface_(interface), timeout(-1) {}
128  boost::mutex mutex;
130 
132  void handleFrame(const can::Frame & msg);
133  int timeout;
134  };
135 
136  std::unordered_set<RPDO::RPDOSharedPtr> rpdos_;
137  std::unordered_set<TPDO::TPDOSharedPtr> tpdos_;
138 
140 
141 public:
142  PDOMapper(const can::CommInterfaceSharedPtr interface);
143  void read(LayerStatus &status);
144  bool write();
145  bool init(const ObjectStorageSharedPtr storage, LayerStatus &status);
146 };
147 
148 class EMCYHandler : public Layer {
149  std::atomic<bool> has_error_;
153  void handleEMCY(const can::Frame & msg);
155 
156  virtual void handleDiag(LayerReport &report);
157 
158  virtual void handleInit(LayerStatus &status);
159  virtual void handleRecover(LayerStatus &status);
160  virtual void handleRead(LayerStatus &status, const LayerState &current_state);
161  virtual void handleWrite(LayerStatus &status, const LayerState &current_state);
162  virtual void handleHalt(LayerStatus &status);
163  virtual void handleShutdown(LayerStatus &status);
164 
165 public:
166  EMCYHandler(const can::CommInterfaceSharedPtr interface, const ObjectStorageSharedPtr storage);
167  void resetErrors(LayerStatus &status);
168 };
169 
172  const uint16_t period_ms_;
173  const uint8_t overflow_;
174  SyncProperties(const can::Header &h, const uint16_t &p, const uint8_t &o) : header_(h), period_ms_(p), overflow_(o) {}
175  bool operator==(const SyncProperties &p) const { return p.header_.key() == header_.key() && p.overflow_ == overflow_ && p.period_ms_ == period_ms_; }
176 
177 };
178 
179 class SyncCounter {
180 public:
182  SyncCounter(const SyncProperties &p) : properties(p) {}
183  virtual void addNode(void * const ptr) = 0;
184  virtual void removeNode(void * const ptr) = 0;
185  virtual ~SyncCounter() {}
186 };
187 typedef std::shared_ptr<SyncCounter> SyncCounterSharedPtr;
188 
189 class Node : public Layer{
190 public:
191  enum State{
192  Unknown = 255, BootUp = 0, Stopped = 4, Operational = 5 , PreOperational = 127
193  };
194  const uint8_t node_id_;
195  Node(const can::CommInterfaceSharedPtr interface, const ObjectDictSharedPtr dict, uint8_t node_id, const SyncCounterSharedPtr sync = SyncCounterSharedPtr());
196 
197  const State getState();
198  void enterState(const State &s);
199 
200  const ObjectStorageSharedPtr getStorage() { return sdo_.storage_; }
201 
202  bool start();
203  bool stop();
204  bool reset();
205  bool reset_com();
206  bool prepare();
207 
208  using StateFunc = std::function<void(const State&)>;
209  using StateDelegate [[deprecated("use StateFunc instead")]] = can::DelegateHelper<StateFunc>;
210 
213 
214  StateListenerConstSharedPtr addStateListener(const StateFunc & s){
215  return state_dispatcher_.createListener(s);
216  }
217 
218  template<typename T> T get(const ObjectDict::Key& k){
219  return getStorage()->entry<T>(k).get();
220  }
221 
222 private:
223  virtual void handleDiag(LayerReport &report);
224 
225  virtual void handleInit(LayerStatus &status);
226  virtual void handleRecover(LayerStatus &status);
227  virtual void handleRead(LayerStatus &status, const LayerState &current_state);
228  virtual void handleWrite(LayerStatus &status, const LayerState &current_state);
229  virtual void handleHalt(LayerStatus &status);
230  virtual void handleShutdown(LayerStatus &status);
231 
232  template<typename T> int wait_for(const State &s, const T &timeout);
233 
234  boost::timed_mutex mutex;
235  boost::mutex cond_mutex;
236  boost::condition_variable cond;
237 
239  const SyncCounterSharedPtr sync_;
241 
243 
245 
246  void handleNMT(const can::Frame & msg);
247  void switchState(const uint8_t &s);
248 
252 
254  uint16_t getHeartbeatInterval() { return heartbeat_.valid()?heartbeat_.get_cached() : 0; }
255  void setHeartbeatInterval() { if(heartbeat_.valid()) heartbeat_.set(heartbeat_.desc().value().get<uint16_t>()); }
256  bool checkHeartbeat();
257 };
258 typedef std::shared_ptr<Node> NodeSharedPtr;
259 
260 template<typename T> class Chain{
261 public:
262  typedef std::shared_ptr<T> MemberSharedPtr;
263  void call(void (T::*func)(void)){
264  typename std::vector<MemberSharedPtr>::iterator it = elements.begin();
265  while(it != elements.end()){
266  ((**it).*func)();
267  ++it;
268  }
269  }
270  template<typename V> void call(void (T::*func)(const V&), const std::vector<V> &vs){
271  typename std::vector<MemberSharedPtr>::iterator it = elements.begin();
272  typename std::vector<V>::const_iterator it_v = vs.begin();
273  while(it_v != vs.end() && it != elements.end()){
274  ((**it).*func)(*it_v);
275  ++it; ++it_v;
276  }
277  }
278  template<typename V> void call(void (T::*func)(V&), std::vector<V> &vs){
279  vs.resize(elements.size());
280 
281  typename std::vector<MemberSharedPtr>::iterator it = elements.begin();
282  typename std::vector<V>::iterator it_v = vs.begin();
283  while(it_v != vs.end() && it != elements.end()){
284  ((**it).*func)(*it_v);
285  ++it; ++it_v;
286  }
287  }
288  void add(MemberSharedPtr t){
289  elements.push_back(t);
290  }
291 protected:
292  std::vector<MemberSharedPtr> elements;
293 };
294 
295 template<typename T> class NodeChain: public Chain<T>{
296 public:
297  const std::vector<typename Chain<T>::MemberSharedPtr>& getElements() { return Chain<T>::elements; }
298  void start() { this->call(&T::start); }
299  void stop() { this->call(&T::stop); }
300  void reset() { this->call(&T::reset); }
301  void reset_com() { this->call(&T::reset_com); }
302  void prepare() { this->call(&T::prepare); }
303 };
304 
305 class SyncLayer: public Layer, public SyncCounter{
306 public:
307  SyncLayer(const SyncProperties &p) : Layer("Sync layer"), SyncCounter(p) {}
308 };
309 typedef std::shared_ptr<SyncLayer> SyncLayerSharedPtr;
310 
311 class Master{
312  Master(const Master&) = delete; // prevent copies
313  Master& operator=(const Master&) = delete;
314 public:
315  Master() = default;
316  virtual SyncLayerSharedPtr getSync(const SyncProperties &properties) = 0;
317  virtual ~Master() {}
318 
319  typedef std::shared_ptr<Master> MasterSharedPtr;
320  class Allocator {
321  public:
322  virtual MasterSharedPtr allocate(const std::string &name, can::CommInterfaceSharedPtr interface) = 0;
323  virtual ~Allocator() {}
324  };
325 };
327 
328 using can::Settings;
329 
330 } // canopen
331 #endif // !H_CANOPEN
static RPDOSharedPtr create(const can::CommInterfaceSharedPtr interface, const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index)
Definition: canopen.h:119
boost::mutex mutex
Definition: canopen.h:128
std::array< value_type, 8 > data
const uint8_t overflow_
Definition: canopen.h:173
const SyncProperties properties
Definition: canopen.h:181
std::shared_ptr< const Listener > ListenerConstSharedPtr
std::atomic< bool > has_error_
Definition: canopen.h:149
ObjectStorage::Entry< ObjectStorage::DataType< ObjectDict::DEFTYPE_UNSIGNED16 >::type > heartbeat_
Definition: canopen.h:242
std::unordered_set< TPDO::TPDOSharedPtr > tpdos_
Definition: canopen.h:137
std::shared_ptr< TPDO > TPDOSharedPtr
Definition: canopen.h:101
can::Frame last_msg
Definition: canopen.h:45
const can::CommInterfaceSharedPtr interface_
Definition: canopen.h:238
can::Frame frame
Definition: canopen.h:95
ObjectStorage::Entry< uint8_t > num_errors_
Definition: canopen.h:151
std::shared_ptr< RPDO > RPDOSharedPtr
Definition: canopen.h:118
const uint8_t node_id_
Definition: canopen.h:194
SyncCounter(const SyncProperties &p)
Definition: canopen.h:182
const can::Header header_
Definition: canopen.h:171
can::FrameListenerConstSharedPtr listener_
Definition: canopen.h:131
FrameOverlay(const Header &h)
Definition: canopen.h:26
boost::mutex mutex
Definition: canopen.h:85
std::shared_ptr< Master > MasterSharedPtr
Definition: canopen.h:319
can::BufferedReader reader_
Definition: canopen.h:38
RPDO(const can::CommInterfaceSharedPtr interface)
Definition: canopen.h:127
boost::timed_mutex mutex
Definition: canopen.h:36
StateListener::ListenerConstSharedPtr StateListenerConstSharedPtr
Definition: canopen.h:212
void call(void(T::*func)(V &), std::vector< V > &vs)
Definition: canopen.h:278
std::unordered_set< RPDO::RPDOSharedPtr > rpdos_
Definition: canopen.h:136
const can::CommInterfaceSharedPtr interface_
Definition: canopen.h:51
can::FrameListenerConstSharedPtr emcy_listener_
Definition: canopen.h:152
boost::chrono::high_resolution_clock::time_point time_point
Definition: canopen.h:18
Buffer(const size_t sz)
Definition: canopen.h:82
std::shared_ptr< SyncCounter > SyncCounterSharedPtr
Definition: canopen.h:187
const SyncCounterSharedPtr sync_
Definition: canopen.h:239
std::shared_ptr< CommInterface > CommInterfaceSharedPtr
boost::chrono::high_resolution_clock::duration time_duration
Definition: canopen.h:19
SyncLayer(const SyncProperties &p)
Definition: canopen.h:307
const can::CommInterfaceSharedPtr interface_
Definition: canopen.h:112
std::shared_ptr< T > MemberSharedPtr
Definition: canopen.h:262
std::shared_ptr< Buffer > BufferSharedPtr
Definition: canopen.h:90
const std::vector< typename Chain< T >::MemberSharedPtr > & getElements()
Definition: canopen.h:297
virtual ~SyncCounter()
Definition: canopen.h:185
ObjectDict::ObjectDictSharedPtr ObjectDictSharedPtr
Definition: objdict.h:235
const ObjectStorageSharedPtr getStorage()
Definition: canopen.h:200
std::vector< BufferSharedPtr > buffers
Definition: canopen.h:97
FrameOverlay(const can::Frame &f)
Definition: canopen.h:29
bool operator==(const SyncProperties &p) const
Definition: canopen.h:175
const canopen::ObjectDict::Entry * current_entry
Definition: canopen.h:46
std::vector< MemberSharedPtr > elements
Definition: canopen.h:292
void call(void(T::*func)(const V &), const std::vector< V > &vs)
Definition: canopen.h:270
boost::mutex cond_mutex
Definition: canopen.h:235
const can::CommInterfaceSharedPtr interface_
Definition: canopen.h:129
can::Header client_id
Definition: canopen.h:34
boost::chrono::high_resolution_clock::time_point heartbeat_timeout_
Definition: canopen.h:253
CommInterface::FrameListenerConstSharedPtr FrameListenerConstSharedPtr
uint8_t transmission_type
Definition: canopen.h:96
value_type * c_array()
unsigned int key() const
uint16_t getHeartbeatInterval()
Definition: canopen.h:254
std::function< void(const State &)> StateFunc
Definition: canopen.h:208
StateListenerConstSharedPtr addStateListener(const StateFunc &s)
Definition: canopen.h:214
SDOClient sdo_
Definition: canopen.h:250
std::vector< char > buffer
Definition: canopen.h:88
SyncProperties(const can::Header &h, const uint16_t &p, const uint8_t &o)
Definition: canopen.h:174
boost::mutex mutex
Definition: canopen.h:113
const ObjectStorageSharedPtr storage_
Definition: canopen.h:154
const can::CommInterfaceSharedPtr interface_
Definition: canopen.h:139
void call(void(T::*func)(void))
Definition: canopen.h:263
can::FrameListenerConstSharedPtr nmt_listener_
Definition: canopen.h:240
Master::MasterSharedPtr MasterSharedPtr
Definition: canopen.h:326
void setHeartbeatInterval()
Definition: canopen.h:255
ObjectStorage::Entry< uint8_t > error_register_
Definition: canopen.h:150
const ObjectDict::Entry & desc() const
Definition: objdict.h:451
PDOMapper pdo_
Definition: canopen.h:251
static TPDOSharedPtr create(const can::CommInterfaceSharedPtr interface, const ObjectStorageSharedPtr &storage, const uint16_t &com_index, const uint16_t &map_index)
Definition: canopen.h:103
boost::mutex mutex_
Definition: canopen.h:72
boost::condition_variable cond
Definition: canopen.h:236
TPDO(const can::CommInterfaceSharedPtr interface)
Definition: canopen.h:110
void set(const T &val)
Definition: objdict.h:420
std::shared_ptr< Node > NodeSharedPtr
Definition: canopen.h:258
std::shared_ptr< SyncLayer > SyncLayerSharedPtr
Definition: canopen.h:309
virtual ~Master()
Definition: canopen.h:317
time_point get_abs_time(const time_duration &timeout)
Definition: canopen.h:20
can::Listener< const StateFunc, const State & > StateListener
Definition: canopen.h:211
const uint16_t period_ms_
Definition: canopen.h:172
void add(MemberSharedPtr t)
Definition: canopen.h:288
ObjectStorage::ObjectStorageSharedPtr ObjectStorageSharedPtr
Definition: objdict.h:537
State state_
Definition: canopen.h:249
void reset_com()
Definition: canopen.h:301
can::SimpleDispatcher< StateListener > state_dispatcher_
Definition: canopen.h:244
const ObjectStorageSharedPtr storage_
Definition: canopen.h:56
boost::timed_mutex mutex
Definition: canopen.h:234
SDOClient(const can::CommInterfaceSharedPtr interface, const ObjectDictSharedPtr dict, uint8_t node_id)
Definition: canopen.h:60


canopen_master
Author(s): Mathias Lüdtke
autogenerated on Mon Feb 28 2022 23:28:03