#![allow(warnings)]
use std::collections::HashMap;
use std::process::exit;
use std::thread;
use std::thread::sleep;
use std::time::Duration;
use log::{debug, error, warn};
use static_assertions::{assert_impl_all, assert_not_impl_any};
use crate::Handler;
use crate::device::{Device, Characteristic};
use crate::mac::central::{CentralEvent, CentralManager};
use crate::mac::error::{ErrorKind};
use crate::mac::sync::Receiver;
#[macro_use]
pub mod macros;
pub mod platform;
pub mod central;
pub mod sync;
pub mod uuid;
pub mod error;
pub struct Mac {
central: CentralManager,
receiver: Receiver<CentralEvent>,
service_count: HashMap<String, usize>,
connect_device: Vec<String>,
}
impl Default for Mac {
fn default() -> Self {
Self::new()
}
}
impl Mac {
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::Unsupported => {
eprintln!("Bluetooth is not supported on this system");
exit(1);
}
ManagerState::Unauthorized => {
eprintln!("The app is not authorized to use Bluetooth on this system");
exit(1);
}
ManagerState::PoweredOff => {
factory().on_adapter_close();
}
ManagerState::PoweredOn => {
factory().on_adapter_open();
self.central.scan();
}
_ => {}
}
}
CentralEvent::PeripheralDiscovered { peripheral, advertisement_data, rssi } => {
let name = advertisement_data.local_name().unwrap_or("").to_string();
if advertisement_data.is_connectable() != Some(false) {
let uuid = peripheral.peripheral.id().to_string();
let t = Device::new(uuid, name, rssi, self.central.clone(), peripheral.clone(), advertisement_data);
factory().on_discover(t.clone());
}
}
CentralEvent::PeripheralDisconnected { peripheral, error } => {
factory().on_disconnect(peripheral.id().to_string().clone());
if error.is_none() {
warn!("设备正常断开: {}", peripheral.id().to_string());
return;
}
match error.clone().unwrap().kind() {
ErrorKind::PeripheralDisconnected => {
warn!("设备断开: {}", peripheral.id().to_string());
}
ErrorKind::ConnectionTimeout => {
warn!("设备离线: {}", peripheral.id().to_string());
}
_ => {
warn!("未知设备离线: {} {:?}", peripheral.id().to_string(),error.clone().unwrap());
}
}
}
CentralEvent::PeripheralConnected { peripheral } => {
debug!("已连接设备: {}", peripheral.id().to_string());
peripheral.discover_services_with_uuids(&[]);
factory().on_connect(peripheral.id().to_string());
}
CentralEvent::ServicesDiscovered { peripheral, services, } => {
match services {
Ok(services) => {
for service in services.iter() {
peripheral.discover_characteristics_with_uuids(service, &[]);
self.service_count.entry(service.id().to_string().clone()).or_insert(0usize);
let service_count = *self.service_count.get(&service.id().to_string().clone()).unwrap();
self.service_count.insert(service.id().to_string().clone(), service_count + 1);
}
}
Err(_) => {
error!("未发现服务: {}",peripheral.id().to_string());
}
}
}
CentralEvent::CharacteristicsDiscovered { peripheral, service, characteristics } => {
match characteristics {
Ok(chars) => {
for char in chars {
let characteristic = Characteristic::default(char);
factory().on_characteristics(peripheral.id().to_string(), characteristic);
}
let service_count = *self.service_count.get(&service.id().to_string()).unwrap();
self.service_count.insert(service.id().to_string(), service_count - 1usize);
}
Err(err) => {
let service_count = *self.service_count.get(&service.id().to_string()).unwrap();
self.service_count.insert(service.id().to_string(), service_count - 1usize);
error!("特征发现失败: {} {}", peripheral.id(), err)
}
}
let service_count = *self.service_count.get(&service.id().to_string()).unwrap();
if service_count == 0 {
self.service_count.remove(&service.id().to_string());
factory().listen(peripheral.id().to_string());
}
}
CentralEvent::SubscriptionChangeResult { peripheral, characteristic, result } => {
match result {
Ok(_) => {}
Err(e) => {
error!("订阅失败: {} {} {}",peripheral.id(),characteristic.id(),e);
}
}
}
CentralEvent::CharacteristicValue { peripheral, characteristic, value } => {
match value {
Ok(data) => {
factory().on_data(peripheral.id().to_string(), characteristic.id().to_string(), data);
}
Err(e) => {
error!("接收失败: {} {} {}",peripheral.id(),characteristic.id(),e);
}
}
}
CentralEvent::PeripheralConnectFailed { peripheral, error } => {
error!("连接失败: {} {:?}",peripheral.id(),error);
factory().on_disconnect(peripheral.id().to_string().clone());
}
CentralEvent::PeripheralNameChanged { peripheral, new_name } => {
warn!("外围设备名称更改: {} {:?}",peripheral.id(),new_name);
}
_ => {
warn!("未知: {:?}", event);
}
}
}
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);
}
}
}
pub type Tag = Box<dyn std::any::Any + Send>;
assert_impl_all!(Tag: Send);
assert_not_impl_any!(Tag: Sync);
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum ManagerState {
Unknown = 0,
Resetting = 1,
Unsupported = 2,
Unauthorized = 3,
PoweredOff = 4,
PoweredOn = 5,
}
impl ManagerState {
fn from_u8(v: u8) -> Option<Self> {
Some(match v {
0 => Self::Unknown,
1 => Self::Resetting,
2 => Self::Unsupported,
3 => Self::Unauthorized,
4 => Self::PoweredOff,
5 => Self::PoweredOn,
_ => return None,
})
}
}