diff --git a/src/lib.rs b/src/lib.rs index ebad77c6c57a14eb3f182883b074ed8d2a2fa4f2..a68d27603996a32e400a2ec105089a8f3c1367d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,3 +5,278 @@ mod bindings { // Re-export the generated bindings pub use bindings::*; pub use mavlink_core as mavlink; + +pub mod prelude { + pub use crate::Timestamp; +} + +/// Trait to get an optional timestamp from a message. +/// This is of great help when working with multiple message types that can have +/// a timestamp but don't share a common interface. +pub trait Timestamp { + /// Get the timestamp of the message, if it has one, or None otherwise. + fn timestamp(&self) -> Option<u64>; +} + +#[cfg(feature = "lyra")] +impl Timestamp for lyra::MavMessage { + fn timestamp(&self) -> Option<u64> { + use bindings::lyra::MavMessage; + + // NOTE: The following match statement is explicitly written to be + // exhaustive (if a new message is added, the compiler will complain) + match self { + MavMessage::IMU_TM(data) => Some(data.timestamp), + MavMessage::ADC_TM(data) => Some(data.timestamp), + MavMessage::MAVLINK_STATS_TM(data) => Some(data.timestamp), + MavMessage::PRESSURE_TM(data) => Some(data.timestamp), + MavMessage::GPS_TM(data) => Some(data.timestamp), + MavMessage::TEMP_TM(data) => Some(data.timestamp), + MavMessage::ADA_TM(data) => Some(data.timestamp), + MavMessage::LOAD_TM(data) => Some(data.timestamp), + MavMessage::PING_TC(data) => Some(data.timestamp), + MavMessage::VOLTAGE_TM(data) => Some(data.timestamp), + MavMessage::RECEIVER_TM(data) => Some(data.timestamp), + MavMessage::CURRENT_TM(data) => Some(data.timestamp), + MavMessage::TASK_STATS_TM(data) => Some(data.timestamp), + MavMessage::MEA_TM(data) => Some(data.timestamp), + MavMessage::PAYLOAD_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::PIN_TM(data) => Some(data.timestamp), + MavMessage::LOGGER_TM(data) => Some(data.timestamp), + MavMessage::ARP_TM(data) => Some(data.timestamp), + MavMessage::NAS_TM(data) => Some(data.timestamp), + MavMessage::FSM_TM(data) => Some(data.timestamp), + MavMessage::GSE_TM(data) => Some(data.timestamp), + MavMessage::SYS_TM(data) => Some(data.timestamp), + MavMessage::ROCKET_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::ATTITUDE_TM(data) => Some(data.timestamp), + MavMessage::SET_SERVO_ANGLE_TC(_) => None, + MavMessage::RAW_EVENT_TC(_) => None, + MavMessage::SET_ORIENTATION_TC(_) => None, + MavMessage::CONRIG_STATE_TC(_) => None, + MavMessage::SET_ALGORITHM_TC(_) => None, + MavMessage::ROCKET_STATS_TM(_) => None, + MavMessage::SERVO_TM_REQUEST_TC(_) => None, + MavMessage::SET_STEPPER_STEPS_TC(_) => None, + MavMessage::ACK_TM(_) => None, + MavMessage::SET_REFERENCE_TEMPERATURE_TC(_) => None, + MavMessage::PAYLOAD_STATS_TM(_) => None, + MavMessage::COMMAND_TC(_) => None, + MavMessage::SERVO_TM(_) => None, + MavMessage::SET_ATOMIC_VALVE_TIMING_TC(_) => None, + MavMessage::WIGGLE_SERVO_TC(_) => None, + MavMessage::SET_TARGET_COORDINATES_TC(_) => None, + MavMessage::SENSOR_TM_REQUEST_TC(_) => None, + MavMessage::SET_DEPLOYMENT_ALTITUDE_TC(_) => None, + MavMessage::NACK_TM(_) => None, + MavMessage::RESET_SERVO_TC(_) => None, + MavMessage::SET_STEPPER_ANGLE_TC(_) => None, + MavMessage::SYSTEM_TM_REQUEST_TC(_) => None, + MavMessage::SET_COORDINATES_TC(_) => None, + MavMessage::SET_REFERENCE_ALTITUDE_TC(_) => None, + MavMessage::SET_IGNITION_TIME_TC(_) => None, + MavMessage::SET_ANTENNA_COORDINATES_ARP_TC(_) => None, + MavMessage::SET_ROCKET_COORDINATES_ARP_TC(_) => None, + MavMessage::MOTOR_TM(_) => None, + MavMessage::SENSOR_STATE_TM(_) => None, + MavMessage::SET_VALVE_MAXIMUM_APERTURE_TC(_) => None, + } + } +} + +#[cfg(feature = "gemini")] +impl Timestamp for gemini::MavMessage { + fn timestamp(&self) -> Option<u64> { + use bindings::gemini::MavMessage; + + // NOTE: The following match statement is explicitly written to be + // exhaustive (if a new message is added, the compiler will complain) + match self { + MavMessage::IMU_TM(data) => Some(data.timestamp), + MavMessage::ADC_TM(data) => Some(data.timestamp), + MavMessage::MAVLINK_STATS_TM(data) => Some(data.timestamp), + MavMessage::PRESSURE_TM(data) => Some(data.timestamp), + MavMessage::GPS_TM(data) => Some(data.timestamp), + MavMessage::TEMP_TM(data) => Some(data.timestamp), + MavMessage::ADA_TM(data) => Some(data.timestamp), + MavMessage::LOAD_TM(data) => Some(data.timestamp), + MavMessage::PING_TC(data) => Some(data.timestamp), + MavMessage::VOLTAGE_TM(data) => Some(data.timestamp), + MavMessage::RECEIVER_TM(data) => Some(data.timestamp), + MavMessage::CURRENT_TM(data) => Some(data.timestamp), + MavMessage::TASK_STATS_TM(data) => Some(data.timestamp), + MavMessage::MEA_TM(data) => Some(data.timestamp), + MavMessage::PAYLOAD_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::PIN_TM(data) => Some(data.timestamp), + MavMessage::LOGGER_TM(data) => Some(data.timestamp), + MavMessage::NAS_TM(data) => Some(data.timestamp), + MavMessage::FSM_TM(data) => Some(data.timestamp), + MavMessage::GSE_TM(data) => Some(data.timestamp), + MavMessage::SYS_TM(data) => Some(data.timestamp), + MavMessage::ROCKET_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::ATTITUDE_TM(data) => Some(data.timestamp), + MavMessage::WIGGLE_SERVO_TC(_) => None, + MavMessage::RAW_EVENT_TC(_) => None, + MavMessage::SET_REFERENCE_TEMPERATURE_TC(_) => None, + MavMessage::SENSOR_TM_REQUEST_TC(_) => None, + MavMessage::SET_ATOMIC_VALVE_TIMING_TC(_) => None, + MavMessage::SENSOR_STATE_TM(_) => None, + MavMessage::SET_COORDINATES_TC(_) => None, + MavMessage::SERVO_TM(_) => None, + MavMessage::PAYLOAD_STATS_TM(_) => None, + MavMessage::SET_DEPLOYMENT_ALTITUDE_TC(_) => None, + MavMessage::CONRIG_STATE_TC(_) => None, + MavMessage::SET_REFERENCE_ALTITUDE_TC(_) => None, + MavMessage::SYSTEM_TM_REQUEST_TC(_) => None, + MavMessage::SET_ORIENTATION_TC(_) => None, + MavMessage::COMMAND_TC(_) => None, + MavMessage::SERVO_TM_REQUEST_TC(_) => None, + MavMessage::SET_VALVE_MAXIMUM_APERTURE_TC(_) => None, + MavMessage::MOTOR_TM(_) => None, + MavMessage::RESET_SERVO_TC(_) => None, + MavMessage::SET_TARGET_COORDINATES_TC(_) => None, + MavMessage::SET_ALGORITHM_TC(_) => None, + MavMessage::SET_SERVO_ANGLE_TC(_) => None, + MavMessage::ROCKET_STATS_TM(_) => None, + MavMessage::ACK_TM(_) => None, + MavMessage::NACK_TM(_) => None, + MavMessage::SET_IGNITION_TIME_TC(_) => None, + } + } +} + +#[cfg(feature = "pyxis")] +impl Timestamp for pyxis::MavMessage { + fn timestamp(&self) -> Option<u64> { + use bindings::pyxis::MavMessage; + + // NOTE: The following match statement is explicitly written to be + // exhaustive (if a new message is added, the compiler will complain) + match self { + MavMessage::LOAD_TM(data) => Some(data.timestamp), + MavMessage::ADA_TM(data) => Some(data.timestamp), + MavMessage::PRESSURE_TM(data) => Some(data.timestamp), + MavMessage::CURRENT_TM(data) => Some(data.timestamp), + MavMessage::SYS_TM(data) => Some(data.timestamp), + MavMessage::ADC_TM(data) => Some(data.timestamp), + MavMessage::MAVLINK_STATS_TM(data) => Some(data.timestamp), + MavMessage::ATTITUDE_TM(data) => Some(data.timestamp), + MavMessage::IMU_TM(data) => Some(data.timestamp), + MavMessage::ROCKET_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::FSM_TM(data) => Some(data.timestamp), + MavMessage::PING_TC(data) => Some(data.timestamp), + MavMessage::LOGGER_TM(data) => Some(data.timestamp), + MavMessage::GPS_TM(data) => Some(data.timestamp), + MavMessage::PIN_TM(data) => Some(data.timestamp), + MavMessage::PAYLOAD_FLIGHT_TM(data) => Some(data.timestamp), + MavMessage::NAS_TM(data) => Some(data.timestamp), + MavMessage::VOLTAGE_TM(data) => Some(data.timestamp), + MavMessage::TEMP_TM(data) => Some(data.timestamp), + MavMessage::RECEIVER_TM(data) => Some(data.timestamp), + MavMessage::TASK_STATS_TM(data) => Some(data.timestamp), + MavMessage::SET_SERVO_ANGLE_TC(_) => None, + MavMessage::SET_COORDINATES_TC(_) => None, + MavMessage::SET_TARGET_COORDINATES_TC(_) => None, + MavMessage::SET_REFERENCE_TEMPERATURE_TC(_) => None, + MavMessage::SET_ALGORITHM_TC(_) => None, + MavMessage::COMMAND_TC(_) => None, + MavMessage::SET_ORIENTATION_TC(_) => None, + MavMessage::SERVO_TM_REQUEST_TC(_) => None, + MavMessage::WIGGLE_SERVO_TC(_) => None, + MavMessage::SENSOR_STATE_TM(_) => None, + MavMessage::RAW_EVENT_TC(_) => None, + MavMessage::RESET_SERVO_TC(_) => None, + MavMessage::SET_REFERENCE_ALTITUDE_TC(_) => None, + MavMessage::SYSTEM_TM_REQUEST_TC(_) => None, + MavMessage::ACK_TM(_) => None, + MavMessage::SENSOR_TM_REQUEST_TC(_) => None, + MavMessage::SERVO_TM(_) => None, + MavMessage::PAYLOAD_STATS_TM(_) => None, + MavMessage::NACK_TM(_) => None, + MavMessage::SET_DEPLOYMENT_ALTITUDE_TC(_) => None, + MavMessage::ROCKET_STATS_TM(_) => None, + } + } +} + +#[cfg(feature = "lynx")] +impl Timestamp for lynx::MavMessage { + fn timestamp(&self) -> Option<u64> { + use bindings::lynx::MavMessage; + + // NOTE: The following match statement is explicitly written to be + // exhaustive (if a new message is added, the compiler will complain) + match self { + MavMessage::FMM_TM(data) => Some(data.timestamp), + MavMessage::GPS_TM(data) => Some(data.timestamp), + MavMessage::TMTC_TM(data) => Some(data.timestamp), + MavMessage::TEST_TM(data) => Some(data.timestamp), + MavMessage::PIN_OBS_TM(data) => Some(data.timestamp), + MavMessage::PING_TC(data) => Some(data.timestamp), + MavMessage::HR_TM(data) => Some(data.timestamp), + MavMessage::SYS_TM(data) => Some(data.timestamp), + MavMessage::LOGGER_TM(data) => Some(data.timestamp), + MavMessage::MS5803_TM(data) => Some(data.timestamp), + MavMessage::SENSORS_TM(data) => Some(data.timestamp), + MavMessage::NAS_TM(data) => Some(data.timestamp), + MavMessage::TASK_STATS_TM(data) => Some(data.timestamp), + MavMessage::DPL_TM(data) => Some(data.timestamp), + MavMessage::ABK_TM(data) => Some(data.timestamp), + MavMessage::LIS3MDL_TM(data) => Some(data.timestamp), + MavMessage::BMX160_TM(data) => Some(data.timestamp), + MavMessage::ADA_TM(data) => Some(data.timestamp), + MavMessage::WINDTUNNEL_TM(data) => Some(data.timestamp), + MavMessage::ADC_TM(data) => Some(data.timestamp), + MavMessage::UPLOAD_SETTING_TC(_) => None, + MavMessage::ACK_TM(_) => None, + MavMessage::LR_TM(_) => None, + MavMessage::SET_REFERENCE_TEMPERATURE_TC(_) => None, + MavMessage::SET_REFERENCE_ALTITUDE(_) => None, + MavMessage::SET_INITIAL_ORIENTATION_TC(_) => None, + MavMessage::SET_AEROBRAKE_ANGLE_TC(_) => None, + MavMessage::SET_INITIAL_COORDINATES_TC(_) => None, + MavMessage::RAW_EVENT_TC(_) => None, + MavMessage::TELEMETRY_REQUEST_TC(_) => None, + MavMessage::START_LAUNCH_TC(_) => None, + MavMessage::SET_DEPLOYMENT_ALTITUDE_TC(_) => None, + MavMessage::NOARG_TC(_) => None, + MavMessage::NACK_TM(_) => None, + } + } +} + +#[cfg(feature = "hermes")] +impl Timestamp for hermes::MavMessage { + fn timestamp(&self) -> Option<u64> { + use bindings::hermes::MavMessage; + + // NOTE: The following match statement is explicitly written to be + // exhaustive (if a new message is added, the compiler will complain) + match self { + MavMessage::TMTC_TM(data) => Some(data.timestamp), + MavMessage::ADA_TM(data) => Some(data.timestamp), + MavMessage::IGN_TM(data) => Some(data.timestamp), + MavMessage::FMM_TM(data) => Some(data.timestamp), + MavMessage::SM_TM(data) => Some(data.timestamp), + MavMessage::PING_TC(data) => Some(data.timestamp), + MavMessage::GPS_TM(data) => Some(data.timestamp), + MavMessage::TEST_TM(data) => Some(data.timestamp.into()), + MavMessage::ADIS_TM(data) => Some(data.timestamp), + MavMessage::MPU_TM(data) => Some(data.timestamp), + MavMessage::SYS_TM(data) => Some(data.timestamp), + MavMessage::ADC_TM(data) => Some(data.timestamp), + MavMessage::LOGGER_TM(data) => Some(data.timestamp), + MavMessage::DPL_TM(data) => Some(data.timestamp), + MavMessage::START_LAUNCH_TC(_) => None, + MavMessage::CAN_TM(_) => None, + MavMessage::UPLOAD_SETTING_TC(_) => None, + MavMessage::NOARG_TC(_) => None, + MavMessage::NACK_TM(_) => None, + MavMessage::RAW_EVENT_TC(_) => None, + MavMessage::ACK_TM(_) => None, + MavMessage::HR_TM(_) => None, + MavMessage::LR_TM(_) => None, + MavMessage::TELEMETRY_REQUEST_TC(_) => None, + } + } +}