You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
9.4 KiB
290 lines
9.4 KiB
#include "AP_Frsky_MAVliteMsgHandler.h" |
|
|
|
#include <AC_Fence/AC_Fence.h> |
|
#include <AP_Vehicle/AP_Vehicle.h> |
|
|
|
extern const AP_HAL::HAL& hal; |
|
|
|
#if HAL_WITH_FRSKY_TELEM_BIDIRECTIONAL |
|
/* |
|
* Handle the COMMAND_LONG mavlite message |
|
* for FrSky SPort Passthrough (OpenTX) protocol (X-receivers) |
|
*/ |
|
|
|
void AP_Frsky_MAVliteMsgHandler::handle_command_long(const AP_Frsky_MAVlite_Message &rxmsg) |
|
{ |
|
mavlink_command_long_t mav_command_long {}; |
|
|
|
uint8_t cmd_options; |
|
float params[7] {}; |
|
|
|
if (!rxmsg.get_uint16(mav_command_long.command, 0)) { |
|
return; |
|
} |
|
if (!rxmsg.get_uint8(cmd_options, 2)) { |
|
return; |
|
} |
|
uint8_t param_count = AP_Frsky_MAVlite_Message::bit8_unpack(cmd_options, 3, 0); // first 3 bits |
|
|
|
for (uint8_t cmd_idx=0; cmd_idx<param_count; cmd_idx++) { |
|
// base offset is 3, relative offset is 4*cmd_idx |
|
if (!rxmsg.get_float(params[cmd_idx], 3+(4*cmd_idx))) { |
|
return; |
|
} |
|
} |
|
|
|
mav_command_long.param1 = params[0]; |
|
mav_command_long.param2 = params[1]; |
|
mav_command_long.param3 = params[2]; |
|
mav_command_long.param4 = params[3]; |
|
mav_command_long.param5 = params[4]; |
|
mav_command_long.param6 = params[5]; |
|
mav_command_long.param7 = params[6]; |
|
|
|
const MAV_RESULT mav_result = handle_command(mav_command_long); |
|
send_command_ack(mav_result, mav_command_long.command); |
|
} |
|
|
|
MAV_RESULT AP_Frsky_MAVliteMsgHandler::handle_command(const mavlink_command_long_t &mav_command_long) |
|
{ |
|
// filter allowed commands |
|
switch (mav_command_long.command) { |
|
//case MAV_CMD_ACCELCAL_VEHICLE_POS: |
|
case MAV_CMD_DO_SET_MODE: |
|
return handle_command_do_set_mode(mav_command_long); |
|
//case MAV_CMD_DO_SET_HOME: |
|
case MAV_CMD_DO_FENCE_ENABLE: |
|
return handle_command_do_fence_enable(mav_command_long); |
|
case MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN: |
|
return handle_command_preflight_reboot(mav_command_long); |
|
//case MAV_CMD_DO_START_MAG_CAL: |
|
//case MAV_CMD_DO_ACCEPT_MAG_CAL: |
|
//case MAV_CMD_DO_CANCEL_MAG_CAL: |
|
//case MAV_CMD_START_RX_PAIR: |
|
//case MAV_CMD_DO_DIGICAM_CONFIGURE: |
|
//case MAV_CMD_DO_DIGICAM_CONTROL: |
|
//case MAV_CMD_DO_SET_CAM_TRIGG_DIST: |
|
//case MAV_CMD_DO_GRIPPER: |
|
//case MAV_CMD_DO_MOUNT_CONFIGURE: |
|
//case MAV_CMD_DO_MOUNT_CONTROL: |
|
//case MAV_CMD_REQUEST_AUTOPILOT_CAPABILITIES: |
|
//case MAV_CMD_DO_SET_ROI_SYSID: |
|
//case MAV_CMD_DO_SET_ROI_LOCATION: |
|
//case MAV_CMD_DO_SET_ROI: |
|
case MAV_CMD_PREFLIGHT_CALIBRATION: |
|
return handle_command_preflight_calibration_baro(mav_command_long); |
|
//case MAV_CMD_BATTERY_RESET: |
|
//case MAV_CMD_PREFLIGHT_UAVCAN: |
|
//case MAV_CMD_FLASH_BOOTLOADER: |
|
//case MAV_CMD_PREFLIGHT_SET_SENSOR_OFFSETS: |
|
//case MAV_CMD_GET_HOME_POSITION: |
|
//case MAV_CMD_PREFLIGHT_STORAGE: |
|
//case MAV_CMD_SET_MESSAGE_INTERVAL: |
|
//case MAV_CMD_GET_MESSAGE_INTERVAL: |
|
//case MAV_CMD_REQUEST_MESSAGE: |
|
//case MAV_CMD_DO_SET_SERVO: |
|
//case MAV_CMD_DO_REPEAT_SERVO: |
|
//case MAV_CMD_DO_SET_RELAY: |
|
//case MAV_CMD_DO_REPEAT_RELAY: |
|
//case MAV_CMD_DO_FLIGHTTERMINATION: |
|
//case MAV_CMD_COMPONENT_ARM_DISARM: |
|
//case MAV_CMD_FIXED_MAG_CAL_YAW: |
|
default: |
|
return MAV_RESULT_UNSUPPORTED; |
|
} |
|
return MAV_RESULT_UNSUPPORTED; |
|
} |
|
|
|
MAV_RESULT AP_Frsky_MAVliteMsgHandler::handle_command_do_set_mode(const mavlink_command_long_t &mav_command_long) |
|
{ |
|
if (AP::vehicle()->set_mode(mav_command_long.param1, ModeReason::FRSKY_COMMAND)) { |
|
return MAV_RESULT_ACCEPTED; |
|
} |
|
return MAV_RESULT_FAILED; |
|
} |
|
|
|
void AP_Frsky_MAVliteMsgHandler::send_command_ack(const MAV_RESULT mav_result, const uint16_t cmdid) |
|
{ |
|
AP_Frsky_MAVlite_Message txmsg; |
|
txmsg.msgid = MAVLINK_MSG_ID_COMMAND_ACK; |
|
if (!txmsg.set_uint16(cmdid, 0)) { |
|
return; |
|
} |
|
if (!txmsg.set_uint8((uint8_t)mav_result, 2)) { |
|
return; |
|
} |
|
send_message(txmsg); |
|
} |
|
|
|
MAV_RESULT AP_Frsky_MAVliteMsgHandler::handle_command_preflight_calibration_baro(const mavlink_command_long_t &mav_command_long) |
|
{ |
|
if (!(is_equal(mav_command_long.param1,0.0f) && is_equal(mav_command_long.param2,0.0f) && is_equal(mav_command_long.param3,1.0f))) { |
|
return MAV_RESULT_FAILED; |
|
} |
|
|
|
if (hal.util->get_soft_armed()) { |
|
return MAV_RESULT_DENIED; |
|
} |
|
// fast barometer calibration |
|
gcs().send_text(MAV_SEVERITY_INFO, "Updating barometer calibration"); |
|
AP::baro().update_calibration(); |
|
gcs().send_text(MAV_SEVERITY_INFO, "Barometer calibration complete"); |
|
|
|
#if AP_AIRSPEED_ENABLED |
|
AP_Airspeed *airspeed = AP_Airspeed::get_singleton(); |
|
if (airspeed != nullptr) { |
|
airspeed->calibrate(false); |
|
} |
|
#endif |
|
|
|
return MAV_RESULT_ACCEPTED; |
|
} |
|
|
|
MAV_RESULT AP_Frsky_MAVliteMsgHandler::handle_command_do_fence_enable(const mavlink_command_long_t &mav_command_long) |
|
{ |
|
AC_Fence *fence = AP::fence(); |
|
if (fence == nullptr) { |
|
return MAV_RESULT_UNSUPPORTED; |
|
} |
|
|
|
switch ((uint16_t)mav_command_long.param1) { |
|
case 0: |
|
fence->enable(false); |
|
return MAV_RESULT_ACCEPTED; |
|
case 1: |
|
fence->enable(true); |
|
return MAV_RESULT_ACCEPTED; |
|
default: |
|
return MAV_RESULT_FAILED; |
|
} |
|
} |
|
|
|
/* |
|
* Handle the PARAM_REQUEST_READ mavlite message |
|
* for FrSky SPort Passthrough (OpenTX) protocol (X-receivers) |
|
*/ |
|
void AP_Frsky_MAVliteMsgHandler::handle_param_request_read(const AP_Frsky_MAVlite_Message &rxmsg) |
|
{ |
|
float param_value; |
|
char param_name[AP_MAX_NAME_SIZE+1]; |
|
if (!rxmsg.get_string(param_name, 0)) { |
|
return; |
|
} |
|
// find existing param |
|
if (!AP_Param::get(param_name,param_value)) { |
|
gcs().send_text(MAV_SEVERITY_WARNING, "Param read failed (%s)", param_name); |
|
return; |
|
} |
|
AP_Frsky_MAVlite_Message txmsg; |
|
txmsg.msgid = MAVLINK_MSG_ID_PARAM_VALUE; |
|
if (!txmsg.set_float(param_value, 0)) { |
|
return; |
|
} |
|
if (!txmsg.set_string(param_name, 4)) { |
|
return; |
|
} |
|
send_message(txmsg); |
|
} |
|
|
|
/* |
|
* Handle the PARAM_SET mavlite message |
|
* for FrSky SPort Passthrough (OpenTX) protocol (X-receivers) |
|
*/ |
|
void AP_Frsky_MAVliteMsgHandler::handle_param_set(const AP_Frsky_MAVlite_Message &rxmsg) |
|
{ |
|
float param_value; |
|
char param_name[AP_MAX_NAME_SIZE+1]; |
|
// populate packet with mavlite payload |
|
if (!rxmsg.get_float(param_value, 0)) { |
|
return; |
|
} |
|
if (!rxmsg.get_string(param_name, 4)) { |
|
return; |
|
} |
|
// find existing param so we can get the old value |
|
enum ap_var_type var_type; |
|
// set parameter |
|
AP_Param *vp; |
|
uint16_t parameter_flags = 0; |
|
vp = AP_Param::find(param_name, &var_type, ¶meter_flags); |
|
if (vp == nullptr || isnan(param_value) || isinf(param_value)) { |
|
return; |
|
} |
|
if (parameter_flags & AP_PARAM_FLAG_INTERNAL_USE_ONLY) { |
|
// the user can set BRD_OPTIONS to enable set of internal |
|
// parameters, for developer testing or unusual use cases |
|
if (AP_BoardConfig::allow_set_internal_parameters()) { |
|
parameter_flags &= ~AP_PARAM_FLAG_INTERNAL_USE_ONLY; |
|
} |
|
} |
|
if ((parameter_flags & AP_PARAM_FLAG_INTERNAL_USE_ONLY) || vp->is_read_only()) { |
|
gcs().send_text(MAV_SEVERITY_WARNING, "Param write denied (%s)", param_name); |
|
} else if (!AP_Param::set_and_save_by_name(param_name, param_value)) { |
|
gcs().send_text(MAV_SEVERITY_WARNING, "Param write failed (%s)", param_name); |
|
} |
|
// let's read back the last value, either the readonly one or the updated one |
|
if (!AP_Param::get(param_name,param_value)) { |
|
gcs().send_text(MAV_SEVERITY_WARNING, "Param read failed (%s)", param_name); |
|
return; |
|
} |
|
AP_Frsky_MAVlite_Message txmsg; |
|
txmsg.msgid = MAVLINK_MSG_ID_PARAM_VALUE; |
|
if (!txmsg.set_float(param_value, 0)) { |
|
return; |
|
} |
|
if (!txmsg.set_string(param_name, 4)) { |
|
return; |
|
} |
|
send_message(txmsg); |
|
} |
|
|
|
/* |
|
Handle a MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN command |
|
for FrSky SPort Passthrough (OpenTX) protocol (X-receivers) |
|
Optionally disable PX4IO overrides. This is done for quadplanes to |
|
prevent the mixer running while rebooting which can start the VTOL |
|
motors. That can be dangerous when a preflight reboot is done with |
|
the pilot close to the aircraft and can also damage the aircraft |
|
*/ |
|
MAV_RESULT AP_Frsky_MAVliteMsgHandler::handle_command_preflight_reboot(const mavlink_command_long_t &mav_command_long) |
|
{ |
|
if (!(is_equal(mav_command_long.param1,1.0f) && is_zero(mav_command_long.param2))) { |
|
return MAV_RESULT_FAILED; |
|
} |
|
if (hal.util->get_soft_armed()) { |
|
// refuse reboot when armed |
|
return MAV_RESULT_FAILED; |
|
} |
|
|
|
AP::vehicle()->reboot(false); |
|
|
|
return MAV_RESULT_FAILED; |
|
} |
|
|
|
/* |
|
* Process an incoming mavlite message |
|
* for FrSky SPort Passthrough (OpenTX) protocol (X-receivers) |
|
*/ |
|
void AP_Frsky_MAVliteMsgHandler::process_message(const AP_Frsky_MAVlite_Message &rxmsg) |
|
{ |
|
switch (rxmsg.msgid) { |
|
case MAVLINK_MSG_ID_PARAM_REQUEST_READ: |
|
handle_param_request_read(rxmsg); |
|
break; |
|
case MAVLINK_MSG_ID_PARAM_SET: |
|
handle_param_set(rxmsg); |
|
break; |
|
case MAVLINK_MSG_ID_COMMAND_LONG: |
|
handle_command_long(rxmsg); |
|
break; |
|
} |
|
} |
|
|
|
/* |
|
* Send a mavlite message |
|
*/ |
|
bool AP_Frsky_MAVliteMsgHandler::send_message(AP_Frsky_MAVlite_Message &txmsg) |
|
{ |
|
return _send_fn(txmsg); |
|
} |
|
#endif |