2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Runtime.InteropServices;
21 using System.Threading.Tasks;
23 namespace Tizen.Network.Bluetooth
26 /// Bluetooth GATT server
28 public class BluetoothGattServer
30 private static BluetoothGattServer _instance;
31 private BluetoothGattServerImpl _impl;
32 private BluetoothGattServer()
34 _impl = new BluetoothGattServerImpl();
38 /// (event) called when indication acknowledgement received, once for each notified client
40 public event EventHandler<NotificationSentEventArg> NotificationSent
44 _impl._notificationSent += value;
48 _impl._notificationSent -= value;
53 /// Creates bluetooth gatt server
55 /// <returns></returns>
56 public static BluetoothGattServer CreateServer()
58 if (_instance == null)
60 BluetoothGattServer server = new BluetoothGattServer();
70 /// Registers the server along with the GATT services of the application it is hosting
78 /// Registers a specified service to this server
80 /// <param name="service">service, which needs to be registered with this server</param>
81 public void RegisterGattService(BluetoothGattService service)
83 if (service.IsRegistered())
85 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
87 _impl.RegisterGattService(this, service);
91 /// Unregisters a specified service from this server
93 /// <param name="service">service, which needs to be unregistered from this server</param>
95 /// Once unregistered, service object will become invalid and should not be used to access sevices's or any children attribute's methods/ members.
97 public void UnregisterGattService(BluetoothGattService service)
99 if (service.GetGattServer() != this)
101 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
104 _impl.UnregisterGattService(service);
108 /// Unregisters all services from this server
111 /// Once unregistered, servicees will become invalid and should not be used to access sevices's or any children attribute's methods/ members.
113 public void UnregisterGattServices()
115 _impl.UnregisterAllGattServices(this);
119 /// Gets service with given UUID that belongs to this server.
121 /// <param name="uuid">UUID for the service to get</param>
122 /// <returns>service with given uuid if it exists, null otherwise</returns>
123 public BluetoothGattService GetService(string uuid)
125 return _impl.GetService(this, uuid);
129 /// Gets list of services that belongs to this server.
131 /// <returns>list of services that belongs to this server</returns>
132 public IEnumerable<BluetoothGattService> GetServices()
134 return _impl.GetServices(this);
138 /// Send indication for value change of the characteristic to the remote devices
140 /// <param name="characteristic">characteristic whose value is changes</param>
141 /// <param name="clientAddress">Remote device address to send notify or indicate and if set to NULL then notify/indicate all is enabled.</param>
142 public async Task<bool> SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
144 return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
148 /// Send notification for value change of the characteristic to the remote devices
150 /// <param name="characteristic">characteristic The characteristic which has a changed value</param>
151 /// <param name="clientAddress">Remote device address to send notify or indicate and if set to NULL then notify/indicate all is enabled.</param>
152 public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
154 _impl.SendNotification(characteristic, clientAddress);
158 /// Sends a response to the remote device as a result of a read/ write request
160 /// <param name="requestId">The identification of a read/ write request</param>
161 /// <param name="type">The request type for read/write</param>
162 /// <param name="status">error value in case of failure, 0 for success</param>
163 /// <param name="value">Value to be sent</param>
164 /// <param name="offset">Fffset from where the value is read</param>
165 public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
167 _impl.SendResponse(requestId, (int)type, status, value, offset);
170 internal bool IsValid()
172 return _impl.GetHandle().IsInvalid == false;
177 /// Bluetooth GATT client
179 public class BluetoothGattClient
181 private BluetoothGattClientImpl _impl;
182 private string _remoteAddress = string.Empty;
184 internal BluetoothGattClient(string remoteAddress)
186 _impl = new BluetoothGattClientImpl(remoteAddress);
187 _remoteAddress = remoteAddress;
190 internal static BluetoothGattClient CreateClient(string remoteAddress)
192 BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
193 return client.Isvalid() ? client : null;
196 public void DestroyClient()
198 _impl.GetHandle().Dispose();
202 /// Address of remote device.
204 public string RemoteAddress
208 if (string.IsNullOrEmpty(_remoteAddress))
210 _remoteAddress = _impl.GetRemoteAddress();
212 return _remoteAddress;
217 /// Gets service with given UUID that belongs to the remote device.
219 /// <param name="uuid">UUID for the service to get</param>
220 /// <returns>service with given uuid if it exists, null otherwise</returns>
221 public BluetoothGattService GetService(string uuid)
223 return _impl.GetService(this, uuid);
227 /// Gets list of services that belongs to the remote device.
229 /// <returns>list of services that belongs to the remote device</returns>
230 public IEnumerable<BluetoothGattService> GetServices()
232 return _impl.GetServices(this);
236 /// Reads the value of given characteristic from the remote device asynchronously.
238 /// <param name="characteristic">characteristic to be read</param>
239 /// <returns>true on success, false otherwise</returns>
240 public async Task<bool> ReadValueAsync(BluetoothGattCharacteristic characteristic)
242 return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
246 /// Reads the value of given descriptor from the remote device asynchronously.
248 /// <param name="descriptor">descriptor to be read</param>
249 /// <returns>true on success, false otherwise</returns>
250 public async Task<bool> ReadValueAsync(BluetoothGattDescriptor descriptor)
252 return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
256 /// Write value of given characteristic to remote device asynchronously.
258 /// <param name="characteristic">characteristic to be written</param>
259 /// <returns>true on success, false otherwise</returns>
260 public async Task<bool> WriteValueAsync(BluetoothGattCharacteristic characteristic)
262 return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
266 /// Write value of given descriptor to remote device asynchronously.
268 /// <param name="descriptor">descriptor to be written</param>
269 /// <returns>true on success, false otherwise</returns>
270 public async Task<bool> WriteValueAsync(BluetoothGattDescriptor descriptor)
272 return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
275 internal bool Isvalid()
277 return _impl.GetHandle().IsInvalid == false;
282 /// Bluetooth GATT service
284 public class BluetoothGattService
286 private BluetoothGattServiceImpl _impl;
287 private BluetoothGattClient _parentClient = null;
288 private BluetoothGattServer _parentServer = null;
289 private BluetoothGattService _parentService = null;
294 /// <param name="uuid">UUID of the service</param>
295 /// <param name="type">type of service</param>
296 public BluetoothGattService(string uuid, BluetoothGattServiceType type)
299 _impl = new BluetoothGattServiceImpl(uuid, type);
302 internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
309 /// Specification name from the UUID
311 public string Uuid { get; }
314 /// Adds a characteristic to this service
316 /// <param name="characteristic">characteristic to be added</param>
317 /// <returns>true on success, false otherwise</returns>
318 public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
320 if (GetGattClient() != null)
322 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
325 if (characteristic.GetService() != null)
327 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
330 _impl.AddCharacteristic(characteristic);
331 characteristic.SetParent(this);
335 /// Gets characteristic with given UUID that belongs to this service.
337 /// <param name="uuid">UUID for the characteristic to get</param>
338 /// <returns>characteristic with given uuid if it exists, null otherwise</returns>
339 public BluetoothGattCharacteristic GetCharacteristic(string uuid)
341 return _impl.GetCharacteristic(this, uuid);
345 /// Gets list of characteristic that belongs to this service.
347 /// <returns>list of characteristic that belongs to this service</returns>
348 public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
350 return _impl.GetCharacteristics(this);
354 /// Includes a service to this service
356 /// <param name="service">service to be included</param>
357 /// <returns>true on success, false otherwise</returns>
358 public void AddService(BluetoothGattService service)
360 if (GetGattClient() != null)
362 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
365 if (service.IsRegistered())
367 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
370 _impl.AddIncludeService(service);
371 service.SetParent(this);
375 /// Gets included service
377 /// <param name="uuid">UUID for the service to get</param>
378 /// <returns>service with given uuid if it exists, null otherwise</returns>
379 public BluetoothGattService GetIncludeService(string uuid)
381 return _impl.GetIncludeService(this, uuid);
385 /// Gets included service list of this service.
387 /// <returns>included service list of this service</returns>
388 public IEnumerable<BluetoothGattService> GetIncludeServices()
390 return _impl.GetIncludeServices(this);
394 /// Gets the server instance which the specified service belongs to.
396 /// <returns>server instance which the specified service belongs to</returns>
397 public BluetoothGattServer GetGattServer()
399 return _parentServer;
403 /// Gets the client instance which the specified service belongs to.
405 /// <returns>client instance which the specified service belongs to</returns>
406 public BluetoothGattClient GetGattClient()
408 return _parentClient;
411 internal BluetoothGattAttributeHandle GetHandle()
413 return _impl.GetHandle();
416 internal void SetParent(BluetoothGattService parent)
420 _parentService = parent;
421 _impl.ReleaseHandleOwnership();
425 internal void SetParent(BluetoothGattClient parent)
429 _parentClient = parent;
430 _impl.ReleaseHandleOwnership();
434 internal void SetParent(BluetoothGattServer parent)
438 _parentServer = parent;
439 _impl.ReleaseHandleOwnership();
443 internal void UnregisterService()
445 _parentServer = null;
446 _parentClient = null;
447 _parentService = null;
450 internal bool IsRegistered()
452 return _parentClient != null || _parentServer != null || _parentService != null;
457 /// Bluetooth GATT characteristic
459 public class BluetoothGattCharacteristic : BluetoothGattAttribute
461 private BluetoothGattCharacteristicImpl _impl;
462 private BluetoothGattService _parent = null;
464 private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
465 private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
467 private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
468 internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
473 /// <param name="uuid">UUID of the characterstic</param>
474 /// <param name="permissions">Permissions for the characterstic</param>
475 /// <param name="properties">Properties set for the characterstic</param>
476 /// <param name="value">Value associated with the characterstic</param>
477 /// <remarks>throws in case of internal error</remarks>
478 public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
480 _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
483 internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
489 /// (event) CharacteristicValueChanged is raised when server notifies for change in this characteristic value
492 /// Adding event handle on charateristic on server side will not have any effect
494 public event EventHandler<ValueChangedEventArgs> ValueChanged
500 if (_characteristicValueChanged == null)
502 _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
504 _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue));
507 _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
509 _characteristicValueChanged = value;
516 _characteristicValueChanged = null;
517 if (_characteristicValueChanged == null)
519 _impl.UnsetCharacteristicValueChangedEvent();
527 /// (event) NotificationStateChanged is called when client enables or disables the Notification/Indication for particular characteristics.
530 /// Adding event handle on charateristic on client side will not have any effect
532 public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
538 if (_notificationStateChangedCallback == null)
540 _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
542 _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
545 _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
548 _notificationStateChanged = value;
555 _notificationStateChanged = null;
556 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
562 /// Property for this characteristic
564 public BluetoothGattProperty Properties
568 return _impl.GetProperties();
574 _impl.SetProperties(value);
580 /// Write type to be used for write operations
582 public BluetoothGattWriteType WriteType
586 return _impl.GetWriteType();
590 _impl.SetWriteType(value);
594 internal override BluetoothGattClient Client
598 return _parent?.GetGattClient();
602 internal override BluetoothGattServer Server
606 return _parent?.GetGattServer();
610 internal override BluetoothGattAttributeImpl Impl
619 /// Adds a descriptor to this characteristic
621 /// <param name="descriptor">descriptor to be added</param>
622 /// <returns>true on success, false otherwise</returns>
623 public void AddDescriptor(BluetoothGattDescriptor descriptor)
627 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
630 if (descriptor.GetCharacteristic() != null)
632 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
635 _impl.AddDescriptor(descriptor);
636 descriptor.SetParent(this);
640 /// Gets descriptor with given UUID that belongs to this characteristic.
642 /// <param name="uuid">UUID for the descriptor to get</param>
643 /// <returns>descriptor with given uuid if it exists, null otherwise</returns>
644 public BluetoothGattDescriptor GetDescriptor(string uuid)
646 return _impl.GetDescriptor(this, uuid);
650 /// Gets list of descriptors that belongs to this characteristic.
652 /// <returns>list of descriptors that belongs to this characteristic</returns>
653 public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
655 return _impl.GetDescriptors(this);
659 /// Gets the service instance which the specified characterstic belongs to.
661 /// <returns>characteristic instance, the specified characterstic belongs to.</returns>
662 public BluetoothGattService GetService()
667 internal void SetParent(BluetoothGattService parent)
672 ReleaseHandleOwnership();
678 /// Bluetooth GATT descriptor
680 public class BluetoothGattDescriptor : BluetoothGattAttribute
682 private BluetoothGattCharacteristic _parent = null;
683 private BluetoothGattDescriptorImpl _impl;
688 /// <param name="uuid">UUID of the descriptor</param>
689 /// <param name="permisions">Permissions for the descriptor</param>
690 /// <param name="value">Value associated with the descriptor</param>
691 /// <remarks>throws in case of internal error</remarks>
692 public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
694 _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
697 internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
702 internal override BluetoothGattClient Client
706 return _parent?.Client;
710 internal override BluetoothGattServer Server
714 return _parent?.Server;
718 internal override BluetoothGattAttributeImpl Impl
727 /// Gets the characteristic instance which the specified descriptor belongs to.
729 /// <returns>characteristic instance, the specified descriptor belongs to.</returns>
730 public BluetoothGattCharacteristic GetCharacteristic()
735 internal void SetParent(BluetoothGattCharacteristic parent)
740 ReleaseHandleOwnership();
746 /// Bluetooth GATT attribute
748 public abstract class BluetoothGattAttribute
750 private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
751 private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
753 private EventHandler<ReadRequestedEventArgs> _readValueRequested;
754 private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
756 public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
759 Permissions = permission;
765 /// Event called when client request to read value of a characteristic or descriptor
767 public event EventHandler<ReadRequestedEventArgs> ReadRequested
771 if (Server == null) return;
772 if (_readValueRequestedCallback == null)
774 _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
776 _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
778 Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
780 _readValueRequested = value;
784 if (Server == null) return;
785 _readValueRequested = null;
786 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
791 /// Event called when a value of a characteristic or descriptor has been changed by a client
793 public event EventHandler<WriteRequestedEventArgs> WriteRequested
797 if (Server == null) return;
798 if (_writeValueRequested == null)
800 _writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, response_needed, valueToWrite, len, userData) =>
802 _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, valueToWrite, offset, response_needed));
804 Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
806 _writeValueRequested = value;
810 if (Server == null) return;
811 _writeValueRequested = null;
812 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
819 public string Uuid { get; }
822 /// Permissions for this attribute
824 public BluetoothGattPermission Permissions { get; }
827 /// Value of this descriptor
833 return Impl.GetValue();
837 Impl.SetValue(value);
841 internal abstract BluetoothGattClient Client { get; }
842 internal abstract BluetoothGattServer Server { get; }
843 internal abstract BluetoothGattAttributeImpl Impl { get; }
846 /// Returns string value at specified offset
848 /// <param name="offset"></param>
849 /// <returns>string value at specified offset</returns>
850 public string GetValue(int offset)
852 return Impl.GetValue(offset);
856 /// Sets string value as specified offset
858 /// <param name="value">value to set</param>
859 /// <exception cref="InvalidOperationException">Throws excetion if value is null</exception>
860 public void SetValue(string value)
862 if (string.IsNullOrEmpty(value))
863 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
865 byte[] val = Encoding.UTF8.GetBytes(value);
870 /// Returns value at specified offset as int value of specified type
872 /// <param name="type">type of int value</param>
873 /// <param name="offset">offset in the attribute value buffer</param>
874 /// <returns>int value at given offset</returns>
875 /// <exception cref="InvalidOperationException">Throws excetion if (offset + size of int value) is greater then length of value buffer</exception>
876 public int GetValue(IntDataType type, int offset)
878 return Impl.GetValue(type, offset);
882 /// Update Value at specified offset by int value of specified type
884 /// <param name="type">type of int value</param>
885 /// <param name="value">value to set</param>
886 /// <param name="offset">offset in the attribute value buffer</param>
887 /// <exception cref="InvalidOperationException">Throws excetion if (offset + size of int value) is greater then length of value buffer</exception>
888 public void SetValue(IntDataType type, int value, int offset)
890 Impl.SetValue(type, value, offset);
894 /// Returns value at specified offset as float value of specified type
896 /// <param name="type">type of float value</param>
897 /// <param name="offset">offset in the attribute value buffer</param>
898 /// <returns>float value at given offset</returns>
899 /// <exception cref="InvalidOperationException">Throws excetion if (offset + size of float value) is greater then length of value buffer</exception>
900 public float GetValue(FloatDataType type, int offset)
902 return Impl.GetValue(type, offset);
906 /// Update Value at specified offset by float value of specified type
908 /// <param name="type">type of float value</param>
909 /// <param name="mantissa">mantissa of float value</param>
910 /// <param name="exponent">exponent of float value</param>
911 /// <param name="offset">offset in the attribute value buffer</param>
912 /// <exception cref="InvalidOperationException">Throws excetion if (offset + size of float value) is greater then length of value buffer</exception>
913 public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
915 Impl.SetValue(type, mantissa, exponent, offset);
918 internal void ReleaseHandleOwnership()
920 Impl.ReleaseHandleOwnership();
923 internal BluetoothGattAttributeHandle GetHandle()
925 return Impl.GetHandle();