diff --git a/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Central.cs b/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Central.cs index 7deb56b..b62a7b1 100644 --- a/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Central.cs +++ b/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Central.cs @@ -125,6 +125,11 @@ public void DidWriteValueForCharacteristic(CBPeripheral peripheral, CBCharacteri } } + public void IsReadyToSendWriteWithoutResponse(CBPeripheral peripheral) + { + Debug.Log($"[IsReadyToSendWriteWithoutResponse] {peripheral}"); + } + public void DidUpdateNotificationStateForCharacteristic(CBPeripheral peripheral, CBCharacteristic characteristic, CBError error) { Debug.Log($"[DidUpdateNotificationStateForCharacteristic] characteristic: {characteristic}"); @@ -149,9 +154,14 @@ public void OnClickWrite() return; } + if (!_peripheral.CanSendWriteWithoutResponse) + { + Debug.Log("CanSendWriteWithoutResponse is false."); + return; + } var value = UnityEngine.Random.Range(100, 1000).ToString(); var data = Encoding.UTF8.GetBytes(value); - _peripheral.WriteValue(data, _remoteCharacteristic, CBCharacteristicWriteType.WithResponse); + _peripheral.WriteValue(data, _remoteCharacteristic, CBCharacteristicWriteType.WithoutResponse); } public void OnClickRead() diff --git a/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Peripheral.cs b/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Peripheral.cs index 6af0ae9..dd31f5c 100644 --- a/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Peripheral.cs +++ b/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Peripheral.cs @@ -32,7 +32,7 @@ public void DidUpdateState(CBPeripheralManager peripheral) var service = new CBMutableService(_serviceUUID, true); _characteristic = new CBMutableCharacteristic( _characteristicUUID, - CBCharacteristicProperties.Read | CBCharacteristicProperties.Write | CBCharacteristicProperties.Notify, + CBCharacteristicProperties.Read | CBCharacteristicProperties.WriteWithoutResponse | CBCharacteristicProperties.Notify, null, CBAttributePermissions.Readable | CBAttributePermissions.Writeable ); diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Plugins/iOS/CoreBluetoothForUnity.framework/CoreBluetoothForUnity b/Packages/com.teach310.core-bluetooth-for-unity/Plugins/iOS/CoreBluetoothForUnity.framework/CoreBluetoothForUnity index 62db518..175ca79 100755 Binary files a/Packages/com.teach310.core-bluetooth-for-unity/Plugins/iOS/CoreBluetoothForUnity.framework/CoreBluetoothForUnity and b/Packages/com.teach310.core-bluetooth-for-unity/Plugins/iOS/CoreBluetoothForUnity.framework/CoreBluetoothForUnity differ diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Plugins/macOS/libCoreBluetoothForUnity.dylib b/Packages/com.teach310.core-bluetooth-for-unity/Plugins/macOS/libCoreBluetoothForUnity.dylib index 2a1956f..9a8160f 100755 Binary files a/Packages/com.teach310.core-bluetooth-for-unity/Plugins/macOS/libCoreBluetoothForUnity.dylib and b/Packages/com.teach310.core-bluetooth-for-unity/Plugins/macOS/libCoreBluetoothForUnity.dylib differ diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/CBPeripheral.cs b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/CBPeripheral.cs index 754b7df..b523257 100644 --- a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/CBPeripheral.cs +++ b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/CBPeripheral.cs @@ -19,6 +19,7 @@ void DidDiscoverServices(CBPeripheral peripheral, CBError error) { } void DidDiscoverCharacteristics(CBPeripheral peripheral, CBService service, CBError error) { } void DidUpdateValueForCharacteristic(CBPeripheral peripheral, CBCharacteristic characteristic, CBError error) { } void DidWriteValueForCharacteristic(CBPeripheral peripheral, CBCharacteristic characteristic, CBError error) { } + void IsReadyToSendWriteWithoutResponse(CBPeripheral peripheral) { } void DidUpdateNotificationStateForCharacteristic(CBPeripheral peripheral, CBCharacteristic characteristic, CBError error) { } } @@ -71,27 +72,44 @@ internal CBPeripheral(SafeNativePeripheralHandle nativePeripheral) /// Discovers the specified services of the peripheral. /// If the servicesUUIDs parameter is nil, this method returns all of the peripheral’s available services. This is much slower than providing an array of service UUIDs to search for. /// - public void DiscoverServices(string[] serviceUUIDs = null) => _nativePeripheral.DiscoverServices(serviceUUIDs); + public void DiscoverServices(string[] serviceUUIDs = null) + { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); + _nativePeripheral.DiscoverServices(serviceUUIDs); + } /// /// Discovers the specified characteristics of a service. /// - public void DiscoverCharacteristics(string[] characteristicUUIDs, CBService service) => _nativePeripheral.DiscoverCharacteristics(characteristicUUIDs, service); + public void DiscoverCharacteristics(string[] characteristicUUIDs, CBService service) + { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); + _nativePeripheral.DiscoverCharacteristics(characteristicUUIDs, service); + } /// /// Discover all characteristics in a service (slow). /// - public void DiscoverCharacteristics(CBService service) => DiscoverCharacteristics(null, service); + public void DiscoverCharacteristics(CBService service) + { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); + DiscoverCharacteristics(null, service); + } /// /// Retrieves the value of a specified characteristic. /// When you call this method to read the value of a characteristic, the peripheral calls the peripheral(_:didUpdateValueFor:error:) method of its delegate object. /// If the peripheral successfully reads the value of the characteristic, you can access it through the characteristic’s value property. /// - public void ReadValue(CBCharacteristic characteristic) => _nativePeripheral.ReadValue(characteristic); + public void ReadValue(CBCharacteristic characteristic) + { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); + _nativePeripheral.ReadValue(characteristic); + } public void WriteValue(byte[] data, CBCharacteristic characteristic, CBCharacteristicWriteType type) { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); _nativePeripheral.WriteValue(data, characteristic, type); } @@ -100,6 +118,7 @@ public void WriteValue(byte[] data, CBCharacteristic characteristic, CBCharacter /// public int GetMaximumWriteValueLength(CBCharacteristicWriteType type) { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); return _nativePeripheral.GetMaximumWriteValueLength(type); } @@ -108,6 +127,7 @@ public int GetMaximumWriteValueLength(CBCharacteristicWriteType type) /// public void SetNotifyValue(bool enabled, CBCharacteristic characteristic) { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); _nativePeripheral.SetNotifyValue(enabled, characteristic); } @@ -123,6 +143,15 @@ public CBPeripheralState State } } + public bool CanSendWriteWithoutResponse + { + get + { + ExceptionUtils.ThrowObjectDisposedExceptionIf(_disposed, this); + return _nativePeripheral.CanSendWriteWithoutResponse; + } + } + internal CBCharacteristic FindCharacteristic(string serviceUUID, string characteristicUUID) { if (string.IsNullOrEmpty(serviceUUID)) @@ -187,6 +216,12 @@ void INativePeripheralDelegate.DidWriteValueForCharacteristic(string serviceUUID Delegate?.DidWriteValueForCharacteristic(this, characteristic, error); } + void INativePeripheralDelegate.IsReadyToSendWriteWithoutResponse() + { + if (_disposed) return; + Delegate?.IsReadyToSendWriteWithoutResponse(this); + } + void INativePeripheralDelegate.DidUpdateNotificationStateForCharacteristic(string serviceUUID, string characteristicUUID, bool isNotifying, CBError error) { if (_disposed) return; diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativeMethods.cs b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativeMethods.cs index 2f67bb9..a651482 100644 --- a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativeMethods.cs +++ b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativeMethods.cs @@ -74,6 +74,7 @@ int serviceUUIDsCount internal delegate void CB4UPeripheralDidDiscoverCharacteristicsHandler(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, IntPtr commaSeparatedCharacteristicUUIDsPtr, int errorCode); internal delegate void CB4UPeripheralDidUpdateValueForCharacteristicHandler(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr, IntPtr dataPtr, int dataLength, int errorCode); internal delegate void CB4UPeripheralDidWriteValueForCharacteristicHandler(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr, int errorCode); + internal delegate void CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler(IntPtr peripheralPtr); internal delegate void CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr, int notificationState, int errorCode); [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] @@ -83,6 +84,7 @@ internal static extern void cb4u_peripheral_register_handlers( CB4UPeripheralDidDiscoverCharacteristicsHandler didDiscoverCharacteristicsHandler, CB4UPeripheralDidUpdateValueForCharacteristicHandler didUpdateValueForCharacteristicHandler, CB4UPeripheralDidWriteValueForCharacteristicHandler didWriteValueForCharacteristicHandler, + CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler isReadyToSendWriteWithoutResponseHandler, CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler didUpdateNotificationStateForCharacteristicHandler ); @@ -146,6 +148,10 @@ internal static extern int cb4u_peripheral_set_notify_value( [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] internal static extern int cb4u_peripheral_state(SafeNativePeripheralHandle handle); + [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + internal static extern bool cb4u_peripheral_can_send_write_without_response(SafeNativePeripheralHandle handle); + [DllImport(DLL_NAME, CallingConvention = CallingConvention.Cdecl)] internal static extern int cb4u_peripheral_characteristic_properties( SafeNativePeripheralHandle handle, diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativePeripheralProxy.cs b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativePeripheralProxy.cs index ab19e0f..17ae967 100644 --- a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativePeripheralProxy.cs +++ b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/NativePeripheralProxy.cs @@ -132,5 +132,13 @@ internal CBPeripheralState State return (CBPeripheralState)state; } } + + internal bool CanSendWriteWithoutResponse + { + get + { + return NativeMethods.cb4u_peripheral_can_send_write_without_response(_handle); + } + } } } diff --git a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/SafeNativePeripheralHandle.cs b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/SafeNativePeripheralHandle.cs index 6388940..9b6cffb 100644 --- a/Packages/com.teach310.core-bluetooth-for-unity/Runtime/SafeNativePeripheralHandle.cs +++ b/Packages/com.teach310.core-bluetooth-for-unity/Runtime/SafeNativePeripheralHandle.cs @@ -10,6 +10,7 @@ void DidDiscoverServices(string[] serviceUUIDs, CBError error) { } void DidDiscoverCharacteristics(string serviceUUID, string[] characteristicUUIDs, CBError error) { } void DidUpdateValueForCharacteristic(string serviceUUID, string characteristicUUID, byte[] data, CBError error) { } void DidWriteValueForCharacteristic(string serviceUUID, string characteristicUUID, CBError error) { } + void IsReadyToSendWriteWithoutResponse() { } void DidUpdateNotificationStateForCharacteristic(string serviceUUID, string characteristicUUID, bool enabled, CBError error) { } } @@ -32,6 +33,7 @@ void RegisterHandlers() DidDiscoverCharacteristics, DidUpdateValueForCharacteristic, DidWriteValueForCharacteristic, + IsReadyToSendWriteWithoutResponse, DidUpdateNotificationStateForCharacteristic ); } @@ -112,6 +114,12 @@ internal static void DidWriteValueForCharacteristic(IntPtr peripheralPtr, IntPtr ); } + [AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler))] + internal static void IsReadyToSendWriteWithoutResponse(IntPtr peripheralPtr) + { + GetDelegate(peripheralPtr)?.IsReadyToSendWriteWithoutResponse(); + } + [AOT.MonoPInvokeCallback(typeof(NativeMethods.CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler))] internal static void DidUpdateNotificationStateForCharacteristic(IntPtr peripheralPtr, IntPtr serviceUUIDPtr, IntPtr characteristicUUIDPtr, int notificationState, int errorCode) { diff --git a/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CB4UPeripheral.swift b/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CB4UPeripheral.swift index e7154d3..aceb531 100644 --- a/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CB4UPeripheral.swift +++ b/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CB4UPeripheral.swift @@ -7,6 +7,7 @@ public class CB4UPeripheral : NSObject { public var didDiscoverCharacteristicsHandler: CB4UPeripheralDidDiscoverCharacteristicsHandler? public var didUpdateValueForCharacteristicHandler: CB4UPeripheralDidUpdateValueForCharacteristicHandler? public var didWriteValueForCharacteristicHandler: CB4UPeripheralDidWriteValueForCharacteristicHandler? + public var isReadyToSendWriteWithoutResponseHandler: CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler? public var didUpdateNotificationStateForCharacteristicHandler: CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler? let success: Int32 = 0 @@ -93,6 +94,10 @@ public class CB4UPeripheral : NSObject { public var state: CBPeripheralState { return peripheral.state } + + public var canSendWriteWithoutResponse: Bool { + return peripheral.canSendWriteWithoutResponse + } } extension CB4UPeripheral : CBPeripheralDelegate { @@ -144,6 +149,10 @@ extension CB4UPeripheral : CBPeripheralDelegate { } } + public func peripheralIsReady(toSendWriteWithoutResponse peripheral: CBPeripheral) { + isReadyToSendWriteWithoutResponseHandler?(selfPointer()) + } + public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) { let serviceId = characteristic.service?.uuid.uuidString ?? "" let characteristicId = characteristic.uuid.uuidString diff --git a/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CoreBluetoothForUnity.swift b/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CoreBluetoothForUnity.swift index 614f19a..54e3f88 100644 --- a/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CoreBluetoothForUnity.swift +++ b/Plugins/CoreBluetoothForUnity/Sources/CoreBluetoothForUnity/CoreBluetoothForUnity.swift @@ -116,6 +116,7 @@ public typealias CB4UPeripheralDidDiscoverServicesHandler = @convention(c) (Unsa public typealias CB4UPeripheralDidDiscoverCharacteristicsHandler = @convention(c) (UnsafeRawPointer, UnsafePointer, UnsafePointer, Int32) -> Void public typealias CB4UPeripheralDidUpdateValueForCharacteristicHandler = @convention(c) (UnsafeRawPointer, UnsafePointer, UnsafePointer, UnsafePointer, Int32, Int32) -> Void public typealias CB4UPeripheralDidWriteValueForCharacteristicHandler = @convention(c) (UnsafeRawPointer, UnsafePointer, UnsafePointer, Int32) -> Void +public typealias CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler = @convention(c) (UnsafeRawPointer) -> Void public typealias CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler = @convention(c) (UnsafeRawPointer, UnsafePointer, UnsafePointer, Int32, Int32) -> Void @_cdecl("cb4u_peripheral_register_handlers") @@ -125,6 +126,7 @@ public func cb4u_peripheral_register_handlers( _ didDiscoverCharacteristicsHandler: @escaping CB4UPeripheralDidDiscoverCharacteristicsHandler, _ didUpdateValueForCharacteristicHandler: @escaping CB4UPeripheralDidUpdateValueForCharacteristicHandler, _ didWriteValueForCharacteristicHandler: @escaping CB4UPeripheralDidWriteValueForCharacteristicHandler, + _ isReadyToSendWriteWithoutResponseHandler: @escaping CB4UPeripheralIsReadyToSendWriteWithoutResponseHandler, _ didUpdateNotificationStateForCharacteristicHandler: @escaping CB4UPeripheralDidUpdateNotificationStateForCharacteristicHandler ) { let instance = Unmanaged.fromOpaque(peripheralPtr).takeUnretainedValue() @@ -133,6 +135,7 @@ public func cb4u_peripheral_register_handlers( instance.didDiscoverCharacteristicsHandler = didDiscoverCharacteristicsHandler instance.didUpdateValueForCharacteristicHandler = didUpdateValueForCharacteristicHandler instance.didWriteValueForCharacteristicHandler = didWriteValueForCharacteristicHandler + instance.isReadyToSendWriteWithoutResponseHandler = isReadyToSendWriteWithoutResponseHandler instance.didUpdateNotificationStateForCharacteristicHandler = didUpdateNotificationStateForCharacteristicHandler } @@ -258,6 +261,13 @@ public func cb4u_peripheral_state(_ peripheralPtr: UnsafeRawPointer) -> Int32 { return Int32(instance.state.rawValue) } +@_cdecl("cb4u_peripheral_can_send_write_without_response") +public func cb4u_peripheral_can_send_write_without_response(_ peripheralPtr: UnsafeRawPointer) -> Bool { + let instance = Unmanaged.fromOpaque(peripheralPtr).takeUnretainedValue() + + return instance.canSendWriteWithoutResponse +} + @_cdecl("cb4u_peripheral_characteristic_properties") public func cb4u_peripheral_characteristic_properties( _ peripheralPtr: UnsafeRawPointer,