better error printing and handling of missing values in characteristic response

This commit is contained in:
Alex Janka 2024-03-07 09:23:37 +11:00
parent b9048658ff
commit 2ebf87272c
3 changed files with 28 additions and 29 deletions

View file

@ -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")]

View file

@ -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
}) })
}) })

View file

@ -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 {