/* * Copyright (C) 2014 Pavel Kirienko */ #pragma once #include #include #include #include namespace uavcan { class NodeStatusMonitor : protected TimerBase { public: typedef typename StorageType::Type NodeStatusCode; struct NodeStatus { NodeStatusCode status_code; ///< Current status code; OFFLINE if not known. bool known; ///< True if the node was online at least once. NodeStatus() : status_code(protocol::NodeStatus::STATUS_OFFLINE) , known(false) { } }; struct NodeStatusChangeEvent { NodeID node_id; NodeStatus status; NodeStatus old_status; }; private: enum { TimerPeriodMs100 = 5 }; typedef MethodBinder&)> NodeStatusCallback; Subscriber sub_; struct Entry { NodeStatusCode status_code; int8_t time_since_last_update_ms100; Entry() : status_code(protocol::NodeStatus::STATUS_OFFLINE) , time_since_last_update_ms100(-1) { } }; mutable Entry entries_[NodeID::Max]; // [1, NodeID::Max] Entry& getEntry(NodeID node_id) const; void changeNodeStatus(const NodeID node_id, const Entry new_entry_value); void handleNodeStatus(const ReceivedDataStructure& msg); void handleTimerEvent(const TimerEvent&); protected: /** * Called when a node becomes online, changes status or goes offline. */ virtual void handleNodeStatusChange(const NodeStatusChangeEvent& event) { (void)event; } /** * Called for every received message uavcan.protocol.NodeStatus after handleNodeStatusChange(). */ virtual void handleNodeStatusMessage(const ReceivedDataStructure& msg) { (void)msg; } public: explicit NodeStatusMonitor(INode& node) : TimerBase(node) , sub_(node) { } virtual ~NodeStatusMonitor() { } int start(); void forgetNode(NodeID node_id); NodeStatus getNodeStatus(NodeID node_id) const; NodeID findNodeWithWorstStatus() const; }; }