LCOV - code coverage report
Current view: top level - AP_OpenDroneID - AP_OpenDroneID_DroneCAN.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 143 0.0 %
Date: 2026-09-09 11:02:08 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /*
       2             :  * This file is free software: you can redistribute it and/or modify it
       3             :  * under the terms of the GNU General Public License as published by the
       4             :  * Free Software Foundation, either version 3 of the License, or
       5             :  * (at your option) any later version.
       6             :  *
       7             :  * This file is distributed in the hope that it will be useful, but
       8             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      10             :  * See the GNU General Public License for more details.
      11             :  *
      12             :  * You should have received a copy of the GNU General Public License along
      13             :  * with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : /*
      16             :   DroneCAN support for OpenDroneID
      17             :  */
      18             : 
      19             : #include "AP_OpenDroneID.h"
      20             : 
      21             : #if AP_OPENDRONEID_ENABLED
      22             : 
      23             : #include <AP_DroneCAN/AP_DroneCAN.h>
      24             : 
      25             : #if HAL_ENABLE_DRONECAN_DRIVERS
      26             : #include <GCS_MAVLink/GCS.h>
      27             : 
      28             : static Canard::Publisher<dronecan_remoteid_Location>* dc_location[HAL_MAX_CAN_PROTOCOL_DRIVERS];
      29             : static Canard::Publisher<dronecan_remoteid_BasicID>* dc_basic_id[HAL_MAX_CAN_PROTOCOL_DRIVERS];
      30             : static Canard::Publisher<dronecan_remoteid_SelfID>* dc_self_id[HAL_MAX_CAN_PROTOCOL_DRIVERS];
      31             : static Canard::Publisher<dronecan_remoteid_System>* dc_system[HAL_MAX_CAN_PROTOCOL_DRIVERS];
      32             : static Canard::Publisher<dronecan_remoteid_OperatorID>* dc_operator_id[HAL_MAX_CAN_PROTOCOL_DRIVERS];
      33             : 
      34             : static void handle_arm_status(AP_DroneCAN* ap_dronecan, const CanardRxTransfer &transfer, const dronecan_remoteid_ArmStatus &msg);
      35             : 
      36           0 : void AP_OpenDroneID::dronecan_init(AP_DroneCAN *uavcan)
      37             : {
      38           0 :     const uint8_t driver_index = uavcan->get_driver_index();
      39           0 :     driver_mask = 1U<<driver_index;
      40           0 :     if (dronecan_done_init & driver_mask) {
      41             :         // already initialised
      42           0 :         return;
      43             :     }
      44             : 
      45           0 :     dc_location[driver_index] = NEW_NOTHROW Canard::Publisher<dronecan_remoteid_Location>(uavcan->get_canard_iface());
      46           0 :     if (dc_location[driver_index] == nullptr) {
      47           0 :         goto alloc_failed;
      48             :     }
      49           0 :     dc_location[driver_index]->set_timeout_ms(20);
      50           0 :     dc_location[driver_index]->set_priority(CANARD_TRANSFER_PRIORITY_LOW);
      51             : 
      52           0 :     dc_basic_id[driver_index] = NEW_NOTHROW Canard::Publisher<dronecan_remoteid_BasicID>(uavcan->get_canard_iface());
      53           0 :     if (dc_basic_id[driver_index] == nullptr) {
      54           0 :         goto alloc_failed;
      55             :     }
      56           0 :     dc_basic_id[driver_index]->set_timeout_ms(20);
      57           0 :     dc_basic_id[driver_index]->set_priority(CANARD_TRANSFER_PRIORITY_LOW);
      58             : 
      59           0 :     dc_self_id[driver_index] = NEW_NOTHROW Canard::Publisher<dronecan_remoteid_SelfID>(uavcan->get_canard_iface());
      60           0 :     if (dc_self_id[driver_index] == nullptr) {
      61           0 :         goto alloc_failed;
      62             :     }
      63           0 :     dc_self_id[driver_index]->set_timeout_ms(20);
      64           0 :     dc_self_id[driver_index]->set_priority(CANARD_TRANSFER_PRIORITY_LOW);
      65             : 
      66           0 :     dc_system[driver_index] = NEW_NOTHROW Canard::Publisher<dronecan_remoteid_System>(uavcan->get_canard_iface());
      67           0 :     if (dc_system[driver_index] == nullptr) {
      68           0 :         goto alloc_failed;
      69             :     }
      70           0 :     dc_system[driver_index]->set_timeout_ms(20);
      71           0 :     dc_system[driver_index]->set_priority(CANARD_TRANSFER_PRIORITY_LOW);
      72             : 
      73           0 :     dc_operator_id[driver_index] = NEW_NOTHROW Canard::Publisher<dronecan_remoteid_OperatorID>(uavcan->get_canard_iface());
      74           0 :     if (dc_operator_id[driver_index] == nullptr) {
      75           0 :         goto alloc_failed;
      76             :     }
      77           0 :     dc_operator_id[driver_index]->set_timeout_ms(20);
      78           0 :     dc_operator_id[driver_index]->set_priority(CANARD_TRANSFER_PRIORITY_LOW);
      79             : 
      80           0 :     if (Canard::allocate_sub_arg_callback(uavcan, &handle_arm_status, driver_index) == nullptr)
      81             :     {
      82           0 :         goto alloc_failed;
      83             :     }
      84             : 
      85           0 :     dronecan_done_init |= driver_mask;
      86           0 :     return;
      87             : 
      88           0 : alloc_failed:
      89           0 :     dronecan_init_failed |= driver_mask;
      90           0 :     GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "OpenDroneID DroneCAN alloc failed");
      91             : }
      92             : 
      93             : /*
      94             :   send pending DroneCAN OpenDroneID packets
      95             :  */
      96           0 : void AP_OpenDroneID::dronecan_send(AP_DroneCAN *uavcan)
      97             : {
      98           0 :     dronecan_init(uavcan);
      99             : 
     100           0 :     if (dronecan_init_failed & driver_mask) {
     101           0 :         return;
     102             :     }
     103             : 
     104           0 :     if (need_send_basic_id & driver_mask) {
     105           0 :         WITH_SEMAPHORE(_sem);
     106           0 :         dronecan_send_basic_id(uavcan);
     107           0 :         need_send_basic_id &= ~driver_mask;
     108           0 :     }
     109           0 :     if (need_send_system & driver_mask) {
     110           0 :         WITH_SEMAPHORE(_sem);
     111           0 :         dronecan_send_system(uavcan);
     112           0 :         need_send_system &= ~driver_mask;
     113           0 :     }
     114           0 :     if (need_send_self_id & driver_mask) {
     115           0 :         WITH_SEMAPHORE(_sem);
     116           0 :         dronecan_send_self_id(uavcan);
     117           0 :         need_send_self_id &= ~driver_mask;
     118           0 :     }
     119           0 :     if (need_send_operator_id & driver_mask) {
     120           0 :         WITH_SEMAPHORE(_sem);
     121           0 :         dronecan_send_operator_id(uavcan);
     122           0 :         need_send_operator_id &= ~driver_mask;
     123           0 :     }
     124           0 :     if (need_send_location & driver_mask) {
     125           0 :         WITH_SEMAPHORE(_sem);
     126           0 :         dronecan_send_location(uavcan);
     127           0 :         need_send_location &= ~driver_mask;
     128           0 :     }
     129             : }
     130             : 
     131             : #define ODID_COPY(name) msg.name = pkt.name
     132             : #define ODID_COPY_STR(name) do { msg.name.len = strncpy_noterm((char*)msg.name.data, (const char*)pkt.name, sizeof(msg.name.data)); } while(0)
     133             : 
     134             : 
     135           0 : void AP_OpenDroneID::dronecan_send_location(AP_DroneCAN *uavcan)
     136             : {
     137           0 :     dronecan_remoteid_Location msg {};
     138           0 :     const auto &pkt = pkt_location;
     139           0 :     ODID_COPY_STR(id_or_mac);
     140           0 :     ODID_COPY(status);
     141           0 :     ODID_COPY(direction);
     142           0 :     ODID_COPY(speed_horizontal);
     143           0 :     ODID_COPY(speed_vertical);
     144           0 :     ODID_COPY(latitude);
     145           0 :     ODID_COPY(longitude);
     146           0 :     ODID_COPY(altitude_barometric);
     147           0 :     ODID_COPY(altitude_geodetic);
     148           0 :     ODID_COPY(height_reference);
     149           0 :     ODID_COPY(height);
     150           0 :     ODID_COPY(horizontal_accuracy);
     151           0 :     ODID_COPY(vertical_accuracy);
     152           0 :     ODID_COPY(barometer_accuracy);
     153           0 :     ODID_COPY(speed_accuracy);
     154           0 :     ODID_COPY(timestamp);
     155           0 :     ODID_COPY(timestamp_accuracy);
     156           0 :     dc_location[uavcan->get_driver_index()]->broadcast(msg);
     157           0 : }
     158             : 
     159           0 : void AP_OpenDroneID::dronecan_send_basic_id(AP_DroneCAN *uavcan)
     160             : {
     161           0 :     dronecan_remoteid_BasicID msg {};
     162           0 :     const auto &pkt = pkt_basic_id;
     163           0 :     ODID_COPY_STR(id_or_mac);
     164           0 :     ODID_COPY(id_type);
     165           0 :     ODID_COPY(ua_type);
     166           0 :     ODID_COPY_STR(uas_id);
     167           0 :     dc_basic_id[uavcan->get_driver_index()]->broadcast(msg);
     168           0 : }
     169             : 
     170           0 : void AP_OpenDroneID::dronecan_send_system(AP_DroneCAN *uavcan)
     171             : {
     172           0 :     dronecan_remoteid_System msg {};
     173           0 :     const auto &pkt = pkt_system;
     174           0 :     ODID_COPY_STR(id_or_mac);
     175           0 :     ODID_COPY(operator_location_type);
     176           0 :     ODID_COPY(classification_type);
     177           0 :     ODID_COPY(operator_latitude);
     178           0 :     ODID_COPY(operator_longitude);
     179           0 :     ODID_COPY(area_count);
     180           0 :     ODID_COPY(area_radius);
     181           0 :     ODID_COPY(area_ceiling);
     182           0 :     ODID_COPY(area_floor);
     183           0 :     ODID_COPY(category_eu);
     184           0 :     ODID_COPY(class_eu);
     185           0 :     ODID_COPY(operator_altitude_geo);
     186           0 :     ODID_COPY(timestamp);
     187           0 :     dc_system[uavcan->get_driver_index()]->broadcast(msg);
     188           0 : }
     189             : 
     190           0 : void AP_OpenDroneID::dronecan_send_self_id(AP_DroneCAN *uavcan)
     191             : {
     192           0 :     dronecan_remoteid_SelfID msg {};
     193           0 :     const auto &pkt = pkt_self_id;
     194           0 :     ODID_COPY_STR(id_or_mac);
     195           0 :     ODID_COPY(description_type);
     196           0 :     ODID_COPY_STR(description);
     197           0 :     dc_self_id[uavcan->get_driver_index()]->broadcast(msg);
     198           0 : }
     199             : 
     200           0 : void AP_OpenDroneID::dronecan_send_operator_id(AP_DroneCAN *uavcan)
     201             : {
     202           0 :     dronecan_remoteid_OperatorID msg {};
     203           0 :     const auto &pkt = pkt_operator_id;
     204           0 :     ODID_COPY_STR(id_or_mac);
     205           0 :     ODID_COPY(operator_id_type);
     206           0 :     ODID_COPY_STR(operator_id);
     207           0 :     dc_operator_id[uavcan->get_driver_index()]->broadcast(msg);
     208           0 : }
     209             : 
     210             : /*
     211             :   handle ArmStatus message from DroneCAN
     212             :  */
     213           0 : static void handle_arm_status(AP_DroneCAN *ap_dronecan, const CanardRxTransfer& transfer, const dronecan_remoteid_ArmStatus &msg)
     214             : {
     215           0 :     mavlink_open_drone_id_arm_status_t status {};
     216             : 
     217           0 :     status.status = msg.status;
     218           0 :     strncpy_noterm((char*)status.error, (const char*)msg.error.data, sizeof(status.error));
     219             : 
     220           0 :     AP::opendroneid().set_arm_status(status);
     221             : 
     222             :     // Push DroneCAN Arm Message to GCS
     223           0 :     gcs().send_to_active_channels(MAVLINK_MSG_ID_OPEN_DRONE_ID_ARM_STATUS,(const char*)&status);
     224           0 : }
     225             : 
     226             : // copy arm status for DroneCAN
     227           0 : void AP_OpenDroneID::set_arm_status(mavlink_open_drone_id_arm_status_t &status)
     228             : {
     229           0 :     WITH_SEMAPHORE(_sem);
     230           0 :     arm_status = status;
     231           0 :     last_arm_status_ms = AP_HAL::millis();
     232           0 : }
     233             : 
     234             : #endif // HAL_ENABLE_DRONECAN_DRIVERS
     235             : #endif // AP_OPENDRONEID_ENABLED

Generated by: LCOV version 1.14