/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the License);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Tizen.Network.Bluetooth
{
///
/// The Bluetooth GATT server.
///
/// 3
public class BluetoothGattServer : IDisposable
{
private static BluetoothGattServer _instance;
private BluetoothGattServerImpl _impl;
private BluetoothGattServer()
{
_impl = new BluetoothGattServerImpl();
}
///
/// (event) This event is called when the indication acknowledgement is received for each notified client.
///
/// 3
public event EventHandler NotificationSent
{
add
{
_impl._notificationSent += value;
}
remove
{
_impl._notificationSent -= value;
}
}
///
/// Creates the Bluetooth GATT server.
///
/// The BluetoothGattServer instance.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the create GATT server fails.
/// 3
public static BluetoothGattServer CreateServer()
{
if (_instance == null)
{
BluetoothGattServer server = new BluetoothGattServer();
if (server.IsValid())
{
_instance = server;
}
}
return _instance;
}
///
/// Registers the server along with the GATT services of the application it is hosting.
///
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the register server application fails.
/// 3
public void Start()
{
_impl.Start();
}
///
/// Registers a specified service to this server.
///
/// The service, which needs to be registered with this server.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the register service fails.
/// 3
public void RegisterGattService(BluetoothGattService service)
{
if (service.IsRegistered())
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
}
_impl.RegisterGattService(this, service);
}
///
/// Unregisters a specified service from this server.
///
/// The service, which needs to be unregistered from this server.
///
/// Once unregistered, the service object will become invalid and should not be used to access sevices or any children attribute's methods/members.
///
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the unregister service fails.
/// 3
public void UnregisterGattService(BluetoothGattService service)
{
if (service.GetGattServer() != this)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
}
_impl.UnregisterGattService(service);
}
///
/// Unregisters all services from this server.
///
///
/// Once unregistered, servicees will become invalid and should not be used to access sevices or any children attribute's methods/members.
///
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the unregister all services fail.
/// 3
public void UnregisterGattServices()
{
_impl.UnregisterAllGattServices(this);
}
///
/// Gets service with given UUID that belongs to this server.
///
/// The UUID for the service to get.
/// The Service with the given UUID if it exists, null otherwise.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the service is not registered.
/// 3
public BluetoothGattService GetService(string uuid)
{
return _impl.GetService(this, uuid);
}
///
/// Gets the list of services that belongs to this server.
///
/// The list of services that belongs to this server.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the service is not registered.
/// 3
public IEnumerable GetServices()
{
return _impl.GetServices(this);
}
///
/// Sends indication for the value change of the characteristic to the remote devices.
///
/// The characteristic whose the value is changed.
/// The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.
/// true on success, false otherwise.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.
/// 3
public async Task SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
{
return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
}
///
/// Sends the notification for the value change of the characteristic to the remote devices.
///
/// The characteristic, which has a changed value.
/// The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.
/// 3
public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
{
_impl.SendNotification(characteristic, clientAddress);
}
///
/// Sends a response to the remote device as a result of a read/write request.
///
/// The identification of a read/write request.
/// The request type for read/write.
/// The error value in case of failure, 0 for success.
/// The value to be sent.
/// The offset from where the value is read.
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or the send response procedure fails.
/// 3
public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
{
_impl.SendResponse(requestId, (int)type, status, value, offset);
}
internal bool IsValid()
{
return _impl.GetHandle().IsInvalid == false;
}
///
/// Destroys the current object.
///
~BluetoothGattServer()
{
Dispose(false);
}
///
/// Destroys the current object.
///
/// http://tizen.org/feature/network.bluetooth.le.gatt.server
/// 6
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases all the resources currently used by this instance.
///
/// true if the managed resources should be disposed, otherwise false.
/// 6
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_impl?.GetHandle()?.Dispose();
_instance = null;
}
}
}
///
/// The Bluetooth GATT client.
///
/// 3
public class BluetoothGattClient : IDisposable
{
private BluetoothGattClientImpl _impl;
private string _remoteAddress = string.Empty;
private TaskCompletionSource _taskForConnection;
private TaskCompletionSource _taskForDisconnection;
private static event EventHandler s_connectionStateChanged;
private static Interop.Bluetooth.GattConnectionStateChangedCallBack s_connectionStateChangeCallback;
internal BluetoothGattClient(string remoteAddress)
{
_impl = new BluetoothGattClientImpl(remoteAddress);
_remoteAddress = remoteAddress;
StaticConnectionStateChanged += OnConnectionStateChanged;
}
///
/// Creates the Bluetooth GATT client.
///
/// The BluetoothGattClient instance.
/// http://tizen.org/feature/network.bluetooth.le.gatt.client
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the create GATT client fails.
/// 6
public static BluetoothGattClient CreateClient(string remoteAddress)
{
BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
return client.Isvalid() ? client : null;
}
///
/// The ConnectionStateChanged event is raised when the gatt connection state is changed.
///
/// 6
public event EventHandler ConnectionStateChanged;
private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
{
if (e.RemoteAddress == _remoteAddress)
{
if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
{
if (e.Result == (int)BluetoothError.None)
{
_taskForConnection.SetResult(true);
}
else
{
_taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
}
_taskForConnection = null;
}
if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
{
if (e.Result == (int)BluetoothError.None)
{
_taskForDisconnection.SetResult(true);
}
else
{
_taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
}
_taskForDisconnection = null;
}
if (e.Result == (int)BluetoothError.None)
{
ConnectionStateChanged?.Invoke(this, e);
}
}
}
private static event EventHandler StaticConnectionStateChanged
{
add
{
if (s_connectionStateChanged == null)
{
RegisterConnectionStateChangedEvent();
}
s_connectionStateChanged += value;
}
remove
{
s_connectionStateChanged -= value;
if (s_connectionStateChanged == null)
{
UnregisterConnectionStateChangedEvent();
}
}
}
private static void RegisterConnectionStateChangedEvent()
{
s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
{
Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
s_connectionStateChanged?.Invoke(null, e);
};
int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
if (ret != (int)BluetoothError.None)
{
Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
BluetoothErrorFactory.ThrowBluetoothException(ret);
}
}
private static void UnregisterConnectionStateChangedEvent()
{
int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
if (ret != (int)BluetoothError.None)
{
Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
BluetoothErrorFactory.ThrowBluetoothException(ret);
}
}
///
/// Connects to the remote GATT server asynchronously.
///
/// The flag for reconnecting when the connection is disconnceted.
/// A task indicating whether the method is done or not.
/// http://tizen.org/feature/network.bluetooth.le.gatt.client
/// http://tizen.org/privilege/bluetooth
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the create GATT client fails.
/// 6
public Task ConnectAsync(bool autoConnect)
{
if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
}
_taskForConnection = new TaskCompletionSource();
_impl.Connect(_remoteAddress, autoConnect);
return _taskForConnection.Task;
}
///
/// Disconnects to the remote GATT server asynchronously.
///
/// A task indicating whether the method is done or not.
/// http://tizen.org/feature/network.bluetooth.le.gatt.client
/// http://tizen.org/privilege/bluetooth
/// Thrown when the BT/BTLE is not supported.
/// Thrown when the create GATT client fails.
/// 6
public Task DisconnectAsync()
{
if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
}
_taskForDisconnection = new TaskCompletionSource();
_impl.Disconnect(_remoteAddress);
return _taskForDisconnection.Task;
}
///
/// Destroy Bluetooth GATT client
///
/// 3
public void DestroyClient()
{
_impl.GetHandle().Dispose();
}
///
/// The address of the remote device.
///
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected.
/// 3
public string RemoteAddress
{
get
{
if (string.IsNullOrEmpty(_remoteAddress))
{
_remoteAddress = _impl.GetRemoteAddress();
}
return _remoteAddress;
}
}
///
/// Gets the service with the given UUID that belongs to the remote device.
///
/// The UUID for the service to get.
/// The service with the given UUID if it exists, null otherwise.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when the get service fails.
/// 3
public BluetoothGattService GetService(string uuid)
{
return _impl.GetService(this, uuid);
}
///
/// Gets list of services that belongs to the remote device.
///
/// The list of services that belongs to the remote device.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when the get service fails.
/// 3
public IEnumerable GetServices()
{
return _impl.GetServices(this);
}
///
/// Reads the value of a given characteristic from the remote device asynchronously.
///
/// The characteristic to be read.
/// true on success, false otherwise.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when the read attribute value fails.
/// 3
public async Task ReadValueAsync(BluetoothGattCharacteristic characteristic)
{
return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
}
///
/// Reads the value of the given descriptor from the remote device asynchronously.
///
/// The descriptor to be read.
/// true on success, false otherwise.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when the read attribute value fails.
/// 3
public async Task ReadValueAsync(BluetoothGattDescriptor descriptor)
{
return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
}
///
/// Writes the value of a given characteristic to the remote device asynchronously.
///
/// The characteristic to be written.
/// true on success, false otherwise.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected or when the write attribute value fails.
/// 3
public async Task WriteValueAsync(BluetoothGattCharacteristic characteristic)
{
return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
}
///
/// Writes the value of the given descriptor to the remote device asynchronously.
///
/// The descriptor to be written.
/// true on success, false otherwise.
/// Thrown when the BT/BTLE is not enabled
/// or when the remote device is disconnected, or when the write attribute value fails.
/// 3
public async Task WriteValueAsync(BluetoothGattDescriptor descriptor)
{
return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
}
internal bool Isvalid()
{
return _impl.GetHandle().IsInvalid == false;
}
///
/// Destroys the current object.
///
~BluetoothGattClient()
{
Dispose(false);
}
///
/// Destroys the current object.
///
/// http://tizen.org/feature/network.bluetooth.le.gatt.client
/// 6
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases all the resources currently used by this instance.
///
/// true if the managed resources should be disposed, otherwise false.
/// 6
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_impl?.GetHandle()?.Dispose();
_impl = null;
StaticConnectionStateChanged -= OnConnectionStateChanged;
}
}
}
///
/// The Bluetooth GATT service.
///
/// 3
public class BluetoothGattService
{
private BluetoothGattServiceImpl _impl;
private BluetoothGattClient _parentClient = null;
private BluetoothGattServer _parentServer = null;
private BluetoothGattService _parentService = null;
///
/// The constructor.
///
/// The UUID of the service.
/// The type of service.
/// Thrown when the create GATT service procedure fails.
/// 3
public BluetoothGattService(string uuid, BluetoothGattServiceType type)
{
Uuid = uuid;
_impl = new BluetoothGattServiceImpl(uuid, type);
}
internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
{
Uuid = uuid;
_impl = impl;
}
///
/// Specification name from the UUID.
///
/// 3
public string Uuid { get; }
///
/// Adds a characteristic to this service.
///
/// The characteristic to be added.
/// true on success, false otherwise.
/// Thrown when the add GATT characteristic procedure fails.
/// 3
public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
{
if (GetGattClient() != null)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
}
if (characteristic.GetService() != null)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
}
_impl.AddCharacteristic(characteristic);
characteristic.SetParent(this);
}
///
/// Gets the characteristic with the given UUID that belongs to this service.
///
/// The UUID for the characteristic to get.
/// The characteristic with a given UUID if it exists, null otherwise.
/// 3
public BluetoothGattCharacteristic GetCharacteristic(string uuid)
{
return _impl.GetCharacteristic(this, uuid);
}
///
/// Gets list of the characteristic that belongs to this service.
///
/// The list of the characteristic that belongs to this service.
/// 3
public IEnumerable GetCharacteristics()
{
return _impl.GetCharacteristics(this);
}
///
/// Includes a service to this service.
///
/// The service to be included.
/// true on success, false otherwise
/// Thrown when the add GATT service procedure fails.///
/// 3
public void AddService(BluetoothGattService service)
{
if (GetGattClient() != null)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
}
if (service.IsRegistered())
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
}
_impl.AddIncludeService(service);
service.SetParent(this);
}
///
/// Gets the included service.
///
/// The UUID for the service to get.
/// The service with a given UUID if it exists, null otherwise.
/// 3
public BluetoothGattService GetIncludeService(string uuid)
{
return _impl.GetIncludeService(this, uuid);
}
///
/// Gets the included service list of this service.
///
/// The included service list of this service.
/// 3
public IEnumerable GetIncludeServices()
{
return _impl.GetIncludeServices(this);
}
///
/// Gets the server instance which the specified service belongs to.
///
/// The server instance which the specified service belongs to.
/// 3
public BluetoothGattServer GetGattServer()
{
return _parentServer;
}
///
/// Gets the client instance which the specified service belongs to.
///
/// The client instance which the specified service belongs to.
/// 3
public BluetoothGattClient GetGattClient()
{
return _parentClient;
}
internal BluetoothGattAttributeHandle GetHandle()
{
return _impl.GetHandle();
}
internal void SetParent(BluetoothGattService parent)
{
if (!IsRegistered())
{
_parentService = parent;
_impl.ReleaseHandleOwnership();
}
}
internal void SetParent(BluetoothGattClient parent)
{
if (!IsRegistered())
{
_parentClient = parent;
_impl.ReleaseHandleOwnership();
}
}
internal void SetParent(BluetoothGattServer parent)
{
if (!IsRegistered())
{
_parentServer = parent;
_impl.ReleaseHandleOwnership();
}
}
internal void UnregisterService()
{
_parentServer = null;
_parentClient = null;
_parentService = null;
}
internal bool IsRegistered()
{
return _parentClient != null || _parentServer != null || _parentService != null;
}
}
///
/// The Bluetooth GATT characteristic.
///
/// 3
public class BluetoothGattCharacteristic : BluetoothGattAttribute
{
private BluetoothGattCharacteristicImpl _impl;
private BluetoothGattService _parent = null;
private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
private EventHandler _characteristicValueChanged;
internal EventHandler _notificationStateChanged;
///
/// The constructor.
///
/// The UUID of the characterstic.
/// Permissions for the characterstic.
/// Properties set for the characterstic.
/// The value associated with the characterstic.
/// throws in case of internal error.
/// Thrown when the create GATT characteristics procedure fails.
/// 3
public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
{
_impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
}
internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
{
_impl = impl;
}
///
/// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
///
///
/// Adding the event handle on characteristic on the server side will not have any effect.
///
/// 3
public event EventHandler ValueChanged
{
add
{
if (Client != null)
{
if (_characteristicValueChanged == null)
{
_characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
{
_characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
};
_impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
}
_characteristicValueChanged = value;
}
}
remove
{
if (Client != null)
{
_characteristicValueChanged = null;
if (_characteristicValueChanged == null)
{
_impl.UnsetCharacteristicValueChangedEvent();
}
}
}
}
///
/// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
///
///
/// Adding event handle on the characteristic on the client side will not have any effect.
///
/// 3
public event EventHandler NotificationStateChanged
{
add
{
if (Server != null)
{
if (_notificationStateChangedCallback == null)
{
_notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
{
_notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
};
_impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
}
_notificationStateChanged = value;
}
}
remove
{
if (Server != null)
{
_notificationStateChanged = null;
// CAPI does not allow unsetting ReadValueRequestedEventCallback.
}
}
}
///
/// The property for this characteristic.
///
/// 3
public BluetoothGattProperty Properties
{
get
{
return _impl.GetProperties();
}
set
{
if (Server != null)
{
_impl.SetProperties(value);
}
}
}
///
/// The write type to be used for write operations.
///
/// 3
public BluetoothGattWriteType WriteType
{
get
{
return _impl.GetWriteType();
}
set
{
_impl.SetWriteType(value);
}
}
internal override BluetoothGattClient Client
{
get
{
return _parent?.GetGattClient();
}
}
internal override BluetoothGattServer Server
{
get
{
return _parent?.GetGattServer();
}
}
internal override BluetoothGattAttributeImpl Impl
{
get
{
return _impl;
}
}
///
/// Adds a descriptor to this characteristic.
///
/// The descriptor to be added.
/// true on success, false otherwise.
/// Thrown when the add GATT descriptor procedure fails.
/// 3
public void AddDescriptor(BluetoothGattDescriptor descriptor)
{
if (Client != null)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
}
if (descriptor.GetCharacteristic() != null)
{
BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
}
_impl.AddDescriptor(descriptor);
descriptor.SetParent(this);
}
///
/// Gets the descriptor with the given UUID that belongs to this characteristic.
///
/// The UUID for the descriptor to get.
/// The descriptor with a given UUID if it exists, null otherwise.
/// 3
public BluetoothGattDescriptor GetDescriptor(string uuid)
{
return _impl.GetDescriptor(this, uuid);
}
///
/// Gets the list of descriptors that belongs to this characteristic.
///
/// The list of descriptors that belongs to this characteristic.
/// 3
public IEnumerable GetDescriptors()
{
return _impl.GetDescriptors(this);
}
///
/// Gets the service instance, which the specified characterstic belongs to.
///
/// The characteristic instance, the specified characterstic belongs to.
/// 3
public BluetoothGattService GetService()
{
return _parent;
}
internal void SetParent(BluetoothGattService parent)
{
if (_parent == null)
{
_parent = parent;
ReleaseHandleOwnership();
}
}
}
///
/// The Bluetooth GATT descriptor.
///
/// 3
public class BluetoothGattDescriptor : BluetoothGattAttribute
{
private BluetoothGattCharacteristic _parent = null;
private BluetoothGattDescriptorImpl _impl;
///
/// The constructor.
///
/// The UUID of the descriptor.
/// Permissions for the descriptor.
/// The value associated with the descriptor.
/// throws in case of internal error.
/// Thrown when the create GATT descriptor procedure fails.
/// 3
public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
{
_impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
}
internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
{
_impl = impl;
}
internal override BluetoothGattClient Client
{
get
{
return _parent?.Client;
}
}
internal override BluetoothGattServer Server
{
get
{
return _parent?.Server;
}
}
internal override BluetoothGattAttributeImpl Impl
{
get
{
return _impl;
}
}
///
/// Gets the characteristic instance, which the specified descriptor belongs to.
///
/// The characteristic instance, the specified descriptor belongs to.
/// 3
public BluetoothGattCharacteristic GetCharacteristic()
{
return _parent;
}
internal void SetParent(BluetoothGattCharacteristic parent)
{
if (_parent == null)
{
_parent = parent;
ReleaseHandleOwnership();
}
}
}
///
/// The Bluetooth GATT attribute.
///
/// 3
public abstract class BluetoothGattAttribute
{
private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
private EventHandler _readValueRequested;
private EventHandler _writeValueRequested;
///
/// The constructor.
///
/// The UUID of the GATT attribute.
/// Permission for the GATT attribute.
/// 3
public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
{
Uuid = uuid;
Permissions = permission;
}
// Events
///
/// This event is called when the client request to read the value of a characteristic or a descriptor.
///
/// Thrown when the set read value requested callback procedure fails.
/// 3
public event EventHandler ReadRequested
{
add
{
if (Server == null) return;
if (_readValueRequestedCallback == null)
{
_readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
{
_readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
};
Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
}
_readValueRequested = value;
}
remove
{
if (Server == null) return;
_readValueRequested = null;
// CAPI does not allow unsetting ReadValueRequestedEventCallback.
}
}
///
/// This event is called when a value of a characteristic or a descriptor has been changed by a client.
///
/// Thrown when the set write value requested callback procedure fails.
/// 3
public event EventHandler WriteRequested
{
add
{
if (Server == null) return;
if (_writeValueRequested == null)
{
_writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, response_needed, offset, valueToWrite, len, userData) =>
{
_writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, valueToWrite, offset, response_needed));
};
Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
}
_writeValueRequested = value;
}
remove
{
if (Server == null) return;
_writeValueRequested = null;
// CAPI does not allow unsetting ReadValueRequestedEventCallback.
}
}
///
/// The attribute's UUID.
///
/// 3
public string Uuid { get; }
///
/// Permissions for this attribute.
///
/// 3
public BluetoothGattPermission Permissions { get; }
///
/// The value of this descriptor.
///
/// 3
public byte[] Value
{
get
{
return Impl.GetValue();
}
set
{
Impl.SetValue(value);
}
}
internal abstract BluetoothGattClient Client { get; }
internal abstract BluetoothGattServer Server { get; }
internal abstract BluetoothGattAttributeImpl Impl { get; }
///
/// Returns a string value at the specified offset.
///
/// An offset in the attribute value buffer.
/// The string value at specified offset.
/// 3
public string GetValue(int offset)
{
return Impl.GetValue(offset);
}
///
/// Sets the string value as a specified offset.
///
/// value to set
/// Throws exception if the value is null.
/// 3
public void SetValue(string value)
{
if (string.IsNullOrEmpty(value))
GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
byte[] val = Encoding.UTF8.GetBytes(value);
Impl.SetValue(val);
}
///
/// Returns a value at specified offset as the int value of the specified type.
///
/// The type of the int value.
/// An offset in the attribute value buffer.
/// The int value at given offset.
/// Throws exception if (offset + size of int value) is greater than the length of the value buffer.
/// 3
public int GetValue(IntDataType type, int offset)
{
return Impl.GetValue(type, offset);
}
///
/// Updates a value at the specified offset by the int value of the specified type.
///
/// The type of the int value.
/// The value to set.
/// An offset in the attribute value buffer.
/// Throws exception if (offset + size of int value) is greater than the length of the value buffer.
/// 3
public void SetValue(IntDataType type, int value, int offset)
{
Impl.SetValue(type, value, offset);
}
///
/// Returns a value at the specified offset as the float value of the specified type.
///
/// The type of the float value.
/// An offset in the attribute value buffer.
/// The float value at given offset.
/// Throws exception if (offset + size of float value) is greater than the length of the value buffer.
/// 3
public float GetValue(FloatDataType type, int offset)
{
return Impl.GetValue(type, offset);
}
///
/// Updates the value at the specified offset by the float value of the specified type.
///
/// The type of the float value.
/// The mantissa of the float value.
/// An exponent of the float value.
/// An offset in the attribute value buffer.
/// Throws exception if (offset + size of float value) is greater than the length of the value buffer.
/// 3
public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
{
Impl.SetValue(type, mantissa, exponent, offset);
}
internal void ReleaseHandleOwnership()
{
Impl.ReleaseHandleOwnership();
}
internal BluetoothGattAttributeHandle GetHandle()
{
return Impl.GetHandle();
}
}
}