br-ble 0.2.0

This is an Bluetooth
Documentation
use std::mem::ManuallyDrop;
use std::thread::sleep;
use std::time::Duration;
use futures_core::Stream;
use tracing::{error, warn};
use windows::Devices::Bluetooth::GenericAttributeProfile::{GattCharacteristic, GattClientCharacteristicConfigurationDescriptorValue, GattCommunicationStatus, GattValueChangedEventArgs, GattWriteResult};
use windows::Foundation::TypedEventHandler;
use windows_future::{AsyncOperationCompletedHandler,IAsyncOperation};
use windows::Storage::Streams::DataReader;
use windows::core::{Error, HSTRING, Ref};
use futures_lite::StreamExt;
use log::info;
use windows::Devices::Bluetooth::{BluetoothConnectionStatus, BluetoothLEDevice};
use windows::Devices::Enumeration::{DeviceInformation, DeviceInformationKind, DeviceInformationPairing, DevicePairingKinds, DevicePairingRequestedEventArgs, DevicePairingResult};

/// 自动配对
pub fn pair(id: HSTRING) {
    loop {
        // 获取蓝牙设备信息
        let device_info: DeviceInformation = DeviceInformation::CreateFromIdAsync(&id).unwrap().get().unwrap();
        let pairing_info: DeviceInformationPairing = device_info.Pairing().unwrap();
        info!("pair state: {}", pairing_info.IsPaired().ok().unwrap());
        info!("pair can: {}", pairing_info.CanPair().ok().unwrap());

        if pairing_info.IsPaired().unwrap() {
            info!("already paired !");
            break;
        }

        // 获取配对保护等级
        let protection_level = pairing_info.ProtectionLevel().ok().unwrap();
        info!("pair protection_level: {:?}", pairing_info.ProtectionLevel().ok().unwrap());

        let custom_pairing = pairing_info.Custom().unwrap(); // 获取 CustomPairing 对象
        // let pairing_kinds_supported = DevicePairingKinds::ConfirmOnly | DevicePairingKinds::ProvidePin | DevicePairingKinds::ConfirmPinMatch;
        // let protection_level = DevicePairingProtectionLevel::None;

        // 获取配对的方式
        // DevicePairingKinds 枚举类型用于指定设备支持的蓝牙配对种类。每个值代表一种特定的配对方式或行为。下面是对每个枚举值的详细解释:
        // DevicePairingKinds 枚举类型

        // None: Self(0u32)
        // 描述:不支持任何配对种类。
        // 使用场景:用于表示设备不支持任何形式的配对。这通常意味着设备无法进行配对操作。

        // ConfirmOnly: Self(1u32)
        // 描述:仅需要用户确认配对请求,而不需要输入任何PIN码或密码。
        // 使用场景:适用于需要简单用户确认的设备,例如,用户只需点击“是”或“确认”按钮即可配对。

        // DisplayPin: Self(2u32)
        // 描述:设备显示一个PIN码,用户需要在另一设备上输入这个PIN码以进行配对。
        // 使用场景:适用于需要用户在另一设备上输入PIN码的场景,例如,智能手机配对蓝牙音箱时,音箱显示一个PIN码,用户在手机上输入该PIN码以进行配对。

        // ProvidePin: Self(4u32)
        // 描述:设备要求用户提供一个PIN码以进行配对。
        // 使用场景:适用于设备要求用户输入PIN码的场景,例如,蓝牙键盘要求用户在配对时输入PIN码。

        // ConfirmPinMatch: Self(8u32)
        // 描述:设备显示一个PIN码,用户需要在另一设备上确认这个PIN码是否匹配。
        // 使用场景:适用于需要用户确认两个设备上的PIN码匹配的场景,例如,智能手机和蓝牙耳机配对时,两个设备都显示相同的PIN码,用户需要确认这两个PIN码匹配。

        // ProvidePasswordCredential: Self(16u32)
        // 描述:设备要求用户提供密码或凭证以进行配对。
        // 使用场景:适用于需要更高安全性配对的设备,例如,要求用户提供Wi-Fi密码或其他形式的凭证。

        // ProvideAddress: Self(32u32)
        // 描述:设备要求用户提供地址信息以进行配对。
        // 使用场景:这种配对方式比较少见,适用于需要用户输入或确认设备地址信息的场景。

        let pairing_kinds_supported = DevicePairingKinds::None
            | DevicePairingKinds::ConfirmOnly
            | DevicePairingKinds::DisplayPin
            | DevicePairingKinds::ProvidePin
            | DevicePairingKinds::ConfirmPinMatch
            | DevicePairingKinds::ProvidePasswordCredential
            | DevicePairingKinds::ProvideAddress;

        // 处理配对请求事件
        let pairing_requested_token = custom_pairing.PairingRequested(&TypedEventHandler::new(
            move |_sender, args: Ref<'_, DevicePairingRequestedEventArgs>| {
                let args = args.unwrap();
                // pairing_kinds_supported = args.PairingKind()?;
                args.Accept()?;

                println!(">>>>>>>> kind: {:?}", pairing_kinds_supported);
                Ok(())
            }
        )).ok().unwrap();

        println!("======= kind: {:?}, level: {:?}", pairing_kinds_supported, protection_level);

        // 开始配对
        let pairing_result_operation: IAsyncOperation<DevicePairingResult> = custom_pairing.PairWithProtectionLevelAsync(pairing_kinds_supported, protection_level).unwrap();
        let _pairing_result: DevicePairingResult = pairing_result_operation.get().unwrap();
        // 移除事件处理器
        custom_pairing.RemovePairingRequested(pairing_requested_token).unwrap();
        // info!("pair res: {}", pairing_result.Status().ok().unwrap().0);
        let device_info: DeviceInformation = DeviceInformation::CreateFromIdAsync(&id).unwrap().get().unwrap();
        let pairing_info: DeviceInformationPairing = device_info.Pairing().unwrap();
        if pairing_info.IsPaired().unwrap() {
            break;
        } else {
            info!("sleep");
            sleep(Duration::from_secs(5));
        }
        info!("****pair state: {}", pairing_info.IsPaired().ok().unwrap());
    }
}
///获取已连接设备
pub fn connected_device() -> Result<Vec<String>, ()> {

    // 创建查询条件,筛选出已连接的蓝牙设备
    let aqs_filter = match BluetoothLEDevice::GetDeviceSelectorFromConnectionStatus(BluetoothConnectionStatus::Connected) {
        Ok(e) => {
            e
        }
        Err(_) => {
            return Err(());
        }
    };

    // 获取所有已连接的蓝牙设备信息
    let device_info_collection = 
        match DeviceInformation::FindAllAsyncWithKindAqsFilterAndAdditionalProperties(
            &aqs_filter, None, DeviceInformationKind::AssociationEndpoint) {
        Ok(e) => {
            e
        }
        Err(_) => {
            return Err(());
        }
    };
    
    // 取出蓝牙设备信息集合
    let devices_list = match device_info_collection.get() {
        Ok(e) => {
            e
        }
        Err(_) => {
            return Err(());
        }
    };

    let mut device_ids = Vec::new();

    // 遍历每个设备信息,获取设备 UUID,push到vec中
    for device_info in devices_list {
        if let Ok(device_id) = device_info.Id() {
            device_ids.push(device_id.to_string().split("-").last().unwrap().to_string());
        }
    }
    
    Ok(device_ids)
}
/// 取消配对
pub fn unpair(id: HSTRING) {
    loop {
        // 获取蓝牙设备信息
        let device_info: DeviceInformation = DeviceInformation::CreateFromIdAsync(&id).unwrap().get().unwrap();
        let pairing_info: DeviceInformationPairing = device_info.Pairing().unwrap();
        info!("before unpair state: {}", pairing_info.IsPaired().ok().unwrap());
        // 如果设备没有配对就直接退出
        if !pairing_info.IsPaired().unwrap() {
            break;
        }

        // 取消配对
        let _unpair_res = pairing_info.UnpairAsync().unwrap().get().ok().unwrap();

        // 解除配对后再次检查该设配的配对状态
        let device_info: DeviceInformation = DeviceInformation::CreateFromIdAsync(&id).unwrap().get().unwrap();
        let pairing_info: DeviceInformationPairing = device_info.Pairing().unwrap();
        info!("after unpair state: {}", pairing_info.IsPaired().ok().unwrap());

        // 配对状态为false就退出
        if !pairing_info.IsPaired().unwrap() {
            break;
        } else {
            info!("sleep");
            sleep(Duration::from_secs(5));
        }

        info!("****pair state: {}", pairing_info.IsPaired().ok().unwrap());
    }
}


/// 用于订阅蓝牙 GATT 特性的通知并将通知数据通过异步流 (Stream) 传递给调用者
/// 该方法接收一个 GattCharacteristic 对象并返回一个实现 Stream 的对象,该对象会产生包含特性值变化通知数据的 Vec<u8>
pub fn subscribe(characteristic: &GattCharacteristic) -> Result<impl Stream<Item=Result<Vec<u8>, Error>> + Send + Unpin + '_, Error> {
    let (mut sender, receiver) = futures_channel::mpsc::channel(16);
    // 为 ValueChanged 事件添加处理器。
    let token = characteristic.ValueChanged(&TypedEventHandler::new(
        // move |_characteristic, event_args: &Option<GattValueChangedEventArgs>| {
        move |_characteristic, event_args: Ref<'_, GattValueChangedEventArgs>| {
            let event_args = event_args
                .as_ref()
                .expect("GattValueChangedEventArgs was null in ValueChanged handler");

            // 定义 get_value 函数,从 event_args 中提取 CharacteristicValue 并读取数据到 Vec<u8>
            fn get_value(event_args: &GattValueChangedEventArgs) -> Result<Vec<u8>, Error> {
                let buf = event_args.CharacteristicValue()?;
                let len = buf.Length()?;
                let mut data: Vec<u8> = vec![0; len as usize];
                let reader = DataReader::FromBuffer(&buf)?;
                reader.ReadBytes(data.as_mut_slice())?;
                Ok(data)
            }

            // 尝试通过异步通道发送提取的数据
            if let Err(err) = sender.try_send(get_value(event_args)) {
                error!("Error sending characteristic value changed notification: {:?}", err);
            }

            Ok(())
        },
    ));

    // 使用 defer 宏在作用域结束时移除 ValueChanged 事件处理器。
    let guard = defer(move || {
        if let Err(err) = characteristic.RemoveValueChanged(token.unwrap()) {
            warn!("Error removing value change event handler: {:?}", err);
        }
    });

    // 写入客户端特性配置描述符以启用通知
    // 允许客户端设备通过写入 CCCD 来启用或禁用特性的通知或指示功能。CCCD 是蓝牙低功耗(BLE)规范中的一个重要部分,允许客户端设备控制特性的通知或指示行为。
    let res = characteristic
        .WriteClientCharacteristicConfigurationDescriptorWithResultAsync(GattClientCharacteristicConfigurationDescriptorValue::Notify)?.get()?;
    // 检查通信状态以确保操作成功。
    check_communication_status(res.Status()?)?;

    // 使用 defer 宏在作用域结束时禁用特性通知
    let guard = defer(move || {
        let _guard = guard;
        // 写入客户端特性配置描述符以禁用通知
        let res = characteristic
            .WriteClientCharacteristicConfigurationDescriptorWithResultAsync(
                GattClientCharacteristicConfigurationDescriptorValue::Notify,
            )
            .and_then(|op| {
                // 设置完成处理器以检查禁用操作的结果
                op.SetCompleted(&AsyncOperationCompletedHandler::new(move |op, _status| {
                    fn check_status(res: Result<GattWriteResult, Error>) -> Result<(), Error> {
                        let res = res?;
                        check_communication_status(
                            res.Status()?,
                        )
                    }

                    if let Err(err) = check_status(op.as_ref().unwrap().GetResults()) {
                        warn!("Error disabling characteristic notifications {:?}", err);
                    }

                    Ok(())
                }))
            });

        if let Err(err) = res {
            warn!("Error disabling characteristic notifications: {:?}", err);
        }
    });

    // 返回通过 map 方法转换后的 receiver 流。
    // map 方法确保 guard 在流处理期间保持作用域,以确保通知配置在需要时被正确禁用。
    Ok(receiver.map(move |x| {
        let _guard = &guard;
        x
    }))
}

struct CommunicationError(GattCommunicationStatus);

impl std::fmt::Debug for CommunicationError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "CommunicationError({})", self)
    }
}

impl std::fmt::Display for CommunicationError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let str = match self.0 {
            GattCommunicationStatus::Success => "success",
            GattCommunicationStatus::AccessDenied => "access denied",
            GattCommunicationStatus::Unreachable => "unreachable",
            GattCommunicationStatus::ProtocolError => "protocol error",
            _ => return write!(f, "unknown ({})", self.0.0),
        };
        f.write_str(str)
    }
}


pub(super) fn check_communication_status(
    status: GattCommunicationStatus,
) -> Result<(), Error> {
    match status {
        GattCommunicationStatus::Success => Ok(()),
        GattCommunicationStatus::Unreachable => Err(Error::new(windows::core::HRESULT(0x8007048Fu32 as i32), "Device is unreachable")), // HRESULT for ERROR_DEVICE_NOT_CONNECTED
        GattCommunicationStatus::ProtocolError => Err(Error::new(windows::core::HRESULT(0x8007044Du32 as i32), "Protocol error occurred")), // HRESULT for ERROR_PROTOCOL
        GattCommunicationStatus::AccessDenied => Err(Error::new(windows::core::HRESULT(0x80070005u32 as i32), "Access denied")), // HRESULT for E_ACCESSDENIED
        _ => Err(Error::new(windows::core::HRESULT(0x80004005u32 as i32), "Unhandled communication status")), // HRESULT for E_FAIL
    }
}
pub struct ScopeGuard<F: FnOnce()> {
    dropfn: ManuallyDrop<F>,
}

impl<F: FnOnce()> Drop for ScopeGuard<F> {
    fn drop(&mut self) {
        // SAFETY: This is OK because `dropfn` is `ManuallyDrop` which will not be dropped by the compiler.
        let dropfn = unsafe { ManuallyDrop::take(&mut self.dropfn) };
        dropfn();
    }
}

pub fn defer<F: FnOnce()>(dropfn: F) -> ScopeGuard<F> {
    ScopeGuard {
        dropfn: ManuallyDrop::new(dropfn),
    }
}