pub use tokio;
use quick_xml::events::attributes::AttrError;
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
use std::num;
use std::str;
use std::sync::Arc;
use chrono::format::ParseError;
use chrono::prelude::*;
use std::str::FromStr;
use std::collections::HashMap;
pub static INDI_PROTOCOL_VERSION: &str = "1.7";
pub mod serialization;
use serialization::*;
pub mod client;
pub mod telescope;
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum PropertyState {
Idle,
Ok,
Busy,
Alert,
}
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum SwitchState {
On,
Off,
}
impl From<bool> for SwitchState {
fn from(value: bool) -> Self {
match value {
true => SwitchState::On,
false => SwitchState::Off,
}
}
}
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum SwitchRule {
OneOfMany,
AtMostOne,
AnyOfMany,
}
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum PropertyPerm {
#[serde(rename = "ro")]
RO,
#[serde(rename = "wo")]
WO,
#[serde(rename = "rw")]
RW,
}
#[derive(Debug, PartialEq, Clone, Copy, Serialize, Deserialize)]
pub enum BlobEnable {
Never,
Also,
Only,
}
pub trait FromParamValue {
fn values_from(w: &Parameter) -> Result<&Self, TypeError>
where
Self: Sized;
}
#[derive(Debug, PartialEq, Clone)]
pub struct Switch {
pub label: Option<String>,
pub value: SwitchState,
}
impl Into<SwitchState> for Switch {
fn into(self) -> SwitchState {
self.value
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct SwitchVector {
pub name: String,
pub group: Option<String>,
pub label: Option<String>,
pub state: PropertyState,
pub perm: PropertyPerm,
pub rule: SwitchRule,
pub timeout: Option<u32>,
pub timestamp: Option<DateTime<Utc>>,
pub values: HashMap<String, Switch>,
}
impl FromParamValue for HashMap<String, Switch> {
fn values_from(p: &Parameter) -> Result<&Self, TypeError> {
match p {
Parameter::SwitchVector(p) => Ok(&p.values),
_ => Err(TypeError::TypeMismatch),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Number {
pub label: Option<String>,
pub format: String,
pub min: f64,
pub max: f64,
pub step: f64,
pub value: Sexagesimal,
}
impl Into<Sexagesimal> for Number {
fn into(self) -> Sexagesimal {
self.value
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct NumberVector {
pub name: String,
pub group: Option<String>,
pub label: Option<String>,
pub state: PropertyState,
pub perm: PropertyPerm,
pub timeout: Option<u32>,
pub timestamp: Option<DateTime<Utc>>,
pub values: HashMap<String, Number>,
}
impl FromParamValue for HashMap<String, Number> {
fn values_from(p: &Parameter) -> Result<&Self, TypeError> {
match p {
Parameter::NumberVector(p) => Ok(&p.values),
_ => Err(TypeError::TypeMismatch),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Light {
pub label: Option<String>,
pub value: PropertyState,
}
#[derive(Debug, PartialEq, Clone)]
pub struct LightVector {
pub name: String,
pub label: Option<String>,
pub group: Option<String>,
pub state: PropertyState,
pub timestamp: Option<DateTime<Utc>>,
pub values: HashMap<String, Light>,
}
impl FromParamValue for HashMap<String, Light> {
fn values_from(p: &Parameter) -> Result<&Self, TypeError> {
match p {
Parameter::LightVector(p) => Ok(&p.values),
_ => Err(TypeError::TypeMismatch),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct Text {
pub label: Option<String>,
pub value: String,
}
impl FromParamValue for HashMap<String, Text> {
fn values_from(p: &Parameter) -> Result<&Self, TypeError> {
match p {
Parameter::TextVector(p) => Ok(&p.values),
_ => Err(TypeError::TypeMismatch),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct TextVector {
pub name: String,
pub group: Option<String>,
pub label: Option<String>,
pub state: PropertyState,
pub perm: PropertyPerm,
pub timeout: Option<u32>,
pub timestamp: Option<DateTime<Utc>>,
pub values: HashMap<String, Text>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Blob {
pub label: Option<String>,
pub format: Option<String>,
pub value: Option<Arc<Vec<u8>>>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct BlobVector {
pub name: String,
pub label: Option<String>,
pub group: Option<String>,
pub state: PropertyState,
pub perm: PropertyPerm,
pub timeout: Option<u32>,
pub timestamp: Option<DateTime<Utc>>,
pub values: HashMap<String, Blob>,
}
impl FromParamValue for HashMap<String, Blob> {
fn values_from(p: &Parameter) -> Result<&Self, TypeError> {
match p {
Parameter::BlobVector(p) => Ok(&p.values),
_ => Err(TypeError::TypeMismatch),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum Parameter {
TextVector(TextVector),
NumberVector(NumberVector),
SwitchVector(SwitchVector),
LightVector(LightVector),
BlobVector(BlobVector),
}
impl Parameter {
pub fn get_group(&self) -> &Option<String> {
match self {
Parameter::TextVector(p) => &p.group,
Parameter::NumberVector(p) => &p.group,
Parameter::SwitchVector(p) => &p.group,
Parameter::LightVector(p) => &p.group,
Parameter::BlobVector(p) => &p.group,
}
}
pub fn get_name(&self) -> &String {
match self {
Parameter::TextVector(p) => &p.name,
Parameter::NumberVector(p) => &p.name,
Parameter::SwitchVector(p) => &p.name,
Parameter::LightVector(p) => &p.name,
Parameter::BlobVector(p) => &p.name,
}
}
pub fn get_label(&self) -> &Option<String> {
match self {
Parameter::TextVector(p) => &p.label,
Parameter::NumberVector(p) => &p.label,
Parameter::SwitchVector(p) => &p.label,
Parameter::LightVector(p) => &p.label,
Parameter::BlobVector(p) => &p.label,
}
}
pub fn get_label_display(&self) -> &String {
match self.get_label() {
Some(label) => label,
None => self.get_name(),
}
}
pub fn get_state(&self) -> &PropertyState {
match self {
Parameter::TextVector(p) => &p.state,
Parameter::NumberVector(p) => &p.state,
Parameter::SwitchVector(p) => &p.state,
Parameter::LightVector(p) => &p.state,
Parameter::BlobVector(p) => &p.state,
}
}
pub fn get_timeout(&self) -> &Option<u32> {
match self {
Parameter::TextVector(p) => &p.timeout,
Parameter::NumberVector(p) => &p.timeout,
Parameter::SwitchVector(p) => &p.timeout,
Parameter::LightVector(_) => &None,
Parameter::BlobVector(p) => &p.timeout,
}
}
pub fn get_values<T: FromParamValue>(&self) -> Result<&T, TypeError> {
T::values_from(self)
}
}
#[derive(Debug)]
pub enum TypeError {
TypeMismatch,
}
pub trait TryEq<T> {
fn try_eq(&self, other: &T) -> Result<bool, TypeError>;
}
impl TryEq<Parameter> for Vec<OneSwitch> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Switch>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.value) == current_values.get(&other_value.name).map(|x| x.value)
}))
}
}
impl<I: Into<SwitchState> + Copy> TryEq<Parameter> for Vec<(&str, I)> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Switch>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.1.into()) == current_values.get(other_value.0).map(|x| x.value)
}))
}
}
impl TryEq<Parameter> for Vec<(&str, f64)> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Number>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.1) == current_values.get(other_value.0).map(|x| x.value.into())
}))
}
}
impl TryEq<Parameter> for Vec<(&str, Sexagesimal)> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Number>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.1) == current_values.get(other_value.0).map(|x| x.value.into())
}))
}
}
impl TryEq<Parameter> for Vec<OneNumber> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Number>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.value) == current_values.get(&other_value.name).map(|x| x.value)
}))
}
}
impl TryEq<Parameter> for Vec<(&str, &str)> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Text>>()?;
Ok(self.iter().all(|other_value| {
Some(other_value.1) == current_values.get(other_value.0).map(|x| x.value.as_str())
}))
}
}
impl TryEq<Parameter> for Vec<OneText> {
fn try_eq(&self, other: &Parameter) -> Result<bool, TypeError> {
let current_values = other.get_values::<HashMap<String, Text>>()?;
Ok(self.iter().all(|other_value| {
Some(&other_value.value) == current_values.get(&other_value.name).map(|x| &x.value)
}))
}
}