562 lines
22 KiB
C#
562 lines
22 KiB
C#
using Assets.Scripts.Ble.Scan;
|
|
using Assets.Scripts.Ble.Win;
|
|
using Assets.Scripts.Devices.Ant;
|
|
using Assets.Scripts.Devices.Ble;
|
|
using Assets.Scripts.Devices.Ble.Interfaces;
|
|
using Assets.Scripts.Devices.Ble.Win;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
|
|
namespace Assets.Scripts.Ble
|
|
{
|
|
public sealed class BleMobileInterface: IBleWinHwInterface
|
|
{
|
|
private static BleMobileInterface hwInterface;
|
|
private BleMobileThread bleMobileThread;
|
|
|
|
private Dictionary<string, BleAdvertisementInfo> _pCache;
|
|
public Dictionary<string, BleAdvertisementInfo> pCache
|
|
{
|
|
get
|
|
{
|
|
if (_pCache == null)
|
|
{
|
|
_pCache = new Dictionary<string, BleAdvertisementInfo>();
|
|
}
|
|
return _pCache;
|
|
}
|
|
set { _pCache = value; }
|
|
}
|
|
private Action<BleAdvertisementInfo> _discoveredCallback;
|
|
|
|
private Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse>> callbacks = new Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse>>();
|
|
private Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse<List<BleServiceInfo>>>> servicesCallbacks = new Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse<List<BleServiceInfo>>>>();
|
|
//private Dictionary<BlePeripheralInfo, Action<BleWinHwInterface, BleServiceInfo, BleResponse<List<BleCharacteristicInfo>>>> characteristicsCallbacks = new Dictionary<BlePeripheralInfo, Action<BleWinHwInterface, BleServiceInfo, BleResponse<List<BleCharacteristicInfo>>>>();
|
|
private Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BleCharacteristicInfo, BleResponse>> characteristicNotificationCallbacks = new Dictionary<BlePeripheralInfo, Action<IBleWinHwInterface, BleCharacteristicInfo, BleResponse>>();
|
|
private Dictionary<BleCharacteristicInfo, CharacteristicReadCallback> characteristicReadCallbacks = new Dictionary<BleCharacteristicInfo, CharacteristicReadCallback>();
|
|
private Dictionary<BleServiceInfo, CharacteristicsDiscoveredCallback> characteristicsDiscoveredCallbacks = new Dictionary<BleServiceInfo, CharacteristicsDiscoveredCallback>();
|
|
|
|
private Dictionary<BlePeripheralInfo, Action> disconnectedCallback = new Dictionary<BlePeripheralInfo, Action>();
|
|
|
|
private CharacteristicReadCallback characteristicReadEvent;
|
|
public event CharacteristicReadCallback CharacteristicReadEvent
|
|
{
|
|
add
|
|
{
|
|
this.characteristicReadEvent += value;
|
|
}
|
|
remove
|
|
{
|
|
this.characteristicReadEvent -= value;
|
|
}
|
|
}
|
|
|
|
|
|
private BluetoothStateChangedCallback bluetoothStateChanged;
|
|
public event BluetoothStateChangedCallback BluetoothStateChangedEvent
|
|
{
|
|
add
|
|
{
|
|
this.bluetoothStateChanged += value;
|
|
}
|
|
remove
|
|
{
|
|
this.bluetoothStateChanged -= value;
|
|
}
|
|
}
|
|
|
|
private BleState nativeState;
|
|
public BleState BleState
|
|
{
|
|
get
|
|
{
|
|
return this.nativeState;
|
|
}
|
|
set
|
|
{
|
|
if(this.nativeState != value)
|
|
{
|
|
this.nativeState = value;
|
|
this.bluetoothStateChanged?.Invoke(this, this.nativeState);
|
|
}
|
|
}
|
|
}
|
|
|
|
private PeripheralDisconnectedCallback peripheralDisconnectedEvent;
|
|
public event PeripheralDisconnectedCallback PeripheralDisconnectedEvent
|
|
{
|
|
add
|
|
{
|
|
this.peripheralDisconnectedEvent += value;
|
|
}
|
|
remove
|
|
{
|
|
this.peripheralDisconnectedEvent -= value;
|
|
}
|
|
}
|
|
|
|
private BleMobileInterface()
|
|
{
|
|
bleMobileThread = new BleMobileThread();
|
|
bleMobileThread.ScanInfoReceived += WatcherScanInfoReceived;
|
|
}
|
|
|
|
private void WatcherScanInfoReceived(BleMobileThread sender, string address, string name, int rssi,string type)
|
|
{
|
|
//if (address != 224160707349234)
|
|
//{
|
|
// return;
|
|
//}
|
|
|
|
SensorType sensor = SensorType.None;
|
|
List<Guid> services = new List<Guid>();
|
|
if (type.Equals("trainer"))
|
|
{
|
|
sensor = SensorType.Trainer;
|
|
}
|
|
else
|
|
{
|
|
sensor = SensorType.HeartRate;
|
|
}
|
|
//if (service != null)
|
|
//{
|
|
// services = new List<Guid> { service.Value };
|
|
// foreach (var item in ServiceUuids.Services)
|
|
// {
|
|
// if (item.IdGuid != service.Value)
|
|
// {
|
|
// continue;
|
|
// }
|
|
// if (item.IdByteArray == ServiceUuids.Ftms)
|
|
// {
|
|
// sensor = SensorType.Trainer;
|
|
// }
|
|
// else if (item.IdByteArray == ServiceUuids.HeartRate)
|
|
// {
|
|
// sensor = SensorType.HeartRate;
|
|
// }
|
|
// else if (item.IdByteArray == ServiceUuids.CyclingPower)
|
|
// {
|
|
// sensor = SensorType.Power;
|
|
// //sensor = SensorType.Trainer;
|
|
// }
|
|
// else if (item.IdByteArray == ServiceUuids.CyclingSpeedCadence)
|
|
// {
|
|
// sensor = SensorType.SpeedCadence;
|
|
// }
|
|
// else if (item.IdByteArray == ServiceUuids.TacxBle)
|
|
// {
|
|
// sensor = SensorType.Trainer;
|
|
// }
|
|
// }
|
|
//};
|
|
|
|
var addressStr = address;
|
|
if (!pCache.ContainsKey(addressStr))
|
|
{
|
|
var device = new BleAdvertisementInfo(new WinBlePeripheralInfo(addressStr, name), rssi, true, services, null, sensor);
|
|
pCache.Add(addressStr, device);
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(name))
|
|
{
|
|
(pCache[addressStr].Peripheral as WinBlePeripheralInfo).SetName(name);
|
|
}
|
|
if (sensor == SensorType.None)
|
|
{
|
|
return;
|
|
}
|
|
pCache[addressStr].SensorType = sensor;
|
|
pCache[addressStr].Rssi = rssi;
|
|
//Debug.Log(sensor);
|
|
//pCache[address.ToString()].SensorType = sensor;
|
|
|
|
//foreach (var item in services)
|
|
//{
|
|
// pCache[addressStr].TryAddService(item);
|
|
//}
|
|
|
|
pCache[addressStr].Index++;
|
|
if (pCache[addressStr].SensorType == SensorType.Power && pCache[addressStr].Services.Any(s => s.Equals(ServiceUuids.Get(ServiceUuids.TacxBle).IdGuid)))
|
|
{
|
|
pCache[addressStr].SensorType = SensorType.Trainer;
|
|
//Debug.Log("纠正为trainer, "+ pCache[address.ToString()].Index);
|
|
}
|
|
|
|
|
|
if (pCache[addressStr].SensorType == SensorType.Power)
|
|
{
|
|
if (pCache[addressStr].Index > 4)
|
|
{
|
|
_discoveredCallback?.Invoke(pCache[addressStr]);
|
|
}
|
|
}
|
|
else if (pCache[addressStr].SensorType != SensorType.None)
|
|
{
|
|
_discoveredCallback?.Invoke(pCache[addressStr]);
|
|
}
|
|
this.BleState = BleState.On;
|
|
}
|
|
|
|
//private WclBleGattThread SetUpGattClient(BlePeripheralInfo peripheral)
|
|
//{
|
|
// WclBleGattThread wclBleGattThread = this.wclBleMainThread.CreateGattThread(peripheral);
|
|
// wclBleGattThread.GattConnected += this.GattConnected;
|
|
// wclBleGattThread.GattDisconnected += this.GattDisconnected;
|
|
// wclBleGattThread.GattServicesDiscovered += this.GattServicesDiscovered;
|
|
// wclBleGattThread.GattCharacteristicsDiscovered += this.GattCharacteristicsDiscovered;
|
|
// wclBleGattThread.GattCharacteristicSubscribed += this.GattCharacteristicSubscribed;
|
|
// wclBleGattThread.GattCharacteristicRead += this.GattCharacteristicRead;
|
|
// wclBleGattThread.GattCharacteristicWrote += this.GattCharacteristicWrote;
|
|
// wclBleGattThread.GattCharacteristicChanged += this.GattCharacteristicChanged;
|
|
// wclBleGattThread.Start();
|
|
// return wclBleGattThread;
|
|
//}
|
|
|
|
List<BleServiceInfo> servicelist = new List<BleServiceInfo>();
|
|
List<BleCharacteristicInfo> characteristilist = new List<BleCharacteristicInfo>();
|
|
public void ConnectPeripheral(BlePeripheralInfo info, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse> callback)
|
|
{
|
|
//this.callbacks.Add(info, callback);
|
|
//WclBleGattThread wclBleGattThread = this.wclBleMainThread.GetGattThread(info);
|
|
|
|
//if (wclBleGattThread == null)
|
|
//{
|
|
|
|
// wclBleGattThread = this.SetUpGattClient(info);
|
|
// this.ConnectInternal(wclBleGattThread);
|
|
// return;
|
|
//}
|
|
//else
|
|
//{
|
|
// this.ConnectInternal(wclBleGattThread);
|
|
//}\
|
|
|
|
BleResponse s = new BleResponse();
|
|
s.IsSuccess = true;
|
|
s.Error = null;
|
|
var self = this;
|
|
BluetoothLEHardwareInterface.ConnectToPeripheral(info.Address, (address) =>
|
|
{
|
|
callback?.Invoke(self, info, s);
|
|
}, (address, service) => {
|
|
var l = servicelist.Where(c => c.Id.ToString().Equals(service)).ToList();
|
|
if (l.Count == 0)
|
|
{
|
|
servicelist.Add(new WinBleServiceInfo(info,new Guid(service)));
|
|
}
|
|
}, (address, service, characteristic) =>
|
|
{
|
|
var l = characteristilist.Where(c => c.Id.ToString().Equals(characteristic)).ToList();
|
|
if (l.Count == 0)
|
|
{
|
|
//characteristilist.Add(new BleCharacteristicInfo new WinBleServiceInfo(info, new Guid(characteristic)));
|
|
}
|
|
|
|
}, null);
|
|
}
|
|
|
|
private void ConnectInternal(WclBleGattThread gattClient)
|
|
{
|
|
//Task.Run(() =>
|
|
//{
|
|
//int num = gattClient.Connect();
|
|
//Debug.Log("连接设备返回" + num);
|
|
|
|
|
|
//});
|
|
}
|
|
|
|
public void DisconnectPeripheral(BlePeripheralInfo peripheral, Action callback)
|
|
{
|
|
//var gattThread = this.wclBleMainThread.GetGattThread(peripheral);
|
|
//if(gattThread != null && gattThread.CanLoadWork)
|
|
//{
|
|
// this.callbacks.Remove(peripheral);
|
|
// this.servicesCallbacks.Remove(peripheral);
|
|
// this.characteristicNotificationCallbacks.Remove(peripheral);
|
|
|
|
// this.disconnectedCallback.Add(peripheral, callback);
|
|
// gattThread.Discounect();
|
|
//}
|
|
}
|
|
|
|
|
|
public static BleMobileInterface GetInterface()
|
|
{
|
|
if(hwInterface == null)
|
|
{
|
|
hwInterface = new BleMobileInterface();
|
|
}
|
|
|
|
return hwInterface;
|
|
}
|
|
|
|
public void StartScan(Action<BleAdvertisementInfo> discoveredCallBack)
|
|
{
|
|
pCache.Clear();
|
|
_discoveredCallback = discoveredCallBack;
|
|
bleMobileThread.StartWatcher();
|
|
}
|
|
|
|
private void ManagerStatusChanged(WclBleMainThread sender, WclBleManagerStatus status)
|
|
{
|
|
//this.BleState = BleMobileInterface.StateFromNativeState(status);
|
|
//Debug.Log("win hw:" + status);
|
|
|
|
}
|
|
|
|
private void GattConnected(WclBleGattThread gattClient, BleResponse response)
|
|
{
|
|
//Debug.Log($"gatt connected { response.ToString() }");
|
|
//if (!response.IsSuccess)
|
|
//{
|
|
// gattClient.Stop();
|
|
|
|
// this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
|
|
// this.callbacks.Remove(gattClient.Peripheral);
|
|
// return;
|
|
//}
|
|
//this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
|
|
//this.callbacks.Remove(gattClient.Peripheral);
|
|
}
|
|
|
|
private void CleanUpPeripheral(BlePeripheralInfo peripheralInfo)
|
|
{
|
|
//this.callbacks.Clear()
|
|
}
|
|
|
|
private void GattDisconnected(WclBleGattThread gattClient, BleResponse response)
|
|
{
|
|
//Debug.Log($"gatt disconnected { gattClient.Peripheral.Name }");
|
|
|
|
//this.callbacks.Remove(gattClient.Peripheral);
|
|
//this.servicesCallbacks.Remove(gattClient.Peripheral);
|
|
//this.characteristicNotificationCallbacks.Remove(gattClient.Peripheral);
|
|
////App.MainDeviceAdapter.PrintStatus();
|
|
|
|
//var manualDisconnect = disconnectedCallback.ContainsKey(gattClient.Peripheral);
|
|
//this.peripheralDisconnectedEvent(this, gattClient.Peripheral, response, manualDisconnect);
|
|
|
|
////App.MainDeviceAdapter.PrintStatus();
|
|
//if (disconnectedCallback.ContainsKey(gattClient.Peripheral))
|
|
//{
|
|
// disconnectedCallback[gattClient.Peripheral].Invoke();
|
|
// disconnectedCallback.Remove(gattClient.Peripheral);
|
|
//}
|
|
////this.pCache.Remove(gattClient.Peripheral.Address);
|
|
|
|
|
|
|
|
}
|
|
private void GattServicesDiscovered(WclBleGattThread gattClient, BleResponse<List<BleServiceInfo>> response)
|
|
{
|
|
////Debug.Log("services discovered");
|
|
////this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
|
|
|
|
////foreach (var item in response.Data)
|
|
////{
|
|
//// Debug.Log(item.ToString());
|
|
////}
|
|
|
|
//if (this.servicesCallbacks.ContainsKey(gattClient.Peripheral))
|
|
//{
|
|
// this.servicesCallbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
|
|
//}
|
|
}
|
|
|
|
private void GattCharacteristicsDiscovered(WclBleGattThread gattClient, BleServiceInfo service, BleResponse<List<BleCharacteristicInfo>> response)
|
|
{
|
|
//Debug.Log("characteristics discovered");
|
|
|
|
if (this.characteristicsDiscoveredCallbacks.ContainsKey(service))
|
|
{
|
|
this.characteristicsDiscoveredCallbacks[service].Invoke(this, service, response);
|
|
}
|
|
}
|
|
|
|
private void GattCharacteristicSubscribed(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse response)
|
|
{
|
|
////Debug.Log("characteristics subscribed");
|
|
//if (this.characteristicNotificationCallbacks.ContainsKey(gattClient.Peripheral))
|
|
//{
|
|
// this.characteristicNotificationCallbacks[gattClient.Peripheral].Invoke(this, characteristic, response);
|
|
//}
|
|
}
|
|
private void GattCharacteristicRead(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response)
|
|
{
|
|
//Debug.Log("characteristic read");
|
|
|
|
//if (this.characteristicReadCallbacks.ContainsKey(characteristic))
|
|
//{
|
|
// this.characteristicReadCallbacks[characteristic].Invoke(this, characteristic, response);
|
|
// this.characteristicReadCallbacks.Remove(characteristic);
|
|
//}
|
|
|
|
//this.characteristicReadEvent.Invoke(this, characteristic, response);
|
|
}
|
|
|
|
private void GattCharacteristicWrote(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<BleCharacteristicWriteType> response)
|
|
{
|
|
Debug.Log("characteristic wrote");
|
|
}
|
|
private void GattCharacteristicChanged(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response)
|
|
{
|
|
////Debug.Log("characteristic changed");
|
|
//if(this.wclBleMainThread.GetGattThread(characteristic.Peripheral) != null)
|
|
//{
|
|
// this.characteristicReadEvent.Invoke(this, characteristic, response);
|
|
//}
|
|
}
|
|
|
|
public void DiscoverServices(BlePeripheralInfo peripheral, Action<IBleWinHwInterface, BlePeripheralInfo, BleResponse<List<BleServiceInfo>>> callback)
|
|
{
|
|
this.servicesCallbacks.Add(peripheral, callback);
|
|
if (servicelist.Count > 0)
|
|
{
|
|
BleResponse<List<BleServiceInfo>> response = new BleResponse<List<BleServiceInfo>>
|
|
{
|
|
IsSuccess = true,
|
|
Error = null,
|
|
Data = (List<BleServiceInfo>)servicelist,
|
|
};
|
|
|
|
callback.Invoke(this, peripheral, response);
|
|
return;
|
|
}
|
|
}
|
|
|
|
public void DiscoverCharacteristic(BleServiceInfo service, CharacteristicsDiscoveredCallback callback)
|
|
{
|
|
//WclBleGattThread gattThread = this.wclBleMainThread.GetGattThread(service.Peripheral);
|
|
//if(gattThread == null)
|
|
//{
|
|
// return;
|
|
//}
|
|
//if (!this.characteristicsDiscoveredCallbacks.ContainsKey(service))
|
|
//{
|
|
// this.characteristicsDiscoveredCallbacks.Add(service, callback);
|
|
//}
|
|
//int num = gattThread.DiscoverCharacteristics(service);
|
|
//if (WclBleErrors.IsSuccessCode(num))
|
|
//{
|
|
// return;
|
|
//}
|
|
//BleResponse<List<BleCharacteristicInfo>> response = new BleResponse<List<BleCharacteristicInfo>>
|
|
//{
|
|
// IsSuccess = false,
|
|
// Error = new BleHwInterfaceError(new int?(num), "WclBleGattClientErrorDomain", string.Format("Error discovering characteristics - {0}", num))
|
|
//};
|
|
//this.GattCharacteristicsDiscovered(gattThread, service, response);
|
|
}
|
|
|
|
public void SubscribeCharacteristic(BleCharacteristicInfo characteristic, Action<IBleWinHwInterface, BleCharacteristicInfo, BleResponse> callback)
|
|
{
|
|
//WclBleGattThread gattThread = this.wclBleMainThread.GetGattThread(characteristic.Peripheral);
|
|
|
|
//this.characteristicNotificationCallbacks.Add(gattThread.Peripheral, callback);
|
|
//int num = gattThread.SubscribeCharacteristic(characteristic);
|
|
//if (WclBleErrors.IsSuccessCode(num))
|
|
//{
|
|
// return;
|
|
//}
|
|
//BleResponse<List<BleServiceInfo>> response = new BleResponse<List<BleServiceInfo>>
|
|
//{
|
|
// IsSuccess = false,
|
|
// Error = new BleHwInterfaceError(new int?(num), "WclBleGattClientErrorDomain", string.Format("Error subscribing characteristic - {0}", num))
|
|
//};
|
|
//this.GattCharacteristicSubscribed(gattThread, characteristic, response);
|
|
}
|
|
|
|
public void WriteCharacteristic(BleCharacteristicInfo characteristic, byte[] data)
|
|
{
|
|
//var gattThread = this.wclBleMainThread.GetGattThread(characteristic.Peripheral);
|
|
//if(gattThread == null)
|
|
//{
|
|
// return;
|
|
//}
|
|
|
|
//int num = gattThread.WriteCharacteristic(characteristic, data);
|
|
//if (WclBleErrors.IsSuccessCode(num))
|
|
//{
|
|
// Debug.Log("设置命令成功");
|
|
// return;
|
|
//}
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
{
|
|
//this.wclBleMainThread.ManagerStatusChanged -= ManagerStatusChanged;
|
|
//this.wclBleMainThread.ScanInfoReceived -= WatcherScanInfoReceived;
|
|
//this.wclBleMainThread.Stop();
|
|
//this.wclBleMainThread = null;
|
|
//hwInterface = null;
|
|
//pCache.Clear();
|
|
}
|
|
|
|
public void ReadCharacteristic(BleCharacteristicInfo characteristic, CharacteristicReadCallback callback)
|
|
{
|
|
//WclBleGattThread gattThread = this.wclBleMainThread.GetGattThread(characteristic.Peripheral);
|
|
//if(gattThread == null)
|
|
//{
|
|
// return;
|
|
//}
|
|
//this.characteristicReadCallbacks.Add(characteristic, callback);
|
|
//int num = gattThread.ReadCharacteristicValue(characteristic);
|
|
//if (WclBleErrors.IsSuccessCode(num))
|
|
//{
|
|
// return;
|
|
//}
|
|
}
|
|
|
|
private static BleState StateFromNativeState(WclBleManagerStatus status)
|
|
{
|
|
switch (status)
|
|
{
|
|
case WclBleManagerStatus.RadioOff:
|
|
return BleState.Off;
|
|
case WclBleManagerStatus.RadioOn:
|
|
return BleState.On;
|
|
case WclBleManagerStatus.Unknown:
|
|
return BleState.Unknown;
|
|
default:
|
|
return BleState.Unavailable;
|
|
}
|
|
}
|
|
|
|
private class WinBlePeripheralInfo : BlePeripheralInfo
|
|
{
|
|
// Token: 0x06003F35 RID: 16181 RVA: 0x000E9FBF File Offset: 0x000E81BF
|
|
public WinBlePeripheralInfo(string address, string name) : base(address, name)
|
|
{
|
|
}
|
|
|
|
// Token: 0x06003F36 RID: 16182 RVA: 0x000E9FC9 File Offset: 0x000E81C9
|
|
public void SetName(string name)
|
|
{
|
|
base.Name = name;
|
|
}
|
|
}
|
|
|
|
private class WinBleServiceInfo : BleServiceInfo
|
|
{
|
|
// Token: 0x06003F86 RID: 16262 RVA: 0x000EA27F File Offset: 0x000E847F
|
|
public WinBleServiceInfo(BlePeripheralInfo peripheral, Guid id) : base(id, peripheral)
|
|
{
|
|
}
|
|
}
|
|
private class WinBleCharacteristicInfo : BleCharacteristicInfo
|
|
{
|
|
// Token: 0x06003F86 RID: 16262 RVA: 0x000EA27F File Offset: 0x000E847F
|
|
public WinBleCharacteristicInfo(Guid id, BleServiceInfo service, BleCharacteristicProperties properties) : base(id,service, properties)
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|