diff --git a/.gitignore b/.gitignore index 07da593..b629ccc 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,8 @@ crashlytics-build.properties # Temporary auto-generated Android Assets /[Aa]ssets/[Ss]treamingAssets/aa.meta -/[Aa]ssets/[Ss]treamingAssets/aa/* \ No newline at end of file +/[Aa]ssets/[Ss]treamingAssets/aa/* + +#Windows Plugin builds +bleplugin_projects/Windows/x64 +bleplugin_projects/Windows/BlePluginWin/x64 \ No newline at end of file diff --git a/Assets/Plugins/Ble.cs b/Assets/Plugins/Ble.cs index 0d428d7..96a0ce2 100644 --- a/Assets/Plugins/Ble.cs +++ b/Assets/Plugins/Ble.cs @@ -12,6 +12,10 @@ #define UNITY_OSX #endif +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +#define UNITY_WIN +#endif + using UnityEngine; using System; using System.Runtime.InteropServices; @@ -31,6 +35,8 @@ public static void Initialize(Action initializedAction, Action errorActi toio.Android.BleAndroid.Initialize(initializedAction, errorAction); #elif UNITY_OSX toio.BlemacOS.Initialize(initializedAction, errorAction); +#elif UNITY_WIN + toio.Windows.BleWin.Initialize(initializedAction, errorAction); #endif } @@ -42,6 +48,8 @@ public static void Finalize(Action finalizedAction = null) toio.Android.BleAndroid.Finalize(finalizedAction); #elif UNITY_OSX toio.BlemacOS.Finalize(finalizedAction); +#elif UNITY_WIN + toio.Windows.BleWin.Finalize(finalizedAction); #endif } @@ -53,6 +61,8 @@ public static void EnableBluetooth(bool enable) toio.Android.BleAndroid.EnableBluetooth(enable); #elif UNITY_OSX toio.BlemacOS.EnableBluetooth(enable); +#elif UNITY_WIN + toio.Windows.BleWin.EnableBluetooth(enable); #endif } @@ -64,6 +74,8 @@ public static void StartScan(string[] serviceUUIDs, Action connect #elif UNITY_OSX toio.BlemacOS.ConnectToPeripheral(identifier, connectedPeripheralAction, discoveredServiceAction, discoveredCharacteristicAction, disconnectedPeripheralAction); +#elif UNITY_WIN + toio.Windows.BleWin.ConnectToPeripheral(identifier, connectedPeripheralAction, discoveredServiceAction, + discoveredCharacteristicAction, disconnectedPeripheralAction); #endif } @@ -100,6 +117,8 @@ public static void DisconnectPeripheral(string identifier, Action discon toio.Android.BleAndroid.DisconnectPeripheral(identifier, disconnectedPeripheralAction); #elif UNITY_OSX toio.BlemacOS.DisconnectPeripheral(identifier, disconnectedPeripheralAction); +#elif UNITY_WIN + toio.Windows.BleWin.DisconnectPeripheral(identifier, disconnectedPeripheralAction); #endif } @@ -111,6 +130,8 @@ public static void DisconnectAllPeripherals() toio.Android.BleAndroid.DisconnectAllPeripherals(); #elif UNITY_OSX toio.BlemacOS.DisconnectAllPeripherals(); +#elif UNITY_WIN + toio.Windows.BleWin.DisconnectAllPeripherals(); #endif } @@ -124,6 +145,9 @@ public static void ReadCharacteristic(string identifier, string serviceUUID, str #elif UNITY_OSX toio.BlemacOS.ReadCharacteristic(identifier, serviceUUID, characteristicUUID, didReadChracteristicAction); +#elif UNITY_WIN + toio.Windows.BleWin.ReadCharacteristic(identifier, serviceUUID, + characteristicUUID, didReadChracteristicAction); #endif } @@ -137,6 +161,9 @@ public static void WriteCharacteristic(string identifier, string serviceUUID, st #elif UNITY_OSX toio.BlemacOS.WriteCharacteristic(identifier, serviceUUID, characteristicUUID, data, length, withResponse, didWriteCharacteristicAction); +#elif UNITY_WIN + toio.Windows.BleWin.WriteCharacteristic(identifier, serviceUUID, characteristicUUID, + data, length, withResponse, didWriteCharacteristicAction); #endif } @@ -150,6 +177,9 @@ public static void SubscribeCharacteristic(string identifier, string serviceUUID #elif UNITY_OSX toio.BlemacOS.SubscribeCharacteristic(identifier, serviceUUID, characteristicUUID, notifiedCharacteristicAction); +#elif UNITY_WIN + toio.Windows.BleWin.SubscribeCharacteristic(identifier, serviceUUID, + characteristicUUID, notifiedCharacteristicAction); #endif } @@ -161,6 +191,8 @@ public static void UnSubscribeCharacteristic(string identifier, string serviceUU toio.Android.BleAndroid.UnSubscribeCharacteristic(identifier, serviceUUID, characteristicUUID, action); #elif UNITY_OSX toio.BlemacOS.UnSubscribeCharacteristic(identifier, serviceUUID, characteristicUUID, action); +#elif UNITY_WIN + toio.Windows.BleWin.UnSubscribeCharacteristic(identifier, serviceUUID, characteristicUUID, action); #endif } } diff --git a/Assets/Editor.meta b/Assets/Plugins/Editor.meta similarity index 100% rename from Assets/Editor.meta rename to Assets/Plugins/Editor.meta diff --git a/Assets/Editor/XcodeModuleEnabling.cs b/Assets/Plugins/Editor/XcodeModuleEnabling.cs similarity index 100% rename from Assets/Editor/XcodeModuleEnabling.cs rename to Assets/Plugins/Editor/XcodeModuleEnabling.cs diff --git a/Assets/Editor/XcodeModuleEnabling.cs.meta b/Assets/Plugins/Editor/XcodeModuleEnabling.cs.meta similarity index 100% rename from Assets/Editor/XcodeModuleEnabling.cs.meta rename to Assets/Plugins/Editor/XcodeModuleEnabling.cs.meta diff --git a/Assets/Editor/XcodePlistUpdating.cs b/Assets/Plugins/Editor/XcodePlistUpdating.cs similarity index 100% rename from Assets/Editor/XcodePlistUpdating.cs rename to Assets/Plugins/Editor/XcodePlistUpdating.cs diff --git a/Assets/Editor/XcodePlistUpdating.cs.meta b/Assets/Plugins/Editor/XcodePlistUpdating.cs.meta similarity index 100% rename from Assets/Editor/XcodePlistUpdating.cs.meta rename to Assets/Plugins/Editor/XcodePlistUpdating.cs.meta diff --git a/Assets/Plugins/ble-plugin-unity.asmdef b/Assets/Plugins/ble-plugin-unity.asmdef new file mode 100644 index 0000000..d0324d8 --- /dev/null +++ b/Assets/Plugins/ble-plugin-unity.asmdef @@ -0,0 +1,3 @@ +{ + "name": "ble-plugin-unity" +} diff --git a/Assets/Plugins/ble-plugin-unity.asmdef.meta b/Assets/Plugins/ble-plugin-unity.asmdef.meta new file mode 100644 index 0000000..7c41467 --- /dev/null +++ b/Assets/Plugins/ble-plugin-unity.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 67661c459d63ac743adc84bcb7d51f9a +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64.meta b/Assets/Plugins/x86_64.meta new file mode 100644 index 0000000..30809c4 --- /dev/null +++ b/Assets/Plugins/x86_64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8bd18c775f8f7f2429fb3a6937c27646 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/BehaviourProxy.cs b/Assets/Plugins/x86_64/BehaviourProxy.cs new file mode 100644 index 0000000..7fd3937 --- /dev/null +++ b/Assets/Plugins/x86_64/BehaviourProxy.cs @@ -0,0 +1,42 @@ + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +namespace toio.Windows +{ + internal class BehaviourProxy : MonoBehaviour + { + private System.Action onUpdate; + private IEnumerator initalizeExecution; + + public static BehaviourProxy Create(IEnumerator initExec,System.Action updateFunc) + { + var gmo = new GameObject("BehaviourProxy"); + gmo.hideFlags = HideFlags.HideAndDontSave; + Object.DontDestroyOnLoad(gmo); + var proxy = gmo.AddComponent(); + proxy.initalizeExecution = initExec; + proxy.onUpdate = updateFunc; + return proxy; + } + void Update() + { + if(initalizeExecution != null) + { + if(!initalizeExecution.MoveNext()) + { + initalizeExecution = null; + } + return; + } + if(onUpdate != null) { + onUpdate(); + } + } + } +} + +#endif diff --git a/Assets/Plugins/x86_64/BehaviourProxy.cs.meta b/Assets/Plugins/x86_64/BehaviourProxy.cs.meta new file mode 100644 index 0000000..95c4c65 --- /dev/null +++ b/Assets/Plugins/x86_64/BehaviourProxy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 16c0bb189d9dcce4e94105564694b86a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/BlePluginWinows.dll b/Assets/Plugins/x86_64/BlePluginWinows.dll new file mode 100644 index 0000000..f48d6e9 Binary files /dev/null and b/Assets/Plugins/x86_64/BlePluginWinows.dll differ diff --git a/Assets/Plugins/x86_64/BlePluginWinows.dll.meta b/Assets/Plugins/x86_64/BlePluginWinows.dll.meta new file mode 100644 index 0000000..06a4f16 --- /dev/null +++ b/Assets/Plugins/x86_64/BlePluginWinows.dll.meta @@ -0,0 +1,63 @@ +fileFormatVersion: 2 +guid: 33224e7743118c4429b1f87bf0b99dd3 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux64: 0 + Exclude OSXUniversal: 0 + Exclude Win: 0 + Exclude Win64: 0 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: Windows + - first: + Standalone: Linux64 + second: + enabled: 1 + settings: + CPU: AnyCPU + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: x86_64 + - first: + Standalone: Win + second: + enabled: 1 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/BleWin.cs b/Assets/Plugins/x86_64/BleWin.cs new file mode 100644 index 0000000..80297bd --- /dev/null +++ b/Assets/Plugins/x86_64/BleWin.cs @@ -0,0 +1,437 @@ + + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + + +using UnityEngine; +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Collections; +using toio.Windows.Data; + +namespace toio.Windows +{ + public class BleWin + { + private static Action s_discoverAction; + private static Dictionary s_deviceDiscoverEvents = new Dictionary(); + + private static List s_writeRequests = new List(); + private static List s_readRequests = new List(); + private static Dictionary s_notifyEvents = new Dictionary(); + + private static HashSet s_allreadyCallServiceBuffer = new HashSet(); + private static List s_removeIdxBuffer = new List(); + private static List s_removeKeyBuffer = new List(); + + private static bool s_isInitialized = false; + + public static void Initialize(Action initializedAction, Action errorAction = null) + { + // clear data + s_discoverAction = null; + s_deviceDiscoverEvents.Clear(); + s_writeRequests.Clear(); + s_readRequests.Clear(); + s_notifyEvents.Clear(); + s_isInitialized = false; + + BehaviourProxy.Create(InitAction(initializedAction,errorAction),OnUpdate); + } + private static IEnumerator InitAction(Action initializedAction, Action errorAction) + { + DllInterface.BleAdapterStatusRequest(); + DllInterface.EBluetoothStatus stat = DllInterface.EBluetoothStatus.None; + + while (stat == DllInterface.EBluetoothStatus.None) + { + stat = DllInterface.BleAdapterUpdate(); + yield return null; + } + switch (stat) + { + case DllInterface.EBluetoothStatus.Fine: + s_isInitialized = true; + if (initializedAction != null){ + initializedAction.Invoke(); + } + break; + case DllInterface.EBluetoothStatus.NotSupportBle: + if (errorAction != null){ + errorAction.Invoke("Bluetooth Adapter not Support BLE Central."); + } + break; + case DllInterface.EBluetoothStatus.BluetoothDisable: + if (errorAction != null) + { + errorAction.Invoke("Bluetooth Adapter isn't enabled."); + } + break; + default: + if (errorAction != null) + { + errorAction.Invoke("UnknonwError"); + } + break; + } + } + + public static void Finalize(Action finalizedAction = null) + { + if (!s_isInitialized) { return; } + //Debug.Log("Finalize"); + DllInterface.FinalizePlugin(); + if(finalizedAction != null) { finalizedAction(); } + } + + public static void EnableBluetooth(bool enable) + { + } + + public static void StartScan(string[] serviceUUIDs, + Action discoveredAction = null) + { + if (!s_isInitialized) { return; } + s_discoverAction = discoveredAction; + DllInterface.ClearScanFilter(); + if (serviceUUIDs != null) + { + foreach (var uuid in serviceUUIDs) + { + var uuidHandle = UuidDatabase.GetUuid(uuid); + DllInterface.AddScanServiceUuid(uuidHandle); + } + } + DllInterface.StartScan(); + } + + public static void StopScan() + { + if (!s_isInitialized) { return; } + //Debug.Log("StopScan " ); + DllInterface.StopScan(); + } + + public static void ConnectToPeripheral(string identifier, + Action connectedPeripheralAction = null, + Action discoveredServiceAction = null, + Action discoveredCharacteristicAction = null, + Action disconnectedPeripheralAction = null) + { + if (!s_isInitialized) { return; } + //Debug.Log("Connect to peripheral " + identifier); + if (s_deviceDiscoverEvents.ContainsKey(identifier)) + { + return; + } + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + DllInterface.ConnectDevice(addr); + var evt = new BleDiscoverEvents(connectedPeripheralAction, + discoveredServiceAction, + discoveredCharacteristicAction, + disconnectedPeripheralAction); + + s_deviceDiscoverEvents.Add(identifier, evt); + } + + public static void DisconnectPeripheral(string identifier, + Action disconnectedPeripheralAction = null) + { + if (!s_isInitialized) { return; } + //Debug.Log("DisconnectPeripheral " + identifier); + + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + DllInterface.DisconnectDevice(addr); + } + + public static void DisconnectAllPeripherals() + { + if (!s_isInitialized) { return; } + DllInterface.DisconnectAllDevice(); + } + + public static void ReadCharacteristic(string identifier, + string serviceUUID, + string characteristicUUID, + Action didReadChracteristicAction) + { + if (!s_isInitialized) { return; } + //Debug.Log("ReadCharacteristic " + identifier); + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + var serviceHandle = UuidDatabase.GetUuid(serviceUUID); + var characteristicHandle = UuidDatabase.GetUuid(characteristicUUID); + var charastricsItem = new BleCharastericsKeyInfo(identifier, serviceUUID, characteristicUUID); + + var readRequestHandle = DllInterface.ReadCharastristicRequest(addr, serviceHandle, characteristicHandle); + var requestData = new BleReadRequestData(charastricsItem, readRequestHandle, didReadChracteristicAction); + s_readRequests.Add(requestData); + } + + public static void WriteCharacteristic(string identifier, + string serviceUUID, string characteristicUUID, + byte[] data, int length, bool withResponse, + Action didWriteCharacteristicAction) + { + if (!s_isInitialized) { return; } + //Debug.Log("WriteCharacteristic " + identifier); + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + + var serviceHandle = UuidDatabase.GetUuid(serviceUUID); + var characteristicHandle = UuidDatabase.GetUuid(characteristicUUID); + var writeRequest = DllInterface.WriteCharastristicRequest(addr, serviceHandle, characteristicHandle, data,0,length); + + if (withResponse && didWriteCharacteristicAction == null) + { + var charastricsItem = new BleCharastericsKeyInfo(identifier, serviceUUID, characteristicUUID); + var requestData = new BleWriteRequestData(charastricsItem, writeRequest, didWriteCharacteristicAction); + s_writeRequests.Add(requestData); + } + else { + DllInterface.ReleaseWriteRequest(addr, writeRequest); + } + } + + public static void SubscribeCharacteristic(string identifier, + string serviceUUID, string characteristicUUID, + Action notifiedCharacteristicAction) + { + //Debug.Log("SubscribeCharacteristic " + identifier + ":" + serviceUUID + ":" + characteristicUUID); + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + var serviceHandle = UuidDatabase.GetUuid(serviceUUID); + var characteristicHandle = UuidDatabase.GetUuid(characteristicUUID); + var charastricsItem = new BleCharastericsKeyInfo(identifier, serviceUUID, characteristicUUID); + + s_notifyEvents[charastricsItem] = new BleNotifyData(notifiedCharacteristicAction); + DllInterface.SetNotificationRequest(addr, serviceHandle,characteristicHandle , true); + } + + public static void UnSubscribeCharacteristic(string identifier, + string serviceUUID, string characteristicUUID, + Action action) + { + if (!s_isInitialized) { return; } + //Debug.Log("UnSubscribeCharacteristic " + identifier + ":" + serviceUUID + ":" + characteristicUUID); + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + var serviceHandle = UuidDatabase.GetUuid(serviceUUID); + var characteristicHandle = UuidDatabase.GetUuid(characteristicUUID); + var charastricsItem = new BleCharastericsKeyInfo(identifier, serviceUUID, characteristicUUID); + DllInterface.SetNotificationRequest(addr, serviceHandle, characteristicHandle, false); + s_notifyEvents.Remove(charastricsItem); + } + + private static void OnUpdate() + { + if (!s_isInitialized) { return; } + DllInterface.UpdateFromMainThread(); + UpdateScanDeviceEvents(); + UpdateDeviceConnectEvents(); + UpdateWriteRequests(); + UpdateReadRequests(); + UpdateNotification(); + UpdateDisconnectedDevice(); + } + + private static void UpdateScanDeviceEvents() + { + if (!s_isInitialized) { return; } + // update scan devices + int scanNum = DllInterface.ScanGetDeviceLength(); + // Debug.Log("UpdateScanDeviceEvents " + scanNum); + for (int i = 0; i < scanNum; ++i) + { + ulong addr = DllInterface.ScanGetDeviceAddr(i); + var identifier = DeviceAddressDatabase.GetAddressStr(addr); + //Debug.Log("UpdateScanDeviceEvents identifier " + identifier); + var name = "";// DllInterface.ScanGetDeviceName(i); + //Debug.Log("UpdateScanDeviceEvents name " + name); + var rssi = DllInterface.ScanGetDeviceRssi(i); + //Debug.Log("UpdateScanDeviceEvents rssi " + rssi); + if (s_discoverAction != null) + { + s_discoverAction(identifier, name, rssi, null); + } + } + } + + private static void UpdateDeviceConnectEvents() + { + if (!s_isInitialized) { return; } + s_allreadyCallServiceBuffer.Clear(); + // update connect Event + int deviceNum = DllInterface.GetConnectDeviceNum(); + //Debug.Log("UpdateDeviceConnectEvents " + deviceNum); + for (int i = 0; i < deviceNum; ++i) + { + var addr = DllInterface.GetConnectDeviceAddr(i); + string identifier = DeviceAddressDatabase.GetAddressStr(addr); + BleDiscoverEvents bleDiscoverEvents; + if( !s_deviceDiscoverEvents.TryGetValue(identifier,out bleDiscoverEvents)) + { + continue; + } + if (bleDiscoverEvents.callDiscoverEvent) + { + continue; + } + if (bleDiscoverEvents.connectedAct != null) + { + bleDiscoverEvents.connectedAct(identifier); + } + + var deviceHandle = DllInterface.GetConnectDevicePtr(i); + int chNum = DllInterface.GetDeviceCharastricsNum(deviceHandle); + for (int j = 0; j < chNum; ++j) + { + var serviceHandle = DllInterface.GetDeviceCharastricServiceUuid(deviceHandle, j); + var charaHandle = DllInterface.GetDeviceCharastricUuid(deviceHandle, j); + var serviceUuidStr = UuidDatabase.GetUuidStr(serviceHandle); + var charaUuidStr = UuidDatabase.GetUuidStr(charaHandle); + + if (!s_allreadyCallServiceBuffer.Contains(serviceUuidStr)) + { + if (bleDiscoverEvents.discoveredServiceAct != null) + { + bleDiscoverEvents.discoveredServiceAct(identifier, serviceUuidStr); + } + s_allreadyCallServiceBuffer.Add(serviceUuidStr); + } + if (bleDiscoverEvents.discoveredCharacteristicAct != null) + { + bleDiscoverEvents.discoveredCharacteristicAct(identifier, serviceUuidStr, charaUuidStr); + } + } + + bleDiscoverEvents.callDiscoverEvent = true; + } + } + + private static void UpdateWriteRequests() + { + if (!s_isInitialized) { return; } + s_removeIdxBuffer.Clear(); + int count = s_writeRequests.Count; + for ( int i = 0; i < count; ++i) + { + var request = s_writeRequests[i]; + if( DllInterface.IsWriteRequestComplete(request.handle)) + { + if (request.didWriteCharacteristicAction != null) + { + request.didWriteCharacteristicAction(request.charastericsInfo.serviceUUID, request.charastericsInfo.characteristicUUID); + } + s_removeIdxBuffer.Add(i); + }else if (DllInterface.IsWriteRequestError(request.handle)) + { + s_removeIdxBuffer.Add(i); + } + } + // remove done request + s_removeIdxBuffer.Reverse(); + foreach( var idx in s_removeIdxBuffer) + { + var request = s_writeRequests[idx]; + var addr = DeviceAddressDatabase.GetAddressValue( request.charastericsInfo.address); + DllInterface.ReleaseWriteRequest(addr,request.handle); + s_writeRequests.RemoveAt(idx); + } + } + private static void UpdateReadRequests() + { + if (!s_isInitialized) { return; } + s_removeIdxBuffer.Clear(); + int count = s_readRequests.Count; + for (int i = 0; i < count; ++i) + { + var request = s_readRequests[i]; + if (DllInterface.IsReadRequestComplete(request.handle)) + { + if (request.didReadChracteristicAction != null) + { + var data = DllInterface.GetReadRequestData(request.handle, 32); + request.didReadChracteristicAction(request.charastericsInfo.serviceUUID, request.charastericsInfo.characteristicUUID,data); + } + s_removeIdxBuffer.Add(i); + } + else if (DllInterface.IsReadRequestError(request.handle)) + { + s_removeIdxBuffer.Add(i); + } + + } + // remove done request + s_removeIdxBuffer.Reverse(); + foreach (var idx in s_removeIdxBuffer) + { + var request = s_readRequests[idx]; + var addr = DeviceAddressDatabase.GetAddressValue(request.charastericsInfo.address); + DllInterface.ReleaseReadRequest(addr, request.handle); + s_readRequests.RemoveAt(idx); + } + } + + private static void UpdateNotification() + { + if (!s_isInitialized) { return; } + int deviceNum = DllInterface.GetConnectDeviceNum(); + for(int i = 0; i < deviceNum; ++i) + { + ulong addr = DllInterface.GetConnectDeviceAddr(i); + string identifier = DeviceAddressDatabase.GetAddressStr(addr); + + int num = DllInterface.GetDeviceNotificateNum(addr); + //Debug.Log("UpdateNotification " + identifier + "::" +num + " " + i + "/" + deviceNum ); + for (int j = 0; j < num; ++j) + { + var data = DllInterface.GetDeviceNotificateData(addr, j); + var serviceHandle = DllInterface.GetDeviceNotificateServiceUuid(addr, j); + var charastricHandle = DllInterface.GetDeviceNotificateCharastricsUuid(addr, j); + string serviceUUID = UuidDatabase.GetUuidStr(serviceHandle); + string characteristicUUID = UuidDatabase.GetUuidStr(charastricHandle); + + var key = new BleCharastericsKeyInfo(identifier, serviceUUID, characteristicUUID); + BleNotifyData bleNotifyData; + if(s_notifyEvents.TryGetValue(key,out bleNotifyData)) + { + if (bleNotifyData.notifiedCharacteristicAction != null) + { + bleNotifyData.notifiedCharacteristicAction(serviceUUID, characteristicUUID, data); + } + } + } + } + } + + private static void UpdateDisconnectedDevice() + { + if (!s_isInitialized) { return; } + s_removeKeyBuffer.Clear(); + foreach (var kvs in s_deviceDiscoverEvents) + { + string identifier = kvs.Key; + var addr = DeviceAddressDatabase.GetAddressValue(identifier); + var discoverEvt = kvs.Value; + if (!discoverEvt.callDiscoverEvent) + { + continue; + } + if (DllInterface.IsDeviceConnected(addr)) + { + continue; + } + if (discoverEvt.disconnectedAct != null) + { + discoverEvt.disconnectedAct(identifier); + } + s_removeKeyBuffer.Add(identifier); + //Debug.Log("DisconnectDevice " + identifier); + } + foreach (var key in s_removeKeyBuffer) + { + s_deviceDiscoverEvents.Remove(key); + } + } + + } +} +#endif diff --git a/Assets/Plugins/x86_64/BleWin.cs.meta b/Assets/Plugins/x86_64/BleWin.cs.meta new file mode 100644 index 0000000..1f84297 --- /dev/null +++ b/Assets/Plugins/x86_64/BleWin.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46739601156b51844bca08723c2218aa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/Data.meta b/Assets/Plugins/x86_64/Data.meta new file mode 100644 index 0000000..31bb050 --- /dev/null +++ b/Assets/Plugins/x86_64/Data.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 163e06647c6a88f4797d91ee8a3146fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs b/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs new file mode 100644 index 0000000..917d8c1 --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs @@ -0,0 +1,77 @@ + + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + + + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +namespace toio.Windows.Data { + internal struct BleCharastericsKeyInfo : IComparer + { + public string address; + public string serviceUUID; + public string characteristicUUID; + + public BleCharastericsKeyInfo(string addr,string service, string ch) + { + this.address = addr.ToLower(); + this.characteristicUUID = ch.ToLower(); + this.serviceUUID = service.ToLower(); + } + + public bool IsSameAddress(string addr) + { + return (this.address == addr.ToLower()); + } + + + public int Compare(BleCharastericsKeyInfo x, BleCharastericsKeyInfo y) + { + int idParam = x.address.CompareTo(y.address); + if (idParam != 0) + { + return idParam; + } + int serviceParam = x.serviceUUID.CompareTo(y.serviceUUID); + if (serviceParam != 0) + { + return serviceParam; + } + int chParam = x.characteristicUUID.CompareTo(y.characteristicUUID); + return chParam; + } + public override int GetHashCode() + { + return address.GetHashCode() + serviceUUID.GetHashCode() + characteristicUUID.GetHashCode(); + } + + public static void GetServices(HashSet destServices , List list) + { + destServices.Clear(); + foreach (var info in list) + { + string serviceUuid = info.serviceUUID; + if (destServices.Contains(serviceUuid)) + { + destServices.Add(serviceUuid); + } + } + } + public static void GetInfoByService(List dest,string service, List src) + { + dest.Clear(); + foreach (var info in src) + { + if (service == info.serviceUUID) + { + dest.Add(info); + } + } + } + + } + +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs.meta b/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs.meta new file mode 100644 index 0000000..7fc8f19 --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleCharastericsKeyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 788a2b6d33e95fb4393afedc7df486fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs b/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs new file mode 100644 index 0000000..e247437 --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs @@ -0,0 +1,46 @@ + + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; + + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +namespace toio.Windows.Data { + internal struct BleWriteRequestData + { + public BleCharastericsKeyInfo charastericsInfo; + public WriteRequestHandler handle; + public Action didWriteCharacteristicAction; + + public BleWriteRequestData(BleCharastericsKeyInfo chInfo,WriteRequestHandler h, Action act) + { + this.charastericsInfo = chInfo; + this.handle = h; + this.didWriteCharacteristicAction = act; + } + } + internal struct BleReadRequestData + { + public BleCharastericsKeyInfo charastericsInfo; + public ReadRequestHandler handle; + public Action didReadChracteristicAction; + + public BleReadRequestData(BleCharastericsKeyInfo chInfo, ReadRequestHandler h, Action act) + { + this.charastericsInfo = chInfo; + this.handle = h; + this.didReadChracteristicAction = act; + } + } + internal struct BleNotifyData + { + public Action notifiedCharacteristicAction; + public BleNotifyData(Action act) + { + this.notifiedCharacteristicAction = act; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs.meta b/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs.meta new file mode 100644 index 0000000..753d70e --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleDeviceRequestData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 231f864a1a0e1d544be857e1dd2c8c98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs b/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs new file mode 100644 index 0000000..192b408 --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs @@ -0,0 +1,34 @@ + + +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System; + + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +namespace toio.Windows.Data { + internal class BleDiscoverEvents + { + public Action connectedAct; + public Action discoveredServiceAct; + public Action discoveredCharacteristicAct; + public Action disconnectedAct; + + public bool callDiscoverEvent = false; + + public BleDiscoverEvents( + Action connectedAct, + Action discoveredServiceAct, + Action discoveredCharacteristicAct, + Action disconnectedAct + ){ + this.connectedAct = connectedAct; + this.discoveredServiceAct = discoveredServiceAct; + this.discoveredCharacteristicAct = discoveredCharacteristicAct; + this.disconnectedAct = disconnectedAct; + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs.meta b/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs.meta new file mode 100644 index 0000000..eb785ec --- /dev/null +++ b/Assets/Plugins/x86_64/Data/BleDiscoverEvents.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 684392ae12473bc4988312eb79c2cdfd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/DeviceAddressDatabase.cs b/Assets/Plugins/x86_64/DeviceAddressDatabase.cs new file mode 100644 index 0000000..e4ec414 --- /dev/null +++ b/Assets/Plugins/x86_64/DeviceAddressDatabase.cs @@ -0,0 +1,89 @@ + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN + +using System.Collections; +using System.Collections.Generic; +using System.Text; +using UnityEngine; + +namespace toio.Windows +{ + public class DeviceAddressDatabase + { + private static readonly char[] Digit = new char[] { + '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' + }; + private static StringBuilder stringBuffer; + private static Dictionary addrDictByStr; + private static Dictionary strDictByAddr; + + static DeviceAddressDatabase() + { + addrDictByStr = new Dictionary(); + strDictByAddr = new Dictionary(); + } + + public static string GetAddressStr(ulong addr) + { + string str; + if (strDictByAddr.TryGetValue(addr, out str)) + { + return str; + } + str = ConvertToString(addr); + addrDictByStr.Add(str, addr); + strDictByAddr.Add(addr, str); + return str; + } + public static ulong GetAddressValue(string str) + { + ulong addr; + if(addrDictByStr.TryGetValue(str,out addr)){ + return addr; + } + addr = ConvertFromString(str); + addrDictByStr.Add(str, addr); + strDictByAddr.Add(addr, str); + return addr; + } + private static string ConvertToString(ulong addr) + { + if(stringBuffer == null) + { + stringBuffer = new StringBuilder(16); + } + stringBuffer.Clear(); + for (int i = 0; i < 16; ++i) + { + int bitShift = (15 - i) * 4; + int val = (int)((addr & (0x0fUL << bitShift)) >> bitShift); + stringBuffer.Append(Digit[val]); + } + return stringBuffer.ToString(); + } + private static ulong ConvertFromString(string str) + { + int max = str.Length; + if( max > 16) { max = 16; } + ulong addr = 0; + for (int i = 0; i < max; ++i) + { + int bitShift = ((max-1) - i) * 4; + int val = 0; + char ch = str[i]; + if( ch >= 'A') + { + val = (ch - 'A') + 10; + } + else + { + val = ch - '0'; + } + addr |= (ulong)val << bitShift; + } + return addr; + } + } +} + +#endif \ No newline at end of file diff --git a/Assets/Plugins/x86_64/DeviceAddressDatabase.cs.meta b/Assets/Plugins/x86_64/DeviceAddressDatabase.cs.meta new file mode 100644 index 0000000..c40a79b --- /dev/null +++ b/Assets/Plugins/x86_64/DeviceAddressDatabase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 727097f0dcb494c489122f6ded6933d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/DllInterface.cs b/Assets/Plugins/x86_64/DllInterface.cs new file mode 100644 index 0000000..93a4b2b --- /dev/null +++ b/Assets/Plugins/x86_64/DllInterface.cs @@ -0,0 +1,440 @@ +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System; + + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +namespace toio.Windows +{ + public struct UuidHandler + { + public IntPtr ptr; + public UuidHandler(IntPtr p) + { + ptr = p; + } + } + public struct BleDeviceHandler + { + public IntPtr ptr; + public BleDeviceHandler(IntPtr p) + { + ptr = p; + } + } + public struct ReadRequestHandler + { + public IntPtr ptr; + public ReadRequestHandler(IntPtr p) + { + ptr = p; + } + } + public struct WriteRequestHandler + { + public IntPtr ptr; + public WriteRequestHandler(IntPtr p) + { + ptr = p; + } + } + public struct UuidData + { + public uint data1; + public uint data2; + public uint data3; + public uint data4; + + public override string ToString() + { + return string.Format("{0:X8}-{1:X4}-{2:X4}-{3:X4}-{4:X4}{5:X8}", data1, + (data2>>16) &0xffff, + (data2 & 0xffff), + (data3 >> 16) & 0xffff, + (data3 & 0xffff),data4 ); + } + } + internal unsafe struct UuidBuffer + { + public fixed uint fixedBuffer[4]; + } + internal unsafe struct CharastricsBuffer + { + public const int BufferSize = 22; + public fixed byte fixedBuffer[BufferSize]; + } + + public class DllInterface + { + const string pluginName = "BlePluginWinows"; + + public enum EBluetoothStatus : int + { + None = -1, + Fine = 0, + NotSupportBle = 1, + BluetoothDisable = 2, + UnknownError = 99 + }; + + [DllImport(pluginName)] + private static extern void _BlePluginBleAdapterStatusRequest(); + public static void BleAdapterStatusRequest() { + _BlePluginBleAdapterStatusRequest(); + } + + [DllImport(pluginName)] + private static extern int _BlePluginBleAdapterUpdate(); + public static EBluetoothStatus BleAdapterUpdate() + { + int val = _BlePluginBleAdapterUpdate(); + EBluetoothStatus status = (EBluetoothStatus)val; + return status; + } + + [DllImport(pluginName)] + private static extern void _BlePluginFinalize(); + public static void FinalizePlugin() + { + _BlePluginFinalize(); + } + + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginGetOrCreateUuidObject(uint d1, uint d2, uint d3, uint d4); + public static UuidHandler GetOrCreateUuidObject(uint d1, uint d2, uint d3, uint d4) + { + var ptr = _BlePluginGetOrCreateUuidObject(d1, d2, d3, d4); + return new UuidHandler(ptr); + } + + + [DllImport(pluginName)] + private static extern void _BlePluginConvertUuidUint128(IntPtr ptr,IntPtr outData); + public static unsafe UuidData ConvertUuidData(UuidHandler handler) + { + UuidData data = new UuidData(); + UuidBuffer uuidBuffer = new UuidBuffer(); + void* ptr = &uuidBuffer.fixedBuffer[0]; + _BlePluginConvertUuidUint128(handler.ptr, new IntPtr(ptr)); + + data.data1 = uuidBuffer.fixedBuffer[0]; + data.data2 = uuidBuffer.fixedBuffer[1]; + data.data3 = uuidBuffer.fixedBuffer[2]; + data.data4 = uuidBuffer.fixedBuffer[3]; + return data; + } + + [DllImport(pluginName)] + private static extern void _BlePluginUpdateWatcher(); + [DllImport(pluginName)] + private static extern void _BlePluginUpdateDevicdeManger(); + + public static void UpdateFromMainThread() + { + _BlePluginUpdateWatcher(); + _BlePluginUpdateDevicdeManger(); + } + + [DllImport(pluginName)] + public static extern void _BlePluginAddScanServiceUuid(IntPtr ptr); + public static void AddScanServiceUuid(UuidHandler uuid) + { + _BlePluginAddScanServiceUuid(uuid.ptr); + } + + [DllImport(pluginName)] + private static extern void _BlePluginStartScan(); + public static void StartScan() + { + _BlePluginStartScan(); + } + + [DllImport(pluginName)] + private static extern void _BlePluginStopScan(); + public static void StopScan() + { + _BlePluginStopScan(); + } + + [DllImport(pluginName)] + private static extern void _BlePluginClearScanFilter(); + public static void ClearScanFilter() + { + _BlePluginClearScanFilter(); + } + + // Scan Data + [DllImport(pluginName)] + private static extern int _BlePluginScanGetDeviceLength(); + public static int ScanGetDeviceLength() + { + return _BlePluginScanGetDeviceLength(); + } + + [DllImport(pluginName)] + private static extern ulong _BlePluginScanGetDeviceAddr(int idx); + public static ulong ScanGetDeviceAddr(int idx) + { + return _BlePluginScanGetDeviceAddr(idx); + } + + [DllImport(pluginName)] + private static extern string _BlePluginScanGetDeviceName(int idx); + public static string ScanGetDeviceName(int idx) + { + return _BlePluginScanGetDeviceName(idx); + } + [DllImport(pluginName)] + private static extern int _BlePluginScanGetDeviceRssi(int idx); + public static int ScanGetDeviceRssi(int idx) + { + return _BlePluginScanGetDeviceRssi(idx); + } + + // Connect Dissconnect + [DllImport(pluginName)] + private static extern IntPtr _BlePluginConnectDevice(ulong addr); + public static void ConnectDevice(ulong addr) + { + _BlePluginConnectDevice(addr); + } + + [DllImport(pluginName)] + private static extern void _BlePluginDisconnectDevice(ulong addr); + public static void DisconnectDevice(ulong addr) + { + _BlePluginDisconnectDevice(addr); + } + [DllImport(pluginName)] + private static extern void _BlePluginDisconnectAllDevice(); + public static void DisconnectAllDevice() + { + _BlePluginDisconnectAllDevice(); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsDeviceConnectedByAddr(ulong addr); + public static bool IsDeviceConnected(ulong addr) + { + return _BlePluginIsDeviceConnectedByAddr(addr); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsDeviceConnected(IntPtr devicePtr); + public static bool IsDeviceConnected(BleDeviceHandler handle) + { + return _BlePluginIsDeviceConnected(handle.ptr); + } + [DllImport(pluginName)] + private static extern ulong _BlePluginDeviceGetAddr(IntPtr devicePtr); + public ulong GetDeviceAddr(BleDeviceHandler handle) { + return _BlePluginDeviceGetAddr(handle.ptr); + } + + // GetDevice + [DllImport(pluginName)] + private static extern int _BlePluginGetConectDeviceNum(); + public static int GetConnectDeviceNum() + { + return _BlePluginGetConectDeviceNum(); + } + + [DllImport(pluginName)] + private static extern ulong _BlePluginGetConectDevicAddr(int idx); + public static ulong GetConnectDeviceAddr(int idx) + { + return _BlePluginGetConectDevicAddr(idx); + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginGetConnectDevicePtr(int idx); + public static BleDeviceHandler GetConnectDevicePtr(int idx) + { + var ptr = _BlePluginGetConnectDevicePtr(idx); + var handle =new BleDeviceHandler(ptr); + return handle; + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginGetDevicePtrByAddr(ulong addr); + public static BleDeviceHandler GetDeviceHandleByAddr(ulong addr) + { + var ptr = _BlePluginGetDevicePtrByAddr(addr); + var handle = new BleDeviceHandler(ptr); + return handle; + } + + [DllImport(pluginName)] + private static extern int _BlePluginDeviceCharastricsNum(IntPtr devicePtr); + public static int GetDeviceCharastricsNum(BleDeviceHandler handle) + { + return _BlePluginDeviceCharastricsNum(handle.ptr); + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginDeviceCharastricUuid(IntPtr devicePtr, int idx); + public static UuidHandler GetDeviceCharastricUuid(BleDeviceHandler handle,int idx) + { + var ptr = _BlePluginDeviceCharastricUuid(handle.ptr, idx); + var uuid = new UuidHandler(ptr); + return uuid; + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginDeviceCharastricServiceUuid(IntPtr devicePtr, int idx); + public static UuidHandler GetDeviceCharastricServiceUuid(BleDeviceHandler handle,int idx) + { + var ptr = _BlePluginDeviceCharastricServiceUuid(handle.ptr, idx); + var uuid = new UuidHandler(ptr); + return uuid; + + } + + + // Read/Write Request + [DllImport(pluginName)] + private static extern IntPtr _BlePluginReadCharacteristicRequest(ulong addr, IntPtr serviceUuid, IntPtr charaUuid); + public static ReadRequestHandler ReadCharastristicRequest(ulong addr,UuidHandler serviceUuid,UuidHandler charaUuid) + { + var ptr = _BlePluginReadCharacteristicRequest(addr, serviceUuid.ptr, charaUuid.ptr); + var handle = new ReadRequestHandler(ptr); + return handle; + } + [DllImport(pluginName)] + private static extern IntPtr _BlePluginWriteCharacteristicRequest(ulong addr, IntPtr serviceUuid, IntPtr charaUuid, IntPtr data, int size); + public static unsafe WriteRequestHandler WriteCharastristicRequest(ulong addr,UuidHandler serviceUuid,UuidHandler charaUuid, byte[] data, int idx,int size) + { + IntPtr resultPtr; + fixed (void* ptr = &data[idx]) + { + var dataPtr = new IntPtr(ptr); + resultPtr = _BlePluginWriteCharacteristicRequest(addr, serviceUuid.ptr, charaUuid.ptr, dataPtr, size); + } + var handle = new WriteRequestHandler(resultPtr); + return handle; + } + public static WriteRequestHandler WriteCharastristicRequest(ulong addr, UuidHandler serviceUuid, UuidHandler charaUuid, byte[] data) + { + return WriteCharastristicRequest(addr, serviceUuid, charaUuid, data, 0, data.Length); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsReadRequestComplete(IntPtr ptr); + public static bool IsReadRequestComplete(ReadRequestHandler handle) + { + return _BlePluginIsReadRequestComplete(handle.ptr); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsReadRequestError(IntPtr ptr); + public static bool IsReadRequestError(ReadRequestHandler handle) + { + return _BlePluginIsReadRequestError(handle.ptr); + } + + [DllImport(pluginName)] + private static extern int _BlePluginCopyReadRequestData(IntPtr ptr, IntPtr data, int maxSize); + public static unsafe byte[] GetReadRequestData(ReadRequestHandler handle,int maxSize) + { + byte[] retData = null; + var buffer = new CharastricsBuffer(); + void* ptr = &buffer.fixedBuffer[0]; + var writePtr = new IntPtr(ptr); + + int size = _BlePluginCopyReadRequestData(handle.ptr, writePtr, + CharastricsBuffer.BufferSize); + + retData = new byte[size]; + for(int i = 0; i < size; ++i) + { + retData[i] = buffer.fixedBuffer[i]; + } + return retData; + } + + [DllImport(pluginName)] + private static extern void _BlePluginReleaseReadRequest(ulong deviceaddr, IntPtr ptr); + public static void ReleaseReadRequest(ulong deviceAddr,ReadRequestHandler handle) + { + _BlePluginReleaseReadRequest(deviceAddr, handle.ptr); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsWriteRequestComplete(IntPtr ptr); + public static bool IsWriteRequestComplete(WriteRequestHandler handle) + { + return _BlePluginIsWriteRequestComplete(handle.ptr); + } + + [DllImport(pluginName)] + private static extern bool _BlePluginIsWriteRequestError(IntPtr ptr); + public static bool IsWriteRequestError(WriteRequestHandler handle) + { + return _BlePluginIsWriteRequestError(handle.ptr); + } + + [DllImport(pluginName)] + private static extern void _BlePluginReleaseWriteRequest(ulong deviceaddr, IntPtr ptr); + + public static void ReleaseWriteRequest(ulong deviceAddr, WriteRequestHandler handle) + { + _BlePluginReleaseWriteRequest(deviceAddr, handle.ptr); + } + + // Notificate + [DllImport(pluginName)] + private static extern void _BlePluginSetNotificateRequest(ulong addr, IntPtr serviceUuid, IntPtr charaUuid, bool enable); + public static void SetNotificationRequest(ulong addr,UuidHandler serviceUuid,UuidHandler charaUuid,bool flag) + { + _BlePluginSetNotificateRequest(addr, serviceUuid.ptr, charaUuid.ptr, flag); + } + + + [DllImport(pluginName)] + private static extern int _BlePluginGetDeviceNotificateNum(ulong addr); + public static int GetDeviceNotificateNum(ulong addr) + { + return _BlePluginGetDeviceNotificateNum(addr); + } + + [DllImport(pluginName)] + private static extern int _BlePluginCopyDeviceNotificateData(ulong addr, int idx, IntPtr ptr, int maxSize); + + public static unsafe byte[] GetDeviceNotificateData(ulong addr, int idx) + { + byte[] retData = null; + var buffer = new CharastricsBuffer(); + void* ptr = &buffer.fixedBuffer[0]; + var writePtr = new IntPtr(ptr); + int size =_BlePluginCopyDeviceNotificateData(addr, idx, writePtr, CharastricsBuffer.BufferSize); + retData = new byte[size]; + for(int i = 0; i< size; ++i) + { + retData[i] = buffer.fixedBuffer[i]; + } + + return retData; + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginGetDeviceNotificateServiceUuid(ulong addr, int idx); + public static UuidHandler GetDeviceNotificateServiceUuid(ulong addr,int idx) + { + var ptr = _BlePluginGetDeviceNotificateServiceUuid(addr,idx); + return new UuidHandler(ptr); + } + + [DllImport(pluginName)] + private static extern IntPtr _BlePluginGetDeviceNotificateCharastricsUuid(ulong addr, int idx); + public static UuidHandler GetDeviceNotificateCharastricsUuid(ulong addr, int idx) + { + var ptr = _BlePluginGetDeviceNotificateCharastricsUuid(addr, idx); + return new UuidHandler(ptr); + } + + + } +} +#endif diff --git a/Assets/Plugins/x86_64/DllInterface.cs.meta b/Assets/Plugins/x86_64/DllInterface.cs.meta new file mode 100644 index 0000000..515aef1 --- /dev/null +++ b/Assets/Plugins/x86_64/DllInterface.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5337fff6ced611a469a4b48bb061c99c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/UuidDatabase.cs b/Assets/Plugins/x86_64/UuidDatabase.cs new file mode 100644 index 0000000..1c5c327 --- /dev/null +++ b/Assets/Plugins/x86_64/UuidDatabase.cs @@ -0,0 +1,99 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +#if UNITY_EDITOR_WIN || UNITY_STANDALONE_WIN +namespace toio.Windows +{ + public class UuidDatabase + { + private static Dictionary uuidDictByStr; + private static Dictionary uuidDictByHandle; + + static UuidDatabase() + { + uuidDictByStr = new Dictionary(); + uuidDictByHandle = new Dictionary(); + } + + public static UuidHandler GetUuid(string str) + { + uint d1, d2, d3, d4; + str = str.ToUpper(); + var handle = new UuidHandler(); + if(uuidDictByStr.TryGetValue(str,out handle)) + { + return handle; + } + ParseUuid(str, out d1, out d2, out d3, out d4); + handle = DllInterface.GetOrCreateUuidObject(d1, d2, d3, d4); + uuidDictByStr.Add(str, handle); + uuidDictByHandle.Add(handle,str); + return handle; + } + + public static string GetUuidStr(UuidHandler handle) + { + string str; + if (uuidDictByHandle.TryGetValue(handle, out str)) + { + return str; + } + var data = DllInterface.ConvertUuidData(handle); + str = data.ToString(); + uuidDictByStr.Add(str, handle); + uuidDictByHandle.Add(handle, str); + return str; + + } + + private static void ParseUuid(string str, + out uint d1, out uint d2, out uint d3, out uint d4) + { + d1 = d2 = d3 = d4 = 0; + int idx = 0; + idx = GetUintFromString(str, idx, out d1); + idx = GetUintFromString(str, idx, out d2); + idx = GetUintFromString(str, idx, out d3); + idx = GetUintFromString(str, idx, out d4); + } + + private static int GetUintFromString(string str, int idx, out uint data) + { + data = 0; + int length = str.Length; + int currentExecChar = 0; + for (; idx < length; ++idx) + { + char ch = str[idx]; + int val = 0; + if ('0' <= ch && ch <= '9') + { + val = ch - '0'; + } + else if ('A' <= ch && ch <= 'F') + { + val = (ch - 'A') + 10; + } + else if ('a' <= ch && ch <= 'f') + { + val = (ch - 'a') + 10; + } + else + { + continue; + } + data = data << 4; + data |= (uint)val; + + ++currentExecChar; + if (currentExecChar >= 8) + { + break; + } + } + return idx + 1; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/x86_64/UuidDatabase.cs.meta b/Assets/Plugins/x86_64/UuidDatabase.cs.meta new file mode 100644 index 0000000..aa6c96d --- /dev/null +++ b/Assets/Plugins/x86_64/UuidDatabase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db5219d5a289ca54e9c696b60e1932b6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef b/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef new file mode 100644 index 0000000..94a8c27 --- /dev/null +++ b/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef @@ -0,0 +1,16 @@ +{ + "name": "bleplugin-x86_64", + "references": [], + "includePlatforms": [ + "Editor", + "WindowsStandalone64" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef.meta b/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef.meta new file mode 100644 index 0000000..602c763 --- /dev/null +++ b/Assets/Plugins/x86_64/bleplugin-x86_64.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 37c867e08014dc241a81d134efb0e6ef +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.cpp b/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.cpp new file mode 100644 index 0000000..7ae9644 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.cpp @@ -0,0 +1,104 @@ +#include "BleDeviceManager.h" +#include "BleDeviceObject.h" + +using namespace BlePlugin; + + +BleDeviceManager BleDeviceManager::s_instance; +BleDeviceManager& BleDeviceManager::GetInstance() { + return s_instance; +} + +BleDeviceObject* BleDeviceManager::ConnectDevice(uint64_t addr) { + + BleDeviceObject* deviceObj = this->GetDeviceByAddr(addr); + if (deviceObj == nullptr) { + deviceObj = new BleDeviceObject(addr); + m_devices.push_back(deviceObj); + } + deviceObj->ConnectRequest(); + return nullptr; +} +BleDeviceObject* BleDeviceManager::GetDeviceByAddr(uint64_t addr) { + for (auto it = m_devices.begin(); it != m_devices.end(); ++it) { + BleDeviceObject* devicePtr = (*it); + if (devicePtr == nullptr) { + continue; + } + if (devicePtr->GetAddr() == addr) { + return devicePtr; + } + } + return nullptr; +} +void BleDeviceManager::DisconnectDevice(uint64_t addr) { + BleDeviceObject* deviceObj = this->GetDeviceByAddr(addr); + if (deviceObj != nullptr) { + deviceObj->Disconnect(); + } +} + + +void BleDeviceManager::DisconnectAll() { + for (auto it = m_devices.begin(); it != m_devices.end(); ++it) { + BleDeviceObject* deviceObj = *it; + if (deviceObj == nullptr) { + continue; + } + if (deviceObj->IsConnected()) { + deviceObj->Disconnect(); + } + } +} +void BleDeviceManager::ResetAll() { + this->DisconnectAll(); + m_connectDevices.clear(); + // clear all device memory + for (auto it = m_devices.begin(); it != m_devices.end(); ++it) { + BleDeviceObject* devicePtr = (*it); + if (devicePtr == nullptr) { + continue; + } + delete devicePtr; + } + m_devices.clear(); +} + + +int BleDeviceManager::GetConnectedDeviceNum()const { + return static_cast( m_connectDevices.size() ); +} + +BleDeviceObject* BleDeviceManager::GetConnectedDeviceByIndex(int idx) { + return m_connectDevices.at(idx); +} + +void BleDeviceManager::Update() { + m_connectDevices.clear(); + for (auto it = m_devices.begin(); it != m_devices.end(); ++it) { + BleDeviceObject* deviceObj = *it; + if (deviceObj == nullptr) { + continue; + } + deviceObj->Update(); + if (deviceObj->IsConnected()) { + m_connectDevices.push_back(deviceObj); + } + } +} + + +winrt::fire_and_forget BleDeviceManager::Characteristic_ValueChanged(WinRtBleCharacteristic const& charastrics, WinRtBleValueChangedEventArgs args) { + winrt::fire_and_forget ret; + uint64_t addr = charastrics.Service().Device().BluetoothAddress(); + BleDeviceObject* obj = BleDeviceManager::GetInstance().GetDeviceByAddr(addr); + if (obj == nullptr) { + return ret; + } + WinRtGuid serviceUuid = charastrics.Service().Uuid(); + WinRtGuid charastricsUuid = charastrics.Uuid(); + uint8_t* data = args.CharacteristicValue().data(); + int length = args.CharacteristicValue().Length(); + obj->OnChangeValue(serviceUuid, charastricsUuid, data, length); + return ret; +} diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.h b/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.h new file mode 100644 index 0000000..a858f7e --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceManager.h @@ -0,0 +1,30 @@ +#pragma once +#include "pch.h" + + + +namespace BlePlugin { + class BleDeviceObject; + class BleDeviceManager { + static BleDeviceManager s_instance; + std::vector < BleDeviceObject*> m_devices; + std::vector < BleDeviceObject*> m_connectDevices; + + public: + static BleDeviceManager& GetInstance(); + + BleDeviceObject* ConnectDevice(uint64_t addr); + BleDeviceObject* GetDeviceByAddr(uint64_t addr); + void DisconnectDevice(uint64_t addr); + void DisconnectAll(); + void ResetAll(); + + int GetConnectedDeviceNum()const; + BleDeviceObject* GetConnectedDeviceByIndex(int idx); + void Update(); + + static winrt::fire_and_forget Characteristic_ValueChanged(WinRtBleCharacteristic const&, WinRtBleValueChangedEventArgs args); + + + }; +} \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.cpp b/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.cpp new file mode 100644 index 0000000..b9b5fe7 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.cpp @@ -0,0 +1,237 @@ +#include "BleDeviceObject.h" +#include "BleDeviceManager.h" +#include "Utility.h" + + +using namespace BlePlugin; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Devices::Bluetooth; + +BleDeviceObject::BleDeviceObject(uint64_t addr) : +m_addr(addr), m_device(nullptr),m_connectState(EConnectState::None) +{ +} + +bool BleDeviceObject::IsConnected()const { + return (m_connectState == EConnectState::GattServiceComplete); +} + + +void BleDeviceObject::ConnectRequest() { + UpdateDisconectCheck(); + if (m_connectState == EConnectState::None) { + m_connectAsync = BluetoothLEDevice::FromBluetoothAddressAsync(m_addr); + m_connectState = EConnectState::Connecting; + } +} +void BleDeviceObject::Disconnect() { + for (auto it = m_services.begin(); it != m_services.end(); ++it) { + it->Close(); + } + if (m_device != nullptr) { + m_device.Close(); + } + this->ClearDeviceInfo(); +} + +void BleDeviceObject::Update() { + // DeviceRequest + switch (m_connectState) { + case EConnectState::Connecting: + if (m_connectAsync.Status() == AsyncStatus::Completed) { + m_device = m_connectAsync.get(); + m_connectGattAsync = m_device.GetGattServicesAsync(); + this->m_connectState = EConnectState::GattServiceRequesting; + } + else if (m_connectAsync.Status() == AsyncStatus::Error) { + Disconnect(); + } + break; + case EConnectState::GattServiceRequesting: + if (m_connectGattAsync.Status() == AsyncStatus::Completed) { + auto gattResult = m_connectGattAsync.get(); + this->SetupGattServices(gattResult); + this->m_connectState = EConnectState::GattCharastricsRequesting; + } + else if (m_connectGattAsync.Status() == AsyncStatus::Error) { + Disconnect(); + } + break; + case EConnectState::GattCharastricsRequesting: + UpdateCharacterisc(); + break; + } + this->UpdateDisconectCheck(); + this->UpdateNotification(); +} +void BleDeviceObject::UpdateCharacterisc() { + bool hasError = false; + for (auto it = m_charastricsRequests.begin(); it != m_charastricsRequests.end(); ) { + if (it->Status() == AsyncStatus::Completed) { + auto result = it->get(); + SetupCharacterisc(result); + it = m_charastricsRequests.erase(it); + } + else if (it->Status() == AsyncStatus::Error) { + hasError = true; + } + else { + ++it; + } + } + if (hasError) { + Disconnect(); + return; + } + if (m_charastricsRequests.size() == 0) { + m_connectState = EConnectState::GattServiceComplete; + } +} + +void BleDeviceObject::SetupCharacterisc(const WinRtBleCharacteristicsResult& result) { + auto charastricses = result.Characteristics(); + int size = charastricses.Size(); + if (size == 0) { + return; + } + auto serviceUUid = charastricses.GetAt(0).Service().Uuid(); + + for (int i = 0; i < size; ++i) { + auto ch = charastricses.GetAt(i); + m_charastrictics.push_back(ch); + } +} + + + +void BleDeviceObject::SetupGattServices(const WinRtBleGattServiceResult& result) { + this->m_services.clear(); + auto services = result.Services(); + int size = services.Size(); + for (int i = 0; i < size; ++i) { + m_services.push_back( services.GetAt(i) ); + } + + this->m_charastricsRequests.clear(); + for (auto it = m_services.begin(); it != m_services.end(); ++it) { + WinRtAsyncOperation request + =it->GetCharacteristicsAsync(); + WinRtGuid guid = it->Uuid(); + + m_charastricsRequests.push_back(request); + } +} + +WinRtBleCharacteristic* BleDeviceObject::GetCharastric(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid) { + for (auto it = m_charastrictics.begin();it != m_charastrictics.end(); ++it) { + if (it->Uuid() == charastricsUuid && + it->Service().Uuid() == serviceUuid) { + return &*it; + } + } + return nullptr; +} + +WinRtAsyncOperation< WinRtGattWriteResult>* BleDeviceObject::WriteRequest(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid, + const uint8_t* src, int size) { + WinRtBleCharacteristic* charastrics = this->GetCharastric(serviceUuid, charastricsUuid); + if (charastrics == nullptr) { + return nullptr; + } + auto buf = winrt::Windows::Storage::Streams::Buffer(size); + buf.Length(size); + uint8_t* ptr = buf.data(); + for (int i = 0; i < size; ++i) { + *ptr = *src; + ++ptr; + ++src; + } + auto result = charastrics->WriteValueWithResultAsync(buf); + auto it = m_writeRequest.insert(m_writeRequest.begin(), result); + return &(*it); +} + +WinRtAsyncOperation< WinRtGattReadResult>* BleDeviceObject::ReadRequest(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid) { + WinRtBleCharacteristic* charastrics = this->GetCharastric(serviceUuid, charastricsUuid); + if (charastrics == nullptr) { + return nullptr; + } + auto result = charastrics->ReadValueAsync(); + + auto it = m_readRequest.insert(m_readRequest.begin(),result); + return &(*it); +} + +void BleDeviceObject::RemoveWriteOperation(WinRtAsyncOperation< WinRtGattWriteResult>* operation) { + for (auto it = m_writeRequest.begin(); it != m_writeRequest.end(); ++it) { + if (&(*it) == operation) { + m_writeRequest.erase(it); + break; + } + } +} +void BleDeviceObject::RemoveReadOperation(WinRtAsyncOperation< WinRtGattReadResult>* operation) { + for (auto it = m_readRequest.begin(); it != m_readRequest.end(); ++it) { + if (&(*it) == operation) { + m_readRequest.erase(it); + break; + } + } +} + + +void BleDeviceObject::SetValueChangeNotification(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid, bool isnotificate) { + WinRtBleCharacteristic* charastrics = this->GetCharastric(serviceUuid, charastricsUuid); + if (charastrics == nullptr) { + return; + } + if (isnotificate) { + charastrics->WriteClientCharacteristicConfigurationDescriptorAsync(WinRtCharacteristicConfigValue::Notify); + charastrics->ValueChanged(BleDeviceManager::Characteristic_ValueChanged); + } + else { + charastrics->WriteClientCharacteristicConfigurationDescriptorAsync(WinRtCharacteristicConfigValue::None); + charastrics->ValueChanged(nullptr); + } +} + +void BleDeviceObject::OnChangeValue(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid, uint8_t* data, int size) { + NotificateData notificateData(serviceUuid, charastricsUuid, data, size); + { + std::lock_guard lock(m_notificateMutex); + this->m_NotificateBuffer.push_back(notificateData); + } +} + +void BleDeviceObject::UpdateNotification() { + m_NotificateResult.clear(); + std::lock_guard lock(m_notificateMutex); + for (auto it = m_NotificateBuffer.begin(); it != m_NotificateBuffer.end(); ++it) { + m_NotificateResult.push_back(*it); + } + m_NotificateBuffer.clear(); +} + +void BleDeviceObject::UpdateDisconectCheck() { + if (this->m_connectState != EConnectState::GattServiceComplete) { + return; + } + if( this->m_device.ConnectionStatus() != WinRtBleConnectStatus::Connected){ + ClearDeviceInfo(); + this->m_connectState = EConnectState::None; + } +} +void BleDeviceObject::ClearDeviceInfo() { + m_services.clear(); + m_charastrictics.clear(); + + m_charastricsRequests.clear(); + + m_readRequest.clear(); + m_writeRequest.clear(); + + m_NotificateBuffer.clear(); + m_NotificateResult.clear(); + + m_device = WinRtBleDevice(nullptr); +} diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.h b/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.h new file mode 100644 index 0000000..3560789 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceObject.h @@ -0,0 +1,129 @@ +#pragma once + +#include "pch.h" + +namespace BlePlugin { + class NotificateData { + public: + // 上限は 22byte… + static const int MaxDataSize = 22; + private: + WinRtGuid service; + WinRtGuid charastrics; + uint8_t data[MaxDataSize]; + int size; + private: + void SetData(const uint8_t* src, int length) { + for (int i = 0; i < length && i < sizeof(data); ++i) { + data[i] = src[i]; + } + } + public: + NotificateData(const WinRtGuid &_service, + const WinRtGuid& _charastrics,uint8_t* _data,int _size) : + service(_service), charastrics(_charastrics),size(_size),data() + { + SetData(_data, _size); + } + NotificateData(const NotificateData& src) : + service (src.service),charastrics(src.charastrics), + size(src.size), data() + { + SetData(src.data, src.size); + } + NotificateData& operator =(const NotificateData& src) { + this->service = src.service; + this->charastrics = src.charastrics; + SetData(src.data, src.size); + return *this; + } + inline const WinRtGuid& GetServiceUuid()const { + return service; + } + inline const WinRtGuid& GetCharastricsUuid()const { + return charastrics; + } + inline const uint8_t* GetData()const { + return data; + } + inline int GetSize()const { + return size; + } + + }; + + class BleDeviceObject { + private: + enum class EConnectState { + None = 0, + Connecting = 1, + GattServiceRequesting = 2, + GattCharastricsRequesting = 3, + GattServiceComplete = 4, + }; + + + WinRtAsyncOperation m_connectAsync; + WinRtAsyncOperation m_connectGattAsync; + + uint64_t m_addr; + WinRtBleDevice m_device; + + std::vector m_services; + std::vector m_charastrictics; + + std::vector > m_charastricsRequests; + EConnectState m_connectState; + + std::list< WinRtAsyncOperation< WinRtGattReadResult> > m_readRequest; + std::list< WinRtAsyncOperation< WinRtGattWriteResult> > m_writeRequest; + std::vector< NotificateData> m_NotificateBuffer; + std::vector< NotificateData> m_NotificateResult; + std::mutex m_notificateMutex; + + public: + BleDeviceObject(uint64_t addr); + + bool IsConnected()const; + void ConnectRequest(); + void Disconnect(); + void Update(); + + WinRtAsyncOperation< WinRtGattWriteResult>* WriteRequest(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid, + const uint8_t* src, int size); + WinRtAsyncOperation< WinRtGattReadResult>* ReadRequest(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid); + + void RemoveWriteOperation(WinRtAsyncOperation< WinRtGattWriteResult>* operation); + void RemoveReadOperation(WinRtAsyncOperation< WinRtGattReadResult>* operation); + + void SetValueChangeNotification(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid,bool isnotificate); + void OnChangeValue(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid,uint8_t *data, int length); + + int GetNofiticateNum()const { + return static_cast(m_NotificateResult.size()); + } + const NotificateData& GetNotificateData(int idx)const { + return m_NotificateResult.at(idx); + } + + inline uint64_t GetAddr()const { + return this->m_addr; + } + + inline int GetCharastricsNum()const { + return static_cast( this->m_charastrictics.size()); + } + const WinRtBleCharacteristic& GetCharastrics(int idx) const { + return m_charastrictics.at(idx); + } + private: + WinRtBleCharacteristic* GetCharastric(const WinRtGuid& serviceUuid, const WinRtGuid& charastricsUuid); + void SetupGattServices(const WinRtBleGattServiceResult& result); + void UpdateCharacterisc(); + void SetupCharacterisc(const WinRtBleCharacteristicsResult& result); + + void UpdateNotification(); + void UpdateDisconectCheck(); + void ClearDeviceInfo(); + }; +} diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.cpp b/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.cpp new file mode 100644 index 0000000..89b5cd0 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.cpp @@ -0,0 +1,172 @@ +#include "BleDeviceWatcher.h" +#include "Utility.h" +#include + +using namespace BlePlugin; + + +BleDeviceWatcher BleDeviceWatcher::s_instance; +// DeviceInfo +BleDeviceWatcher::DeviceInfo::DeviceInfo(const char* _name, + uint64_t _addr,int _rssi) : + //name(_name), + addr(_addr), rssi(_rssi) { + this->lastFound = clock(); +} + +BleDeviceWatcher::DeviceInfo::DeviceInfo(const BleDeviceWatcher::DeviceInfo& src) + : + //name(src.name), + addr(src.addr),rssi(src.rssi),lastFound(src.lastFound) +{ +} + + + + +const BleDeviceWatcher::DeviceInfo & + BleDeviceWatcher::DeviceInfo::operator= (const BleDeviceWatcher::DeviceInfo &src) +{ +// this->name = src.name; + this->addr = src.addr; + this->rssi = src.rssi; + this->lastFound = src.lastFound; + return *this; +} + + +void BleDeviceWatcher::DeviceInfo::Update(int _rssi) { + lastFound = clock(); + this->rssi = _rssi; +} + + + +// BleWatcher +BleDeviceWatcher& BleDeviceWatcher::GetInstance() { + return s_instance; +} + +void BleDeviceWatcher::ClearFilterServiceUUID() { + m_filer.Advertisement().ServiceUuids().Clear(); +} + +void BleDeviceWatcher::AddServiceUUID(const WinRtGuid& guid) { + m_filer.Advertisement().ServiceUuids().Append(guid); +} + +void BleDeviceWatcher::AddServiceUUID(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) { + auto guid = Utility::CreateGUID(d1, d2, d3, d4); + m_filer.Advertisement().ServiceUuids().Append(guid); +} + +void BleDeviceWatcher::Start() { + + // TODO + // https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothlescanningmode?view=winrt-22000 + // Activeスキャンすれば、ScanResponseとかでデータが取れるはずですが… + // Filterを設定していると、ScanResponseがフィルターされて来ませんでした。 + // ※nameとManufactureData対応をチャントやるとしたら自前で ServiceのUUIDでフィルターしないといけなさそうです… + m_watcher.AdvertisementFilter(m_filer); + m_watcher.ScanningMode(WinRtBleScanMode::Passive); + m_watcher.Received(BleDeviceWatcher::ReceiveCallBack); + m_watcher.Start(); + +} +void BleDeviceWatcher::Stop() { + m_watcher.Stop(); +} + +void BleDeviceWatcher::UpdateCache() { + + clock_t current = clock(); + std::lock_guard lock(mtx); + m_cacheData.clear(); + for (auto it = m_DeviceMap.begin(); + it != m_DeviceMap.end(); ++it) { + if (it->second.IsTimeout(current)) { + continue; + } + m_cacheData.push_back(it->second); + } +} + +int BleDeviceWatcher::GetDeviceNum()const { + return static_cast(m_cacheData.size()); +} + +const char* BleDeviceWatcher::GetName(int idx)const { + if (idx < 0 || idx >= m_cacheData.size()) { + return nullptr; + } + return "";// m_cacheData.at(idx).name.c_str(); +} +uint64_t BleDeviceWatcher::GetAddr(int idx)const { + if (idx < 0 || idx >= m_cacheData.size()) { + return 0; + } + return m_cacheData.at(idx).addr; +} + +int BleDeviceWatcher::GetRssi(int idx)const { + if (idx < 0 || idx >= m_cacheData.size()) { + return 0; + } + return m_cacheData.at(idx).rssi; +} + +void BleDeviceWatcher::OnConnectDevice(uint64_t addr) { + m_DeviceMap.erase(addr); +} + +BleDeviceWatcher::BleDeviceWatcher() { +} +BleDeviceWatcher::~BleDeviceWatcher() { +} + +void BleDeviceWatcher::ReceiveCallBack( + WinRtBleAdvertiseWatcher sender, + WinRtBleAdvertiseRecieveEventArg args) { + GetInstance().OnReceive(sender, args); +} + +void BleDeviceWatcher::OnReceive( + WinRtBleAdvertiseWatcher sender, + WinRtBleAdvertiseRecieveEventArg args) +{ + std::lock_guard lock(mtx); + int rssi = args.RawSignalStrengthInDBm(); + uint64_t addr = args.BluetoothAddress(); + auto advertisement = args.Advertisement(); + + +#if false + auto advertiseType = args.AdvertisementType(); + // toioだと、ConnectableUndirectedでは・・・ + // Advertiseのセクション 0x01と 0x07が来るが・・・ほかが来ない… + // ScanResponseでNameとManufactureDataが返ってきました。 + // ScanFilterをしないといけない + int dataSectionNum = advertisement.DataSections().Size(); + for (int i = 0; i < dataSectionNum; ++i) { + auto dataSection = advertisement.DataSections().GetAt(i); + uint8_t dataType = dataSection.DataType(); + uint8_t* dataBody = dataSection.Data().data(); + int sectionLength = dataSection.Data().Length(); + } + // name And ManufactureData + // toioでは ScanResponseで入ってくるデータ + int manufactureSize = advertisement.ManufacturerData().Size(); + auto name = advertisement.LocalName().c_str(); + int nameSize = advertisement.LocalName().size(); +#endif + + auto findIt = m_DeviceMap.find(addr); + if (findIt == m_DeviceMap.end()) { + DeviceInfo deviceInfo("", addr, rssi); + m_DeviceMap.emplace(addr, deviceInfo); + } + else { + findIt->second.Update(rssi); + } +} + diff --git a/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.h b/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.h new file mode 100644 index 0000000..8d9812d --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BleDeviceWatcher.h @@ -0,0 +1,82 @@ +#pragma once + +#include "pch.h" +#include +#include + +namespace BlePlugin { + + + class BleDeviceWatcher { + private: + + // デバイス情報 + struct DeviceInfo { + static const int TimeoutSec = 1500; +// std::string name; + uint64_t addr; + int rssi; + clock_t lastFound; + DeviceInfo() : + /* name(""),*/ + addr(0), rssi(0), lastFound(0) + { + } + DeviceInfo(const DeviceInfo& src); + DeviceInfo(const char* _name, + uint64_t _addr, + int _rssi); + + const DeviceInfo& operator =(const DeviceInfo& src); + + inline bool IsTimeout(clock_t current)const { + return ((current - this->lastFound) >= TimeoutSec); + } + + void Update(int _rssi); + + }; + // member + std::map m_DeviceMap; + std::vector m_cacheData; + static BleDeviceWatcher s_instance; + std::mutex mtx; + + public: + static BleDeviceWatcher& GetInstance(); + + void ClearFilterServiceUUID(); + void AddServiceUUID(const WinRtGuid &guid); + void AddServiceUUID(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4); + + void Start(); + void Stop(); + + void UpdateCache(); + int GetDeviceNum()const; + const char* GetName(int idx)const; + uint64_t GetAddr(int idx)const; + int GetRssi(int idx)const; + + void OnConnectDevice(uint64_t addr); + + private: + + BleDeviceWatcher(); + ~BleDeviceWatcher(); + + static void ReceiveCallBack( + WinRtBleAdvertiseWatcher sender, + WinRtBleAdvertiseRecieveEventArg args); + + void OnReceive( + WinRtBleAdvertiseWatcher sender, + WinRtBleAdvertiseRecieveEventArg args); + + WinRtBleAdvertiseWatcher m_watcher; + WinRtBleAdvertiseFilter m_filer; + + + }; + +} diff --git a/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj b/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj new file mode 100644 index 0000000..23bf9f7 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj @@ -0,0 +1,145 @@ + + + + + Debug + x64 + + + Release + x64 + + + UnityDll + x64 + + + + 16.0 + Win32Proj + {067aec9b-07d2-46d6-8e15-1624071c15c9} + BlePluginWin + 10.0.19041.0 + C++/WinRT + BlePluginWinows + + + + Application + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + MultiByte + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + true + + + false + + + false + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + stdcpp17 + NotUsing + pch.h + + + Console + true + windowsapp.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + pch.h + stdcpp17 + MultiThreaded + + + Windows + true + true + true + + + + + Level3 + true + true + true + UNITY_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + + + + + + Create + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj.filters b/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj.filters new file mode 100644 index 0000000..6f02df5 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BlePluginWin.vcxproj.filters @@ -0,0 +1,69 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + ソース ファイル + + + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + ヘッダー ファイル + + + \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.cpp b/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.cpp new file mode 100644 index 0000000..f4232e7 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.cpp @@ -0,0 +1,90 @@ +#include "BluetoothAdapterChecker.h" + +using namespace BlePlugin; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Devices::Radios; + +BluetoothAdapterChecker BluetoothAdapterChecker::s_instance; + + +BluetoothAdapterChecker::BluetoothAdapterChecker(): +bluetoothStatus(EBluetoothStatus::None), +status(ESearchStatus::None), +radio(nullptr), adapter(nullptr), +asyncBluetoothAdapter(), asyncRadio() +{ +} + +BluetoothAdapterChecker& BluetoothAdapterChecker::GetInstance() { + return s_instance; +} +void BluetoothAdapterChecker::Request() { + asyncBluetoothAdapter = winrt::Windows::Devices::Bluetooth::BluetoothAdapter::GetDefaultAsync(); + status = ESearchStatus::WaitingAdapter; + bluetoothStatus = EBluetoothStatus::None; +} +void BluetoothAdapterChecker::Update() { + switch (status) { + case ESearchStatus::WaitingAdapter: + UpdateWaitingAdapter(); + break; + case ESearchStatus::WaitingRadio: + UpdateWaitingRadio(); + break; + } +} + +void BluetoothAdapterChecker::UpdateWaitingAdapter() { + if (asyncBluetoothAdapter.Status() == AsyncStatus::Error) { + SetBluetoothStatus(EBluetoothStatus::UnknownError); + } + else if (asyncBluetoothAdapter.Status() == AsyncStatus::Completed) { + this->adapter = asyncBluetoothAdapter.get(); + if (this->adapter == nullptr) { + SetBluetoothStatus(EBluetoothStatus::UnknownError); + return; + } + if (!this->adapter.IsLowEnergySupported() || + !this->adapter.IsCentralRoleSupported()) { + SetBluetoothStatus(EBluetoothStatus::NotSupportBle); + return; + } + this->asyncRadio = this->adapter.GetRadioAsync(); + status = ESearchStatus::WaitingRadio; + } +} +void BluetoothAdapterChecker::UpdateWaitingRadio() { + if (asyncRadio.Status() == AsyncStatus::Error) { + SetBluetoothStatus(EBluetoothStatus::UnknownError); + } + else if (asyncRadio.Status() == AsyncStatus::Completed) { + this->radio = asyncRadio.get(); + if (this->radio == nullptr) { + SetBluetoothStatus(EBluetoothStatus::UnknownError); + return; + } + auto radioState = this->radio.State(); + if (radioState == RadioState::On) { + SetBluetoothStatus(EBluetoothStatus::Fine); + return; + } + else { + SetBluetoothStatus(EBluetoothStatus::BluetoothDisable); + } + } +} + +bool supportBle(){ + + + WinRtAsyncOperation res = winrt::Windows::Devices::Bluetooth::BluetoothAdapter::GetDefaultAsync(); + while (!res.Completed()) { + break; + } + winrt::Windows::Devices::Bluetooth::BluetoothAdapter adapter = res.get(); + bool enableBle = adapter.IsLowEnergySupported(); + auto radioSync = adapter.GetRadioAsync(); + winrt::Windows::Devices::Radios::Radio radio = radioSync.get(); + auto stat = radioSync.get().State(); + return true; +} diff --git a/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.h b/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.h new file mode 100644 index 0000000..9cda45b --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/BluetoothAdapterChecker.h @@ -0,0 +1,55 @@ +#pragma once + +#include "pch.h" +#include +#include + +namespace BlePlugin { + class BluetoothAdapterChecker { + public: + enum class EBluetoothStatus :int{ + None = -1, + Fine = 0, + NotSupportBle = 1, + BluetoothDisable = 2, + UnknownError = 99 + }; + private: + enum class ESearchStatus { + None, + WaitingAdapter, + WaitingRadio, + Complete + }; + static BluetoothAdapterChecker s_instance; + EBluetoothStatus bluetoothStatus; + ESearchStatus status; + + WinRtBluetoothAdapter adapter; + WinRtRadio radio; + + WinRtAsyncOperation asyncBluetoothAdapter; + WinRtAsyncOperation asyncRadio; + + BluetoothAdapterChecker(); + public: + static BluetoothAdapterChecker& GetInstance(); + void Request(); + void Update(); + inline bool IsRequestComplete()const { + return (this->bluetoothStatus != EBluetoothStatus::None); + } + EBluetoothStatus GetStatus()const { + return this->bluetoothStatus; + } + private: + + void UpdateWaitingAdapter(); + void UpdateWaitingRadio(); + + inline void SetBluetoothStatus(EBluetoothStatus stat) { + this->bluetoothStatus = stat; + this->status = ESearchStatus::Complete; + } + }; +} diff --git a/bleplugin_projects/Windows/BlePluginWin/UnityInterface.cpp b/bleplugin_projects/Windows/BlePluginWin/UnityInterface.cpp new file mode 100644 index 0000000..f035c15 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/UnityInterface.cpp @@ -0,0 +1,374 @@ +#include "pch.h" +#include "BleDeviceObject.h" +#include "BleDeviceWatcher.h" +#include "BleDeviceManager.h" +#include "BluetoothAdapterChecker.h" +#include "UUidManager.h" +#include "Utility.h" +#include +#include "UnityInterface.h" +using namespace BlePlugin; + +using namespace winrt::Windows::Foundation; + +// DLL EntryPoint +BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved +) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +DllExport void _BlePluginBleAdapterStatusRequest() { + BluetoothAdapterChecker &checker = BluetoothAdapterChecker::GetInstance(); + checker.Request(); +} +DllExport int _BlePluginBleAdapterUpdate() { + BluetoothAdapterChecker& checker = BluetoothAdapterChecker::GetInstance(); + checker.Update(); + return static_cast( checker.GetStatus() ); +} + +DllExport void _BlePluginFinalize() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.Stop(); + watcher.ClearFilterServiceUUID(); + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + manager.ResetAll(); +} + +DllExport void _BlePluginUpdateWatcher() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.UpdateCache(); +} + + +DllExport void _BlePluginUpdateDevicdeManger() { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + manager.Update(); +} + +DllExport UuidHandle _BlePluginGetOrCreateUuidObject(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) { + UuidManager& manager = UuidManager::GetInstance(); + auto ptr = manager.GetOrCreate(d1, d2, d3, d4); + return ptr; +} +DllExport void _BlePluginConvertUuidUint128(UuidHandle ptr, void* out) { + WinRtGuid* guid = reinterpret_cast(ptr); + Utility::ConvertFromGUID(*guid, reinterpret_cast(out)); +} + + +DllExport void _BlePluginAddScanServiceUuid(UuidHandle uuid) { + auto guid = reinterpret_cast(uuid); + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.AddServiceUUID(*guid); +} +DllExport void _BlePluginStartScan() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.Start(); +} +DllExport void _BlePluginStopScan() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.Stop(); +} + +DllExport void _BlePluginClearScanFilter() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + watcher.ClearFilterServiceUUID(); +} + +DllExport int _BlePluginScanGetDeviceLength() { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + return watcher.GetDeviceNum(); +} + +DllExport uint64_t _BlePluginScanGetDeviceAddr(int idx) { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + return watcher.GetAddr(idx); +} +const char* _BlePluginScanGetDeviceName(int idx) { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + return watcher.GetName(idx); +} + +DllExport int32_t _BlePluginScanGetDeviceRssi(int idx) { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); + return watcher.GetRssi(idx); +} + +DllExport void _BlePluginScanCopyDeviceManifactureData(int idx, void* ptr, int max) { + BleDeviceWatcher& watcher = BleDeviceWatcher::GetInstance(); +} + + + +DllExport DeviceHandle _BlePluginConnectDevice(uint64_t addr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject *obj = manager.ConnectDevice(addr); + return obj; +} +DllExport void _BlePluginDisconnectDevice(uint64_t addr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + manager.DisconnectDevice(addr); +} + +DllExport void _BlePluginDisconnectAllDevice() { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + manager.DisconnectAll(); +} + +DllExport bool _BlePluginIsDeviceConnectedByAddr(uint64_t addr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* obj = manager.GetDeviceByAddr(addr); + if (obj == nullptr) { + return false; + } + return obj->IsConnected(); +} +DllExport bool _BlePluginIsDeviceConnected(DeviceHandle devicePtr) { + + BleDeviceObject* obj = reinterpret_cast(devicePtr); + if (obj == nullptr) { + return false; + } + return obj->IsConnected(); +} +DllExport uint64_t _BlePluginDeviceGetAddr(DeviceHandle devicePtr) { + BleDeviceObject* obj = reinterpret_cast(devicePtr); + if (obj == nullptr) { + return 0; + } + return obj->GetAddr(); +} + + +DllExport int _BlePluginGetConectDeviceNum() { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + return manager.GetConnectedDeviceNum(); +} +DllExport uint64_t _BlePluginGetConectDevicAddr(int idx) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* obj = manager.GetConnectedDeviceByIndex(idx); + if (obj != nullptr) { + return obj->GetAddr(); + } + return 0; +} + +DllExport DeviceHandle _BlePluginGetConnectDevicePtr(int idx) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* obj = manager.GetConnectedDeviceByIndex(idx); + return obj; +} +DllExport DeviceHandle _BlePluginGetDevicePtrByAddr(uint64_t addr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* obj = manager.GetDeviceByAddr(addr); + return obj; +} + +DllExport int _BlePluginDeviceCharastricsNum(DeviceHandle devicePtr) { + BleDeviceObject* deviceObj = reinterpret_cast(devicePtr); + if (deviceObj == nullptr) { + return 0; + } + return deviceObj->GetCharastricsNum(); +} +DllExport UuidHandle _BlePluginDeviceCharastricUuid(DeviceHandle devicePtr, int idx) { + BleDeviceObject* deviceObj = reinterpret_cast(devicePtr); + if (deviceObj == nullptr) { + return nullptr; + } + WinRtGuid guid = deviceObj->GetCharastrics(idx).Uuid(); + WinRtGuid *retval = UuidManager::GetInstance().GetOrCreate(guid); + return retval; +} +DllExport UuidHandle _BlePluginDeviceCharastricServiceUuid(DeviceHandle devicePtr, int idx) { + BleDeviceObject* deviceObj = reinterpret_cast(devicePtr); + if (deviceObj == nullptr) { + return nullptr; + } + WinRtGuid guid = deviceObj->GetCharastrics(idx).Service().Uuid(); + WinRtGuid* retval = UuidManager::GetInstance().GetOrCreate(guid); + return retval; +} + + +DllExport ReadRequestHandle _BlePluginReadCharacteristicRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + WinRtGuid* serviceUuidObj = reinterpret_cast(serviceUuid); + WinRtGuid* charaUuidObj = reinterpret_cast(charaUuid); + if (deviceObj == nullptr || serviceUuidObj == nullptr || + charaUuidObj == nullptr) { + return nullptr; + } + auto ptr = deviceObj->ReadRequest(*serviceUuidObj, *charaUuidObj); + return reinterpret_cast(ptr); +} + +DllExport WriteRequestHandle _BlePluginWriteCharacteristicRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid, void* data, int size) { + + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject *deviceObj = manager.GetDeviceByAddr(addr); + WinRtGuid* serviceUuidObj = reinterpret_cast(serviceUuid); + WinRtGuid* charaUuidObj = reinterpret_cast(charaUuid); + if (deviceObj == nullptr || serviceUuidObj == nullptr || + charaUuidObj == nullptr ) { + return nullptr; + } + auto ptr = deviceObj->WriteRequest(*serviceUuidObj, *charaUuidObj, + reinterpret_cast(data), size); + return reinterpret_cast(ptr); + +} +DllExport bool _BlePluginIsReadRequestComplete(ReadRequestHandle ptr) { + auto operation = reinterpret_cast*>(ptr); + if (operation == nullptr) { + return true; + } + return (operation->Status() == AsyncStatus::Completed); +} +DllExport bool _BlePluginIsReadRequestError(ReadRequestHandle ptr) { + auto operation = reinterpret_cast*>(ptr); + if (operation == nullptr) { + return true; + } + return (operation->Status() == AsyncStatus::Error); +} +DllExport int _BlePluginCopyReadRequestData(ReadRequestHandle ptr, void* data, int maxSize) { + auto operation = reinterpret_cast*>(ptr); + if (operation == nullptr) { + return 0; + } + if (operation->Status() != AsyncStatus::Completed) { + return 0; + } + if (operation->get().Status() != WinRtGattCommunicateState::Success) { + return 0; + } + if (maxSize > NotificateData::MaxDataSize) { + maxSize = NotificateData::MaxDataSize; + } + int size = operation->get().Value().Length(); + uint8_t* dest = reinterpret_cast(data); + auto src = operation->get().Value().data(); + + for (int i = 0; i < size && i < maxSize; ++i) { + dest[i] = src[i]; + } + return size; +} +DllExport void _BlePluginReleaseReadRequest(uint64_t deviceaddr, ReadRequestHandle ptr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(deviceaddr); + if (deviceObj == nullptr) { + return; + } + auto operation = reinterpret_cast*>(ptr); + deviceObj->RemoveReadOperation(operation); +} + +DllExport bool _BlePluginIsWriteRequestComplete(WriteRequestHandle ptr) { + auto operation = reinterpret_cast*>(ptr); + if (operation == nullptr) { + return true; + } + return (operation->Status() == AsyncStatus::Completed); +} +DllExport bool _BlePluginIsWriteRequestError(WriteRequestHandle ptr) { + auto operation = reinterpret_cast*>(ptr); + if (operation == nullptr) { + return false; + } + if (operation->Status() == AsyncStatus::Error) { + return true; + } + if (operation->Status() == AsyncStatus::Completed && + operation->get().Status() != WinRtGattCommunicateState::Success) { + return true; + } + return false; +} +DllExport void _BlePluginReleaseWriteRequest(uint64_t deviceaddr, WriteRequestHandle ptr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(deviceaddr); + if (deviceObj == nullptr) { + return; + } + auto operation = reinterpret_cast*>(ptr); + deviceObj->RemoveWriteOperation(operation); +} + + +// Notification +DllExport void _BlePluginSetNotificateRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid, bool enable) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + WinRtGuid* serviceUuidObj = reinterpret_cast(serviceUuid); + WinRtGuid* charaUuidObj = reinterpret_cast(charaUuid); + if (deviceObj == nullptr || serviceUuidObj == nullptr || + charaUuidObj == nullptr) { + return; + } + deviceObj->SetValueChangeNotification(*serviceUuidObj, *charaUuidObj, enable); +} + +DllExport int _BlePluginGetDeviceNotificateNum(uint64_t addr) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + if (deviceObj == nullptr) { + return 0; + } + return deviceObj->GetNofiticateNum(); +} +DllExport int _BlePluginCopyDeviceNotificateData(uint64_t addr, int idx, void* ptr, int maxSize) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + if (deviceObj == nullptr) { + return 0; + } + const NotificateData& notifyData = deviceObj->GetNotificateData(idx); + const uint8_t* src = notifyData.GetData(); + int size = notifyData.GetSize(); + if (maxSize > NotificateData::MaxDataSize) { + maxSize = NotificateData::MaxDataSize; + } + uint8_t* dest = reinterpret_cast(ptr); + for (int i = 0; i < maxSize && i < size; ++i) { + dest[i] = src[i]; + } + return size; +} + +DllExport UuidHandle _BlePluginGetDeviceNotificateServiceUuid(uint64_t addr, int idx) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + if (deviceObj == nullptr) { + return nullptr; + } + const NotificateData& notifyData = deviceObj->GetNotificateData(idx); + UuidManager &uuidMgr = UuidManager::GetInstance(); + return uuidMgr.GetOrCreate( notifyData.GetServiceUuid() ); +} + +DllExport UuidHandle _BlePluginGetDeviceNotificateCharastricsUuid(uint64_t addr, int idx) { + BleDeviceManager& manager = BleDeviceManager::GetInstance(); + BleDeviceObject* deviceObj = manager.GetDeviceByAddr(addr); + if (deviceObj == nullptr) { + return nullptr; + } + const NotificateData& notifyData = deviceObj->GetNotificateData(idx); + UuidManager& uuidMgr = UuidManager::GetInstance(); + return uuidMgr.GetOrCreate(notifyData.GetCharastricsUuid()); +} + diff --git a/bleplugin_projects/Windows/BlePluginWin/UnityInterface.h b/bleplugin_projects/Windows/BlePluginWin/UnityInterface.h new file mode 100644 index 0000000..7e93851 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/UnityInterface.h @@ -0,0 +1,76 @@ +#pragma once +#include "pch.h" + +#define DllExport __declspec(dllexport) + +extern "C" { + typedef void* UuidHandle; + typedef void* DeviceHandle; + typedef void* WriteRequestHandle; + typedef void* ReadRequestHandle; + + DllExport void _BlePluginBleAdapterStatusRequest(); + DllExport int _BlePluginBleAdapterUpdate(); + + + DllExport void _BlePluginFinalize(); + + + DllExport UuidHandle _BlePluginGetOrCreateUuidObject(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4); + DllExport void _BlePluginConvertUuidUint128(UuidHandle ptr, void* out); + + DllExport void _BlePluginUpdateWatcher(); + DllExport void _BlePluginUpdateDevicdeManger(); + + DllExport void _BlePluginAddScanServiceUuid(UuidHandle uuid); + DllExport void _BlePluginStartScan(); + DllExport void _BlePluginStopScan(); + DllExport void _BlePluginClearScanFilter(); + + // Scan Data + DllExport int _BlePluginScanGetDeviceLength(); + DllExport uint64_t _BlePluginScanGetDeviceAddr(int idx); + DllExport const char* _BlePluginScanGetDeviceName(int idx); + DllExport int32_t _BlePluginScanGetDeviceRssi(int idx); + + // Connect Dissconnect + DllExport DeviceHandle _BlePluginConnectDevice(uint64_t addr); + DllExport void _BlePluginDisconnectDevice(uint64_t addr); + DllExport void _BlePluginDisconnectAllDevice(); + DllExport bool _BlePluginIsDeviceConnectedByAddr(uint64_t addr); + DllExport bool _BlePluginIsDeviceConnected(DeviceHandle devicePtr); + DllExport uint64_t _BlePluginDeviceGetAddr(DeviceHandle devicePtr); + + + // GetDevice + DllExport int _BlePluginGetConectDeviceNum(); + DllExport uint64_t _BlePluginGetConectDevicAddr(int idx); + DllExport DeviceHandle _BlePluginGetConnectDevicePtr(int idx); + DllExport DeviceHandle _BlePluginGetDevicePtrByAddr(uint64_t addr); + DllExport int _BlePluginDeviceCharastricsNum(DeviceHandle devicePtr); + DllExport UuidHandle _BlePluginDeviceCharastricUuid(DeviceHandle devicePtr, int idx); + DllExport UuidHandle _BlePluginDeviceCharastricServiceUuid(DeviceHandle devicePtr, int idx); + + // Read/Write Request + DllExport ReadRequestHandle _BlePluginReadCharacteristicRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid); + DllExport WriteRequestHandle _BlePluginWriteCharacteristicRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid, void* data, int size); + + DllExport bool _BlePluginIsReadRequestComplete(ReadRequestHandle ptr); + DllExport bool _BlePluginIsReadRequestError(ReadRequestHandle ptr); + DllExport int _BlePluginCopyReadRequestData(ReadRequestHandle ptr, void* data, int maxSize); + DllExport void _BlePluginReleaseReadRequest(uint64_t deviceaddr , ReadRequestHandle ptr); + + DllExport bool _BlePluginIsWriteRequestComplete(WriteRequestHandle ptr); + DllExport bool _BlePluginIsWriteRequestError(WriteRequestHandle ptr); + DllExport void _BlePluginReleaseWriteRequest(uint64_t deviceaddr, WriteRequestHandle ptr); + + // notificate + DllExport void _BlePluginSetNotificateRequest(uint64_t addr, UuidHandle serviceUuid, UuidHandle charaUuid, bool enable); + + DllExport int _BlePluginGetDeviceNotificateNum(uint64_t addr); + DllExport int _BlePluginCopyDeviceNotificateData(uint64_t addr, int idx, void* ptr, int maxSize); + DllExport UuidHandle _BlePluginGetDeviceNotificateServiceUuid(uint64_t addr, int idx); + DllExport UuidHandle _BlePluginGetDeviceNotificateCharastricsUuid(uint64_t addr, int idx); + +} + diff --git a/bleplugin_projects/Windows/BlePluginWin/Utility.h b/bleplugin_projects/Windows/BlePluginWin/Utility.h new file mode 100644 index 0000000..1c096ca --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/Utility.h @@ -0,0 +1,52 @@ +#pragma once + +#include "pch.h" +namespace BlePlugin { + class Utility { + public: + inline static WinRtGuid CreateGUID(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) { + WinRtGuid guid; + guid.Data1 = d1; + guid.Data2 = (d2 & 0xffff0000)>>16; + guid.Data3 = (d2 & 0xffff); + + for (int i = 0; i < 8; ++i) { + int idx = i & 0x03; + int shift = (3 - idx) * 8; + int val = d3; + if (i >= 4) { + val = d4; + } + guid.Data4[i] = (((val & (0xff << shift)) >> shift) & 0xff); + } + return guid; + } + inline static void ConvertFromGUID(const WinRtGuid &uuid, + uint32_t *data) { + data[0] = uuid.Data1; + data[1] = (uuid.Data2 << 16) | uuid.Data3; + + for (int i = 0; i < 2; ++i) { + data[2+i] = 0; + for (int j = 0; j < 4; ++j) { + int idx = j + i *4; + int shift = (3 - idx) * 8; + data[2 + i] |= uuid.Data4[idx] << shift; + } + } + } + + +#if defined(_DEBUG) + inline static void DebugGuid(const WinRtGuid &src) { + std::cout << std::hex << src.Data1 << "-" << + src.Data2 << "-" << src.Data3 << "-"; + for (int i = 0; i < 8; ++i) { + std::cout << (int)(src.Data4[i]); + } + } +#endif + + + }; +} \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/UuidManager.cpp b/bleplugin_projects/Windows/BlePluginWin/UuidManager.cpp new file mode 100644 index 0000000..3e6f952 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/UuidManager.cpp @@ -0,0 +1,28 @@ +#include "UuidManager.h" +#include "Utility.h" + +using namespace BlePlugin; + +UuidManager UuidManager::s_instance; +UuidManager::UuidManager() { +} +WinRtGuid* UuidManager::GetOrCreate(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) { + WinRtGuid guid = Utility::CreateGUID(d1, d2, d3, d4); + return this->GetOrCreate(guid); +} + +WinRtGuid* UuidManager::GetOrCreate(const WinRtGuid& guid) { + for (auto it = m_cache.begin(); it != m_cache.end(); ++it) { + if (guid == *it) { + return &(*it); + } + } + auto insertIt = (m_cache.insert(m_cache.begin(), guid)); + return &(*insertIt); +} + + +UuidManager& UuidManager::GetInstance() { + return s_instance; +} + diff --git a/bleplugin_projects/Windows/BlePluginWin/UuidManager.h b/bleplugin_projects/Windows/BlePluginWin/UuidManager.h new file mode 100644 index 0000000..602bf29 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/UuidManager.h @@ -0,0 +1,19 @@ +#pragma once + +#include "pch.h" +#include +#include + +namespace BlePlugin { + class UuidManager { + private: + std::list m_cache; + static UuidManager s_instance; + UuidManager(); + public: + WinRtGuid* GetOrCreate(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4); + WinRtGuid* GetOrCreate(const WinRtGuid &guid); + static UuidManager &GetInstance(); + + }; +} \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/bleTestConsole.cpp b/bleplugin_projects/Windows/BlePluginWin/bleTestConsole.cpp new file mode 100644 index 0000000..4813024 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/bleTestConsole.cpp @@ -0,0 +1,120 @@ +#if defined(_DEBUG) +#include "pch.h" +#include +#include "Utility.h" +#include "BleDeviceWatcher.h" +#include "BleDeviceObject.h" +#include "UuidManager.h" +#include "UnityInterface.h" + +using namespace BlePlugin; + +void debugDevices(const BlePlugin::BleDeviceWatcher& watcher) { + int deviceNum = watcher.GetDeviceNum(); + std::cout << "device " << deviceNum << std::endl; + for (int i = 0; i < deviceNum; ++i) { + std::cout << " "<< std::hex << watcher.GetAddr(i) << "::" << + watcher.GetName(i) << " " << watcher.GetRssi(i) << + std::endl; + } +} + +void ButtonSetSubscrive(uint64_t addr) { + void* serviceUUID = _BlePluginGetOrCreateUuidObject(0x10B20100U, 0x5B3B4571U, 0x9508CF3EU, 0xFCD7BBAEU); + + void* charaStrics = _BlePluginGetOrCreateUuidObject(0x10B20107U, + 0x5B3B4571U, 0x9508CF3EU, 0xFCD7BBAEU); + + _BlePluginSetNotificateRequest(addr, serviceUUID, charaStrics, true); + // 0x10B20107,0x5B3B4571 ,0x9508CF3E , 0xFCD7BBAE +} + +void TestRun(){ + auto uuidMgr = BlePlugin::UuidManager::GetInstance(); + void* gattUUID = _BlePluginGetOrCreateUuidObject(0x10B20100U, + 0x5B3B4571U, 0x9508cf3eU, 0xfcd7bbaeU); + + void* serviceUUID = _BlePluginGetOrCreateUuidObject(0x10B20100U, 0x5B3B4571U, 0x9508CF3EU, 0xFCD7BBAEU); + void* charaUUID = _BlePluginGetOrCreateUuidObject(0x10B20102U, 0x5B3B4571U, 0x9508CF3EU, 0xFCD7BBAEU); + void* gattUUID2 = _BlePluginGetOrCreateUuidObject(0x10B20100U, + 0x5B3B4571U, 0x9508cf3eU, 0xfcd7bbaeU); + + + _BlePluginClearScanFilter(); + _BlePluginAddScanServiceUuid(gattUUID); + _BlePluginStartScan(); + BlePlugin::BleDeviceWatcher& watcher = BlePlugin::BleDeviceWatcher::GetInstance(); + + while (true) { + _BlePluginUpdateWatcher(); + + debugDevices(watcher); + if (_BlePluginScanGetDeviceLength() > 0) { + break; + } + Sleep(500); + } + + auto addr = _BlePluginScanGetDeviceAddr(0); + _BlePluginConnectDevice(addr); + + byte data[7]; + data[0] = 0x01; + data[1] = 0x01; + data[2] = 0x01; + data[3] = 100; + data[4] = 0x02; + data[5] = 0x01; + data[6] = 100; + bool isWrite = false; + + while (true) { + _BlePluginUpdateDevicdeManger(); + + if (!isWrite && _BlePluginGetConectDeviceNum() > 0 ) + { + isWrite = true; + _BlePluginWriteCharacteristicRequest(addr, serviceUUID, + charaUUID, data, 7); + break; + } + } + ButtonSetSubscrive(addr); + for (int i = 0; i < 10; ++i) { + _BlePluginUpdateDevicdeManger(); + int deviceNum = _BlePluginGetConectDeviceNum(); + std::cout << "ButtonCheck " << deviceNum << std::endl; + for (int j = 0; j < deviceNum; ++j) { + int notificateNum = _BlePluginGetDeviceNotificateNum(addr); + std::cout << "Notificate " << notificateNum << std::endl; + } + Sleep(100); + } + +} + + +int main() +{ + // init + _BlePluginBleAdapterStatusRequest(); + + int adapterStatus; + while (true) { + adapterStatus = _BlePluginBleAdapterUpdate(); + if (adapterStatus >= 0) { + break; + } + } + if (adapterStatus != 0) { + std::cout << "Bluetooth adapter Error " << adapterStatus << std::endl; + return 0; + } + while (true) { + TestRun(); + _BlePluginDisconnectAllDevice(); + _BlePluginFinalize(); + Sleep(300); + } +} +#endif diff --git a/bleplugin_projects/Windows/BlePluginWin/pch.cpp b/bleplugin_projects/Windows/BlePluginWin/pch.cpp new file mode 100644 index 0000000..699b941 --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/pch.cpp @@ -0,0 +1,3 @@ +#include "pch.h" + +#pragma comment(lib, "windowsapp") \ No newline at end of file diff --git a/bleplugin_projects/Windows/BlePluginWin/pch.h b/bleplugin_projects/Windows/BlePluginWin/pch.h new file mode 100644 index 0000000..b69011f --- /dev/null +++ b/bleplugin_projects/Windows/BlePluginWin/pch.h @@ -0,0 +1,58 @@ +#pragma once +// https://blog.okazuki.jp/entry/2018/10/16/144556 + +/* workaround */ +#define USE_WORKAROUND 1 + +#if defined(USE_WORKAROUND) +#include "winrt/base.h" +namespace winrt::impl +{ + template + auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); +} +#endif + +#include "winrt/Windows.Foundation.h" +#include "winrt/Windows.Foundation.Collections.h" +#include "winrt/Windows.Devices.Bluetooth.h" +#include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h" +#include "winrt/Windows.Devices.Bluetooth.Advertisement.h" +#include "winrt/Windows.Devices.Radios.h" +#include + +#include + +// namespace長いので省略型を用意します + +namespace BlePlugin { + using WinRtGuid = winrt::guid; + using WinRtBleAdvertiseWatcher = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementWatcher; + using WinRtBleScanMode = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEScanningMode; + + using WinRtBleDevice = winrt::Windows::Devices::Bluetooth::BluetoothLEDevice; + using WinRtBleAdvertiseRecieveEventArg = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementReceivedEventArgs; + using WinRtBleAdvertiseFilter = winrt::Windows::Devices::Bluetooth::Advertisement::BluetoothLEAdvertisementFilter; + using WinRtBleGattService = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService; + using WinRtBleGattServiceResult = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceServicesResult; + + using WinRtBleCharacteristicsResult = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristicsResult; + using WinRtBleCharacteristic = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCharacteristic; + using WinRtBleValueChangedEventArgs = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattValueChangedEventArgs; + + using WinRtGattReadResult = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult; + using WinRtGattWriteResult = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattWriteResult; + using WinRtGattCommunicateState = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattCommunicationStatus; + + template + using WinRtAsyncOperation = winrt::Windows::Foundation::IAsyncOperation; + + using WinRtIBuffer = winrt::Windows::Storage::Streams::IBuffer; + using WinRtBleConnectStatus = winrt::Windows::Devices::Bluetooth::BluetoothConnectionStatus; + + using WinRtCharacteristicConfigValue = winrt::Windows::Devices::Bluetooth::GenericAttributeProfile::GattClientCharacteristicConfigurationDescriptorValue; + + using WinRtBluetoothAdapter = winrt::Windows::Devices::Bluetooth::BluetoothAdapter; + using WinRtRadio = winrt::Windows::Devices::Radios::Radio; +} + diff --git a/bleplugin_projects/Windows/ReadMe.txt b/bleplugin_projects/Windows/ReadMe.txt new file mode 100644 index 0000000..840bb45 --- /dev/null +++ b/bleplugin_projects/Windows/ReadMe.txt @@ -0,0 +1,6 @@ +このプロジェクトはBLE PluginのDll生成用のプロジェクトです。 +ビルドした環境はVisual Studio2019,Windows SDK+UWPにてビルドしました。 + +Debugビルドでは検証するための exeファイル書き出しを行います。 +Releaseビルドにすることで、DLL書き出しを行います。 + diff --git a/bleplugin_projects/Windows/copyDllToProjectPlugin.bat b/bleplugin_projects/Windows/copyDllToProjectPlugin.bat new file mode 100644 index 0000000..f0194fd --- /dev/null +++ b/bleplugin_projects/Windows/copyDllToProjectPlugin.bat @@ -0,0 +1,3 @@ +chdir %~dp0 +copy x64\Release\BlePluginWinows.dll ..\..\Assets\Plugins\x86_64\ +pause; \ No newline at end of file