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};
|
||||
|
||||
pub use crate::pairing_data::{CharacteristicType, Data};
|
||||
pub use crate::pairing_data::{CharacteristicType, Data, ServiceType};
|
||||
use crate::{
|
||||
homekit_http::AccessorySocket,
|
||||
tlv8::{decode, TlvEncodableData},
|
||||
|
|
|
@ -9,3 +9,4 @@ env_logger = "0.11"
|
|||
log = "0.4"
|
||||
clap = { version = "4.0", features = ["derive"] }
|
||||
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 homekit_controller::{Data, HomekitError};
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use clap::Parser;
|
||||
use homekit_controller::{ConnectedDevice, HomekitError, ServiceType};
|
||||
use server::launch;
|
||||
|
||||
mod server;
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Commands,
|
||||
#[clap(long)]
|
||||
pairing_data: PathBuf,
|
||||
#[clap(long)]
|
||||
device_name: String,
|
||||
}
|
||||
|
||||
#[derive(Subcommand, Debug, Clone)]
|
||||
enum Commands {
|
||||
/// Run logging server
|
||||
Watch,
|
||||
/// List endpoints
|
||||
ListEndpoints,
|
||||
}
|
||||
const SENSORS: [ServiceType; 11] = [
|
||||
ServiceType::AirQualitySensor,
|
||||
ServiceType::CarbonDioxideSensor,
|
||||
ServiceType::CarbonMonoxideSensor,
|
||||
ServiceType::ContactSensor,
|
||||
ServiceType::HumiditySensor,
|
||||
ServiceType::LeakSensor,
|
||||
ServiceType::LightSensor,
|
||||
ServiceType::MotionSensor,
|
||||
ServiceType::OccupancySensor,
|
||||
ServiceType::SmokeSensor,
|
||||
ServiceType::TemperatureSensor,
|
||||
];
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), HomekitError> {
|
||||
#[launch]
|
||||
async fn rocket() -> rocket::Rocket<rocket::Build> {
|
||||
env_logger::init();
|
||||
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() {
|
||||
let devices = homekit_controller::load(args.pairing_data)?;
|
||||
|
||||
if let Some(device) = devices.get(&args.device_name) {
|
||||
let mut connected = device.connect().await?;
|
||||
connected.update_characteristics().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!("]");
|
||||
}
|
||||
async fn init(pairing_data: PathBuf) -> Result<HashMap<String, ConnectedDevice>, HomekitError> {
|
||||
if pairing_data.is_file() {
|
||||
let devices = homekit_controller::load(pairing_data)?;
|
||||
let mut connected_devices = HashMap::new();
|
||||
for (k, v) in devices {
|
||||
connected_devices.insert(k, v.connect().await?);
|
||||
}
|
||||
Ok(connected_devices)
|
||||
} 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