node_status_monitor.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #ifndef UAVCAN_PROTOCOL_NODE_STATUS_MONITOR_HPP_INCLUDED
6 #define UAVCAN_PROTOCOL_NODE_STATUS_MONITOR_HPP_INCLUDED
7 
8 #include <uavcan/debug.hpp>
11 #include <uavcan/node/timer.hpp>
12 #include <uavcan/protocol/NodeStatus.hpp>
13 #include <cassert>
14 #include <cstdlib>
15 
16 namespace uavcan
17 {
23 {
24 public:
25  struct NodeStatus
26  {
30 
32  health(protocol::NodeStatus::HEALTH_CRITICAL),
33  mode(protocol::NodeStatus::MODE_OFFLINE),
34  sub_mode(0)
35  {
36  StaticAssert<protocol::NodeStatus::FieldTypes::health::BitLen == 2>::check();
37  StaticAssert<protocol::NodeStatus::FieldTypes::mode::BitLen == 3>::check();
38  StaticAssert<protocol::NodeStatus::FieldTypes::sub_mode::BitLen == 3>::check();
39  }
40 
41  bool operator!=(const NodeStatus rhs) const { return !operator==(rhs); }
42  bool operator==(const NodeStatus rhs) const
43  {
44  return ( this->health == rhs.health
45  && this->mode == rhs.mode
46  && this->sub_mode == rhs.sub_mode
47  );
48  }
49 
50 #if UAVCAN_TOSTRING
51  std::string toString() const
52  {
53  char buf[40];
54  (void)snprintf(buf, sizeof(buf), "health=%d mode=%d sub_mode=%d", int(health), int(mode), int(sub_mode));
55  return std::string(buf);
56  }
57 #endif
58  };
59 
61  {
65  bool was_known;
66 
68  was_known(false)
69  { }
70  };
71 
72 private:
73  enum { TimerPeriodMs100 = 2 };
74 
78 
80 
82 
84 
85  struct Entry
86  {
89  Entry() :
90  time_since_last_update_ms100(-1)
91  { }
92  };
93 
94  mutable Entry entries_[NodeID::Max]; // [1, NodeID::Max]
95 
96  Entry& getEntry(NodeID node_id) const
97  {
98  if (node_id.get() < 1 || node_id.get() > NodeID::Max)
99  {
100  handleFatalError("NodeStatusMonitor NodeID");
101  }
102  return entries_[node_id.get() - 1];
103  }
104 
105  void changeNodeStatus(const NodeID node_id, const Entry new_entry_value)
106  {
107  Entry& entry = getEntry(node_id);
108  if (entry.status != new_entry_value.status)
109  {
110  NodeStatusChangeEvent event;
111  event.node_id = node_id;
112  event.old_status = entry.status;
113  event.status = new_entry_value.status;
114  event.was_known = entry.time_since_last_update_ms100 >= 0;
115 
116  UAVCAN_TRACE("NodeStatusMonitor", "Node %i [%s] status change: [%s] --> [%s]", int(node_id.get()),
117  (event.was_known ? "known" : "new"),
118  event.old_status.toString().c_str(), event.status.toString().c_str());
119 
120  handleNodeStatusChange(event);
121  }
122  entry = new_entry_value;
123  }
124 
126  {
127  Entry new_entry;
128  new_entry.time_since_last_update_ms100 = 0;
129  new_entry.status.health = msg.health & ((1 << protocol::NodeStatus::FieldTypes::health::BitLen) - 1);
130  new_entry.status.mode = msg.mode & ((1 << protocol::NodeStatus::FieldTypes::mode::BitLen) - 1);
131  new_entry.status.sub_mode = msg.sub_mode & ((1 << protocol::NodeStatus::FieldTypes::sub_mode::BitLen) - 1);
132 
133  changeNodeStatus(msg.getSrcNodeID(), new_entry);
134 
135  handleNodeStatusMessage(msg);
136  }
137 
139  {
140  const int OfflineTimeoutMs100 = protocol::NodeStatus::OFFLINE_TIMEOUT_MS / 100;
141 
142  for (uint8_t i = 1; i <= NodeID::Max; i++)
143  {
144  Entry& entry = getEntry(i);
145  if (entry.time_since_last_update_ms100 >= 0 &&
146  entry.status.mode != protocol::NodeStatus::MODE_OFFLINE)
147  {
149  int8_t(entry.time_since_last_update_ms100 + int8_t(TimerPeriodMs100));
150 
151  if (entry.time_since_last_update_ms100 > OfflineTimeoutMs100)
152  {
153  Entry new_entry_value = entry;
154  new_entry_value.time_since_last_update_ms100 = OfflineTimeoutMs100;
155  new_entry_value.status.mode = protocol::NodeStatus::MODE_OFFLINE;
156  changeNodeStatus(i, new_entry_value);
157  }
158  }
159  }
160  }
161 
162 protected:
169  {
170  (void)event;
171  }
172 
179  {
180  (void)msg;
181  }
182 
183 public:
185  : sub_(node)
186  , timer_(node)
187  { }
188 
189  virtual ~NodeStatusMonitor() { }
190 
196  int start()
197  {
198  const int res = sub_.start(NodeStatusCallback(this, &NodeStatusMonitor::handleNodeStatus));
199  if (res >= 0)
200  {
202  timer_.startPeriodic(MonotonicDuration::fromMSec(TimerPeriodMs100 * 100));
203  }
204  return res;
205  }
206 
210  void forgetNode(NodeID node_id)
211  {
212  if (node_id.isValid())
213  {
214  Entry& entry = getEntry(node_id);
215  entry = Entry();
216  }
217  else
218  {
219  UAVCAN_ASSERT(0);
220  }
221  }
222 
227  {
228  for (unsigned i = 0; i < (sizeof(entries_) / sizeof(entries_[0])); i++)
229  {
230  entries_[i] = Entry();
231  }
232  }
233 
240  {
241  if (!node_id.isValid())
242  {
243  UAVCAN_ASSERT(0);
244  return NodeStatus();
245  }
246 
247  const Entry& entry = getEntry(node_id);
248  if (entry.time_since_last_update_ms100 >= 0)
249  {
250  return entry.status;
251  }
252  else
253  {
254  return NodeStatus();
255  }
256  }
257 
262  bool isNodeKnown(NodeID node_id) const
263  {
264  if (!node_id.isValid())
265  {
266  UAVCAN_ASSERT(0);
267  return false;
268  }
269  return getEntry(node_id).time_since_last_update_ms100 >= 0;
270  }
271 
278  {
279  NodeID nid_with_worst_health;
280  uint8_t worst_health = protocol::NodeStatus::HEALTH_OK;
281 
282  for (uint8_t i = 1; i <= NodeID::Max; i++)
283  {
284  const NodeID nid(i);
285  UAVCAN_ASSERT(nid.isUnicast());
286  const Entry& entry = getEntry(nid);
287  if (entry.time_since_last_update_ms100 >= 0)
288  {
289  if (entry.status.health > worst_health || !nid_with_worst_health.isValid())
290  {
291  nid_with_worst_health = nid;
292  worst_health = entry.status.health;
293  }
294  }
295  }
296 
297  return nid_with_worst_health;
298  }
299 
305  template <typename Operator>
306  void forEachNode(Operator op) const
307  {
308  for (uint8_t i = 1; i <= NodeID::Max; i++)
309  {
310  const NodeID nid(i);
311  UAVCAN_ASSERT(nid.isUnicast());
312  const Entry& entry = getEntry(nid);
313  if (entry.time_since_last_update_ms100 >= 0)
314  {
315  op(nid, entry.status);
316  }
317  }
318  }
319 };
320 
321 }
322 
323 #endif // UAVCAN_PROTOCOL_NODE_STATUS_MONITOR_HPP_INCLUDED
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::node_id
NodeID node_id
Definition: node_status_monitor.hpp:62
subscriber.hpp
uavcan::NodeID::isValid
bool isValid() const
Definition: transfer.hpp:134
uavcan::operator==
UAVCAN_EXPORT EnableIf<!IsSameType< R, Array< T, ArrayMode, MaxSize > >::Result, bool >::Type operator==(const R &rhs, const Array< T, ArrayMode, MaxSize > &lhs)
Definition: array.hpp:1101
uavcan::NodeStatusMonitor::NodeStatus
Definition: node_status_monitor.hpp:25
debug.hpp
uavcan::Subscriber
Definition: subscriber.hpp:45
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::was_known
bool was_known
Definition: node_status_monitor.hpp:65
uavcan::NodeStatusMonitor::~NodeStatusMonitor
virtual ~NodeStatusMonitor()
Definition: node_status_monitor.hpp:189
uavcan::NodeStatusMonitor::sub_
Subscriber< protocol::NodeStatus, NodeStatusCallback > sub_
Definition: node_status_monitor.hpp:81
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::NodeStatusMonitor::NodeStatus::operator==
bool operator==(const NodeStatus rhs) const
Definition: node_status_monitor.hpp:42
uavcan::NodeID
Definition: transfer.hpp:112
uavcan::NodeStatusMonitor::getEntry
Entry & getEntry(NodeID node_id) const
Definition: node_status_monitor.hpp:96
uavcan::DurationBase< MonotonicDuration >::fromMSec
static MonotonicDuration fromMSec(int64_t ms)
Definition: time.hpp:41
uavcan::NodeStatusMonitor::timer_
TimerEventForwarder< TimerCallback > timer_
Definition: node_status_monitor.hpp:83
uavcan::NodeStatusMonitor::handleNodeStatus
void handleNodeStatus(const ReceivedDataStructure< protocol::NodeStatus > &msg)
Definition: node_status_monitor.hpp:125
uavcan::NodeStatusMonitor::handleNodeStatusChange
virtual void handleNodeStatusChange(const NodeStatusChangeEvent &event)
Definition: node_status_monitor.hpp:168
uavcan::ReceivedDataStructure
Definition: generic_subscriber.hpp:39
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::Subscriber::start
int start(const Callback &callback)
Definition: subscriber.hpp:83
uavcan::NodeStatusMonitor
Definition: node_status_monitor.hpp:22
timer.hpp
uavcan::NodeStatusMonitor::NodeStatus::mode
uint8_t mode
Definition: node_status_monitor.hpp:28
uavcan::TimerBase::startPeriodic
void startPeriodic(MonotonicDuration period)
Definition: uc_timer.cpp:42
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::status
NodeStatus status
Definition: node_status_monitor.hpp:63
uavcan::NodeStatusMonitor::changeNodeStatus
void changeNodeStatus(const NodeID node_id, const Entry new_entry_value)
Definition: node_status_monitor.hpp:105
uavcan::TimerEventForwarder::setCallback
void setCallback(const Callback &callback)
Definition: timer.hpp:132
uavcan::NodeStatusMonitor::forEachNode
void forEachNode(Operator op) const
Definition: node_status_monitor.hpp:306
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan::snprintf
int snprintf(char *out, std::size_t maxlen, const char *format,...)
Definition: std.hpp:73
uavcan::NodeStatusMonitor::NodeStatus::operator!=
bool operator!=(const NodeStatus rhs) const
Definition: node_status_monitor.hpp:41
uavcan::NodeStatusMonitor::Entry::status
NodeStatus status
Definition: node_status_monitor.hpp:87
uavcan::NodeStatusMonitor::Entry::Entry
Entry()
Definition: node_status_monitor.hpp:89
uavcan::NodeID::isUnicast
bool isUnicast() const
Definition: transfer.hpp:136
uavcan::NodeStatusMonitor::NodeStatus::NodeStatus
NodeStatus()
Definition: node_status_monitor.hpp:31
toString
static std::string toString(long x)
Definition: multiset.cpp:16
UAVCAN_EXPORT
#define UAVCAN_EXPORT
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:108
uavcan::NodeStatusMonitor::isNodeKnown
bool isNodeKnown(NodeID node_id) const
Definition: node_status_monitor.hpp:262
uavcan::NodeStatusMonitor::Entry::time_since_last_update_ms100
int8_t time_since_last_update_ms100
Definition: node_status_monitor.hpp:88
method_binder.hpp
uavcan::INode
Definition: abstract_node.hpp:19
uavcan::NodeStatusMonitor::findNodeWithWorstHealth
NodeID findNodeWithWorstHealth() const
Definition: node_status_monitor.hpp:277
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::old_status
NodeStatus old_status
Definition: node_status_monitor.hpp:64
uavcan::NodeStatusMonitor::forgetNode
void forgetNode(NodeID node_id)
Definition: node_status_monitor.hpp:210
int
int
Definition: libstubs.cpp:120
uavcan::int8_t
std::int8_t int8_t
Definition: std.hpp:29
uavcan::NodeStatusMonitor::getNodeStatus
NodeStatus getNodeStatus(NodeID node_id) const
Definition: node_status_monitor.hpp:239
uavcan::MethodBinder
Definition: method_binder.hpp:20
uavcan::NodeStatusMonitor::Entry
Definition: node_status_monitor.hpp:85
uavcan::handleFatalError
UAVCAN_EXPORT void handleFatalError(const char *msg)
Definition: uc_error.cpp:20
uavcan::NodeStatusMonitor::NodeStatusMonitor
NodeStatusMonitor(INode &node)
Definition: node_status_monitor.hpp:184
uavcan::NodeStatusMonitor::NodeStatusChangeEvent::NodeStatusChangeEvent
NodeStatusChangeEvent()
Definition: node_status_monitor.hpp:67
uavcan::NodeStatusMonitor::forgetAllNodes
void forgetAllNodes()
Definition: node_status_monitor.hpp:226
uavcan::NodeID::Max
static const uint8_t Max
Definition: transfer.hpp:120
pyuavcan_v0.introspect.node
node
Definition: introspect.py:398
uavcan::NodeStatusMonitor::NodeStatus::sub_mode
uint8_t sub_mode
Definition: node_status_monitor.hpp:29
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::ReceivedDataStructure::getSrcNodeID
NodeID getSrcNodeID() const
Definition: generic_subscriber.hpp:75
uavcan::NodeStatusMonitor::handleNodeStatusMessage
virtual void handleNodeStatusMessage(const ReceivedDataStructure< protocol::NodeStatus > &msg)
Definition: node_status_monitor.hpp:178
uavcan::TimerEventForwarder
Definition: timer.hpp:96
uavcan::NodeStatusMonitor::NodeStatus::health
uint8_t health
Definition: node_status_monitor.hpp:27
uavcan::NodeStatusMonitor::NodeStatusChangeEvent
Definition: node_status_monitor.hpp:60
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::TimerEvent
Definition: timer.hpp:32
uavcan::NodeStatusMonitor::start
int start()
Definition: node_status_monitor.hpp:196
uavcan::NodeStatusMonitor::handleTimerEvent
void handleTimerEvent(const TimerEvent &)
Definition: node_status_monitor.hpp:138


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02