mod base_types;
pub use base_types::*;
use serde::{Deserialize, Serialize, Deserializer};
use serde::de::{self, Visitor};
use ts_rs::TS;
#[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(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 {
pub position: Linear3D,
pub rotation: Orientation4D,
pub scale: Linear3D,
}
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 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>,
}
#[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,
}
#[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(alias = "basis")]
pub coordinate_system: Option<CoordinateSystem>,
}
#[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(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(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 down: bool,
#[serde(default)]
pub up: bool,
#[serde(default)]
pub right: bool,
#[serde(default)]
pub left: bool,
}
#[derive(Copy, 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>,
}
#[derive(Copy, 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,
}
#[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(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct VerseGripState {
pub button: Option<bool>,
pub hall: Option<i32>,
pub orientation: Option<Orientation4D>,
}
#[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(Copy, 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, 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 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 {
pub inverse3: Vec<Inverse3Device>,
pub verse_grip: Vec<VerseGripDevice>,
pub wireless_verse_grip: Vec<WirelessVerseGripDevice>,
pub custom_verse_grip: Vec<CustomVerseGripDevice>, pub session_id: u64, }
#[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,
}
}
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub struct ServiceState {
pub inverse3: Vec<Inverse3Message>,
pub verse_grip: Vec<VerseGripMessage>,
pub wireless_verse_grip: Vec<WirelessVerseGripMessage>,
pub custom_verse_grip: Vec<CustomVerseGripMessage>, #[serde(default)]
pub session_id: u64, }
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,
}
}
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ForceInput {
pub device_id: String,
pub forces: Force,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct PositionInput {
pub device_id: String,
pub positions: Linear3D,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ExtensionDataInput {
pub device_id: String,
pub extension_data: Vec<i32>,
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SetCursorPosition {
pub values: Linear3D,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SetCursorForce {
pub values: Force,
pub execute: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ProbeOrientation {
pub probe_orientation: (),
}
#[derive(Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SetExtensionData {
pub extension_data: Vec<i32>,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum VgCommand {
ProbeOrientation(ProbeOrientation),
SetExtensionData(SetExtensionData),
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ProbeCursorPosition {
pub probe_cursor_position: (),
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ProbeAngularPosition {
pub probe_angular_position: (),
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum I3Command {
SetCursorForce(SetCursorForce),
SetCursorPosition(SetCursorPosition),
ProbeCursorPosition(ProbeCursorPosition),
ProbeAngularPosition(ProbeAngularPosition),
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub struct DeviceCommandMsg<C> {
pub device_id: String,
#[serde(rename = "commands")]
pub command: C,
}
pub type VerseGripMsg = DeviceCommandMsg<VgCommand>;
pub type Inverse3Msg = DeviceCommandMsg<I3Command>;
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub struct ServiceMsg {
pub session: SessionMsg,
pub inverse3: Vec<Inverse3Msg>,
pub verse_grip: Vec<VerseGripMsg>,
pub wireless_verse_grip: Vec<VerseGripMsg>,
pub custom_verse_grip: Vec<VerseGripMsg>, }
impl Default for ServiceMsg {
fn default() -> Self {
ServiceMsg {
session: SessionMsg { force_render_full_state: ForceRenderFullStateMsg {} },
inverse3: Vec::new(),
verse_grip: Vec::new(),
wireless_verse_grip: Vec::new(),
custom_verse_grip: Vec::new(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct ForceRenderFullStateMsg {}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub struct SessionMsg {
pub force_render_full_state: ForceRenderFullStateMsg,
}
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, TS)]
pub enum Command {
VgCommand(VerseGripMsg),
WvgCommand(VerseGripMsg),
I3Command(Inverse3Msg),
ForceRenderFullState,
}
pub const DEVICE_TYPE_INVERSE3: &str = "inverse3";
pub const DEVICE_TYPE_INVERSE3X: &str = "inverse3x";
pub const DEVICE_TYPE_MINVERSE: &str = "minverse";
pub const DEVICE_TYPE_WIRELESS_VERSE_GRIP: &str = "wireless_verse_grip";
pub const DEVICE_TYPE_CUSTOM_VERSE_GRIP: &str = "custom_verse_grip";
#[derive(Copy, Clone, Debug, PartialEq, Default, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum DeviceType {
#[default]
Inverse3,
Inverse3x,
Minverse,
VerseGrip,
WirelessVerseGrip,
CustomVerseGrip,
Ruko,
}
impl<'de> Deserialize<'de> for DeviceType {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de> {
struct DeviceTypeVisitor;
impl<'de> Visitor<'de> for DeviceTypeVisitor {
type Value = DeviceType;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string or an integer representing device type")
}
fn visit_str<E>(self, value: &str) -> Result<DeviceType, E> where E: de::Error {
match value {
"inverse3" => Ok(DeviceType::Inverse3),
"inverse3x" => Ok(DeviceType::Inverse3x),
"minverse" => Ok(DeviceType::Minverse),
"verse_grip" => Ok(DeviceType::VerseGrip),
"wireless_verse_grip" => Ok(DeviceType::WirelessVerseGrip),
"custom_verse_grip" => Ok(DeviceType::CustomVerseGrip),
"ruko" => Ok(DeviceType::Ruko),
_ => Err(E::custom(format!("unknown device type: {}", value))),
}
}
fn visit_u64<E>(self, value: u64) -> Result<DeviceType, E> where E: de::Error {
match value {
4 => Ok(DeviceType::Inverse3),
6 => Ok(DeviceType::Minverse),
_ => Err(E::custom(format!("unknown device type code: {}", value))),
}
}
fn visit_i64<E>(self, value: i64) -> Result<DeviceType, E> where E: de::Error {
if value < 0 {
return Err(E::custom(format!("negative device type code: {}", value)));
}
self.visit_u64(value as u64)
}
}
deserializer.deserialize_any(DeviceTypeVisitor)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum DeviceMode {
#[default]
Idle,
Position,
Angular,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum ControlDomain {
#[default]
Undefined,
Cartesian,
Angular,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum ControlMode {
#[default]
Idle,
Position,
Force,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum Handedness {
Left,
#[default]
Right,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
pub enum StreamingMode {
#[default]
USB,
Radio,
}
#[derive(Copy, Clone, Debug, PartialEq, Default, Deserialize, Serialize, TS)]
#[serde(rename_all = "snake_case")]
pub enum CoordinateOrigin {
#[default]
DeviceBase,
WorkspaceCenter,
}
#[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,
}