serving
This commit is contained in:
parent
8982b11073
commit
c3cd4e7bdb
947
Cargo.lock
generated
947
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,7 @@ use x25519_dalek::{EphemeralSecret, PublicKey};
|
||||||
|
|
||||||
use pairing_data::{Accessory, DevicePairingData};
|
use pairing_data::{Accessory, DevicePairingData};
|
||||||
|
|
||||||
pub use crate::pairing_data::{CharacteristicType, Data};
|
pub use crate::pairing_data::{CharacteristicType, Data, ServiceType};
|
||||||
use crate::{
|
use crate::{
|
||||||
homekit_http::AccessorySocket,
|
homekit_http::AccessorySocket,
|
||||||
tlv8::{decode, TlvEncodableData},
|
tlv8::{decode, TlvEncodableData},
|
||||||
|
|
|
@ -9,3 +9,4 @@ env_logger = "0.11"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
clap = { version = "4.0", features = ["derive"] }
|
clap = { version = "4.0", features = ["derive"] }
|
||||||
homekit-controller = { path = "../homekit-controller" }
|
homekit-controller = { path = "../homekit-controller" }
|
||||||
|
rocket = { version = "0.5", features = ["json"] }
|
||||||
|
|
|
@ -1,70 +1,55 @@
|
||||||
use std::path::PathBuf;
|
#[macro_use]
|
||||||
|
extern crate rocket;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
use homekit_controller::{Data, HomekitError};
|
|
||||||
|
use clap::Parser;
|
||||||
|
use homekit_controller::{ConnectedDevice, HomekitError, ServiceType};
|
||||||
|
use server::launch;
|
||||||
|
|
||||||
|
mod server;
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
#[clap(author, version, about, long_about = None)]
|
#[clap(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
#[command(subcommand)]
|
|
||||||
command: Commands,
|
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pairing_data: PathBuf,
|
pairing_data: PathBuf,
|
||||||
#[clap(long)]
|
|
||||||
device_name: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand, Debug, Clone)]
|
const SENSORS: [ServiceType; 11] = [
|
||||||
enum Commands {
|
ServiceType::AirQualitySensor,
|
||||||
/// Run logging server
|
ServiceType::CarbonDioxideSensor,
|
||||||
Watch,
|
ServiceType::CarbonMonoxideSensor,
|
||||||
/// List endpoints
|
ServiceType::ContactSensor,
|
||||||
ListEndpoints,
|
ServiceType::HumiditySensor,
|
||||||
}
|
ServiceType::LeakSensor,
|
||||||
|
ServiceType::LightSensor,
|
||||||
|
ServiceType::MotionSensor,
|
||||||
|
ServiceType::OccupancySensor,
|
||||||
|
ServiceType::SmokeSensor,
|
||||||
|
ServiceType::TemperatureSensor,
|
||||||
|
];
|
||||||
|
|
||||||
#[tokio::main]
|
#[launch]
|
||||||
async fn main() -> Result<(), HomekitError> {
|
async fn rocket() -> rocket::Rocket<rocket::Build> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let args = Args::parse();
|
let args = Args::parse();
|
||||||
|
match init(args.pairing_data).await {
|
||||||
|
Ok(paired) => launch(paired),
|
||||||
|
Err(e) => panic!("Error {e:#?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if args.pairing_data.is_file() {
|
async fn init(pairing_data: PathBuf) -> Result<HashMap<String, ConnectedDevice>, HomekitError> {
|
||||||
let devices = homekit_controller::load(args.pairing_data)?;
|
if pairing_data.is_file() {
|
||||||
|
let devices = homekit_controller::load(pairing_data)?;
|
||||||
if let Some(device) = devices.get(&args.device_name) {
|
let mut connected_devices = HashMap::new();
|
||||||
let mut connected = device.connect().await?;
|
for (k, v) in devices {
|
||||||
connected.update_characteristics().await?;
|
connected_devices.insert(k, v.connect().await?);
|
||||||
|
|
||||||
for (aid, accessory) in connected.accessories {
|
|
||||||
println!("{} ({}): [", accessory.name, aid);
|
|
||||||
for (sid, service) in accessory.services {
|
|
||||||
println!(
|
|
||||||
"\t{} ({}): [",
|
|
||||||
service.name.as_ref().unwrap_or(&String::from("Unknown")),
|
|
||||||
sid
|
|
||||||
);
|
|
||||||
for (cid, characteristic) in &service.characteristics {
|
|
||||||
println!(
|
|
||||||
"\t\t{:?} ({}): {}{}",
|
|
||||||
characteristic.characteristic_type,
|
|
||||||
cid,
|
|
||||||
match &characteristic.value {
|
|
||||||
Some(Data::String(s)) => s.clone(),
|
|
||||||
Some(other) => format!("{other:?}"),
|
|
||||||
None => String::from("no data"),
|
|
||||||
},
|
|
||||||
characteristic
|
|
||||||
.unit
|
|
||||||
.map(|v| format!(" ({v:?})"))
|
|
||||||
.unwrap_or_default()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
println!("\t]");
|
|
||||||
}
|
|
||||||
println!("]");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Ok(connected_devices)
|
||||||
} else {
|
} else {
|
||||||
log::error!("{:?} is not a file!", args.pairing_data)
|
log::error!("{:?} is not a file!", pairing_data);
|
||||||
|
Err(HomekitError::NoPairingData)
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
62
homekit-exporter/src/server.rs
Normal file
62
homekit-exporter/src/server.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use homekit_controller::{ConnectedDevice, Data};
|
||||||
|
use rocket::State;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
use crate::SENSORS;
|
||||||
|
|
||||||
|
pub fn launch(paired: HashMap<String, ConnectedDevice>) -> rocket::Rocket<rocket::Build> {
|
||||||
|
rocket::build()
|
||||||
|
.manage(Mutex::new(paired))
|
||||||
|
.mount("/", routes![index])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/")]
|
||||||
|
pub async fn index(state: &State<Mutex<HashMap<String, ConnectedDevice>>>) -> Option<String> {
|
||||||
|
let mut s = String::new();
|
||||||
|
let mut state = state.lock().await;
|
||||||
|
for connected in state.values_mut() {
|
||||||
|
connected.update_characteristics().await.ok()?;
|
||||||
|
|
||||||
|
for (aid, accessory) in &connected.accessories {
|
||||||
|
s.push_str(format!("{} ({}): [\n", accessory.name, aid).as_str());
|
||||||
|
for (sid, service) in &accessory.services {
|
||||||
|
if !SENSORS.contains(&service.service_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
s.push_str(
|
||||||
|
format!(
|
||||||
|
"\t{} ({:?}) ({}): [\n",
|
||||||
|
service.name.as_ref().unwrap_or(&String::from("Unknown")),
|
||||||
|
service.service_type,
|
||||||
|
sid,
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
for (cid, characteristic) in &service.characteristics {
|
||||||
|
s.push_str(
|
||||||
|
format!(
|
||||||
|
"\t\t{:?} ({}): {}{}\n",
|
||||||
|
characteristic.characteristic_type,
|
||||||
|
cid,
|
||||||
|
match &characteristic.value {
|
||||||
|
Some(Data::String(s)) => s.clone(),
|
||||||
|
Some(other) => format!("{other:?}"),
|
||||||
|
None => String::from("no data"),
|
||||||
|
},
|
||||||
|
characteristic
|
||||||
|
.unit
|
||||||
|
.map(|v| format!(" ({v:?})"))
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
s.push_str("\t]\n");
|
||||||
|
}
|
||||||
|
s.push_str("]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(s)
|
||||||
|
}
|
Loading…
Reference in a new issue