解决蓝牙卡顿问题

This commit is contained in:
suntao 2021-06-08 10:30:26 +08:00
parent 432e02e3de
commit aa75bb281f
14 changed files with 409 additions and 319 deletions

View File

@ -41,14 +41,14 @@ namespace Assets.Scripts.Devices.Ble
//base.Name = this.peripheralInfo.Name; //base.Name = this.peripheralInfo.Name;
//Debug.Log(base.Name + "," + sensor.ToString()); Debug.Log(base.Name + "," + sensor.ToString() + "," + this.Address);
Characteristics.Add(new BatteryLevel()); Characteristics.Add(new BatteryLevel());
Characteristics.Add(new ManufacturerNameCharacteristic()); Characteristics.Add(new ManufacturerNameCharacteristic());
Characteristics.Add(new ModelNumberCharacteristic()); Characteristics.Add(new ModelNumberCharacteristic());
} }
public void ConnectToPeripheralIfPossible() private void ConnectToPeripheralIfPossible()
{ {
if(this.peripheralInfo == null) if(this.peripheralInfo == null)
{ {
@ -61,28 +61,39 @@ namespace Assets.Scripts.Devices.Ble
this.State = DeviceState.Connecting; this.State = DeviceState.Connecting;
try try
{ {
Debug.Log("连接设备");
this.hwInterface.ConnectPeripheral(this.peripheralInfo, PeripheralConnectedAction); this.hwInterface.ConnectPeripheral(this.peripheralInfo, PeripheralConnectedAction);
} }
catch (Exception) catch (Exception ex)
{ {
Debug.LogError(ex);
this.State = DeviceState.Disconnected; this.State = DeviceState.Disconnected;
} }
} }
private void PeripheralConnectedAction(BleWinHwInterface hwInterface, BlePeripheralInfo sender, BleResponse response) private void PeripheralConnectedAction(BleWinHwInterface hwInterface, BlePeripheralInfo sender, BleResponse response)
{ {
Debug.Log($"连接{ this.Name }"+response.IsSuccess);
if (response.IsSuccess) if (response.IsSuccess)
{ {
State = DeviceState.Connected; State = DeviceState.Connected;
Debug.Log("连接成功"); //Debug.Log("连接成功"+this.Name);
hwInterface.DiscoverServices(this.peripheralInfo, ServicesDiscoveredAction);//, this.ServicesDiscoveredAction); hwInterface.DiscoverServices(this.peripheralInfo, ServicesDiscoveredAction);//, this.ServicesDiscoveredAction);
return;
} }
this.State = DeviceState.Disconnected;
} }
private void ServicesDiscoveredAction(BleWinHwInterface hwInterface, BlePeripheralInfo sender, BleResponse<List<BleServiceInfo>> response) private void ServicesDiscoveredAction(BleWinHwInterface hwInterface, BlePeripheralInfo sender, BleResponse<List<BleServiceInfo>> response)
{ {
//Debug.Log("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh"); //Debug.Log("搜索service");
if(!response.IsSuccess || !response.Data.Any())
{
this.Disconnect();
return;
}
this.CreateServices(response.Data); this.CreateServices(response.Data);
} }
@ -263,5 +274,18 @@ namespace Assets.Scripts.Devices.Ble
//this.hwInterface.DisconnectPeripheral(this.peripheralInfo, null); //this.hwInterface.DisconnectPeripheral(this.peripheralInfo, null);
this.Disconnect(); this.Disconnect();
} }
public void Dispose()
{
if(this.State == DeviceState.Connected)
{
this.Disconnect();
}
this.services.Clear();
this.pendingServices.Clear();
this.Characteristics.Clear();
this.hwInterface.BluetoothStateChangedEvent -= BluetoothStateChangedEvent;
}
} }
} }

View File

@ -1,6 +1,7 @@
using Assets.Scripts.Ble; using Assets.Scripts.Ble;
using Assets.Scripts.Ble.Service; using Assets.Scripts.Ble.Service;
using Assets.Scripts.Devices.Ble.Devices; using Assets.Scripts.Devices.Ble.Devices;
using Assets.Scripts.UI.Prefab.Device;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -72,7 +73,24 @@ namespace Assets.Scripts.Devices.Ble
var device1 = new SpeedCadence(device.Peripheral, hwInterface); var device1 = new SpeedCadence(device.Peripheral, hwInterface);
discoveredDevices.Add(device.Peripheral.Address, device1); discoveredDevices.Add(device.Peripheral.Address, device1);
} }
else
{
return;
}
var device111 = discoveredDevices.Last().Value;
if (device111 != null && device111.State == Ant.DeviceState.Disconnected)
{
if (DeviceCache.Exist(device111))
{
//TODO:取消注释,自动连接设备
//Debug.Log("自动连接" + device111.Id);
//device111.Connect();
}
}
//discoveredDevices.Add(device.Peripheral.Address, new BleDevice(device.Peripheral, hwInterface, device.SensorType)); //discoveredDevices.Add(device.Peripheral.Address, new BleDevice(device.Peripheral, hwInterface, device.SensorType));
} }
if (discoveredDevices.ContainsKey(device.Peripheral.Address)) if (discoveredDevices.ContainsKey(device.Peripheral.Address))
{ {
@ -89,8 +107,17 @@ namespace Assets.Scripts.Devices.Ble
public override void Dispose() public override void Dispose()
{ {
this.ReleaseDevices();
hwInterface.Dispose(); hwInterface.Dispose();
base.Dispose(); base.Dispose();
} }
public void ReleaseDevices()
{
foreach (var item in discoveredDevices)
{
item.Value.Dispose();
}
}
} }
} }

View File

@ -33,7 +33,6 @@ namespace Assets.Scripts.Devices.Ble.Devices
foreach (var service in this.Services) foreach (var service in this.Services)
{ {
//Debug.Log($"11111 "+ service.Id.ToString());
hwInterface.DiscoverCharacteristic(service, (hwInterface, service1, response) => hwInterface.DiscoverCharacteristic(service, (hwInterface, service1, response) =>
{ {
foreach (var character in response.Data) foreach (var character in response.Data)
@ -47,7 +46,7 @@ namespace Assets.Scripts.Devices.Ble.Devices
continue; continue;
} }
} }
foreach (var item in Characteristics.Where(c=>c.IsOptional)) foreach (var item in Characteristics.Where(c => c.IsOptional))
{ {
//Debug.Log(item.GetType() + "服务可用"+ item.Uuid.ToString() +", service:" + item.ServiceUuid); //Debug.Log(item.GetType() + "服务可用"+ item.Uuid.ToString() +", service:" + item.ServiceUuid);
var ccc = response.Data.FirstOrDefault(r => r.MatchGuid(item.Uuid)); var ccc = response.Data.FirstOrDefault(r => r.MatchGuid(item.Uuid));
@ -58,7 +57,7 @@ namespace Assets.Scripts.Devices.Ble.Devices
else else
{ {
Debug.Log(item.GetType() + "服务可用"); Debug.Log(item.GetType() + "服务可用");
GetBatteryLevel(ccc); GetBatteryLevel(ccc);
} }
} }

View File

@ -40,7 +40,7 @@ namespace Assets.Scripts.Ble.Scan
} }
public void TryAddService(Guid service) public void TryAddService(Guid service)
{ {
if (this.services.Contains(service)) if (this.services.Contains(service))
return; return;
this.services.Add(service); this.services.Add(service);

View File

@ -99,29 +99,14 @@ namespace Assets.Scripts.Ble
{ {
//if(address != 224160707349234) //if(address != 224160707349234)
//{ //{
//return; //return;
//} //}
if (service.HasValue) //Debug.Log($"address:{ address }, name:{ name }, service:{ (service == null ? "" : service.Value.ToString()) }");
{
//Debug.Log($"address:{ address }, name:{ name }, service:{ (service == null ? "" : service.Value.ToString()) }");
}
if (!string.IsNullOrWhiteSpace(name))
{
if (pCache.ContainsKey(address.ToString()))
{
(pCache[address.ToString()].Peripheral as WinBlePeripheralInfo).SetName(name);
}
}
//Debug.Log("service:" + service.ToString()+",name:" + name);
if (!service.HasValue || ServiceUuids.Services.Select(s => s.IdGuid).All(x => !x.Equals(service.Value)))
{
return;
}
SensorType sensor = SensorType.None; SensorType sensor = SensorType.None;
List<Guid> services = null; List<Guid> services = new List<Guid>();
if (service != null) if (service != null)
{ {
services = new List<Guid> { service.Value }; services = new List<Guid> { service.Value };
foreach(var item in ServiceUuids.Services) foreach(var item in ServiceUuids.Services)
{ {
@ -152,36 +137,51 @@ namespace Assets.Scripts.Ble
} }
} }
}; };
var addressStr = address.ToString("X12");
if (!pCache.ContainsKey(address.ToString())) if (!pCache.ContainsKey(addressStr))
{ {
var device = new BleAdvertisementInfo(new WinBlePeripheralInfo(address.ToString(), name), rssi, true, services, null, sensor); var device = new BleAdvertisementInfo(new WinBlePeripheralInfo(addressStr, name), rssi, true, services, null, sensor);
pCache.Add(address.ToString(), device); pCache.Add(addressStr, device);
WclBleGattThread gattClient = this.SetUpGattClient(device.Peripheral); //WclBleGattThread gattClient = this.SetUpGattClient(device.Peripheral);
//this.ConnectInternal(gattClient); //this.ConnectInternal(gattClient);
} }
else if (!string.IsNullOrWhiteSpace(name))
{ {
//Debug.Log(sensor); (pCache[addressStr].Peripheral as WinBlePeripheralInfo).SetName(name);
//pCache[address.ToString()].SensorType = sensor; }
if(sensor == SensorType.None)
{
return;
}
pCache[addressStr].SensorType = sensor;
//Debug.Log(sensor);
//pCache[address.ToString()].SensorType = sensor;
foreach (var item in services) foreach (var item in services)
{ {
pCache[address.ToString()].TryAddService(item); pCache[addressStr].TryAddService(item);
}
pCache[address.ToString()].Index++;
if(pCache[address.ToString()].SensorType == SensorType.Power && pCache[address.ToString()].Services.Any(s=> s.Equals(ServiceUuids.Get(ServiceUuids.TacxBle).IdGuid)))
{
pCache[address.ToString()].SensorType = SensorType.Trainer;
//Debug.Log("纠正为trainer, "+ pCache[address.ToString()].Index);
} }
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[address.ToString()].Index > 4 || pCache[address.ToString()].SensorType != SensorType.Power) {
if (pCache[addressStr].Index > 4)
{ {
_discoveredCallback?.Invoke(pCache[address.ToString()]); _discoveredCallback?.Invoke(pCache[addressStr]);
} }
} }
else if(pCache[addressStr].SensorType != SensorType.None)
{
_discoveredCallback?.Invoke(pCache[addressStr]);
}
} }
private WclBleGattThread SetUpGattClient(BlePeripheralInfo peripheral) private WclBleGattThread SetUpGattClient(BlePeripheralInfo peripheral)
@ -203,8 +203,10 @@ namespace Assets.Scripts.Ble
{ {
this.callbacks.Add(info, callback); this.callbacks.Add(info, callback);
WclBleGattThread wclBleGattThread = this.wclBleMainThread.GetGattThread(info); WclBleGattThread wclBleGattThread = this.wclBleMainThread.GetGattThread(info);
if(wclBleGattThread == null) if(wclBleGattThread == null)
{ {
wclBleGattThread = this.SetUpGattClient(info); wclBleGattThread = this.SetUpGattClient(info);
this.ConnectInternal(wclBleGattThread); this.ConnectInternal(wclBleGattThread);
return; return;
@ -259,7 +261,7 @@ namespace Assets.Scripts.Ble
private void ManagerStatusChanged(WclBleMainThread sender, WclBleManagerStatus status) private void ManagerStatusChanged(WclBleMainThread sender, WclBleManagerStatus status)
{ {
this.BleState = BleWinHwInterface.StateFromNativeState(status); this.BleState = BleWinHwInterface.StateFromNativeState(status);
Debug.Log("win hw:" + status); //Debug.Log("win hw:" + status);
} }
@ -272,6 +274,7 @@ namespace Assets.Scripts.Ble
return; return;
} }
this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response); this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
this.callbacks.Remove(gattClient.Peripheral);
} }
private void CleanUpPeripheral(BlePeripheralInfo peripheralInfo) private void CleanUpPeripheral(BlePeripheralInfo peripheralInfo)
@ -285,13 +288,13 @@ namespace Assets.Scripts.Ble
} }
private void GattServicesDiscovered(WclBleGattThread gattClient, BleResponse<List<BleServiceInfo>> response) private void GattServicesDiscovered(WclBleGattThread gattClient, BleResponse<List<BleServiceInfo>> response)
{ {
Debug.Log("services discovered"); //Debug.Log("services discovered");
//this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response); //this.callbacks[gattClient.Peripheral].Invoke(this, gattClient.Peripheral, response);
foreach (var item in response.Data) //foreach (var item in response.Data)
{ //{
Debug.Log(item.ToString()); // Debug.Log(item.ToString());
} //}
if (this.servicesCallbacks.ContainsKey(gattClient.Peripheral)) if (this.servicesCallbacks.ContainsKey(gattClient.Peripheral))
{ {
@ -311,7 +314,7 @@ namespace Assets.Scripts.Ble
private void GattCharacteristicSubscribed(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse response) private void GattCharacteristicSubscribed(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse response)
{ {
Debug.Log("characteristics subscribed"); //Debug.Log("characteristics subscribed");
if (this.characteristicNotificationCallbacks.ContainsKey(gattClient.Peripheral)) if (this.characteristicNotificationCallbacks.ContainsKey(gattClient.Peripheral))
{ {
this.characteristicNotificationCallbacks[gattClient.Peripheral].Invoke(this, characteristic, response); this.characteristicNotificationCallbacks[gattClient.Peripheral].Invoke(this, characteristic, response);
@ -428,6 +431,8 @@ namespace Assets.Scripts.Ble
public void Dispose() public void Dispose()
{ {
this.wclBleMainThread.ManagerStatusChanged -= ManagerStatusChanged;
this.wclBleMainThread.ScanInfoReceived -= WatcherScanInfoReceived;
this.wclBleMainThread.Stop(); this.wclBleMainThread.Stop();
this.wclBleMainThread = null; this.wclBleMainThread = null;
hwInterface = null; hwInterface = null;

View File

@ -218,6 +218,7 @@ namespace Assets.Scripts.Ble.Win
{ {
try try
{ {
Debug.Log("onconnected");
WclBleGattClient.GattConnectionChanged connected = this.Connected; WclBleGattClient.GattConnectionChanged connected = this.Connected;
if (connected != null) if (connected != null)
{ {

View File

@ -12,8 +12,8 @@ using UnityEngine;
namespace Assets.Scripts.Devices.Ble.Win namespace Assets.Scripts.Devices.Ble.Win
{ {
internal class WclBleGattThread internal class WclBleGattThread: WclBleThread
{ {
public delegate void GattCharacteristicChangedDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response); public delegate void GattCharacteristicChangedDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response);
public delegate void GattCharacteristicReadDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response); public delegate void GattCharacteristicReadDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<byte[]> response);
public delegate void GattCharacteristicsDiscoveredDelegate(WclBleGattThread gattClient, BleServiceInfo service, BleResponse<List<BleCharacteristicInfo>> response); public delegate void GattCharacteristicsDiscoveredDelegate(WclBleGattThread gattClient, BleServiceInfo service, BleResponse<List<BleCharacteristicInfo>> response);
@ -175,57 +175,7 @@ namespace Assets.Scripts.Devices.Ble.Win
this.Peripheral = bleDevice; this.Peripheral = bleDevice;
this.rPtr = radio; this.rPtr = radio;
_bleDevice = bleDevice; _bleDevice = bleDevice;
//this.address = long.Parse(_bleDevice.Address, System.Globalization.NumberStyles.HexNumber); this.address = long.Parse(_bleDevice.Address, System.Globalization.NumberStyles.HexNumber);
this.address = long.Parse(_bleDevice.Address);
}
public bool Start()
{
if (this.start)
{
return false;
}
this.start = true;
this.sEvent = new ManualResetEvent(false);
this.tEvent = new ManualResetEvent(false);
this.aEvent = new AutoResetEvent(false);
//thread = new Thread(new ThreadStart(ThreadProc));
// this.sEvent.Set();
// IntPtr[] handle = new IntPtr[]
// {
// this.tEvent.SafeWaitHandle.DangerousGetHandle(),
// this.aEvent.SafeWaitHandle.DangerousGetHandle()
// };
// while (WclAlertableWait.Wait(handle, 2U, WclAlertableWait.INFINITE) != WclAlertableWait.WAIT_OBJECT_0)
// {
// Action action;
// if (this.actions.TryDequeue(out action))
// {
// if (action != null)
// {
// Debug.Log("连接设备");
// action();
// }
// }
// }
// }));
//thread.Start();
//this.sEvent.WaitOne();
ThreadProc();
return true;
}
public void Stop()
{
Debug.Log("停止");
start = false;
thread?.Abort();
} }
private void ThreadProc() private void ThreadProc()
@ -238,28 +188,15 @@ namespace Assets.Scripts.Devices.Ble.Win
//this.InternalCleanUp(); //this.InternalCleanUp();
} }
private void CleanUpWorkerThread() protected override void CleanUpWorkerThread()
{ {
this.gatt.Disconnect(); this.gatt.Disconnect();
base.ProcessPendingAPCMessages();
this.gatt.Dispose(); this.gatt.Dispose();
this.gatt = null; this.gatt = null;
} }
private void InternalCleanUp()
{
this.sEvent.Close();
this.sEvent.Dispose();
this.sEvent = null;
this.aEvent.Close(); protected override void SetUpWorkerThread()
this.aEvent.Dispose();
this.aEvent = null;
this.tEvent.Close();
this.tEvent.Dispose();
this.tEvent = null;
}
private void SetUpWorkerThread()
{ {
this.gatt = new WclBleGattClient(this.address, this.rPtr) this.gatt = new WclBleGattClient(this.address, this.rPtr)
{ {
@ -302,7 +239,13 @@ namespace Assets.Scripts.Devices.Ble.Win
IsSuccess = true, IsSuccess = true,
Data = value Data = value
}; };
this.gattCharacteristicChanged?.Invoke(this, characteristic, response); if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicChanged?.Invoke(this, characteristic, response);
//});
}
} }
private void OnCharacteristicRead(BleCharacteristicInfo characteristic, int result, byte[] data) private void OnCharacteristicRead(BleCharacteristicInfo characteristic, int result, byte[] data)
@ -319,7 +262,13 @@ namespace Assets.Scripts.Devices.Ble.Win
{ {
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading value"); response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading value");
} }
this.gattCharacteristicRead.Invoke(this, characteristic, response); if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicRead.Invoke(this, characteristic, response);
//});
}
} }
private void OnCharacteristicsDiscovered(BleServiceInfo service, int result, GattCharacteristics characteristics) private void OnCharacteristicsDiscovered(BleServiceInfo service, int result, GattCharacteristics characteristics)
@ -336,18 +285,33 @@ namespace Assets.Scripts.Devices.Ble.Win
{ {
// response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services"); // response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services");
} }
this.gattCharacteristicsDiscovered(this, service, response);
if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicsDiscovered(this, service, response);
//});
}
} }
private void OnConnected(WclBleGattClient sender, int error) private void OnConnected(WclBleGattClient sender, int error)
{ {
BleResponse response = new BleResponse //Debug.Log("gatt thread onconnected");
{ if (base.IsTerminating)
IsSuccess = WclBleErrors.IsSuccessCode(error) {
}; return;
}
this.gattConnected?.Invoke(this, response); BleResponse response = new BleResponse
} {
IsSuccess = WclBleErrors.IsSuccessCode(error)
};
//Loom.QueueOnMainThread(() =>
//{
this.gattConnected?.Invoke(this, response);
//});
}
private void OnDisconnected(WclBleGattClient sender, int reason) private void OnDisconnected(WclBleGattClient sender, int reason)
{ {
@ -356,16 +320,29 @@ namespace Assets.Scripts.Devices.Ble.Win
IsSuccess = true, IsSuccess = true,
Error = new BleHwInterfaceError(new int?(reason), "WclBleGattClientErrorDomain", string.Format("GATT disconnect reason is - {0}", reason)) Error = new BleHwInterfaceError(new int?(reason), "WclBleGattClientErrorDomain", string.Format("GATT disconnect reason is - {0}", reason))
}; };
this.gattDisconnected?.Invoke(this, response); //Loom.QueueOnMainThread(() =>
//{
this.gattDisconnected?.Invoke(this, response);
//});
} }
public int Connect() public int Connect()
{ {
this.gatt.Connect(); if (!base.CanLoadWork)
//this.actions.Enqueue(() => {
//{ return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
// this.gatt.Connect();
//}); }
if(this.gatt.State != WclBleGattClientState.Disconnected)
{
return WclBleErrors.WCL_E_BLUETOOTH_CLIENT_CONNECTED;
}
base.ClearActionQueue();
base.EnqueueAction(() =>
{
this.gatt.Connect();
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
@ -378,9 +355,12 @@ namespace Assets.Scripts.Devices.Ble.Win
public int DiscoverServices() public int DiscoverServices()
{ {
GattServices services; base.EnqueueAction(() =>
int result = this.gatt.DiscoverServices(out services); {
this.OnServicesDiscovered(result, services); GattServices services;
int result = this.gatt.DiscoverServices(out services);
this.OnServicesDiscovered(result, services);
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
@ -398,8 +378,12 @@ namespace Assets.Scripts.Devices.Ble.Win
{ {
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services"); response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services");
} }
if (!base.IsTerminating) {
gattServicesDiscovered(this, response); //Loom.QueueOnMainThread(() =>
//{
gattServicesDiscovered(this, response);
//});
}
} }
private List<BleCharacteristicInfo> ProcessCharacteristics(BleServiceInfo service, GattCharacteristics characteristics) private List<BleCharacteristicInfo> ProcessCharacteristics(BleServiceInfo service, GattCharacteristics characteristics)
@ -431,10 +415,12 @@ namespace Assets.Scripts.Devices.Ble.Win
{ {
GattService ns = this.servicesMapping[service]; GattService ns = this.servicesMapping[service];
GattCharacteristics characteristics; base.EnqueueAction(() =>
int result = this.gatt.DiscoverCharacteristics(ns, out characteristics); {
this.OnCharacteristicsDiscovered(service, result, characteristics); GattCharacteristics characteristics;
int result = this.gatt.DiscoverCharacteristics(ns, out characteristics);
this.OnCharacteristicsDiscovered(service, result, characteristics);
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
@ -447,10 +433,12 @@ namespace Assets.Scripts.Devices.Ble.Win
} }
GattCharacteristic nCh = this.charMapping[characteristic]; GattCharacteristic nCh = this.charMapping[characteristic];
byte[] data; base.EnqueueAction(() =>
int result = this.gatt.ReadCharacteristicValue(nCh, out data); {
this.OnCharacteristicRead(characteristic, result, data); byte[] data;
int result = this.gatt.ReadCharacteristicValue(nCh, out data);
this.OnCharacteristicRead(characteristic, result, data);
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
@ -462,16 +450,17 @@ namespace Assets.Scripts.Devices.Ble.Win
} }
GattCharacteristic nCh = this.charMapping[characteristic]; GattCharacteristic nCh = this.charMapping[characteristic];
base.EnqueueAction(() =>
int result = this.gatt.SubscribeCharacteristic(nCh); {
this.OnCharacteristicsSubscribed(characteristic, nCh, result); int result = this.gatt.SubscribeCharacteristic(nCh);
this.OnCharacteristicsSubscribed(characteristic, nCh, result);
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
private void OnCharacteristicsSubscribed(BleCharacteristicInfo characteristic, GattCharacteristic nCharacteristic, int result) private void OnCharacteristicsSubscribed(BleCharacteristicInfo characteristic, GattCharacteristic nCharacteristic, int result)
{ {
Debug.Log("char subscribed"); //Debug.Log("char subscribed");
BleResponse response = new BleResponse BleResponse response = new BleResponse
{ {
IsSuccess = WclBleErrors.IsSuccessCode(result) IsSuccess = WclBleErrors.IsSuccessCode(result)
@ -484,7 +473,12 @@ namespace Assets.Scripts.Devices.Ble.Win
{ {
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when subscribing Characteristics"); response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when subscribing Characteristics");
} }
this.gattCharacteristicsSubscribed(this, characteristic, response); if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() => {
this.gattCharacteristicsSubscribed(this, characteristic, response);
//});
}
} }
public int WriteCharacteristic(BleCharacteristicInfo characteristicInfo, byte[] data) public int WriteCharacteristic(BleCharacteristicInfo characteristicInfo, byte[] data)
@ -494,14 +488,27 @@ namespace Assets.Scripts.Devices.Ble.Win
return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE; return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
} }
GattCharacteristic gCh = this.charMapping[characteristicInfo]; GattCharacteristic gCh = this.charMapping[characteristicInfo];
base.EnqueueAction(() =>
int result = this.gatt.WriteCharacteristic(gCh, data); {
int result = this.gatt.WriteCharacteristic(gCh, data);
this.OnCharactersisticsWrote(characteristicInfo, result);
});
return WclBleErrors.WCL_E_SUCCESS; return WclBleErrors.WCL_E_SUCCESS;
} }
private void OnCharactersisticsWrote(BleCharacteristicInfo characteristic, int result)
{
var response = new BleResponse<BleCharacteristicWriteType>
{
IsSuccess = WclBleErrors.IsSuccessCode(result),
Data = BleCharacteristicWriteType.WriteWithResponse
};
this.gattCharacteristicWrote?.Invoke(this, characteristic, response);
}
private class WinBleCharacteristicInfo : BleCharacteristicInfo private class WinBleCharacteristicInfo : BleCharacteristicInfo
{ {
// Token: 0x06003F85 RID: 16261 RVA: 0x000EA274 File Offset: 0x000E8474 // Token: 0x06003F85 RID: 16261 RVA: 0x000EA274 File Offset: 0x000E8474

View File

@ -11,7 +11,7 @@ using UnityEngine;
namespace Assets.Scripts.Devices.Ble.Win namespace Assets.Scripts.Devices.Ble.Win
{ {
internal class WclBleMainThread internal class WclBleMainThread: WclBleThread
{ {
internal delegate void ManagerStatusChangedCallback(WclBleMainThread thread, WclBleManagerStatus status); internal delegate void ManagerStatusChangedCallback(WclBleMainThread thread, WclBleManagerStatus status);
@ -34,24 +34,11 @@ namespace Assets.Scripts.Devices.Ble.Win
private readonly Dictionary<BlePeripheralInfo, WclBleGattThread> gattClients = new Dictionary<BlePeripheralInfo, WclBleGattThread>(); private readonly Dictionary<BlePeripheralInfo, WclBleGattThread> gattClients = new Dictionary<BlePeripheralInfo, WclBleGattThread>();
internal WclBleMainThread() internal WclBleMainThread()
{ {
WclAlertableWait.SetApcSync();
}
private Thread wThread;
public bool Start()
{
//this.wThread = new Thread(new ThreadStart(this.SetUpWorkerThread));
//this.wThread.Start();
//Task.Run(() =>
//{
// this.SetUpWorkerThread();
//});
SetUpWorkerThread();
return true;
} }
private void SetUpWorkerThread()
protected override void SetUpWorkerThread()
{ {
wclBleManager = new WclBleManager wclBleManager = new WclBleManager
{ {
@ -72,6 +59,28 @@ namespace Assets.Scripts.Devices.Ble.Win
//Debug.Log("bbb"); //Debug.Log("bbb");
} }
protected override void CleanUpWorkerThread()
{
this.wclWatcher.InfoPacketReceived = null;
this.wclWatcher.UuidPacketReceived = null;
if (this.wclWatcher.Active)
{
this.wclWatcher.StopScan();
}
//this.StopGattThreads();
if (this.wclBleManager.Active)
{
this.wclBleManager.ManagerStatusChanged = null;
this.wclBleManager.Close();
}
base.ProcessPendingAPCMessages();
this.wclWatcher.Dispose();
this.wclBleManager.Dispose();
this.wclBleManager = null;
this.wclWatcher = null;
}
private void OnManagerStatusChanged(WclBleManager manager, WclBleManagerStatus status) private void OnManagerStatusChanged(WclBleManager manager, WclBleManagerStatus status)
{ {
//Debug.Log(status); //Debug.Log(status);

View File

@ -62,11 +62,6 @@ namespace Assets.Scripts.Ble
// Token: 0x06002178 RID: 8568 RVA: 0x0008B1CD File Offset: 0x000893CD // Token: 0x06002178 RID: 8568 RVA: 0x0008B1CD File Offset: 0x000893CD
private void OnStatusChanges(IntPtr sender, WclBleManagerStatus status) private void OnStatusChanges(IntPtr sender, WclBleManagerStatus status)
{ {
//if (WclBleManager.Info)
//{
Debug.Log(string.Format("WCLBleManger state changed -> new state {0}", status));
//}
//System.IO.File.WriteAllText("d:/demo.log", status.ToString()); //System.IO.File.WriteAllText("d:/demo.log", status.ToString());
this.BleStatus = status; this.BleStatus = status;
} }

View File

@ -103,7 +103,10 @@ namespace Assets.Scripts.Ble
//{ //{
// WclBleWatcher.SafeInvoke(this.InfoPacketReceived, this, address, timestamp, rssi, name, packetType, flags); // WclBleWatcher.SafeInvoke(this.InfoPacketReceived, this, address, timestamp, rssi, name, packetType, flags);
//}.OnUIThreadAsync(); //}.OnUIThreadAsync();
this.InfoPacketReceived(this, address, timestamp, rssi, name, packetType, flags); Loom.QueueOnMainThread(() =>
{
this.InfoPacketReceived(this, address, timestamp, rssi, name, packetType, flags);
});
} }
// Token: 0x06002133 RID: 8499 RVA: 0x000895BC File Offset: 0x000877BC // Token: 0x06002133 RID: 8499 RVA: 0x000895BC File Offset: 0x000877BC
@ -115,7 +118,10 @@ namespace Assets.Scripts.Ble
// WclBleWatcher.SafeInvoke(this.UuidPacketReceived, this, address, timestamp, rssi, uuid); // WclBleWatcher.SafeInvoke(this.UuidPacketReceived, this, address, timestamp, rssi, uuid);
//}.OnUIThreadAsync(); //}.OnUIThreadAsync();
this.UuidPacketReceived(this, address, timestamp, rssi, uuid); Loom.QueueOnMainThread(() =>
{
this.UuidPacketReceived(this, address, timestamp, rssi, uuid);
});
} }
// Token: 0x06002134 RID: 8500 RVA: 0x000895F9 File Offset: 0x000877F9 // Token: 0x06002134 RID: 8500 RVA: 0x000895F9 File Offset: 0x000877F9

View File

@ -17,7 +17,7 @@ public class MainController : MonoBehaviour
Version = this.transform.Find("GameObject").Find("Version").GetComponent<Text>(); Version = this.transform.Find("GameObject").Find("Version").GetComponent<Text>();
Version.text = "V"+App.AppVersion; Version.text = "V"+App.AppVersion;
DeviceCache.Init(PFConstants.DeviceCacheFolder); DeviceCache.Init(PFConstants.DeviceCacheFolder);
Loom.Initialize();
//AntConnector.Instance((device2) => { //AntConnector.Instance((device2) => {
// if (device2.State == DeviceState.Disconnected) // if (device2.State == DeviceState.Disconnected)
// { // {

View File

@ -13,7 +13,7 @@ namespace Assets.Scripts.UI.Prefab.Device
{ {
public class DeviceCache public class DeviceCache
{ {
private static Dictionary<string, ushort> dict = null; private static Dictionary<string, string> dict = null;
private static string _dataPath; private static string _dataPath;
public static void Init(string dataPath) { public static void Init(string dataPath) {
if(dict != null) if(dict != null)
@ -24,23 +24,23 @@ namespace Assets.Scripts.UI.Prefab.Device
if(!System.IO.File.Exists(_dataPath + "/Devices.txt")) if(!System.IO.File.Exists(_dataPath + "/Devices.txt"))
{ {
dict = new Dictionary<string, ushort>(); dict = new Dictionary<string, string>();
return; return;
} }
//var str = PlayerPrefs.GetString("DeviceCache", ""); //var str = PlayerPrefs.GetString("DeviceCache", "");
var str = System.IO.File.ReadAllText(_dataPath + "/Devices.txt", Encoding.UTF8); var str = System.IO.File.ReadAllText(_dataPath + "/Devices.txt", Encoding.UTF8);
if (!string.IsNullOrWhiteSpace(str)) { if (!string.IsNullOrWhiteSpace(str)) {
dict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, ushort>>(str); dict = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(str);
} }
else { else {
dict = new Dictionary<string, ushort>(); dict = new Dictionary<string, string>();
} }
} }
public static void Add(AbstractDevice antDevice) public static void Add(AbstractDevice antDevice)
{ {
Debug.Log("添加设备" + antDevice.DeviceNumber); //Debug.Log("添加设备" + antDevice.DeviceNumber);
//new System.Collections.Concurrent.ConcurrentDictionary<string, string>().AddOrUpdate //new System.Collections.Concurrent.ConcurrentDictionary<string, string>().AddOrUpdate
//dict.AddOrUpdate(antDevice.Sensor.ToString(), antDevice.DeviceNumber, (key, oldValue)=> { //dict.AddOrUpdate(antDevice.Sensor.ToString(), antDevice.DeviceNumber, (key, oldValue)=> {
@ -49,16 +49,16 @@ namespace Assets.Scripts.UI.Prefab.Device
// return antDevice.DeviceNumber; // return antDevice.DeviceNumber;
//}); //});
dict[antDevice.Sensor.ToString()] = antDevice.DeviceNumber; dict[antDevice.Sensor.ToString()] = antDevice.Id;
Write(); Write();
} }
public static bool Exist(AbstractDevice antDevice) public static bool Exist(AbstractDevice antDevice)
{ {
ushort a; string a;
if(dict.TryGetValue(antDevice.Sensor.ToString(), out a)) if(dict.TryGetValue(antDevice.Sensor.ToString(), out a))
{ {
return a == antDevice.DeviceNumber; return a == antDevice.Id;
} }
return false; return false;
@ -72,7 +72,7 @@ namespace Assets.Scripts.UI.Prefab.Device
} }
if (dict.ContainsKey(antDevice.Sensor.ToString())) if (dict.ContainsKey(antDevice.Sensor.ToString()))
{ {
if(dict[antDevice.Sensor.ToString()] == antDevice.DeviceNumber) if(dict[antDevice.Sensor.ToString()] == antDevice.Id)
{ {
dict.Remove(antDevice.Sensor.ToString()); dict.Remove(antDevice.Sensor.ToString());
Write(); Write();

View File

@ -199,9 +199,13 @@ public class DeviceView : MonoBehaviour
// Update is called once per frame // Update is called once per frame
void Update() void Update()
{ {
//if(SensorType != SensorType.Trainer)
//{
// return;
//}
timer -= Time.deltaTime; timer -= Time.deltaTime;
if (timer <= 0) if (timer <= 0)
{ {
Main(); Main();
timer = 1.0f; timer = 1.0f;
@ -232,6 +236,8 @@ public class DeviceView : MonoBehaviour
mSearchButton.SetActive(false); mSearchButton.SetActive(false);
mPairButton.SetActive(true); mPairButton.SetActive(true);
logo.sprite = sprite1; logo.sprite = sprite1;
//App.MainDeviceAdapter.GetDevices().First(d => d.Sensor == SensorType).Connect();
} }
else else
{ {
@ -280,7 +286,9 @@ public class DeviceView : MonoBehaviour
{ {
powerValue.text = GetValue(connectedDevice); powerValue.text = GetValue(connectedDevice);
} }
} }
//Debug.Log(Newtonsoft.Json.JsonConvert.SerializeObject(App.MainDeviceAdapter.GetDevices().Where(d => d.Sensor == SensorType)));
} }
string GetTitle() string GetTitle()

View File

@ -10,145 +10,154 @@ using UnityEngine;
/// </summary> /// </summary>
public class Loom : MonoBehaviour public class Loom : MonoBehaviour
{ {
public static int maxThreads = 8; public static int maxThreads = 8;
static int numThreads; static int numThreads;
private static Loom _current; private static Loom _current;
private int _count; public static Loom Current
public static Loom Current {
{ get
get {
{ Initialize();
Initialize(); return _current;
return _current; }
} }
} //####去除Awake
// void Awake()
// {
// _current = this;
// initialized = true;
// }
void Awake() static bool initialized;
{
_current = this;
initialized = true;
}
static bool initialized; //####作为初始化方法自己调用,可在初始化场景调用一次即可
public static void Initialize()
{
if (!initialized)
{
static void Initialize() if (!Application.isPlaying)
{ return;
if (!initialized) initialized = true;
{ GameObject g = new GameObject("Loom");
//####永不销毁
DontDestroyOnLoad(g);
_current = g.AddComponent<Loom>();
}
if (!Application.isPlaying) }
return;
initialized = true;
var g = new GameObject("Loom");
_current = g.AddComponent<Loom>();
}
} private List<Action> _actions = new List<Action>();
public struct DelayedQueueItem
{
public float time;
public Action action;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
private List<Action> _actions = new List<Action>(); List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
public struct DelayedQueueItem
{
public float time;
public Action action;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>(); public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
if (Current != null)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
}
else
{
if (Current != null)
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
}
public static void QueueOnMainThread(Action action) public static Thread RunAsync(Action a)
{ {
QueueOnMainThread(action, 0f); Initialize();
} while (numThreads >= maxThreads)
public static void QueueOnMainThread(Action action, float time) {
{ Thread.Sleep(1);
if (time != 0) }
{ Interlocked.Increment(ref numThreads);
lock (Current._delayed) ThreadPool.QueueUserWorkItem(RunAction, a);
{ return null;
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action }); }
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
public static Thread RunAsync(Action a) private static void RunAction(object action)
{ {
Initialize(); try
while (numThreads >= maxThreads) {
{ ((Action)action)();
Thread.Sleep(1); }
} catch
Interlocked.Increment(ref numThreads); {
ThreadPool.QueueUserWorkItem(RunAction, a); }
return null; finally
} {
Interlocked.Decrement(ref numThreads);
}
private static void RunAction(object action) }
{
try
{
((Action)action)();
}
catch
{
}
finally
{
Interlocked.Decrement(ref numThreads);
}
}
void OnDisable() void OnDisable()
{ {
if (_current == this) if (_current == this)
{ {
_current = null; _current = null;
} }
} }
// Use this for initialization // Use this for initialization
void Start() void Start()
{ {
} }
List<Action> _currentActions = new List<Action>(); List<Action> _currentActions = new List<Action>();
// Update is called once per frame // Update is called once per frame
void Update() void Update()
{ {
lock (_actions) lock (_actions)
{ {
_currentActions.Clear(); _currentActions.Clear();
_currentActions.AddRange(_actions); _currentActions.AddRange(_actions);
_actions.Clear(); _actions.Clear();
} }
foreach (var a in _currentActions) foreach (var a in _currentActions)
{ {
a(); a();
} }
lock (_delayed) lock (_delayed)
{ {
_currentDelayed.Clear(); _currentDelayed.Clear();
_currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time)); _currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
foreach (var item in _currentDelayed) foreach (var item in _currentDelayed)
_delayed.Remove(item); _delayed.Remove(item);
} }
foreach (var delayed in _currentDelayed) foreach (var delayed in _currentDelayed)
{ {
delayed.action(); delayed.action();
} }
}
}
} }