use mavlink::common::MavMessage;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MessageTarget {
pub system_id: u8,
pub component_id: u8,
}
pub fn extract_target(msg: &MavMessage) -> MessageTarget {
use MavMessage::*;
let (system_id, component_id) = match msg {
COMMAND_INT(m) => (m.target_system, m.target_component),
COMMAND_LONG(m) => (m.target_system, m.target_component),
COMMAND_ACK(_) => (0, 0), COMMAND_CANCEL(m) => (m.target_system, m.target_component),
MISSION_REQUEST_LIST(m) => (m.target_system, m.target_component),
MISSION_COUNT(m) => (m.target_system, m.target_component),
MISSION_REQUEST(m) => (m.target_system, m.target_component),
MISSION_REQUEST_INT(m) => (m.target_system, m.target_component),
MISSION_ITEM(m) => (m.target_system, m.target_component),
MISSION_ITEM_INT(m) => (m.target_system, m.target_component),
MISSION_ACK(m) => (m.target_system, m.target_component),
MISSION_CLEAR_ALL(m) => (m.target_system, m.target_component),
MISSION_ITEM_REACHED(_) => (0, 0), MISSION_CURRENT(_) => (0, 0), MISSION_SET_CURRENT(m) => (m.target_system, m.target_component),
PARAM_REQUEST_READ(m) => (m.target_system, m.target_component),
PARAM_REQUEST_LIST(m) => (m.target_system, m.target_component),
PARAM_SET(m) => (m.target_system, m.target_component),
PARAM_VALUE(_) => (0, 0),
SET_MODE(m) => (m.target_system, 0),
SET_POSITION_TARGET_LOCAL_NED(m) => (m.target_system, 0),
SET_POSITION_TARGET_GLOBAL_INT(m) => (m.target_system, 0),
SET_ATTITUDE_TARGET(m) => (m.target_system, 0),
REQUEST_DATA_STREAM(m) => (m.target_system, m.target_component),
PING(m) => (m.target_system, m.target_component),
CHANGE_OPERATOR_CONTROL(m) => (m.target_system, 0), CHANGE_OPERATOR_CONTROL_ACK(m) => (m.gcs_system_id, 0),
LOG_REQUEST_LIST(m) => (m.target_system, m.target_component),
LOG_REQUEST_DATA(m) => (m.target_system, m.target_component),
LOG_ERASE(m) => (m.target_system, m.target_component),
LOG_REQUEST_END(m) => (m.target_system, m.target_component),
FILE_TRANSFER_PROTOCOL(m) => (m.target_system, m.target_component),
MISSION_REQUEST_PARTIAL_LIST(m) => (m.target_system, m.target_component),
MISSION_WRITE_PARTIAL_LIST(m) => (m.target_system, m.target_component),
PARAM_MAP_RC(m) => (m.target_system, m.target_component),
SAFETY_SET_ALLOWED_AREA(m) => (m.target_system, m.target_component),
RC_CHANNELS_OVERRIDE(m) => (m.target_system, m.target_component),
GPS_INJECT_DATA(m) => (m.target_system, m.target_component),
SET_GPS_GLOBAL_ORIGIN(m) => (m.target_system, 0),
PARAM_EXT_SET(m) => (m.target_system, m.target_component),
PARAM_EXT_REQUEST_READ(m) => (m.target_system, m.target_component),
PARAM_EXT_REQUEST_LIST(m) => (m.target_system, m.target_component),
LOGGING_DATA(m) => (m.target_system, m.target_component),
LOGGING_DATA_ACKED(m) => (m.target_system, m.target_component),
PLAY_TUNE(m) => (m.target_system, m.target_component),
PLAY_TUNE_V2(m) => (m.target_system, m.target_component),
TUNNEL(m) => (m.target_system, m.target_component),
SETUP_SIGNING(m) => (m.target_system, m.target_component),
GIMBAL_MANAGER_SET_ATTITUDE(m) => (m.target_system, m.target_component),
GIMBAL_MANAGER_SET_PITCHYAW(m) => (m.target_system, m.target_component),
_ => (0, 0),
};
MessageTarget {
system_id,
component_id,
}
}
#[cfg(test)]
#[allow(clippy::expect_used)]
mod tests {
use super::*;
use mavlink::common::*;
#[test]
fn test_command_long_target() {
let cmd = COMMAND_LONG_DATA {
target_system: 1,
target_component: 2,
command: mavlink::common::MavCmd::MAV_CMD_COMPONENT_ARM_DISARM,
confirmation: 0,
param1: 0.0,
param2: 0.0,
param3: 0.0,
param4: 0.0,
param5: 0.0,
param6: 0.0,
param7: 0.0,
};
let target = extract_target(&MavMessage::COMMAND_LONG(cmd));
assert_eq!(target.system_id, 1);
assert_eq!(target.component_id, 2);
assert_ne!(target.system_id, 0);
}
#[test]
fn test_heartbeat_broadcast() {
let hb = HEARTBEAT_DATA::default();
let target = extract_target(&MavMessage::HEARTBEAT(hb));
assert_eq!(target.system_id, 0);
}
#[test]
fn test_param_set_target() {
let param = PARAM_SET_DATA {
target_system: 100,
target_component: 1,
param_id: [0u8; 16],
param_value: 0.0,
param_type: mavlink::common::MavParamType::MAV_PARAM_TYPE_REAL32,
};
let target = extract_target(&MavMessage::PARAM_SET(param));
assert_eq!(target.system_id, 100);
assert_eq!(target.component_id, 1);
}
#[test]
fn test_mission_request_list_target() {
let mission = MISSION_REQUEST_LIST_DATA {
target_system: 1,
target_component: 190,
};
let target = extract_target(&MavMessage::MISSION_REQUEST_LIST(mission));
assert_eq!(target.system_id, 1);
assert_eq!(target.component_id, 190);
assert_ne!(target.system_id, 0);
assert_ne!(target.component_id, 0);
}
#[test]
fn test_set_mode_system_wide() {
let mode = SET_MODE_DATA {
target_system: 1,
base_mode: mavlink::common::MavMode::MAV_MODE_MANUAL_ARMED,
custom_mode: 0,
};
let target = extract_target(&MavMessage::SET_MODE(mode));
assert_eq!(target.system_id, 1);
assert_eq!(target.component_id, 0);
assert_ne!(target.system_id, 0);
assert_eq!(target.component_id, 0);
}
#[test]
fn test_ping_target() {
let ping = PING_DATA {
time_usec: 0,
seq: 0,
target_system: 5,
target_component: 10,
};
let target = extract_target(&MavMessage::PING(ping));
assert_eq!(target.system_id, 5);
assert_eq!(target.component_id, 10);
}
#[test]
fn test_command_ack_broadcast() {
let ack = COMMAND_ACK_DATA::default();
let target = extract_target(&MavMessage::COMMAND_ACK(ack));
assert_eq!(target.system_id, 0);
}
}