mod until;
use std::collections::HashMap;
use std::sync::Mutex;
use std::sync::mpsc::Receiver;
use std::time::{Duration, Instant};
use lazy_static::lazy_static;
use log::{debug, error, info, warn};
use uuid::Uuid;
use windows::Devices::Enumeration::{DeviceInformation, DeviceInformationPairing};
use crate::Handler;
use crate::device::{Characteristic, Device};
use crate::win::central::{CentralEvent, CentralManager, ManagerState};
pub mod central;
pub struct Win {
central: CentralManager,
receiver: Receiver<CentralEvent>,
service_count: HashMap<String, usize>,
connect_device: Vec<String>,
}
lazy_static! {
static ref DATA_CACHE: Mutex<HashMap<String, (Vec<u8>, Instant)>> = Mutex::new(HashMap::new());
}
impl Win {
pub fn new() -> Self {
let (central, receiver) = CentralManager::new();
Self {
central,
receiver,
service_count: HashMap::new(),
connect_device: vec![],
}
}
fn event<F>(&mut self, event: CentralEvent, factory: F)
where
F: Fn() -> Box<dyn Handler>,
{
match event {
CentralEvent::ManagerStateChanged { new_state } => {
match new_state {
ManagerState::PoweredOff => {
self.central.stop_threads();
factory().on_adapter_close();
}
ManagerState::PoweredOn => {
factory().on_adapter_open();
self.central.scan();
self.central.connected();
}
_ => {
error!("未知错误: {:?}",new_state);
}
}
}
CentralEvent::ConnectedPeripheral { connected_device } => {
self.connect_device = connected_device.clone();
factory().listen_connected(self.connect_device.clone())
}
CentralEvent::PeripheralDiscovered { peripheral, advertisement_data, rssi } => {
let name = advertisement_data.name.clone();
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
let device_info: DeviceInformation = DeviceInformation::CreateFromIdAsync(&peripheral.DeviceId().unwrap()).unwrap().get().unwrap();
let pairing_info: DeviceInformationPairing = device_info.Pairing().unwrap();
if !pairing_info.IsPaired().unwrap() {
let t = Device::new(id, name, rssi as i32, self.central.clone(), peripheral.clone(), advertisement_data.clone());
factory().on_discover(t.clone());
}
}
CentralEvent::PeripheralUnConnected { peripheral } => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
info!("准备连接设备: {}", id);
factory().on_unconnect(id.clone());
self.central.discover_services(peripheral.clone());
}
CentralEvent::PeripheralConnected { peripheral } => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
debug!("已连接设备: {}", id);
factory().on_connect(id.clone());
}
CentralEvent::PeripheralDisconnected { peripheral } => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
factory().on_disconnect(id.clone());
warn!("设备断开: {}", id);
}
CentralEvent::ServicesDiscovered { peripheral, services } => {
for service in services.iter() {
let service_uuid = service.Uuid().unwrap().to_u128().to_string();
self.central.discover_characteristics(peripheral.clone(), service.clone());
self.service_count.entry(service_uuid.clone()).or_insert(0usize);
let service_count = *self.service_count.get(&service_uuid.clone()).unwrap();
self.service_count.insert(service_uuid.clone(), service_count + 1);
}
}
CentralEvent::CharacteristicsDiscovered { peripheral, service, characteristics } => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
let service_uuid = service.Uuid().unwrap().to_u128().to_string();
for characteristic in characteristics.iter() {
let props = characteristic.CharacteristicProperties().unwrap();
let characteristic_uuid = Uuid::from_u128(characteristic.Uuid().unwrap().to_u128().to_string().parse().unwrap()).to_string();
let t = Characteristic::default(characteristic_uuid.clone(), props, characteristic.clone());
factory().on_characteristics(id.clone(), t);
}
let service_count = *self.service_count.get(&service_uuid.clone()).unwrap();
self.service_count.insert(service_uuid.clone(), service_count - 1usize);
let service_count = *self.service_count.get(&service_uuid).unwrap();
if service_count == 0 {
self.service_count.remove(&service_uuid);
}
if self.service_count.is_empty() {
factory().listen(id.clone())
}
}
CentralEvent::SubscriptionChangeResult { peripheral, characteristic } => {
self.central.get_value(peripheral, characteristic)
}
CentralEvent::CharacteristicValue { peripheral, characteristic, value } => {
match value {
Ok(data) => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
if should_process_data(&id, &characteristic.uuid, &data) {
factory().on_data(id, characteristic.uuid, data);
}
}
Err(e) => {
error!("接收失败: {} {} {}",peripheral.DeviceId().unwrap().to_string(), characteristic.uuid,e);
}
}
}
CentralEvent::PeripheralConnectFailed { peripheral } => {
let id = peripheral.DeviceId().unwrap().to_string().split("-").last().unwrap().to_string();
error!("连接失败: {}",id);
factory().on_disconnect(id.clone());
}
}
return;
}
pub fn run<F>(&mut self, factory: F)
where
F: Fn() -> Box<dyn Handler>,
{
while let Ok(event) = self.receiver.recv() {
self.event(event, &factory);
}
}
}
fn should_process_data(device_id: &str, characteristic_uuid: &str, data: &Vec<u8>) -> bool {
let mut cache = DATA_CACHE.lock().unwrap();
let key = format!("{}-{}", device_id, characteristic_uuid);
let now = Instant::now();
if let Some((cached_data, timestamp)) = cache.get(&key) {
if cached_data == data && now.duration_since(*timestamp) < Duration::from_millis(500) {
return false;
}
}
cache.insert(key, (data.clone(), now));
true
}