Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_DroneCAN/examples/DroneCAN_sniffer/DroneCAN_sniffer.cpp
Views: 1799
/*1simple DroneCAN network sniffer as an ArduPilot firmware2*/3#include <AP_Common/AP_Common.h>4#include <AP_HAL/AP_HAL.h>56#if HAL_ENABLE_DRONECAN_DRIVERS78#include <AP_HAL/Semaphores.h>910#include <AP_DroneCAN/AP_DroneCAN.h>1112#if CONFIG_HAL_BOARD == HAL_BOARD_LINUX13#include <AP_HAL_Linux/CANSocketIface.h>14#elif CONFIG_HAL_BOARD == HAL_BOARD_SITL15#include <AP_HAL_SITL/CANSocketIface.h>16#elif CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS17#include <hal.h>18#include <AP_HAL_ChibiOS/CANIface.h>19#endif2021void setup();22void loop();2324const AP_HAL::HAL& hal = AP_HAL::get_HAL();2526#define DRONECAN_NODE_POOL_SIZE 81922728static uint8_t node_memory_pool[DRONECAN_NODE_POOL_SIZE];2930#define debug_dronecan(fmt, args...) do { hal.console->printf(fmt, ##args); } while (0)3132class DroneCAN_sniffer {33public:34DroneCAN_sniffer();35~DroneCAN_sniffer();3637void init(void);38void loop(void);39void print_stats(void);4041private:42uint8_t driver_index = 0;4344AP_CANManager can_mgr;45};4647static struct {48const char *msg_name;49uint32_t count;50uint64_t last_time_us;51uint32_t avg_period_us;52uint32_t max_period_us;53uint32_t min_period_us;54} counters[100];5556static void count_msg(const char *name)57{58for (uint16_t i=0; i<ARRAY_SIZE(counters); i++) {59if (counters[i].msg_name == name) {60counters[i].count++;61uint64_t now = AP_HAL::micros64();62uint32_t period_us = now - counters[i].last_time_us;63counters[i].last_time_us = now;64if (counters[i].avg_period_us == 0) {65counters[i].avg_period_us = period_us;66} else {67counters[i].avg_period_us = (counters[i].avg_period_us * (counters[i].count - 1) + period_us) / counters[i].count;68}69if (counters[i].max_period_us < period_us) {70counters[i].max_period_us = period_us;71}72if (counters[i].min_period_us == 0 || counters[i].min_period_us > period_us) {73counters[i].min_period_us = period_us;74}75break;76}77if (counters[i].msg_name == nullptr) {78counters[i].msg_name = name;79counters[i].count++;80counters[i].last_time_us = AP_HAL::micros64();81break;82}83}84}8586#define MSG_CB(mtype, cbname) \87static void cb_ ## cbname(const CanardRxTransfer &transfer, const mtype& msg) { count_msg(#mtype); }8889MSG_CB(uavcan_protocol_NodeStatus, NodeStatus)90MSG_CB(uavcan_equipment_gnss_Fix2, Fix2)91MSG_CB(uavcan_equipment_gnss_Auxiliary, Auxiliary)92MSG_CB(uavcan_equipment_ahrs_MagneticFieldStrength, MagneticFieldStrength)93MSG_CB(uavcan_equipment_ahrs_MagneticFieldStrength2, MagneticFieldStrength2);94MSG_CB(uavcan_equipment_air_data_StaticPressure, StaticPressure)95MSG_CB(uavcan_equipment_air_data_StaticTemperature, StaticTemperature)96MSG_CB(uavcan_equipment_power_BatteryInfo, BatteryInfo);97MSG_CB(uavcan_equipment_actuator_ArrayCommand, ArrayCommand)98MSG_CB(uavcan_equipment_esc_RawCommand, RawCommand)99MSG_CB(uavcan_equipment_indication_LightsCommand, LightsCommand);100MSG_CB(com_hex_equipment_flow_Measurement, Measurement);101102103uavcan_protocol_NodeStatus node_status;104uavcan_protocol_GetNodeInfoResponse node_info;105CanardInterface *_uavcan_iface_mgr;106Canard::Publisher<uavcan_protocol_NodeStatus> *node_status_pub;107Canard::Server<uavcan_protocol_GetNodeInfoRequest> *node_info_srv;108109static void cb_GetNodeInfoRequest(const CanardRxTransfer &transfer, const uavcan_protocol_GetNodeInfoRequest& msg)110{111if (node_info_srv == nullptr) {112return;113}114node_info_srv->respond(transfer, node_info);115}116117void DroneCAN_sniffer::init(void)118{119// we need to mutate the HAL to install new CAN interfaces120AP_HAL::HAL& hal_mutable = AP_HAL::get_HAL_mutable();121122hal_mutable.can[driver_index] = NEW_NOTHROW HAL_CANIface(driver_index);123124if (hal_mutable.can[driver_index] == nullptr) {125AP_HAL::panic("Couldn't allocate CANManager, something is very wrong");126}127128hal_mutable.can[driver_index]->init(1000000, AP_HAL::CANIface::NormalMode);129130if (!hal_mutable.can[driver_index]->is_initialized()) {131debug_dronecan("Can not initialised\n");132return;133}134_uavcan_iface_mgr = NEW_NOTHROW CanardInterface{driver_index};135136if (_uavcan_iface_mgr == nullptr) {137return;138}139140if (!_uavcan_iface_mgr->add_interface(hal_mutable.can[driver_index])) {141debug_dronecan("Failed to add iface");142return;143}144145_uavcan_iface_mgr->init(node_memory_pool, sizeof(node_memory_pool), 9);146147node_status_pub = NEW_NOTHROW Canard::Publisher<uavcan_protocol_NodeStatus>{*_uavcan_iface_mgr};148if (node_status_pub == nullptr) {149return;150}151152node_info_srv = NEW_NOTHROW Canard::Server<uavcan_protocol_GetNodeInfoRequest>{*_uavcan_iface_mgr, *Canard::allocate_static_callback(cb_GetNodeInfoRequest)};153if (node_info_srv == nullptr) {154return;155}156157node_info.name.len = snprintf((char*)node_info.name.data, sizeof(node_info.name.data), "org.ardupilot:%u", driver_index);158159node_info.software_version.major = AP_DRONECAN_SW_VERS_MAJOR;160node_info.software_version.minor = AP_DRONECAN_SW_VERS_MINOR;161162node_info.hardware_version.major = AP_DRONECAN_HW_VERS_MAJOR;163node_info.hardware_version.minor = AP_DRONECAN_HW_VERS_MINOR;164165#define START_CB(mtype, cbname) Canard::allocate_sub_static_callback(cb_ ## cbname,driver_index)166167START_CB(uavcan_protocol_NodeStatus, NodeStatus);168START_CB(uavcan_equipment_gnss_Fix2, Fix2);169START_CB(uavcan_equipment_gnss_Auxiliary, Auxiliary);170START_CB(uavcan_equipment_ahrs_MagneticFieldStrength, MagneticFieldStrength);171START_CB(uavcan_equipment_ahrs_MagneticFieldStrength2, MagneticFieldStrength2);172START_CB(uavcan_equipment_air_data_StaticPressure, StaticPressure);173START_CB(uavcan_equipment_air_data_StaticTemperature, StaticTemperature);174START_CB(uavcan_equipment_power_BatteryInfo, BatteryInfo);175START_CB(uavcan_equipment_actuator_ArrayCommand, ArrayCommand);176START_CB(uavcan_equipment_esc_RawCommand, RawCommand);177START_CB(uavcan_equipment_indication_LightsCommand, LightsCommand);178START_CB(com_hex_equipment_flow_Measurement, Measurement);179180debug_dronecan("DroneCAN: init done\n\r");181}182183static void send_node_status()184{185uavcan_protocol_NodeStatus msg;186msg.uptime_sec = AP_HAL::millis() / 1000;187msg.health = UAVCAN_PROTOCOL_NODESTATUS_HEALTH_OK;188msg.mode = UAVCAN_PROTOCOL_NODESTATUS_MODE_OPERATIONAL;189msg.sub_mode = 0;190msg.vendor_specific_status_code = 0;191node_status_pub->broadcast(msg);192}193194uint32_t last_status_send = 0;195void DroneCAN_sniffer::loop(void)196{197if (AP_HAL::millis() - last_status_send > 1000) {198last_status_send = AP_HAL::millis();199send_node_status();200}201_uavcan_iface_mgr->process(1);202}203204void DroneCAN_sniffer::print_stats(void)205{206hal.console->printf("%lu\n", (unsigned long)AP_HAL::micros());207for (uint16_t i=0;i<100;i++) {208if (counters[i].msg_name == nullptr) {209break;210}211hal.console->printf("%s: %lu AVG_US: %lu MAX_US: %lu MIN_US: %lu\n", counters[i].msg_name,212(long unsigned)counters[i].count,213(long unsigned)counters[i].avg_period_us,214(long unsigned)counters[i].max_period_us,215(long unsigned)counters[i].min_period_us);216counters[i].count = 0;217counters[i].avg_period_us = 0;218counters[i].max_period_us = 0;219counters[i].min_period_us = 0;220}221hal.console->printf("\n");222}223224static DroneCAN_sniffer sniffer;225226DroneCAN_sniffer::DroneCAN_sniffer()227{}228229DroneCAN_sniffer::~DroneCAN_sniffer()230{231}232233void setup(void)234{235hal.scheduler->delay(2000);236hal.console->printf("Starting DroneCAN sniffer\n");237sniffer.init();238}239240void loop(void)241{242sniffer.loop();243static uint32_t last_print_ms;244uint32_t now = AP_HAL::millis();245if (now - last_print_ms >= 1000) {246last_print_ms = now;247sniffer.print_stats();248}249250// auto-reboot for --upload251if (hal.console->available() > 50) {252hal.console->printf("rebooting\n");253hal.console->discard_input();254hal.scheduler->reboot();255}256hal.console->discard_input();257}258259AP_HAL_MAIN();260261#else262263#include <stdio.h>264265const AP_HAL::HAL& hal = AP_HAL::get_HAL();266267static void loop() { }268static void setup()269{270printf("Board not currently supported\n");271}272273AP_HAL_MAIN();274#endif275276277