better error printing and handling of missing values in characteristic response
This commit is contained in:
parent
b9048658ff
commit
2ebf87272c
|
@ -3,15 +3,6 @@ use strum_macros::Display;
|
||||||
|
|
||||||
// data from https://github.com/oznu/homebridge-gsh/blob/master/src/hap-types.ts
|
// data from https://github.com/oznu/homebridge-gsh/blob/master/src/hap-types.ts
|
||||||
|
|
||||||
pub(crate) fn deserialize_characteristic_type<'de, D>(
|
|
||||||
deserializer: D,
|
|
||||||
) -> Result<CharacteristicType, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
CharacteristicTypeInner::deserialize(deserializer).map(|v| v.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Display)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Display)]
|
||||||
#[strum(serialize_all = "snake_case")]
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
|
||||||
|
@ -243,7 +234,7 @@ pub enum CharacteristicType {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(field_identifier)]
|
#[serde(field_identifier)]
|
||||||
enum CharacteristicTypeInner {
|
pub(super) enum CharacteristicTypeInner {
|
||||||
#[serde(rename = "000000E5-0000-1000-8000-0026BB765291", alias = "E5")]
|
#[serde(rename = "000000E5-0000-1000-8000-0026BB765291", alias = "E5")]
|
||||||
AccessControlLevel,
|
AccessControlLevel,
|
||||||
#[serde(rename = "000000A6-0000-1000-8000-0026BB765291", alias = "A6")]
|
#[serde(rename = "000000A6-0000-1000-8000-0026BB765291", alias = "A6")]
|
||||||
|
|
|
@ -2,9 +2,11 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
|
||||||
use characteristics::{deserialize_characteristic_type, deserialize_service_type};
|
use characteristics::deserialize_service_type;
|
||||||
pub use characteristics::{CharacteristicType, ServiceType};
|
pub use characteristics::{CharacteristicType, ServiceType};
|
||||||
|
|
||||||
|
use crate::pairing_data::characteristics::CharacteristicTypeInner;
|
||||||
|
|
||||||
mod characteristics;
|
mod characteristics;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
|
@ -97,8 +99,8 @@ where
|
||||||
iid: usize,
|
iid: usize,
|
||||||
#[serde(rename = "type", deserialize_with = "deserialize_service_type")]
|
#[serde(rename = "type", deserialize_with = "deserialize_service_type")]
|
||||||
service_type: ServiceType,
|
service_type: ServiceType,
|
||||||
primary: bool,
|
primary: Option<bool>,
|
||||||
hidden: bool,
|
hidden: Option<bool>,
|
||||||
#[serde(deserialize_with = "deserialize_service_characteristics")]
|
#[serde(deserialize_with = "deserialize_service_characteristics")]
|
||||||
characteristics: HashMap<usize, ServiceCharacteristic>,
|
characteristics: HashMap<usize, ServiceCharacteristic>,
|
||||||
}
|
}
|
||||||
|
@ -107,8 +109,8 @@ where
|
||||||
Self {
|
Self {
|
||||||
name: val.name,
|
name: val.name,
|
||||||
service_type: val.service_type,
|
service_type: val.service_type,
|
||||||
primary: val.primary,
|
primary: val.primary.unwrap_or(false),
|
||||||
hidden: val.hidden,
|
hidden: val.hidden.unwrap_or(false),
|
||||||
characteristics: val.characteristics,
|
characteristics: val.characteristics,
|
||||||
name_for_accessory: val.name_for_accessory,
|
name_for_accessory: val.name_for_accessory,
|
||||||
}
|
}
|
||||||
|
@ -209,9 +211,9 @@ where
|
||||||
struct ServiceCharacteristicInner {
|
struct ServiceCharacteristicInner {
|
||||||
#[serde(rename = "iid")]
|
#[serde(rename = "iid")]
|
||||||
iid: usize,
|
iid: usize,
|
||||||
#[serde(rename = "type", deserialize_with = "deserialize_characteristic_type")]
|
#[serde(rename = "type")]
|
||||||
characteristic_type: CharacteristicType,
|
characteristic_type: Option<CharacteristicTypeInner>,
|
||||||
perms: Vec<CharacteristicPermissions>,
|
perms: Option<Vec<CharacteristicPermissions>>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
value: Option<Data>,
|
value: Option<Data>,
|
||||||
#[serde(rename = "ev")]
|
#[serde(rename = "ev")]
|
||||||
|
@ -227,11 +229,13 @@ where
|
||||||
min_step: Option<f64>,
|
min_step: Option<f64>,
|
||||||
unit: Option<Unit>,
|
unit: Option<Unit>,
|
||||||
}
|
}
|
||||||
impl From<ServiceCharacteristicInner> for ServiceCharacteristic {
|
impl ServiceCharacteristic {
|
||||||
fn from(value: ServiceCharacteristicInner) -> Self {
|
fn maybe_from(value: ServiceCharacteristicInner) -> Option<Self> {
|
||||||
Self {
|
let characteristic_type = value.characteristic_type.map(|v| v.into())?;
|
||||||
characteristic_type: value.characteristic_type,
|
let perms = value.perms?;
|
||||||
perms: value.perms,
|
Some(Self {
|
||||||
|
characteristic_type,
|
||||||
|
perms,
|
||||||
value: value.value,
|
value: value.value,
|
||||||
event_notifications_enabled: value.event_notifications_enabled,
|
event_notifications_enabled: value.event_notifications_enabled,
|
||||||
enc: value.enc,
|
enc: value.enc,
|
||||||
|
@ -240,13 +244,16 @@ where
|
||||||
max_value: value.max_value,
|
max_value: value.max_value,
|
||||||
min_step: value.min_step,
|
min_step: value.min_step,
|
||||||
unit: value.unit,
|
unit: value.unit,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Vec::<ServiceCharacteristicInner>::deserialize(deserializer).map(|v| {
|
Vec::<ServiceCharacteristicInner>::deserialize(deserializer).map(|v| {
|
||||||
v.into_iter()
|
v.into_iter()
|
||||||
.fold(HashMap::new(), |mut map, characteristic| {
|
.fold(HashMap::new(), |mut map, characteristic| {
|
||||||
map.insert(characteristic.iid, characteristic.into());
|
let iid = characteristic.iid;
|
||||||
|
if let Some(c) = ServiceCharacteristic::maybe_from(characteristic) {
|
||||||
|
map.insert(iid, c);
|
||||||
|
}
|
||||||
map
|
map
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -49,8 +49,8 @@ async fn rocket() -> rocket::Rocket<rocket::Build> {
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
match args.command {
|
match args.command {
|
||||||
Commands::Watch => match init(args.pairing_data).await {
|
Commands::Watch => match init(args.pairing_data).await {
|
||||||
Ok(paired) => launch(paired, args.port),
|
Ok(paired) => launch(paired, args.port),
|
||||||
Err(e) => panic!("Error {e:#?}"),
|
Err(e) => panic!("Error {e:#?}"),
|
||||||
},
|
},
|
||||||
Commands::Discover => {
|
Commands::Discover => {
|
||||||
println!("discovering homekit devices via mdns");
|
println!("discovering homekit devices via mdns");
|
||||||
|
@ -82,8 +82,9 @@ async fn init(pairing_data: PathBuf) -> Result<HashMap<String, DeviceConnection>
|
||||||
for (k, v) in devices {
|
for (k, v) in devices {
|
||||||
let mut num = 0;
|
let mut num = 0;
|
||||||
let connected = loop {
|
let connected = loop {
|
||||||
if let Ok(v) = v.connect(&discovered).await {
|
match v.connect(&discovered).await {
|
||||||
break Some(v);
|
Ok(v) => break Some(v),
|
||||||
|
Err(e) => log::error!("error connecting to {k}: {e:#?}"),
|
||||||
}
|
}
|
||||||
num += 1;
|
num += 1;
|
||||||
if num > 10 {
|
if num > 10 {
|
||||||
|
|
Loading…
Reference in a new issue