powerfun-unity/Assets/Scripts/Devices/Ble/Win/WclBleGattThread.cs

543 lines
16 KiB
C#

using Assets.Scripts.Ble;
using Assets.Scripts.Ble.Win;
using Assets.Scripts.Ble.Win.CPPBridge;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
namespace Assets.Scripts.Devices.Ble.Win
{
internal class WclBleGattThread: WclBleThread
{
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 GattCharacteristicsDiscoveredDelegate(WclBleGattThread gattClient, BleServiceInfo service, BleResponse<List<BleCharacteristicInfo>> response);
public delegate void GattCharacteristicSubscribedDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse response);
public delegate void GattCharacteristicWroteDelegate(WclBleGattThread gattClient, BleCharacteristicInfo characteristic, BleResponse<BleCharacteristicWriteType> response);
private WclBleGattThread.GattCharacteristicChangedDelegate gattCharacteristicChanged;
private WclBleGattThread.GattCharacteristicReadDelegate gattCharacteristicRead;
// Token: 0x0400131E RID: 4894
private WclBleGattThread.GattCharacteristicsDiscoveredDelegate gattCharacteristicsDiscovered;
// Token: 0x0400131F RID: 4895
private WclBleGattThread.GattCharacteristicSubscribedDelegate gattCharacteristicsSubscribed;
private GattConnected gattConnected;
// Token: 0x04001322 RID: 4898
private GattDisconnected gattDisconnected;
private GattServicesDiscovered gattServicesDiscovered;
public event WclBleGattThread.GattCharacteristicChangedDelegate GattCharacteristicChanged
{
add
{
this.gattCharacteristicChanged += value;
}
remove
{
this.gattCharacteristicChanged -= value;
}
}
// Token: 0x14000039 RID: 57
// (add) Token: 0x060020AE RID: 8366 RVA: 0x00087BB3 File Offset: 0x00085DB3
// (remove) Token: 0x060020AF RID: 8367 RVA: 0x00087BC7 File Offset: 0x00085DC7
public event WclBleGattThread.GattCharacteristicReadDelegate GattCharacteristicRead
{
add
{
this.gattCharacteristicRead += value;
}
remove
{
this.gattCharacteristicRead -= value;
}
}
// Token: 0x1400003A RID: 58
// (add) Token: 0x060020B0 RID: 8368 RVA: 0x00087BDB File Offset: 0x00085DDB
// (remove) Token: 0x060020B1 RID: 8369 RVA: 0x00087BEF File Offset: 0x00085DEF
public event WclBleGattThread.GattCharacteristicsDiscoveredDelegate GattCharacteristicsDiscovered
{
add
{
this.gattCharacteristicsDiscovered += value;
}
remove
{
this.gattCharacteristicsDiscovered -= value;
}
}
// Token: 0x1400003B RID: 59
// (add) Token: 0x060020B2 RID: 8370 RVA: 0x00087C03 File Offset: 0x00085E03
// (remove) Token: 0x060020B3 RID: 8371 RVA: 0x00087C17 File Offset: 0x00085E17
public event WclBleGattThread.GattCharacteristicSubscribedDelegate GattCharacteristicSubscribed
{
add
{
this.gattCharacteristicsSubscribed += value;
}
remove
{
this.gattCharacteristicsSubscribed -= value;
}
}
private WclBleGattThread.GattCharacteristicWroteDelegate gattCharacteristicWrote;
public event WclBleGattThread.GattCharacteristicWroteDelegate GattCharacteristicWrote
{
add
{
this.gattCharacteristicWrote += value;
}
remove
{
this.gattCharacteristicWrote -= value;
}
}
// Token: 0x1400003D RID: 61
// (add) Token: 0x060020B6 RID: 8374 RVA: 0x00087C53 File Offset: 0x00085E53
// (remove) Token: 0x060020B7 RID: 8375 RVA: 0x00087C67 File Offset: 0x00085E67
public event GattConnected GattConnected
{
add
{
this.gattConnected += value;
}
remove
{
this.gattConnected -= value;
}
}
// Token: 0x1400003E RID: 62
// (add) Token: 0x060020B8 RID: 8376 RVA: 0x00087C7B File Offset: 0x00085E7B
// (remove) Token: 0x060020B9 RID: 8377 RVA: 0x00087C8F File Offset: 0x00085E8F
public event GattDisconnected GattDisconnected
{
add
{
this.gattDisconnected += value;
}
remove
{
this.gattDisconnected -= value;
}
}
// Token: 0x1400003F RID: 63
// (add) Token: 0x060020BA RID: 8378 RVA: 0x00087CA3 File Offset: 0x00085EA3
// (remove) Token: 0x060020BB RID: 8379 RVA: 0x00087CB7 File Offset: 0x00085EB7
public event GattServicesDiscovered GattServicesDiscovered
{
add
{
this.gattServicesDiscovered += value;
}
remove
{
this.gattServicesDiscovered -= value;
}
}
private readonly Dictionary<BleCharacteristicInfo, GattCharacteristic> charMapping = new Dictionary<BleCharacteristicInfo, GattCharacteristic>();
private readonly Dictionary<BleServiceInfo, GattService> servicesMapping = new Dictionary<BleServiceInfo, GattService>();
private readonly Dictionary<ushort, BleCharacteristicInfo> subscribedCharHandles = new Dictionary<ushort, BleCharacteristicInfo>();
private WclBleGattClient gatt;
private IntPtr rPtr;
private BlePeripheralInfo _bleDevice;
private readonly long address;
public BlePeripheralInfo Peripheral { get; }
private Thread thread;
private ConcurrentQueue<Action> actions = new ConcurrentQueue<Action>();
private bool start = false;
private ManualResetEvent sEvent;
private AutoResetEvent aEvent;
private ManualResetEvent tEvent;
internal WclBleGattThread(BlePeripheralInfo bleDevice, IntPtr radio, WclBleGattThread.WclBleGattThreadStoppedCallback stopCallback)
{
this.Peripheral = bleDevice;
this.rPtr = radio;
_bleDevice = bleDevice;
this.address = long.Parse(_bleDevice.Address, System.Globalization.NumberStyles.HexNumber);
this.threadStoppedCallback = stopCallback;
}
//private void ThreadProc()
// {
// this.SetUpWorkerThread();
// //this.sEvent.Set();
// //this.DoWorkerLoop();
// //this.CleanUpWorkerThread();
// //this.InternalCleanUp();
//}
protected override void CleanUpWorkerThread()
{
this.gatt.Disconnect();
base.ProcessPendingAPCMessages();
this.gatt.Dispose();
this.gatt = null;
this.threadStoppedCallback?.Invoke(this);
}
protected override void SetUpWorkerThread()
{
this.gatt = new WclBleGattClient(this.address, this.rPtr)
{
Connected = new WclBleGattClient.GattConnectionChanged(this.OnConnected),
Disconnected = new WclBleGattClient.GattConnectionChanged(this.OnDisconnected),
CharacteristicChanged = new WclBleGattClient.GattCharacteristicChanged(this.OnCharacteristicChanged)
};
}
private void DoWorkerLoop()
{
IntPtr[] handle = new IntPtr[]
{
this.tEvent.SafeWaitHandle.DangerousGetHandle(),
this.aEvent.SafeWaitHandle.DangerousGetHandle()
};
while (WclAlertableWait.Wait(handle, 2U, 4294967295U) != 0U)
{
//this.InvokeQueuedActions();
Action action;
if (this.actions.TryDequeue(out action))
{
if (action != null)
{
Debug.Log("连接设备");
action();
}
}
}
}
private void OnCharacteristicChanged(WclBleGattClient connection, ushort handle, byte[] value)
{
if (!this.subscribedCharHandles.ContainsKey(handle)) {
return;
}
BleCharacteristicInfo characteristic = this.subscribedCharHandles[handle];
BleResponse<byte[]> response = new BleResponse<byte[]>
{
IsSuccess = true,
Data = value
};
if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicChanged?.Invoke(this, characteristic, response);
//});
}
}
private void OnCharacteristicRead(BleCharacteristicInfo characteristic, int result, byte[] data)
{
BleResponse<byte[]> response = new BleResponse<byte[]>
{
IsSuccess = WclBleErrors.IsSuccessCode(result)
};
if (response.IsSuccess)
{
response.Data = data;
}
else
{
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading value");
}
if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicRead.Invoke(this, characteristic, response);
//});
}
}
private void OnCharacteristicsDiscovered(BleServiceInfo service, int result, GattCharacteristics characteristics)
{
BleResponse<List<BleCharacteristicInfo>> response = new BleResponse<List<BleCharacteristicInfo>>
{
IsSuccess = WclBleErrors.IsSuccessCode(result)
};
if (response.IsSuccess)
{
response.Data = this.ProcessCharacteristics(service, characteristics);
}
else
{
// response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services");
}
if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() =>
//{
this.gattCharacteristicsDiscovered(this, service, response);
//});
}
}
private void OnConnected(WclBleGattClient sender, int error)
{
//Debug.Log("gatt thread onconnected");
if (base.IsTerminating)
{
return;
}
BleResponse response = new BleResponse
{
IsSuccess = WclBleErrors.IsSuccessCode(error),
};
if (!response.IsSuccess)
{
response.Error = new BleHwInterfaceError(error, "", "");
}
//Loom.QueueOnMainThread(() =>
//{
this.gattConnected?.Invoke(this, response);
//});
}
private void OnDisconnected(WclBleGattClient sender, int reason)
{
BleResponse response = new BleResponse
{
IsSuccess = true,
Error = new BleHwInterfaceError(new int?(reason), "WclBleGattClientErrorDomain", string.Format("GATT disconnect reason is - {0}", reason))
};
//Loom.QueueOnMainThread(() =>
//{
this.gattDisconnected?.Invoke(this, response);
//});
}
public int Connect()
{
if (!base.CanLoadWork)
{
return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
}
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;
}
public int Discounect()
{
this.gatt.Disconnect();
return WclBleErrors.WCL_E_SUCCESS;
}
public int DiscoverServices()
{
base.EnqueueAction(() =>
{
GattServices services;
int result = this.gatt.DiscoverServices(out services);
this.OnServicesDiscovered(result, services);
});
return WclBleErrors.WCL_E_SUCCESS;
}
private void OnServicesDiscovered(int result, GattServices services)
{
BleResponse<List<BleServiceInfo>> response = new BleResponse<List<BleServiceInfo>>
{
IsSuccess = WclBleErrors.IsSuccessCode(result)
};
if (response.IsSuccess)
{
response.Data = this.ProcessServices(services);
}
else
{
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when reading BLE services");
}
if (!base.IsTerminating) {
//Loom.QueueOnMainThread(() =>
//{
gattServicesDiscovered(this, response);
//});
}
}
private List<BleCharacteristicInfo> ProcessCharacteristics(BleServiceInfo service, GattCharacteristics characteristics)
{
List<BleCharacteristicInfo> list = new List<BleCharacteristicInfo>((int)characteristics.Count);
for (int i = 0; i < (int)characteristics.Count; i++)
{
GattCharacteristic gattCharacteristic = characteristics.Chars[i];
WclBleGattThread.WinBleCharacteristicInfo winBleCharacteristicInfo = new WclBleGattThread.WinBleCharacteristicInfo(service, gattCharacteristic.Uuid.WclGuidToNormalizedGuid());
this.charMapping[winBleCharacteristicInfo] = gattCharacteristic;
list.Add(winBleCharacteristicInfo);
}
return list;
}
private List<BleServiceInfo> ProcessServices(GattServices services)
{
List<BleServiceInfo> list = new List<BleServiceInfo>((int)services.Count);
for (int i = 0; i < (int)services.Count; i++)
{
GattService gattService = services.Services[i];
WclBleGattThread.WinBleServiceInfo winBleServiceInfo = new WclBleGattThread.WinBleServiceInfo(this._bleDevice, gattService.Uuid.WclGuidToNormalizedGuid());
this.servicesMapping[winBleServiceInfo] = gattService;
list.Add(winBleServiceInfo);
}
return list;
}
public int DiscoverCharacteristics(BleServiceInfo service)
{
GattService ns = this.servicesMapping[service];
base.EnqueueAction(() =>
{
GattCharacteristics characteristics;
int result = this.gatt.DiscoverCharacteristics(ns, out characteristics);
this.OnCharacteristicsDiscovered(service, result, characteristics);
});
return WclBleErrors.WCL_E_SUCCESS;
}
public int ReadCharacteristicValue(BleCharacteristicInfo characteristic)
{
if (!charMapping.ContainsKey(characteristic))
{
return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
}
GattCharacteristic nCh = this.charMapping[characteristic];
base.EnqueueAction(() =>
{
byte[] data;
int result = this.gatt.ReadCharacteristicValue(nCh, out data);
this.OnCharacteristicRead(characteristic, result, data);
});
return WclBleErrors.WCL_E_SUCCESS;
}
public int SubscribeCharacteristic(BleCharacteristicInfo characteristic)
{
if (!this.charMapping.ContainsKey(characteristic))
{
return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
}
GattCharacteristic nCh = this.charMapping[characteristic];
base.EnqueueAction(() =>
{
int result = this.gatt.SubscribeCharacteristic(nCh);
this.OnCharacteristicsSubscribed(characteristic, nCh, result);
});
return WclBleErrors.WCL_E_SUCCESS;
}
private void OnCharacteristicsSubscribed(BleCharacteristicInfo characteristic, GattCharacteristic nCharacteristic, int result)
{
//Debug.Log("char subscribed");
BleResponse response = new BleResponse
{
IsSuccess = WclBleErrors.IsSuccessCode(result)
};
if (response.IsSuccess)
{
this.subscribedCharHandles[nCharacteristic.Handle] = characteristic;
}
else
{
response.Error = new BleHwInterfaceError(new int?(result), "WclBleGattClientErrorDomain", "Error when subscribing Characteristics");
}
if (!base.IsTerminating)
{
//Loom.QueueOnMainThread(() => {
this.gattCharacteristicsSubscribed(this, characteristic, response);
//});
}
}
public int WriteCharacteristic(BleCharacteristicInfo characteristicInfo, byte[] data)
{
if (!this.charMapping.ContainsKey(characteristicInfo))
{
return WclBleErrors.WCL_E_CONNECTION_NOT_ACTIVE;
}
GattCharacteristic gCh = this.charMapping[characteristicInfo];
base.EnqueueAction(() =>
{
int result = this.gatt.WriteCharacteristic(gCh, data);
this.OnCharactersisticsWrote(characteristicInfo, result);
});
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 WclBleGattThread.WclBleGattThreadStoppedCallback threadStoppedCallback;
public delegate void WclBleGattThreadStoppedCallback(WclBleGattThread clientThread);
private class WinBleCharacteristicInfo : BleCharacteristicInfo
{
// Token: 0x06003F85 RID: 16261 RVA: 0x000EA274 File Offset: 0x000E8474
public WinBleCharacteristicInfo(BleServiceInfo service, Guid id) : base(id, service, (BleCharacteristicProperties)0)
{
}
}
private class WinBleServiceInfo : BleServiceInfo
{
// Token: 0x06003F86 RID: 16262 RVA: 0x000EA27F File Offset: 0x000E847F
public WinBleServiceInfo(BlePeripheralInfo peripheral, Guid id) : base(id, peripheral)
{
}
}
}
}