DroneCAN.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /*
  2. DroneCAN class for handling OpenDroneID messages
  3. with thanks to David Buzz for ArduPilot ESP32 HAL
  4. */
  5. #include <Arduino.h>
  6. #include "board_config.h"
  7. #include "version.h"
  8. #include <time.h>
  9. #include "DroneCAN.h"
  10. #include "parameters.h"
  11. #include <stdarg.h>
  12. #include "util.h"
  13. #include "monocypher.h"
  14. #include <canard.h>
  15. #include <uavcan.protocol.NodeStatus.h>
  16. #include <uavcan.protocol.GetNodeInfo.h>
  17. #include <uavcan.protocol.RestartNode.h>
  18. #include <uavcan.protocol.dynamic_node_id.Allocation.h>
  19. #include <uavcan.protocol.param.GetSet.h>
  20. #include <uavcan.protocol.debug.LogMessage.h>
  21. #include <dronecan.remoteid.BasicID.h>
  22. #include <dronecan.remoteid.Location.h>
  23. #include <dronecan.remoteid.SelfID.h>
  24. #include <dronecan.remoteid.System.h>
  25. #include <dronecan.remoteid.OperatorID.h>
  26. #include <dronecan.remoteid.ArmStatus.h>
  27. #ifndef CAN_BOARD_ID
  28. #define CAN_BOARD_ID 10001
  29. #endif
  30. #ifndef CAN_APP_NODE_NAME
  31. #define CAN_APP_NODE_NAME "ArduPilot RemoteIDModule"
  32. #endif
  33. #define UNUSED(x) (void)(x)
  34. static void onTransferReceived_trampoline(CanardInstance* ins, CanardRxTransfer* transfer);
  35. static bool shouldAcceptTransfer_trampoline(const CanardInstance* ins, uint64_t* out_data_type_signature, uint16_t data_type_id,
  36. CanardTransferType transfer_type,
  37. uint8_t source_node_id);
  38. // decoded messages
  39. void DroneCAN::init(void)
  40. {
  41. #if defined(BOARD_BLUEMARK_DB210)
  42. gpio_reset_pin(GPIO_NUM_19);
  43. gpio_reset_pin(GPIO_NUM_20);
  44. #endif
  45. /*
  46. the ESP32 has a very inefficient CAN (TWAI) stack. If we let it
  47. receive all message types then when the bus is busy it will
  48. spend all its time in processRx(). To cope we need to use
  49. acceptance filters so we don't see most traffic. Unfortunately
  50. the ESP32 has a very rudimentary acceptance filter system which
  51. cannot be setup to block the high rate messages (such as ESC
  52. commands) while still allowing all of the RemoteID messages we
  53. need. The best we can do is use the message priority. The high
  54. rate messages all have a low valued priority number (which means
  55. a high priority). So by setting a single bit acceptance code in
  56. the top bit of the 3 bit priority field we only see messages
  57. that have a priority number of 16 or higher (which means
  58. CANARD_TRANSFER_PRIORITY_MEDIUM or lower priority)
  59. */
  60. const uint32_t acceptance_code = 0x10000000U<<3;
  61. const uint32_t acceptance_mask = 0x0FFFFFFFU<<3;
  62. can_driver.init(1000000, acceptance_code, acceptance_mask);
  63. canardInit(&canard, (uint8_t *)canard_memory_pool, sizeof(canard_memory_pool),
  64. onTransferReceived_trampoline, shouldAcceptTransfer_trampoline, NULL);
  65. if (g.can_node > 0 && g.can_node < 128) {
  66. canardSetLocalNodeID(&canard, g.can_node);
  67. }
  68. canard.user_reference = (void*)this;
  69. }
  70. void DroneCAN::update(void)
  71. {
  72. if (do_DNA()) {
  73. const uint32_t now_ms = millis();
  74. if (now_ms - last_node_status_ms >= 1000) {
  75. last_node_status_ms = now_ms;
  76. node_status_send();
  77. arm_status_send();
  78. }
  79. }
  80. processTx();
  81. processRx();
  82. }
  83. void DroneCAN::node_status_send(void)
  84. {
  85. uint8_t buffer[UAVCAN_PROTOCOL_NODESTATUS_MAX_SIZE];
  86. node_status.uptime_sec = millis() / 1000U;
  87. node_status.vendor_specific_status_code = 0;
  88. const uint16_t len = uavcan_protocol_NodeStatus_encode(&node_status, buffer);
  89. static uint8_t tx_id;
  90. canardBroadcast(&canard,
  91. UAVCAN_PROTOCOL_NODESTATUS_SIGNATURE,
  92. UAVCAN_PROTOCOL_NODESTATUS_ID,
  93. &tx_id,
  94. CANARD_TRANSFER_PRIORITY_LOW,
  95. (void*)buffer,
  96. len);
  97. }
  98. void DroneCAN::arm_status_send(void)
  99. {
  100. uint8_t buffer[DRONECAN_REMOTEID_ARMSTATUS_MAX_SIZE];
  101. dronecan_remoteid_ArmStatus arm_status {};
  102. const uint8_t status = parse_fail==nullptr? MAV_ODID_ARM_STATUS_GOOD_TO_ARM:MAV_ODID_ARM_STATUS_PRE_ARM_FAIL_GENERIC;
  103. const char *reason = parse_fail==nullptr?"":parse_fail;
  104. arm_status.status = status;
  105. arm_status.error.len = strlen(reason);
  106. strncpy((char*)arm_status.error.data, reason, sizeof(arm_status.error.data));
  107. const uint16_t len = dronecan_remoteid_ArmStatus_encode(&arm_status, buffer);
  108. static uint8_t tx_id;
  109. canardBroadcast(&canard,
  110. DRONECAN_REMOTEID_ARMSTATUS_SIGNATURE,
  111. DRONECAN_REMOTEID_ARMSTATUS_ID,
  112. &tx_id,
  113. CANARD_TRANSFER_PRIORITY_LOW,
  114. (void*)buffer,
  115. len);
  116. }
  117. void DroneCAN::onTransferReceived(CanardInstance* ins,
  118. CanardRxTransfer* transfer)
  119. {
  120. if (canardGetLocalNodeID(ins) == CANARD_BROADCAST_NODE_ID) {
  121. if (transfer->transfer_type == CanardTransferTypeBroadcast &&
  122. transfer->data_type_id == UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_ID) {
  123. handle_allocation_response(ins, transfer);
  124. }
  125. return;
  126. }
  127. const uint32_t now_ms = millis();
  128. switch (transfer->data_type_id) {
  129. case UAVCAN_PROTOCOL_GETNODEINFO_ID:
  130. handle_get_node_info(ins, transfer);
  131. break;
  132. case UAVCAN_PROTOCOL_RESTARTNODE_ID:
  133. Serial.printf("DroneCAN: restartNode\n");
  134. delay(20);
  135. esp_restart();
  136. break;
  137. case DRONECAN_REMOTEID_BASICID_ID:
  138. Serial.printf("DroneCAN: got BasicID\n");
  139. handle_BasicID(transfer);
  140. break;
  141. case DRONECAN_REMOTEID_LOCATION_ID:
  142. Serial.printf("DroneCAN: got Location\n");
  143. handle_Location(transfer);
  144. break;
  145. case DRONECAN_REMOTEID_SELFID_ID:
  146. Serial.printf("DroneCAN: got SelfID\n");
  147. handle_SelfID(transfer);
  148. break;
  149. case DRONECAN_REMOTEID_SYSTEM_ID:
  150. Serial.printf("DroneCAN: got System\n");
  151. handle_System(transfer);
  152. break;
  153. case DRONECAN_REMOTEID_OPERATORID_ID:
  154. Serial.printf("DroneCAN: got OperatorID\n");
  155. handle_OperatorID(transfer);
  156. break;
  157. case UAVCAN_PROTOCOL_PARAM_GETSET_ID:
  158. handle_param_getset(ins, transfer);
  159. break;
  160. case DRONECAN_REMOTEID_SECURECOMMAND_ID:
  161. handle_SecureCommand(ins, transfer);
  162. break;
  163. default:
  164. //Serial.printf("reject %u\n", transfer->data_type_id);
  165. break;
  166. }
  167. }
  168. bool DroneCAN::shouldAcceptTransfer(const CanardInstance* ins,
  169. uint64_t* out_data_type_signature,
  170. uint16_t data_type_id,
  171. CanardTransferType transfer_type,
  172. uint8_t source_node_id)
  173. {
  174. if (canardGetLocalNodeID(ins) == CANARD_BROADCAST_NODE_ID &&
  175. data_type_id == UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_ID) {
  176. *out_data_type_signature = UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_SIGNATURE;
  177. return true;
  178. }
  179. #define ACCEPT_ID(name) case name ## _ID: *out_data_type_signature = name ## _SIGNATURE; return true
  180. switch (data_type_id) {
  181. ACCEPT_ID(UAVCAN_PROTOCOL_GETNODEINFO);
  182. ACCEPT_ID(UAVCAN_PROTOCOL_RESTARTNODE);
  183. ACCEPT_ID(DRONECAN_REMOTEID_BASICID);
  184. ACCEPT_ID(DRONECAN_REMOTEID_LOCATION);
  185. ACCEPT_ID(DRONECAN_REMOTEID_SELFID);
  186. ACCEPT_ID(DRONECAN_REMOTEID_OPERATORID);
  187. ACCEPT_ID(DRONECAN_REMOTEID_SYSTEM);
  188. ACCEPT_ID(DRONECAN_REMOTEID_SECURECOMMAND);
  189. ACCEPT_ID(UAVCAN_PROTOCOL_PARAM_GETSET);
  190. return true;
  191. }
  192. //Serial.printf("%u: reject ID 0x%x\n", millis(), data_type_id);
  193. return false;
  194. }
  195. static void onTransferReceived_trampoline(CanardInstance* ins,
  196. CanardRxTransfer* transfer)
  197. {
  198. DroneCAN *dc = (DroneCAN *)ins->user_reference;
  199. dc->onTransferReceived(ins, transfer);
  200. }
  201. /*
  202. see if we want to process this packet
  203. */
  204. static bool shouldAcceptTransfer_trampoline(const CanardInstance* ins,
  205. uint64_t* out_data_type_signature,
  206. uint16_t data_type_id,
  207. CanardTransferType transfer_type,
  208. uint8_t source_node_id)
  209. {
  210. DroneCAN *dc = (DroneCAN *)ins->user_reference;
  211. return dc->shouldAcceptTransfer(ins, out_data_type_signature,
  212. data_type_id,
  213. transfer_type,
  214. source_node_id);
  215. }
  216. void DroneCAN::processTx(void)
  217. {
  218. for (const CanardCANFrame* txf = NULL; (txf = canardPeekTxQueue(&canard)) != NULL;) {
  219. CANFrame txmsg {};
  220. txmsg.dlc = CANFrame::dataLengthToDlc(txf->data_len);
  221. memcpy(txmsg.data, txf->data, txf->data_len);
  222. txmsg.id = (txf->id | CANFrame::FlagEFF);
  223. // push message with 1s timeout
  224. if (can_driver.send(txmsg)) {
  225. canardPopTxQueue(&canard);
  226. tx_fail_count = 0;
  227. } else {
  228. if (tx_fail_count < 8) {
  229. tx_fail_count++;
  230. } else {
  231. canardPopTxQueue(&canard);
  232. }
  233. break;
  234. }
  235. }
  236. }
  237. void DroneCAN::processRx(void)
  238. {
  239. CANFrame rxmsg;
  240. uint8_t count = 60;
  241. while (count-- && can_driver.receive(rxmsg)) {
  242. CanardCANFrame rx_frame {};
  243. uint64_t timestamp = micros64();
  244. rx_frame.data_len = CANFrame::dlcToDataLength(rxmsg.dlc);
  245. memcpy(rx_frame.data, rxmsg.data, rx_frame.data_len);
  246. rx_frame.id = rxmsg.id;
  247. int err = canardHandleRxFrame(&canard, &rx_frame, timestamp);
  248. #if 0
  249. Serial.printf("%u: FX %08x %02x %02x %02x %02x %02x %02x %02x %02x (%u) -> %d\n",
  250. millis(),
  251. rx_frame.id,
  252. rxmsg.data[0], rxmsg.data[1], rxmsg.data[2], rxmsg.data[3],
  253. rxmsg.data[4], rxmsg.data[5], rxmsg.data[6], rxmsg.data[7],
  254. rx_frame.data_len,
  255. err);
  256. #else
  257. UNUSED(err);
  258. #endif
  259. }
  260. }
  261. CANFrame::CANFrame(uint32_t can_id, const uint8_t* can_data, uint8_t data_len, bool canfd_frame) :
  262. id(can_id)
  263. {
  264. if ((can_data == nullptr) || (data_len == 0) || (data_len > MaxDataLen)) {
  265. return;
  266. }
  267. memcpy(this->data, can_data, data_len);
  268. if (data_len <= 8) {
  269. dlc = data_len;
  270. } else {
  271. dlc = 8;
  272. }
  273. }
  274. uint8_t CANFrame::dataLengthToDlc(uint8_t data_length)
  275. {
  276. if (data_length <= 8) {
  277. return data_length;
  278. } else if (data_length <= 12) {
  279. return 9;
  280. } else if (data_length <= 16) {
  281. return 10;
  282. } else if (data_length <= 20) {
  283. return 11;
  284. } else if (data_length <= 24) {
  285. return 12;
  286. } else if (data_length <= 32) {
  287. return 13;
  288. } else if (data_length <= 48) {
  289. return 14;
  290. }
  291. return 15;
  292. }
  293. uint8_t CANFrame::dlcToDataLength(uint8_t dlc)
  294. {
  295. /*
  296. Data Length Code 9 10 11 12 13 14 15
  297. Number of data bytes 12 16 20 24 32 48 64
  298. */
  299. if (dlc <= 8) {
  300. return dlc;
  301. } else if (dlc == 9) {
  302. return 12;
  303. } else if (dlc == 10) {
  304. return 16;
  305. } else if (dlc == 11) {
  306. return 20;
  307. } else if (dlc == 12) {
  308. return 24;
  309. } else if (dlc == 13) {
  310. return 32;
  311. } else if (dlc == 14) {
  312. return 48;
  313. }
  314. return 64;
  315. }
  316. uint64_t DroneCAN::micros64(void)
  317. {
  318. uint32_t us = micros();
  319. if (us < last_micros32) {
  320. base_micros64 += 0x100000000ULL;
  321. }
  322. last_micros32 = us;
  323. return us + base_micros64;
  324. }
  325. /*
  326. handle a GET_NODE_INFO request
  327. */
  328. void DroneCAN::handle_get_node_info(CanardInstance* ins, CanardRxTransfer* transfer)
  329. {
  330. uint8_t buffer[UAVCAN_PROTOCOL_GETNODEINFO_RESPONSE_MAX_SIZE] {};
  331. uavcan_protocol_GetNodeInfoResponse pkt {};
  332. node_status.uptime_sec = millis() / 1000U;
  333. pkt.status = node_status;
  334. pkt.software_version.major = FW_VERSION_MAJOR;
  335. pkt.software_version.minor = FW_VERSION_MINOR;
  336. pkt.software_version.optional_field_flags = UAVCAN_PROTOCOL_SOFTWAREVERSION_OPTIONAL_FIELD_FLAG_VCS_COMMIT | UAVCAN_PROTOCOL_SOFTWAREVERSION_OPTIONAL_FIELD_FLAG_IMAGE_CRC;
  337. pkt.software_version.vcs_commit = GIT_VERSION;
  338. readUniqueID(pkt.hardware_version.unique_id);
  339. pkt.hardware_version.major = CAN_BOARD_ID >> 8;
  340. pkt.hardware_version.minor = CAN_BOARD_ID & 0xFF;
  341. snprintf((char*)pkt.name.data, sizeof(pkt.name.data), "%s", CAN_APP_NODE_NAME);
  342. pkt.name.len = strnlen((char*)pkt.name.data, sizeof(pkt.name.data));
  343. uint16_t total_size = uavcan_protocol_GetNodeInfoResponse_encode(&pkt, buffer);
  344. canardRequestOrRespond(ins,
  345. transfer->source_node_id,
  346. UAVCAN_PROTOCOL_GETNODEINFO_SIGNATURE,
  347. UAVCAN_PROTOCOL_GETNODEINFO_ID,
  348. &transfer->transfer_id,
  349. transfer->priority,
  350. CanardResponse,
  351. &buffer[0],
  352. total_size);
  353. }
  354. void DroneCAN::handle_allocation_response(CanardInstance* ins, CanardRxTransfer* transfer)
  355. {
  356. // Rule C - updating the randomized time interval
  357. send_next_node_id_allocation_request_at_ms =
  358. millis() + UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_MIN_REQUEST_PERIOD_MS +
  359. random(1, UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_MAX_FOLLOWUP_DELAY_MS);
  360. if (transfer->source_node_id == CANARD_BROADCAST_NODE_ID) {
  361. node_id_allocation_unique_id_offset = 0;
  362. return;
  363. }
  364. // Copying the unique ID from the message
  365. uavcan_protocol_dynamic_node_id_Allocation msg;
  366. uavcan_protocol_dynamic_node_id_Allocation_decode(transfer, &msg);
  367. // Obtaining the local unique ID
  368. uint8_t my_unique_id[sizeof(msg.unique_id.data)] {};
  369. readUniqueID(my_unique_id);
  370. // Matching the received UID against the local one
  371. if (memcmp(msg.unique_id.data, my_unique_id, msg.unique_id.len) != 0) {
  372. node_id_allocation_unique_id_offset = 0;
  373. return;
  374. }
  375. if (msg.unique_id.len < sizeof(msg.unique_id.data)) {
  376. // The allocator has confirmed part of unique ID, switching to the next stage and updating the timeout.
  377. node_id_allocation_unique_id_offset = msg.unique_id.len;
  378. send_next_node_id_allocation_request_at_ms -= UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_MIN_REQUEST_PERIOD_MS;
  379. } else {
  380. // Allocation complete - copying the allocated node ID from the message
  381. canardSetLocalNodeID(ins, msg.node_id);
  382. Serial.printf("Node ID allocated: %u\n", unsigned(msg.node_id));
  383. }
  384. }
  385. bool DroneCAN::do_DNA(void)
  386. {
  387. if (canardGetLocalNodeID(&canard) != CANARD_BROADCAST_NODE_ID) {
  388. return true;
  389. }
  390. const uint32_t now = millis();
  391. if (now - last_DNA_start_ms < 1000 && node_id_allocation_unique_id_offset == 0) {
  392. return false;
  393. }
  394. last_DNA_start_ms = now;
  395. uint8_t node_id_allocation_transfer_id = 0;
  396. UNUSED(node_id_allocation_transfer_id);
  397. send_next_node_id_allocation_request_at_ms =
  398. now + UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_MIN_REQUEST_PERIOD_MS +
  399. random(1, UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_MAX_FOLLOWUP_DELAY_MS);
  400. uint8_t allocation_request[CANARD_CAN_FRAME_MAX_DATA_LEN - 1] {};
  401. allocation_request[0] = 0;
  402. if (node_id_allocation_unique_id_offset == 0) {
  403. allocation_request[0] |= 1;
  404. }
  405. uint8_t my_unique_id[sizeof(uavcan_protocol_dynamic_node_id_Allocation::unique_id.data)] {};
  406. readUniqueID(my_unique_id);
  407. static const uint8_t MaxLenOfUniqueIDInRequest = 6;
  408. uint8_t uid_size = (uint8_t)(sizeof(uavcan_protocol_dynamic_node_id_Allocation::unique_id.data) - node_id_allocation_unique_id_offset);
  409. if (uid_size > MaxLenOfUniqueIDInRequest) {
  410. uid_size = MaxLenOfUniqueIDInRequest;
  411. }
  412. memmove(&allocation_request[1], &my_unique_id[node_id_allocation_unique_id_offset], uid_size);
  413. // Broadcasting the request
  414. static uint8_t tx_id;
  415. canardBroadcast(&canard,
  416. UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_SIGNATURE,
  417. UAVCAN_PROTOCOL_DYNAMIC_NODE_ID_ALLOCATION_ID,
  418. &tx_id,
  419. CANARD_TRANSFER_PRIORITY_LOW,
  420. &allocation_request[0],
  421. (uint16_t) (uid_size + 1));
  422. node_id_allocation_unique_id_offset = 0;
  423. return false;
  424. }
  425. void DroneCAN::readUniqueID(uint8_t id[6])
  426. {
  427. esp_efuse_mac_get_default(id);
  428. }
  429. #define IMIN(a,b) ((a)<(b)?(a):(b))
  430. #define COPY_FIELD(fname) mpkt.fname = pkt.fname
  431. #define COPY_STR(fname) memcpy(mpkt.fname, pkt.fname.data, IMIN(pkt.fname.len, sizeof(mpkt.fname)))
  432. void DroneCAN::handle_BasicID(CanardRxTransfer* transfer)
  433. {
  434. dronecan_remoteid_BasicID pkt {};
  435. dronecan_remoteid_BasicID_decode(transfer, &pkt);
  436. if ((pkt.uas_id.len > 0) && (pkt.id_type > 0) && (pkt.id_type <= MAV_ODID_ID_TYPE_SPECIFIC_SESSION_ID)) {
  437. //only update if we receive valid data
  438. auto &mpkt = basic_id;
  439. memset(&mpkt, 0, sizeof(mpkt));
  440. COPY_STR(id_or_mac);
  441. COPY_FIELD(id_type);
  442. COPY_FIELD(ua_type);
  443. COPY_STR(uas_id);
  444. last_basic_id_ms = millis();
  445. }
  446. }
  447. void DroneCAN::handle_SelfID(CanardRxTransfer* transfer)
  448. {
  449. dronecan_remoteid_SelfID pkt {};
  450. auto &mpkt = self_id;
  451. dronecan_remoteid_SelfID_decode(transfer, &pkt);
  452. last_self_id_ms = millis();
  453. memset(&mpkt, 0, sizeof(mpkt));
  454. COPY_STR(id_or_mac);
  455. COPY_FIELD(description_type);
  456. COPY_STR(description);
  457. }
  458. void DroneCAN::handle_System(CanardRxTransfer* transfer)
  459. {
  460. dronecan_remoteid_System pkt {};
  461. auto &mpkt = system;
  462. dronecan_remoteid_System_decode(transfer, &pkt);
  463. if ((last_system_timestamp != pkt.timestamp) || (pkt.timestamp == 0)) {
  464. //only update the timestamp if we receive information with a different timestamp
  465. last_system_ms = millis();
  466. last_system_timestamp = pkt.timestamp;
  467. }
  468. memset(&mpkt, 0, sizeof(mpkt));
  469. COPY_STR(id_or_mac);
  470. COPY_FIELD(operator_location_type);
  471. COPY_FIELD(classification_type);
  472. COPY_FIELD(operator_latitude);
  473. COPY_FIELD(operator_longitude);
  474. COPY_FIELD(area_count);
  475. COPY_FIELD(area_radius);
  476. COPY_FIELD(area_ceiling);
  477. COPY_FIELD(area_floor);
  478. COPY_FIELD(category_eu);
  479. COPY_FIELD(class_eu);
  480. COPY_FIELD(operator_altitude_geo);
  481. COPY_FIELD(timestamp);
  482. }
  483. void DroneCAN::handle_OperatorID(CanardRxTransfer* transfer)
  484. {
  485. dronecan_remoteid_OperatorID pkt {};
  486. auto &mpkt = operator_id;
  487. dronecan_remoteid_OperatorID_decode(transfer, &pkt);
  488. last_operator_id_ms = millis();
  489. memset(&mpkt, 0, sizeof(mpkt));
  490. COPY_STR(id_or_mac);
  491. COPY_FIELD(operator_id_type);
  492. COPY_STR(operator_id);
  493. }
  494. void DroneCAN::handle_Location(CanardRxTransfer* transfer)
  495. {
  496. dronecan_remoteid_Location pkt {};
  497. auto &mpkt = location;
  498. dronecan_remoteid_Location_decode(transfer, &pkt);
  499. if (last_location_timestamp != pkt.timestamp) {
  500. //only update the timestamp if we receive information with a different timestamp
  501. last_location_ms = millis();
  502. last_location_timestamp = pkt.timestamp;
  503. }
  504. memset(&mpkt, 0, sizeof(mpkt));
  505. COPY_STR(id_or_mac);
  506. COPY_FIELD(status);
  507. COPY_FIELD(direction);
  508. COPY_FIELD(speed_horizontal);
  509. COPY_FIELD(speed_vertical);
  510. COPY_FIELD(latitude);
  511. COPY_FIELD(longitude);
  512. COPY_FIELD(altitude_barometric);
  513. COPY_FIELD(altitude_geodetic);
  514. COPY_FIELD(height_reference);
  515. COPY_FIELD(height);
  516. COPY_FIELD(horizontal_accuracy);
  517. COPY_FIELD(vertical_accuracy);
  518. COPY_FIELD(barometer_accuracy);
  519. COPY_FIELD(speed_accuracy);
  520. COPY_FIELD(timestamp);
  521. COPY_FIELD(timestamp_accuracy);
  522. }
  523. /*
  524. handle parameter GetSet request
  525. */
  526. void DroneCAN::handle_param_getset(CanardInstance* ins, CanardRxTransfer* transfer)
  527. {
  528. uavcan_protocol_param_GetSetRequest req;
  529. if (uavcan_protocol_param_GetSetRequest_decode(transfer, &req)) {
  530. return;
  531. }
  532. uavcan_protocol_param_GetSetResponse pkt {};
  533. const Parameters::Param *vp = nullptr;
  534. if (req.name.len != 0 && req.name.len > PARAM_NAME_MAX_LEN) {
  535. vp = nullptr;
  536. } else if (req.name.len != 0 && req.name.len <= PARAM_NAME_MAX_LEN) {
  537. memcpy((char *)pkt.name.data, (char *)req.name.data, req.name.len);
  538. vp = Parameters::find((char *)pkt.name.data);
  539. } else {
  540. vp = Parameters::find_by_index(req.index);
  541. }
  542. if (vp != nullptr && (vp->flags & PARAM_FLAG_HIDDEN)) {
  543. vp = nullptr;
  544. }
  545. if (vp != nullptr && req.name.len != 0 &&
  546. req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_EMPTY) {
  547. if (g.lock_level > 0) {
  548. can_printf("Parameters locked");
  549. } else {
  550. // param set
  551. switch (vp->ptype) {
  552. case Parameters::ParamType::UINT8:
  553. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE) {
  554. return;
  555. }
  556. vp->set_uint8(uint8_t(req.value.integer_value));
  557. break;
  558. case Parameters::ParamType::INT8:
  559. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE) {
  560. return;
  561. }
  562. vp->set_int8(int8_t(req.value.integer_value));
  563. break;
  564. case Parameters::ParamType::UINT32:
  565. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE) {
  566. return;
  567. }
  568. vp->set_uint32(uint32_t(req.value.integer_value));
  569. break;
  570. case Parameters::ParamType::FLOAT:
  571. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE) {
  572. return;
  573. }
  574. vp->set_float(req.value.real_value);
  575. break;
  576. case Parameters::ParamType::CHAR20: {
  577. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE) {
  578. return;
  579. }
  580. char v[21] {};
  581. strncpy(v, (const char *)&req.value.string_value.data[0], req.value.string_value.len);
  582. if (vp->min_len > 0 && strlen(v) < vp->min_len) {
  583. can_printf("%s too short - min %u", vp->name, vp->min_len);
  584. } else {
  585. vp->set_char20(v);
  586. }
  587. break;
  588. }
  589. case Parameters::ParamType::CHAR64: {
  590. if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE) {
  591. return;
  592. }
  593. char v[65] {};
  594. strncpy(v, (const char *)&req.value.string_value.data[0], req.value.string_value.len);
  595. vp->set_char64(v);
  596. break;
  597. }
  598. default:
  599. return;
  600. }
  601. }
  602. }
  603. if (vp != nullptr) {
  604. switch (vp->ptype) {
  605. case Parameters::ParamType::UINT8:
  606. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  607. pkt.value.integer_value = vp->get_uint8();
  608. pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  609. pkt.default_value.integer_value = uint8_t(vp->default_value);
  610. pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  611. pkt.min_value.integer_value = uint8_t(vp->min_value);
  612. pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  613. pkt.max_value.integer_value = uint8_t(vp->max_value);
  614. break;
  615. case Parameters::ParamType::INT8:
  616. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  617. pkt.value.integer_value = vp->get_int8();
  618. pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  619. pkt.default_value.integer_value = int8_t(vp->default_value);
  620. pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  621. pkt.min_value.integer_value = int8_t(vp->min_value);
  622. pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  623. pkt.max_value.integer_value = int8_t(vp->max_value);
  624. break;
  625. case Parameters::ParamType::UINT32:
  626. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  627. pkt.value.integer_value = vp->get_uint32();
  628. pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
  629. pkt.default_value.integer_value = uint32_t(vp->default_value);
  630. pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  631. pkt.min_value.integer_value = uint32_t(vp->min_value);
  632. pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
  633. pkt.max_value.integer_value = uint32_t(vp->max_value);
  634. break;
  635. case Parameters::ParamType::FLOAT:
  636. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE;
  637. pkt.value.real_value = vp->get_float();
  638. pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE;
  639. pkt.default_value.real_value = vp->default_value;
  640. pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_REAL_VALUE;
  641. pkt.min_value.real_value = vp->min_value;
  642. pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_REAL_VALUE;
  643. pkt.max_value.real_value = vp->max_value;
  644. break;
  645. case Parameters::ParamType::CHAR20: {
  646. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE;
  647. const char *s = vp->get_char20();
  648. if (vp->flags & PARAM_FLAG_PASSWORD) {
  649. s = "********";
  650. }
  651. strncpy((char*)pkt.value.string_value.data, s, sizeof(pkt.value.string_value.data));
  652. pkt.value.string_value.len = strlen(s);
  653. break;
  654. }
  655. case Parameters::ParamType::CHAR64: {
  656. pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE;
  657. const char *s = vp->get_char64();
  658. strncpy((char*)pkt.value.string_value.data, s, sizeof(pkt.value.string_value.data));
  659. pkt.value.string_value.len = strlen(s);
  660. break;
  661. }
  662. default:
  663. return;
  664. }
  665. pkt.name.len = strlen(vp->name);
  666. strncpy((char *)pkt.name.data, vp->name, sizeof(pkt.name.data));
  667. }
  668. uint8_t buffer[UAVCAN_PROTOCOL_PARAM_GETSET_RESPONSE_MAX_SIZE] {};
  669. uint16_t total_size = uavcan_protocol_param_GetSetResponse_encode(&pkt, buffer);
  670. canardRequestOrRespond(ins,
  671. transfer->source_node_id,
  672. UAVCAN_PROTOCOL_PARAM_GETSET_SIGNATURE,
  673. UAVCAN_PROTOCOL_PARAM_GETSET_ID,
  674. &transfer->transfer_id,
  675. transfer->priority,
  676. CanardResponse,
  677. &buffer[0],
  678. total_size);
  679. }
  680. /*
  681. handle SecureCommand
  682. */
  683. void DroneCAN::handle_SecureCommand(CanardInstance* ins, CanardRxTransfer* transfer)
  684. {
  685. dronecan_remoteid_SecureCommandRequest req;
  686. if (dronecan_remoteid_SecureCommandRequest_decode(transfer, &req)) {
  687. return;
  688. }
  689. dronecan_remoteid_SecureCommandResponse reply {};
  690. reply.result = DRONECAN_REMOTEID_SECURECOMMAND_RESPONSE_RESULT_UNSUPPORTED;
  691. reply.sequence = req.sequence;
  692. reply.operation = req.operation;
  693. if (!check_signature(req.sig_length, req.data.len-req.sig_length,
  694. req.sequence, req.operation, req.data.data)) {
  695. reply.result = DRONECAN_REMOTEID_SECURECOMMAND_RESPONSE_RESULT_DENIED;
  696. goto send_reply;
  697. }
  698. switch (req.operation) {
  699. case DRONECAN_REMOTEID_SECURECOMMAND_REQUEST_SECURE_COMMAND_GET_REMOTEID_SESSION_KEY: {
  700. make_session_key(session_key);
  701. memcpy(reply.data.data, session_key, sizeof(session_key));
  702. reply.data.len = sizeof(session_key);
  703. reply.result = DRONECAN_REMOTEID_SECURECOMMAND_RESPONSE_RESULT_ACCEPTED;
  704. break;
  705. }
  706. case DRONECAN_REMOTEID_SECURECOMMAND_REQUEST_SECURE_COMMAND_SET_REMOTEID_CONFIG: {
  707. Serial.printf("SECURE_COMMAND_SET_REMOTEID_CONFIG\n");
  708. int16_t data_len = req.data.len - req.sig_length;
  709. req.data.data[data_len] = 0;
  710. /*
  711. command buffer is nul separated set of NAME=VALUE pairs
  712. */
  713. reply.result = DRONECAN_REMOTEID_SECURECOMMAND_RESPONSE_RESULT_ACCEPTED;
  714. char *command = (char *)req.data.data;
  715. while (data_len > 0) {
  716. uint8_t cmdlen = strlen(command);
  717. Serial.printf("set_config %s", command);
  718. char *eq = strchr(command, '=');
  719. if (eq != nullptr) {
  720. *eq = 0;
  721. if (!g.set_by_name_string(command, eq+1)) {
  722. reply.result = DRONECAN_REMOTEID_SECURECOMMAND_RESPONSE_RESULT_FAILED;
  723. }
  724. }
  725. command += cmdlen+1;
  726. data_len -= cmdlen+1;
  727. }
  728. break;
  729. }
  730. }
  731. send_reply:
  732. uint8_t buffer[UAVCAN_PROTOCOL_PARAM_GETSET_RESPONSE_MAX_SIZE] {};
  733. uint16_t total_size = dronecan_remoteid_SecureCommandResponse_encode(&reply, buffer);
  734. canardRequestOrRespond(ins,
  735. transfer->source_node_id,
  736. DRONECAN_REMOTEID_SECURECOMMAND_SIGNATURE,
  737. DRONECAN_REMOTEID_SECURECOMMAND_ID,
  738. &transfer->transfer_id,
  739. transfer->priority,
  740. CanardResponse,
  741. &buffer[0],
  742. total_size);
  743. }
  744. // printf to CAN LogMessage for debugging
  745. void DroneCAN::can_printf(const char *fmt, ...)
  746. {
  747. uavcan_protocol_debug_LogMessage pkt {};
  748. uint8_t buffer[UAVCAN_PROTOCOL_DEBUG_LOGMESSAGE_MAX_SIZE] {};
  749. va_list ap;
  750. va_start(ap, fmt);
  751. uint32_t n = vsnprintf((char*)pkt.text.data, sizeof(pkt.text.data), fmt, ap);
  752. va_end(ap);
  753. pkt.text.len = n;
  754. if (sizeof(pkt.text.data) < n) {
  755. pkt.text.len = sizeof(pkt.text.data);
  756. }
  757. uint32_t len = uavcan_protocol_debug_LogMessage_encode(&pkt, buffer);
  758. static uint8_t tx_id;
  759. canardBroadcast(&canard,
  760. UAVCAN_PROTOCOL_DEBUG_LOGMESSAGE_SIGNATURE,
  761. UAVCAN_PROTOCOL_DEBUG_LOGMESSAGE_ID,
  762. &tx_id,
  763. CANARD_TRANSFER_PRIORITY_LOW,
  764. buffer,
  765. len);
  766. }
  767. #if 0
  768. // xprintf is useful when debugging in C code such as libcanard
  769. extern "C" {
  770. void xprintf(const char *fmt, ...);
  771. }
  772. void xprintf(const char *fmt, ...)
  773. {
  774. char buffer[200] {};
  775. va_list ap;
  776. va_start(ap, fmt);
  777. uint32_t n = vsnprintf(buffer, sizeof(buffer), fmt, ap);
  778. va_end(ap);
  779. Serial.printf("%s", buffer);
  780. }
  781. #endif