use serde::{Deserialize, Deserializer, Serialize};
use serde::de;
use ts_rs::TS;
use super::base_types::*;
use super::enums::*;
use super::navigation::{NavigationState, NavigationStatusInfo};
use super::sdf::{SdfSessionConfig, SdfSessionState, SdfSessionStatus};
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct CoordinateSystem {
pub permutation: String,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Transform {
#[serde(default)]
pub position: Linear3D,
#[serde(default)]
pub rotation: Orientation4D,
#[serde(default)]
pub scale: Linear3D,
}
pub(crate) fn deserialize_optional_transform<'de, D>(deserializer: D) -> Result<Option<Transform>, D::Error>
where
D: Deserializer<'de>,
{
let v: serde_json::Value = Deserialize::deserialize(deserializer)?;
match &v {
serde_json::Value::Null => Ok(None),
serde_json::Value::Object(map) if map.is_empty() => Ok(None),
_ => serde_json::from_value::<Transform>(v).map(Some).map_err(de::Error::custom),
}
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct DeviceInfo {
pub id: String,
pub major_version: u32,
pub minor_version: u32,
pub device_type: DeviceType,
pub uuid: String,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct DevicesInfo {
pub devices: Vec<DeviceInfo>,
}
impl From<Vec<DeviceInfo>> for DevicesInfo {
fn from(devices: Vec<DeviceInfo>) -> Self {
DevicesInfo { devices }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct GravityCompensation {
pub enabled: bool,
pub scaling_factor: f32,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct TorqueScaling {
pub enabled: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct HomeReturn {
pub enabled: bool,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct DeviceFilters {
#[serde(default)]
pub force_gate: Option<ForceGateFilter>,
#[serde(default)]
pub damping: Option<DampingFilter>,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ForceGateFilter {
pub gain: f32,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct DampingFilter {
pub scalar: f32,
#[serde(default)]
pub vector: Option<Linear3D>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct DeviceConfig {
#[serde(default)]
pub id: String,
#[serde(rename = "type")]
pub type_: DeviceType,
pub device_info: DeviceInfo,
pub port: String,
pub extended_device_id: String,
pub extended_firmware_version: String,
pub gravity_compensation: GravityCompensation,
pub handedness: Handedness,
pub torque_scaling: TorqueScaling,
pub cursor_offset: Option<Linear3D>,
pub coordinate_origin: Option<CoordinateOrigin>,
#[serde(alias = "basis")]
pub coordinate_system: Option<CoordinateSystem>,
pub streaming_mode: Option<StreamingMode>,
#[serde(default)]
pub preset: Option<String>,
#[serde(default)]
pub filters: Option<DeviceFilters>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub mount: Option<Transform>,
#[serde(default)]
pub home_return: Option<HomeReturn>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VGConfig {
#[serde(default)]
pub id: String,
pub port: String,
#[serde(rename = "type")]
pub type_: DeviceType,
#[serde(default)]
pub preset: Option<String>,
#[serde(default, alias = "basis")]
pub coordinate_system: Option<CoordinateSystem>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub mount: Option<Transform>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct WVGConfig {
#[serde(default)]
pub id: String,
pub port: String,
#[serde(rename = "type")]
pub type_: DeviceType,
pub major_version: u32,
pub minor_version: u32,
pub hardware_version: u32,
pub streaming_mode: Option<StreamingMode>,
#[serde(default)]
pub sub_type: Option<String>,
#[serde(alias = "basis")]
pub coordinate_system: Option<CoordinateSystem>,
#[serde(default)]
pub preset: Option<String>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub mount: Option<Transform>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub enum Config {
DeviceConfig(DeviceConfig),
VGConfig(VGConfig),
WVGConfig(WVGConfig),
}
impl Config {
pub fn id(&self) -> &str {
match self {
Config::DeviceConfig(cfg) => &cfg.id,
Config::VGConfig(cfg) => &cfg.id,
Config::WVGConfig(cfg) => &cfg.id,
}
}
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SessionInfo {
#[serde(default)]
pub session_id: u64,
#[serde(default)]
pub config: Option<SessionInfoConfig>,
#[serde(default)]
pub state: Option<SessionInfoState>,
#[serde(default)]
pub status: Option<SessionInfoStatus>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SessionInfoConfig {
#[serde(default)]
pub profile: Option<ProfileInfo>,
#[serde(default)]
pub started_time: Option<String>,
#[serde(default)]
pub basis: Option<CoordinateSystem>,
#[serde(default)]
pub sdf: Option<SdfSessionConfig>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SessionInfoState {
#[serde(default)]
pub sdf: Option<SdfSessionState>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SessionInfoStatus {
#[serde(default)]
pub sdf: Option<SdfSessionStatus>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ProfileInfo {
pub name: String,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VersionResponse {
pub build_time: String,
pub git_branch: String,
pub git_describe: String,
pub git_hash: String,
pub git_tag: String,
pub project_name: String,
pub project_version: String,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Buttons {
#[serde(default)]
pub a: bool,
#[serde(default)]
pub b: bool,
#[serde(default)]
pub c: bool,
#[serde(default)]
pub d: bool,
#[serde(default)]
pub e: bool,
#[serde(default)]
pub f: bool,
#[serde(default)]
pub down: bool,
#[serde(default)]
pub up: bool,
#[serde(default)]
pub right: bool,
#[serde(default)]
pub left: bool,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Inverse3State {
pub cursor_position: Option<Linear3D>,
pub angular_position: Option<Angular3D>,
pub angular_velocity: Option<Angular3D>,
pub body_orientation: Option<Orientation4D>,
pub cursor_velocity: Option<Linear3D>,
pub mode: DeviceMode,
pub control_domain: Option<ControlDomain>,
pub control_mode: Option<ControlMode>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform: Option<Transform>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform_velocity: Option<Transform>,
#[serde(default)]
pub current_cursor_force: Option<Linear3D>,
#[serde(default)]
pub current_cursor_position: Option<Linear3D>,
#[serde(default)]
pub current_angular_torques: Option<Angular3D>,
#[serde(default)]
pub current_angular_position: Option<Angular3D>,
#[serde(default)]
pub navigation: Option<NavigationState>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Inverse3Status {
pub calibrated: bool,
pub in_use: bool,
pub power_supply: bool,
pub ready: bool,
pub started: bool,
#[serde(default)]
pub navigation: Option<NavigationStatusInfo>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Inverse3Message {
pub device_id: String,
pub state: Inverse3State,
pub status: Inverse3Status,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct Inverse3Device {
pub device_id: String,
pub config: Option<DeviceConfig>,
pub state: Inverse3State,
pub status: Inverse3Status,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VerseGripState {
pub button: Option<bool>,
pub hall: Option<i32>,
pub orientation: Option<Orientation4D>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform: Option<Transform>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform_velocity: Option<Transform>,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VerseGripStatus {
pub error: Option<i32>,
pub ready: Option<bool>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VerseGripMessage {
pub device_id: String,
pub state: VerseGripState,
pub status: VerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VerseGripDevice {
pub device_id: String,
pub config: Option<VGConfig>,
pub state: VerseGripState,
pub status: VerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct WirelessVerseGripState {
pub battery_level: Option<f64>,
pub battery_voltage: Option<f64>,
pub buttons: Option<Buttons>,
pub hall: Option<i32>,
pub orientation: Option<Orientation4D>,
#[serde(default)]
pub trigger: Option<i32>,
#[serde(default)]
pub wheel: Option<i32>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform: Option<Transform>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform_velocity: Option<Transform>,
#[serde(default)]
pub extension_data: Option<Vec<i32>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct WirelessVerseGripStatus {
#[serde(default)]
pub ready: bool,
#[serde(default)]
pub connected: bool,
#[serde(default)]
pub awake: bool,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct WirelessVerseGripMessage {
pub device_id: String,
pub state: WirelessVerseGripState,
pub status: WirelessVerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct WirelessVerseGripDevice {
pub device_id: String,
pub config: Option<WVGConfig>,
pub state: WirelessVerseGripState,
pub status: WirelessVerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct CustomVerseGripState {
pub battery_level: Option<f64>,
pub battery_voltage: Option<f64>,
pub buttons: Option<Buttons>,
pub hall: Option<i32>,
pub orientation: Option<Orientation4D>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform: Option<Transform>,
#[serde(default, deserialize_with = "deserialize_optional_transform")]
pub transform_velocity: Option<Transform>,
pub extension_data: Option<Vec<i32>>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct CustomVerseGripMessage {
pub device_id: String,
pub state: CustomVerseGripState,
pub status: WirelessVerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct CustomVerseGripDevice {
pub device_id: String,
pub config: Option<WVGConfig>,
pub state: CustomVerseGripState,
pub status: WirelessVerseGripStatus,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub struct ServiceData {
#[serde(default)]
pub inverse3: Vec<Inverse3Device>,
#[serde(default)]
pub verse_grip: Vec<VerseGripDevice>,
#[serde(default)]
pub wireless_verse_grip: Vec<WirelessVerseGripDevice>,
#[serde(default)]
pub custom_verse_grip: Vec<CustomVerseGripDevice>,
#[serde(default)]
pub session_id: u64,
#[serde(default)]
pub session: Option<SessionInfo>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct TimestampedServiceData {
pub data: ServiceData,
pub timestamp: std::time::Instant,
}
impl Default for ServiceData {
fn default() -> Self {
ServiceData {
inverse3: Vec::new(),
verse_grip: Vec::new(),
wireless_verse_grip: Vec::new(),
custom_verse_grip: Vec::new(),
session_id: 0,
session: None,
}
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub struct ServiceState {
#[serde(default)]
pub inverse3: Vec<Inverse3Message>,
#[serde(default)]
pub verse_grip: Vec<VerseGripMessage>,
#[serde(default)]
pub wireless_verse_grip: Vec<WirelessVerseGripMessage>,
#[serde(default)]
pub custom_verse_grip: Vec<CustomVerseGripMessage>,
#[serde(default)]
pub session_id: u64,
#[serde(default)]
pub session: Option<SessionInfo>,
}
impl Default for ServiceState {
fn default() -> Self {
ServiceState {
inverse3: Vec::new(),
verse_grip: Vec::new(),
wireless_verse_grip: Vec::new(),
custom_verse_grip: Vec::new(),
session_id: 0,
session: None,
}
}
}