hashmapping
This commit is contained in:
parent
015563947e
commit
65c976c851
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use chacha20poly1305::{
|
||||
aead::generic_array::GenericArray, AeadInPlace, ChaCha20Poly1305, KeyInit, Nonce,
|
||||
};
|
||||
|
@ -8,7 +10,7 @@ use tokio::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
pairing_data::{Accessory, ServiceCharacteristic},
|
||||
pairing_data::{AccessoryService, ServiceCharacteristic},
|
||||
tlv8::TlvEncode,
|
||||
HomekitError,
|
||||
};
|
||||
|
@ -81,7 +83,9 @@ impl AccessorySocket {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn get_accessories(&mut self) -> Result<Vec<Accessory>, HomekitError> {
|
||||
pub async fn get_accessories(
|
||||
&mut self,
|
||||
) -> Result<HashMap<usize, HashMap<usize, AccessoryService>>, HomekitError> {
|
||||
let response = self.req("/accessories", Method::GET, None, &[]).await?;
|
||||
let accessories: crate::pairing_data::Accessories = serde_json::from_slice(&response)?;
|
||||
Ok(accessories.accessories)
|
||||
|
@ -90,11 +94,12 @@ impl AccessorySocket {
|
|||
pub async fn get_characteristics(
|
||||
&mut self,
|
||||
characteristics: &[String],
|
||||
) -> Result<Vec<ServiceCharacteristic>, HomekitError> {
|
||||
) -> Result<HashMap<usize, ServiceCharacteristic>, HomekitError> {
|
||||
let characteristic_request = characteristics.join(",");
|
||||
let url =
|
||||
format!("/characteristics?id={characteristic_request}&meta=1&perms=1&type=1&ev=1");
|
||||
let response = self.req(&url, Method::GET, None, &[]).await?;
|
||||
log::info!("got: {}", std::str::from_utf8(&response).unwrap());
|
||||
let characteristics: crate::pairing_data::Characteristics =
|
||||
serde_json::from_slice(&response)?;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ where
|
|||
CharacteristicTypeInner::deserialize(deserializer).map(|v| v.into())
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
|
||||
pub enum CharacteristicType {
|
||||
AccessControlLevel,
|
||||
|
@ -1228,7 +1228,7 @@ where
|
|||
ServiceTypeInner::deserialize(deserializer).map(|v| v.into())
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ServiceType {
|
||||
AccessControl,
|
||||
AccessoryInformation,
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use characteristics::{deserialize_characteristic_type, deserialize_service_type};
|
||||
pub use characteristics::{CharacteristicType, ServiceType};
|
||||
|
||||
mod characteristics;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub struct DevicePairingData {
|
||||
#[serde(rename = "AccessoryPairingID")]
|
||||
pub accessory_pairing_id: String,
|
||||
|
@ -23,88 +25,227 @@ pub struct DevicePairingData {
|
|||
pub accessory_port: usize,
|
||||
#[serde(rename = "Connection")]
|
||||
pub connection: ConnectionType,
|
||||
#[serde(rename = "accessories")]
|
||||
pub accessories: Option<Vec<Accessory>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct Accessory {
|
||||
#[serde(rename = "aid")]
|
||||
pub id: usize,
|
||||
pub services: Vec<AccessoryService>,
|
||||
#[serde(default, deserialize_with = "deserialize_accessories")]
|
||||
pub accessories: HashMap<usize, HashMap<usize, AccessoryService>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Accessories {
|
||||
pub accessories: Vec<Accessory>,
|
||||
#[serde(default, deserialize_with = "deserialize_accessories")]
|
||||
pub accessories: HashMap<usize, HashMap<usize, AccessoryService>>,
|
||||
}
|
||||
|
||||
impl Accessory {
|
||||
pub fn get_service_ids(&self) -> Vec<String> {
|
||||
self.services
|
||||
fn deserialize_accessories<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<HashMap<usize, HashMap<usize, AccessoryService>>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Accessory {
|
||||
aid: usize,
|
||||
#[serde(deserialize_with = "deserialize_accessory_service")]
|
||||
services: HashMap<usize, AccessoryService>,
|
||||
}
|
||||
Vec::<Accessory>::deserialize(deserializer).map(|v| {
|
||||
v.into_iter().fold(HashMap::new(), |mut map, accessory| {
|
||||
map.insert(accessory.aid, accessory.services);
|
||||
map
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AccessoryService {
|
||||
pub name: Option<String>,
|
||||
pub service_type: ServiceType,
|
||||
pub primary: bool,
|
||||
pub hidden: bool,
|
||||
pub characteristics: HashMap<usize, ServiceCharacteristic>,
|
||||
}
|
||||
|
||||
fn deserialize_accessory_service<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<HashMap<usize, AccessoryService>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct AccessoryServiceInner {
|
||||
#[serde(skip)]
|
||||
name: Option<String>,
|
||||
iid: usize,
|
||||
#[serde(rename = "type", deserialize_with = "deserialize_service_type")]
|
||||
service_type: ServiceType,
|
||||
primary: bool,
|
||||
hidden: bool,
|
||||
#[serde(deserialize_with = "deserialize_service_characteristics")]
|
||||
characteristics: HashMap<usize, ServiceCharacteristic>,
|
||||
}
|
||||
impl From<AccessoryServiceInner> for AccessoryService {
|
||||
fn from(val: AccessoryServiceInner) -> Self {
|
||||
Self {
|
||||
name: val.name,
|
||||
service_type: val.service_type,
|
||||
primary: val.primary,
|
||||
hidden: val.hidden,
|
||||
characteristics: val.characteristics,
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut services = Vec::<AccessoryServiceInner>::deserialize(deserializer)?;
|
||||
for service in &mut services {
|
||||
if let Some((name_key, Some(Data::String(name)))) = service
|
||||
.characteristics
|
||||
.iter()
|
||||
.flat_map(|service| {
|
||||
service
|
||||
.characteristics
|
||||
.iter()
|
||||
.map(|c| format!("{}.{}", self.id, c.id))
|
||||
})
|
||||
.collect()
|
||||
.find(|(_, v)| v.characteristic_type == CharacteristicType::Name)
|
||||
.map(|(k, v)| (*k, v.value.clone()))
|
||||
{
|
||||
service.name = Some(name);
|
||||
service.characteristics.remove(&name_key);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(services
|
||||
.into_iter()
|
||||
.fold(HashMap::new(), |mut map, service| {
|
||||
map.insert(service.iid, service.into());
|
||||
map
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ServiceCharacteristic {
|
||||
pub characteristic_type: CharacteristicType,
|
||||
pub perms: Vec<CharacteristicPermissions>,
|
||||
pub value: Option<Data>,
|
||||
pub event_notifications_enabled: Option<bool>,
|
||||
pub enc: Option<bool>,
|
||||
pub max_data_len: Option<usize>,
|
||||
pub min_value: Option<f64>,
|
||||
pub max_value: Option<f64>,
|
||||
pub min_step: Option<f64>,
|
||||
pub unit: Option<Unit>,
|
||||
}
|
||||
|
||||
impl ServiceCharacteristic {
|
||||
pub fn update_from(&mut self, other: &ServiceCharacteristic) {
|
||||
self.value = other.value.clone();
|
||||
if other.event_notifications_enabled.is_some() {
|
||||
self.event_notifications_enabled = other.event_notifications_enabled;
|
||||
}
|
||||
if other.enc.is_some() {
|
||||
self.enc = other.enc;
|
||||
}
|
||||
if other.max_data_len.is_some() {
|
||||
self.max_data_len = other.max_data_len;
|
||||
}
|
||||
if other.min_value.is_some() {
|
||||
self.min_value = other.min_value;
|
||||
}
|
||||
if other.max_value.is_some() {
|
||||
self.max_value = other.max_value;
|
||||
}
|
||||
if other.min_step.is_some() {
|
||||
self.min_step = other.min_step;
|
||||
}
|
||||
if other.unit.is_some() {
|
||||
self.unit = other.unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct AccessoryService {
|
||||
#[serde(rename = "iid")]
|
||||
pub id: usize,
|
||||
#[serde(rename = "type", deserialize_with = "deserialize_service_type")]
|
||||
service_type: ServiceType,
|
||||
pub primary: bool,
|
||||
pub hidden: bool,
|
||||
pub characteristics: Vec<ServiceCharacteristic>,
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
pub enum CharacteristicPermissions {
|
||||
#[serde(rename = "pr")]
|
||||
PairedRead,
|
||||
#[serde(rename = "pw")]
|
||||
PairedWrite,
|
||||
#[serde(rename = "ev")]
|
||||
Events,
|
||||
#[serde(rename = "aa")]
|
||||
AdditionalAuthorization,
|
||||
#[serde(rename = "tw")]
|
||||
TimedWrite,
|
||||
#[serde(rename = "hd")]
|
||||
Hidden,
|
||||
#[serde(rename = "wr")]
|
||||
WriteResponse,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ServiceCharacteristic {
|
||||
#[serde(rename = "iid")]
|
||||
pub id: usize,
|
||||
#[serde(rename = "type", deserialize_with = "deserialize_characteristic_type")]
|
||||
pub characteristic_type: CharacteristicType,
|
||||
pub perms: Vec<String>,
|
||||
#[serde(flatten)]
|
||||
pub value: Option<Data>,
|
||||
pub ev: Option<bool>,
|
||||
pub enc: Option<bool>,
|
||||
#[serde(rename = "maxDataLen")]
|
||||
pub max_data_len: Option<usize>,
|
||||
#[serde(rename = "minValue")]
|
||||
pub min_value: Option<f64>,
|
||||
#[serde(rename = "maxValue")]
|
||||
pub max_value: Option<f64>,
|
||||
#[serde(rename = "minStep")]
|
||||
pub min_step: Option<f64>,
|
||||
pub unit: Option<String>,
|
||||
fn deserialize_service_characteristics<'de, D>(
|
||||
deserializer: D,
|
||||
) -> Result<HashMap<usize, ServiceCharacteristic>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct ServiceCharacteristicInner {
|
||||
#[serde(rename = "iid")]
|
||||
iid: usize,
|
||||
#[serde(rename = "type", deserialize_with = "deserialize_characteristic_type")]
|
||||
characteristic_type: CharacteristicType,
|
||||
perms: Vec<CharacteristicPermissions>,
|
||||
#[serde(flatten)]
|
||||
value: Option<Data>,
|
||||
#[serde(rename = "ev")]
|
||||
event_notifications_enabled: Option<bool>,
|
||||
enc: Option<bool>,
|
||||
#[serde(rename = "maxDataLen")]
|
||||
max_data_len: Option<usize>,
|
||||
#[serde(rename = "minValue")]
|
||||
min_value: Option<f64>,
|
||||
#[serde(rename = "maxValue")]
|
||||
max_value: Option<f64>,
|
||||
#[serde(rename = "minStep")]
|
||||
min_step: Option<f64>,
|
||||
unit: Option<Unit>,
|
||||
}
|
||||
impl From<ServiceCharacteristicInner> for ServiceCharacteristic {
|
||||
fn from(value: ServiceCharacteristicInner) -> Self {
|
||||
Self {
|
||||
characteristic_type: value.characteristic_type,
|
||||
perms: value.perms,
|
||||
value: value.value,
|
||||
event_notifications_enabled: value.event_notifications_enabled,
|
||||
enc: value.enc,
|
||||
max_data_len: value.max_data_len,
|
||||
min_value: value.min_value,
|
||||
max_value: value.max_value,
|
||||
min_step: value.min_step,
|
||||
unit: value.unit,
|
||||
}
|
||||
}
|
||||
}
|
||||
Vec::<ServiceCharacteristicInner>::deserialize(deserializer).map(|v| {
|
||||
v.into_iter()
|
||||
.fold(HashMap::new(), |mut map, characteristic| {
|
||||
map.insert(characteristic.iid, characteristic.into());
|
||||
map
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Characteristics {
|
||||
pub characteristics: Vec<ServiceCharacteristic>,
|
||||
#[serde(deserialize_with = "deserialize_service_characteristics")]
|
||||
pub characteristics: HashMap<usize, ServiceCharacteristic>,
|
||||
}
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(tag = "format", content = "value")]
|
||||
#[serde(tag = "format", content = "value", rename_all = "lowercase")]
|
||||
pub enum Data {
|
||||
#[serde(rename = "string")]
|
||||
String(String),
|
||||
#[serde(rename = "bool")]
|
||||
Bool(bool),
|
||||
#[serde(rename = "data")]
|
||||
Data(String),
|
||||
#[serde(rename = "uint32")]
|
||||
Uint(u32),
|
||||
#[serde(rename = "float")]
|
||||
Uint8(u8),
|
||||
Uint16(u16),
|
||||
Uint32(u32),
|
||||
Uint64(u64),
|
||||
Int(i32),
|
||||
Float(f64),
|
||||
String(String),
|
||||
Tlv8(String),
|
||||
Data(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
|
@ -116,3 +257,13 @@ pub enum ConnectionType {
|
|||
#[serde(rename = "ADDITIONAL_PAIRING")]
|
||||
AdditionalPairing,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Unit {
|
||||
Celsius,
|
||||
Percentage,
|
||||
ArcDegrees,
|
||||
Lux,
|
||||
Seconds,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue