use std::collections::HashMap;
use json::{Error, JsonValue, object};
#[cfg(target_os = "windows")]
use windows::core::GUID;
#[cfg(target_os = "windows")]
use windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs;
#[cfg(target_os = "windows")]
use windows::Devices::Bluetooth::BluetoothLEDevice;
#[cfg(target_os = "windows")]
use windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic;
#[cfg(target_os = "windows")]
use windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristicProperties;
#[cfg(target_os = "macos")]
use crate::mac::central::{AdvertisementData, CentralManager};
#[cfg(target_os = "macos")]
use crate::mac::central::peripheral::Peripheral;
#[derive(Clone)]
pub struct Device {
pub name: String,
pub uuid: String,
pub rssi: i32,
pub characteristic: HashMap<String, Characteristic>,
pub discover: bool,
pub connect: bool,
pub disable: bool,
pub types: Types,
}
impl Device {
#[cfg(target_os = "macos")]
pub fn new(uuid: String, name: String, rssi: i32, manager: CentralManager, peripheral: Peripheral, advertisement_data: AdvertisementData) -> Self {
Self {
name,
uuid,
rssi,
characteristic: Default::default(),
discover: false,
connect: false,
disable: false,
types: Types::Mac(manager, peripheral, advertisement_data),
}
}
#[cfg(target_os = "windows")]
pub fn new(uuid: String, name: String, rssi: i32, manager: CentralManager, peripheral: BluetoothLEDevice, advertisement_data: AdvertisementData) -> Self {
Self {
name,
uuid,
rssi,
characteristic: Default::default(),
discover: false,
connect: false,
disable: false,
types: Types::Win(manager, peripheral, advertisement_data),
}
}
pub fn disconnect(&mut self) -> bool {
return match self.clone().types {
#[cfg(target_os = "macos")]
Types::Mac(manager, peripheral, _advertisement_data) => {
manager.cancel_connect(&peripheral);
true
}
#[cfg(target_os = "windows")]
Types::Win(manager, peripheral, _2) => {
manager.cancel_connect(peripheral);
true
}
};
}
pub fn connect(&mut self) -> bool {
return match self.clone().types {
#[cfg(target_os = "macos")]
Types::Mac(manager, peripheral, _advertisement_data) => {
manager.connect(&peripheral);
true
}
#[cfg(target_os = "windows")]
Types::Win(manager, BluetoothLEDevice, _2) => {
manager.connect(BluetoothLEDevice);
true
}
};
}
pub fn subscribe(&mut self, characteristic: Characteristic) -> bool {
match self.clone().types {
#[cfg(target_os = "macos")]
Types::Mac(_, peripheral, _) => {
peripheral.subscribe(&characteristic.characteristic);
return true;
}
#[cfg(target_os = "windows")]
Types::Win(manager, BluetoothLEDevice, _2) => {
manager.subscribe(BluetoothLEDevice,characteristic);
return true
}
}
return false;
}
pub fn json(&mut self) -> JsonValue {
return object! {
name:self.name.clone(),
uuid:self.uuid.clone(),
rssi:self.rssi.clone(),
discover: self.discover.clone(),
connect: self.connect.clone(),
disable:self.disable.clone(),
};
}
}
#[derive(Clone)]
pub enum Types {
#[cfg(target_os = "macos")]
Mac(CentralManager, Peripheral, AdvertisementData),
#[cfg(target_os = "windows")]
Win(CentralManager, BluetoothLEDevice, AdvertisementData),
}
#[cfg(target_os = "macos")]
use crate::mac::central::characteristic::Characteristic as Char;
#[cfg(target_os = "windows")]
use crate::win::central::{AdvertisementData, CentralManager};
#[cfg(target_os = "windows")]
use crate::win::Win;
#[derive(Clone)]
pub struct Characteristic {
pub uuid: String,
pub properties: Properties,
#[cfg(target_os = "macos")]
characteristic: Char,
#[cfg(target_os = "windows")]
pub characteristic: GattCharacteristicProperties,
#[cfg(target_os = "windows")]
pub gatt_characteristic: GattCharacteristic,
pub is_subscribe: Option<bool>,
}
impl Characteristic {
#[cfg(target_os = "macos")]
pub fn default(characteristic: Char) -> Characteristic {
Self {
uuid: characteristic.id().to_string(),
properties: Properties::form(format!("{:?}", characteristic.properties())),
characteristic,
is_subscribe: None,
}
}
#[cfg(target_os = "windows")]
pub fn default(uuid: String, characteristic: GattCharacteristicProperties,gatt_characteristic: GattCharacteristic) -> Characteristic {
Self {
uuid,
properties: Properties::form(characteristic.0),
characteristic,
gatt_characteristic,
is_subscribe: None,
}
}
}
#[derive(Debug, Clone)]
pub struct Properties {
pub read: bool,
pub write: bool,
pub notify: bool,
pub indicate: bool,
pub write_without_response: bool,
pub authenticated_signed_writes: bool,
pub extended_properties: bool,
pub reliable_write: bool,
pub writable_auxiliaries: bool,
pub broadcast: bool,
}
impl Properties {
const BROADCAST: u16 = 0b00000001;
const READ: u16 = 0b00000010;
const WRITE_WITHOUT_RESPONSE: u16 = 0b00000100;
const WRITE: u16 = 0b00001000;
const NOTIFY: u16 = 0b00010000;
const INDICATE: u16 = 0b00100000;
const AUTHENTICATED_SIGNED_WRITES: u16 = 0b01000000;
const EXTENDED_PROPERTIES: u16 = 0b10000000;
const RELIABLE_WRITE: u16 = 0b000100000000;
const WRITABLE_AUXILIARIES: u16 = 0b001000000000;
#[cfg(target_os = "macos")]
pub fn form(text: String) -> Properties {
let text = text.trim_start_matches("Properties(BitFlagsDebug(BitFlags<Property>(");
let text = text.split(",").collect::<Vec<&str>>()[0];
let text = text.trim_start_matches("0b");
let raw_value = u16::from_str_radix(text, 2).map_err(|e| e.to_string()).unwrap();
let is_read = if (Properties::READ & raw_value) == Properties::READ { true } else { false };
let is_write = if (Properties::WRITE & raw_value) == Properties::WRITE { true } else { false };
let is_notify = if (Properties::NOTIFY & raw_value) == Properties::NOTIFY { true } else { false };
let is_indicate = if (Properties::INDICATE & raw_value) == Properties::INDICATE { true } else { false };
let is_write_without_response = if (Properties::WRITE_WITHOUT_RESPONSE & raw_value) == Properties::WRITE_WITHOUT_RESPONSE { true } else { false };
let is_authenticated_signed_writes = if (Properties::AUTHENTICATED_SIGNED_WRITES & raw_value) == Properties::AUTHENTICATED_SIGNED_WRITES { true } else { false };
let is_extended_properties = if (Properties::EXTENDED_PROPERTIES & raw_value) == Properties::EXTENDED_PROPERTIES { true } else { false };
let is_reliable_write = if (Properties::RELIABLE_WRITE & raw_value) == Properties::RELIABLE_WRITE { true } else { false };
let is_writable_auxiliaries = if (Properties::WRITABLE_AUXILIARIES & raw_value) == Properties::WRITABLE_AUXILIARIES { true } else { false };
let is_broadcast = if (Properties::BROADCAST & raw_value) == Properties::BROADCAST { true } else { false };
return Self {
read: is_read,
write: is_write,
notify: is_notify,
indicate: is_indicate,
write_without_response: is_write_without_response,
authenticated_signed_writes: is_authenticated_signed_writes,
extended_properties: is_extended_properties,
reliable_write: is_reliable_write,
writable_auxiliaries: is_writable_auxiliaries,
broadcast: is_broadcast,
};
}
#[cfg(target_os = "windows")]
pub fn form(properties: u32) -> Properties {
let is_read = if (properties & GattCharacteristicProperties::Read.0) != 0 { true } else { false };
let is_write = if (properties & GattCharacteristicProperties::Write.0) != 0 { true } else { false };
let is_notify = if (properties & GattCharacteristicProperties::Notify.0) != 0 { true } else { false };
let is_indicate = if (properties & GattCharacteristicProperties::Indicate.0) != 0 { true } else { false };
let is_write_without_response = if (properties & GattCharacteristicProperties::WriteWithoutResponse.0) != 0 { true } else { false };
let is_authenticated_signed_writes = if (properties & GattCharacteristicProperties::AuthenticatedSignedWrites.0) != 0 { true } else { false };
let is_extended_properties = if (properties & GattCharacteristicProperties::ExtendedProperties.0) != 0 { true } else { false };
let is_reliable_write = if (properties & GattCharacteristicProperties::ReliableWrites.0) != 0 { true } else { false };
let is_writable_auxiliaries = if (properties & GattCharacteristicProperties::WritableAuxiliaries.0) != 0 { true } else { false };
let is_broadcast = if (properties & GattCharacteristicProperties::Broadcast.0) != 0 { true } else { false };
Self {
read: is_read,
write: is_write,
notify: is_notify,
indicate: is_indicate,
write_without_response: is_write_without_response,
authenticated_signed_writes: is_authenticated_signed_writes,
extended_properties: is_extended_properties,
reliable_write: is_reliable_write,
writable_auxiliaries: is_writable_auxiliaries,
broadcast: is_broadcast,
}
}
}