LCOV - code coverage report
Current view: top level - AP_DroneCAN - AP_DroneCAN_DNA_Server.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 4 4 100.0 %
Date: 2026-09-09 11:02:08 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #pragma once
       2             : #include <AP_HAL/AP_HAL_Boards.h>
       3             : #include <AP_HAL/Semaphores.h>
       4             : 
       5             : #if HAL_ENABLE_DRONECAN_DRIVERS
       6             : #include <AP_Common/Bitmask.h>
       7             : #include <StorageManager/StorageManager.h>
       8             : #include <AP_CANManager/AP_CANManager.h>
       9             : #include <canard/publisher.h>
      10             : #include <canard/subscriber.h>
      11             : #include <canard/service_client.h>
      12             : #include "AP_Canard_iface.h"
      13             : #include <dronecan_msgs.h>
      14             : 
      15             : class AP_DroneCAN;
      16             : //Forward declaring classes
      17             : class AP_DroneCAN_DNA_Server
      18             : {
      19             :     StorageAccess storage;
      20             : 
      21             :     struct NodeRecord {
      22             :         uint8_t uid_hash[6];
      23             :         uint8_t crc;
      24             :     };
      25             : 
      26             :     /*
      27             :      * For each node ID (1 through MAX_NODE_ID), the database can have one
      28             :      * registration for it. Each registration consists of a NodeRecord which
      29             :      * contains the (hash of the) unique ID reported by that node ID. Other
      30             :      * info could be added to the registration in the future.
      31             :      *
      32             :      * Physically, the database is stored as a header and format version,
      33             :      * followed by an array of NodeRecords indexed by node ID. If a particular
      34             :      * NodeRecord has an all-zero unique ID hash or an invalid CRC, then that
      35             :      * node ID isn't considerd to have a registration.
      36             :      *
      37             :      * The database has public methods which handle the server behavior for the
      38             :      * relevant message. The methods can be used by multiple servers in
      39             :      * different threads, so each holds a lock for its duration.
      40             :      */
      41             :     class Database {
      42             :     public:
      43        2193 :         Database() {};
      44             : 
      45             :         // initialize database (storage accessor is always replaced with the one supplied)
      46             :         void init(StorageAccess *storage_);
      47             : 
      48             :         // remove all registrations from the database
      49             :         void reset();
      50             : 
      51             :         // return true if the given node ID is registered
      52         109 :         bool is_registered(uint8_t node_id) {
      53         109 :             return node_registered.get(node_id);
      54             :         }
      55             : 
      56             :         // handle initializing the server with its own node ID and unique ID
      57             :         void init_server(uint8_t own_node_id, const uint8_t own_unique_id[], uint8_t own_unique_id_len);
      58             : 
      59             :         // handle processing the node info message. returns true if from a duplicate node
      60             :         bool handle_node_info(uint8_t source_node_id, const uint8_t unique_id[]);
      61             : 
      62             :         // handle the allocation message. returns the allocated node ID, or 0 if allocation failed
      63             :         uint8_t handle_allocation(const uint8_t unique_id[]);
      64             : 
      65             :     private:
      66             :         // retrieve node ID that matches the given unique ID. returns 0 if not found
      67             :         uint8_t find_node_id(const uint8_t unique_id[], uint8_t size);
      68             : 
      69             :         // fill the given record with the hash of the given unique ID
      70             :         void compute_uid_hash(NodeRecord &record, const uint8_t unique_id[], uint8_t size) const;
      71             : 
      72             :         // register a given unique ID to a given node ID, deleting any existing registration for the unique ID
      73             :         void register_uid(uint8_t node_id, const uint8_t unique_id[], uint8_t size);
      74             : 
      75             :         // create the registration for the given node ID and set its record's unique ID
      76             :         void create_registration(uint8_t node_id, const uint8_t unique_id[], uint8_t size);
      77             : 
      78             :         // delete the given node ID's registration
      79             :         void delete_registration(uint8_t node_id);
      80             : 
      81             :         // return true if the given node ID has a registration
      82             :         bool check_registration(uint8_t node_id);
      83             : 
      84             :         // read the given node ID's registration's record
      85             :         void read_record(NodeRecord &record, uint8_t node_id);
      86             : 
      87             :         // write the given node ID's registration's record
      88             :         void write_record(const NodeRecord &record, uint8_t node_id);
      89             : 
      90             :         // bitmasks containing a status for each possible node ID (except 0 and > MAX_NODE_ID)
      91             :         Bitmask<128> node_registered; // have a registration for this node ID
      92             : 
      93             :         StorageAccess *storage;
      94             :         HAL_Semaphore sem;
      95             :     };
      96             : 
      97             :     static Database db;
      98             : 
      99             :     enum ServerState {
     100             :         NODE_STATUS_UNHEALTHY = -5,
     101             :         DUPLICATE_NODES = -2,
     102             :         HEALTHY = 0
     103             :     };
     104             : 
     105             :     uint32_t last_verification_request;
     106             :     uint8_t curr_verifying_node;
     107             :     uint8_t self_node_id;
     108             :     bool nodeInfo_resp_rcvd;
     109             : 
     110             :     // bitmasks containing a status for each possible node ID (except 0 and > MAX_NODE_ID)
     111             :     Bitmask<128> node_verified; // node seen and unique ID matches stored
     112             :     Bitmask<128> node_seen; // received NodeStatus
     113             :     Bitmask<128> node_logged; // written to log fle
     114             :     Bitmask<128> node_healthy; // reports healthy
     115             : 
     116             :     uint8_t last_logging_count;
     117             : 
     118             :     //Error State
     119             :     enum ServerState server_state;
     120             :     uint8_t fault_node_id;
     121             :     char fault_node_name[15];
     122             : 
     123             : 
     124             :     // dynamic node ID allocation state variables
     125             :     uint8_t rcvd_unique_id[16];
     126             :     uint8_t rcvd_unique_id_offset;
     127             :     uint32_t last_alloc_msg_ms;
     128             : 
     129             :     AP_DroneCAN &_ap_dronecan;
     130             :     CanardInterface &_canard_iface;
     131             : 
     132             :     Canard::Publisher<uavcan_protocol_dynamic_node_id_Allocation> allocation_pub{_canard_iface};
     133             : 
     134             :     Canard::ObjCallback<AP_DroneCAN_DNA_Server, uavcan_protocol_dynamic_node_id_Allocation> allocation_cb{this, &AP_DroneCAN_DNA_Server::handle_allocation};
     135             :     Canard::Subscriber<uavcan_protocol_dynamic_node_id_Allocation> allocation_sub;
     136             : 
     137             :     Canard::ObjCallback<AP_DroneCAN_DNA_Server, uavcan_protocol_NodeStatus> node_status_cb{this, &AP_DroneCAN_DNA_Server::handleNodeStatus};
     138             :     Canard::Subscriber<uavcan_protocol_NodeStatus> node_status_sub;
     139             : 
     140             :     Canard::ObjCallback<AP_DroneCAN_DNA_Server, uavcan_protocol_GetNodeInfoResponse> node_info_cb{this, &AP_DroneCAN_DNA_Server::handleNodeInfo};
     141             :     Canard::Client<uavcan_protocol_GetNodeInfoResponse> node_info_client;
     142             : 
     143             : #if HAL_LOGGING_ENABLED
     144             :     // Linked list of node status timestamps used for logging
     145             :     struct node_status_log_data {
     146           2 :         node_status_log_data(const uint8_t _id):id(_id) {};
     147             :         node_status_log_data *next;
     148             :         uint32_t last_uptime_sec;
     149             :         uint32_t last_log_ms;
     150             :         const uint8_t id;
     151             :     };
     152             :     node_status_log_data *node_status_list;
     153             :     node_status_log_data *find_node_status_item(const uint8_t source_node_id);
     154             :     void update_node_status(const uint8_t source_node_id, const uavcan_protocol_NodeStatus& msg);
     155             : #endif // #if HAL_LOGGING_ENABLED
     156             : 
     157             : public:
     158             :     AP_DroneCAN_DNA_Server(AP_DroneCAN &ap_dronecan, CanardInterface &canard_iface, uint8_t driver_index);
     159             : 
     160             : 
     161             :     // Do not allow copies
     162             :     CLASS_NO_COPY(AP_DroneCAN_DNA_Server);
     163             : 
     164             :     //Initialises publisher and Server Record for specified uavcan driver
     165             :     bool init(uint8_t own_unique_id[], uint8_t own_unique_id_len, uint8_t node_id);
     166             : 
     167             :     //report the server state, along with failure message if any
     168             :     bool prearm_check(char* fail_msg, uint8_t fail_msg_len) const;
     169             : 
     170             :     // canard message handler callbacks
     171             :     void handle_allocation(const CanardRxTransfer& transfer, const uavcan_protocol_dynamic_node_id_Allocation& msg);
     172             :     void handleNodeStatus(const CanardRxTransfer& transfer, const uavcan_protocol_NodeStatus& msg);
     173             :     void handleNodeInfo(const CanardRxTransfer& transfer, const uavcan_protocol_GetNodeInfoResponse& rsp);
     174             : 
     175             :     //Run through the list of seen node ids for verification
     176             :     void verify_nodes();
     177             : };
     178             : 
     179             : #endif

Generated by: LCOV version 1.14