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.ComponentModel;
20 using System.Runtime.InteropServices;
22 using System.Threading.Tasks;
24 namespace Tizen.Network.Bluetooth
27 /// The Bluetooth GATT server.
29 /// <since_tizen> 3 </since_tizen>
30 public class BluetoothGattServer : IDisposable
32 private static BluetoothGattServer _instance;
33 private BluetoothGattServerImpl _impl;
35 private BluetoothGattServer()
37 _impl = new BluetoothGattServerImpl();
38 _impl._notificationSent += (s, e) =>
41 NotificationSent?.Invoke(this, e);
46 /// (event) This event is called when the indication acknowledgement is received for each notified client.
48 /// <since_tizen> 3 </since_tizen>
49 public event EventHandler<NotificationSentEventArg> NotificationSent;
52 /// Creates the Bluetooth GATT server.
54 /// <returns>The BluetoothGattServer instance.</returns>
55 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
56 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
57 /// <exception cref="InvalidOperationException">Thrown when the create GATT server fails.</exception>
58 /// <since_tizen> 3 </since_tizen>
59 public static BluetoothGattServer CreateServer()
61 if (_instance == null)
63 BluetoothGattServer server = new BluetoothGattServer();
73 /// Registers the server along with the GATT services of the application it is hosting.
75 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
76 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
77 /// <exception cref="InvalidOperationException">Thrown when the register server application fails.</exception>
78 /// <since_tizen> 3 </since_tizen>
85 /// Registers a specified service to this server.
87 /// <param name="service">The service, which needs to be registered with this server.</param>
88 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
89 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
90 /// <exception cref="InvalidOperationException">Thrown when the register service fails.</exception>
91 /// <since_tizen> 3 </since_tizen>
92 public void RegisterGattService(BluetoothGattService service)
94 if (service.IsRegistered())
96 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
98 _impl.RegisterGattService(this, service);
102 /// Unregisters a specified service from this server.
104 /// <param name="service">The service, which needs to be unregistered from this server.</param>
106 /// Once unregistered, the service object will become invalid and should not be used to access sevices or any children attribute's methods/members.
108 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
109 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
110 /// <exception cref="InvalidOperationException">Thrown when the unregister service fails.</exception>
111 /// <since_tizen> 3 </since_tizen>
112 public void UnregisterGattService(BluetoothGattService service)
114 if (service.GetGattServer() != this)
116 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
119 _impl.UnregisterGattService(service);
123 /// Unregisters all services from this server.
126 /// Once unregistered, servicees will become invalid and should not be used to access sevices or any children attribute's methods/members.
128 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
129 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
130 /// <exception cref="InvalidOperationException">Thrown when the unregister all services fail.</exception>
131 /// <since_tizen> 3 </since_tizen>
132 public void UnregisterGattServices()
134 _impl.UnregisterAllGattServices(this);
138 /// Gets service with given UUID that belongs to this server.
140 /// <param name="uuid">The UUID for the service to get.</param>
141 /// <returns>The Service with the given UUID if it exists, null otherwise.</returns>
142 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
143 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
144 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
145 /// <since_tizen> 3 </since_tizen>
146 public BluetoothGattService GetService(string uuid)
148 return _impl.GetService(this, uuid);
152 /// Gets the list of services that belongs to this server.
154 /// <returns>The list of services that belongs to this server.</returns>
155 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
156 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
157 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
158 /// <since_tizen> 3 </since_tizen>
159 public IEnumerable<BluetoothGattService> GetServices()
161 return _impl.GetServices(this);
165 /// Sends indication for the value change of the characteristic to the remote devices.
167 /// <param name="characteristic">The characteristic whose the value is changed.</param>
168 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
169 /// <returns>true on success, false otherwise.</returns>
170 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
171 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
172 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
173 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
174 /// <since_tizen> 3 </since_tizen>
175 public async Task<bool> SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
177 return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
181 /// Sends the notification for the value change of the characteristic to the remote devices.
183 /// <param name="characteristic">The characteristic, which has a changed value.</param>
184 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
185 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
186 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
187 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
188 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
189 /// <since_tizen> 3 </since_tizen>
190 public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
192 _ = _impl.SendIndicationAsync(this, characteristic, clientAddress);
196 /// Sends a response to the remote device as a result of a read/write request.
198 /// <param name="requestId">The identification of a read/write request.</param>
199 /// <param name="type">The request type for read/write.</param>
200 /// <param name="status">The error value in case of failure, 0 for success.</param>
201 /// <param name="value">The value to be sent.</param>
202 /// <param name="offset">The offset from where the value is read.</param>
203 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
204 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
205 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
206 /// or when the remote device is disconnected, or the send response procedure fails.</exception>
207 /// <since_tizen> 3 </since_tizen>
208 public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
210 _impl.SendResponse(requestId, (int)type, status, value, offset);
213 internal bool IsValid()
215 return _impl.GetHandle().IsInvalid == false;
219 /// Destroys the current object.
221 ~BluetoothGattServer()
227 /// Destroys the current object.
229 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
230 /// <since_tizen> 6 </since_tizen>
231 public void Dispose()
234 GC.SuppressFinalize(this);
238 /// Releases all the resources currently used by this instance.
240 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
241 /// <since_tizen> 6 </since_tizen>
242 protected virtual void Dispose(bool disposing)
246 _impl?.GetHandle()?.Dispose();
253 /// The Bluetooth GATT client.
255 /// <since_tizen> 3 </since_tizen>
256 public class BluetoothGattClient : IDisposable
258 private BluetoothGattClientImpl _impl;
259 private string _remoteAddress = string.Empty;
260 private TaskCompletionSource<bool> _taskForConnection;
261 private TaskCompletionSource<bool> _taskForDisconnection;
262 private static event EventHandler<GattConnectionStateChangedEventArgs> s_connectionStateChanged;
263 private static Interop.Bluetooth.GattConnectionStateChangedCallBack s_connectionStateChangeCallback;
265 internal BluetoothGattClient(string remoteAddress)
267 _impl = new BluetoothGattClientImpl(remoteAddress);
268 _remoteAddress = remoteAddress;
269 StaticConnectionStateChanged += OnConnectionStateChanged;
270 _impl.AttMtuChanged += OnAttMtuChanged;
273 private void OnAttMtuChanged(object s, AttMtuChangedEventArgs e)
275 AttMtuChanged?.Invoke(this, e);
279 /// Creates the Bluetooth GATT client.
281 /// <param name="remoteAddress">The remote device address.</param>
282 /// <returns>The BluetoothGattClient instance.</returns>
283 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
284 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
285 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
286 /// <since_tizen> 6 </since_tizen>
287 public static BluetoothGattClient CreateClient(string remoteAddress)
289 BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
290 return client.Isvalid() ? client : null;
294 /// The ConnectionStateChanged event is raised when the gatt connection state is changed.
296 /// <since_tizen> 6 </since_tizen>
297 public event EventHandler<GattConnectionStateChangedEventArgs> ConnectionStateChanged;
299 private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
301 if (e.RemoteAddress == _remoteAddress)
303 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
305 if (e.Result == (int)BluetoothError.None)
307 _taskForConnection.SetResult(true);
311 _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
313 _taskForConnection = null;
316 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
318 if (e.Result == (int)BluetoothError.None)
320 _taskForDisconnection.SetResult(true);
324 _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
326 _taskForDisconnection = null;
329 if (e.Result == (int)BluetoothError.None)
331 ConnectionStateChanged?.Invoke(this, e);
336 internal static event EventHandler<GattConnectionStateChangedEventArgs> StaticConnectionStateChanged
340 if (s_connectionStateChanged == null)
342 RegisterConnectionStateChangedEvent();
344 s_connectionStateChanged += value;
348 s_connectionStateChanged -= value;
349 if (s_connectionStateChanged == null)
351 UnregisterConnectionStateChangedEvent();
356 private static void RegisterConnectionStateChangedEvent()
358 s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
360 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
361 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
362 s_connectionStateChanged?.Invoke(null, e);
365 int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
366 if (ret != (int)BluetoothError.None)
368 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
372 private static void UnregisterConnectionStateChangedEvent()
374 int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
375 if (ret != (int)BluetoothError.None)
377 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
382 /// Connects to the remote GATT server asynchronously.
384 /// <param name="autoConnect">The flag for reconnecting when the connection is disconnceted.</param>
385 /// <returns> A task indicating whether the method is done or not.</returns>
386 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
387 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
388 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
389 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
390 /// <since_tizen> 6 </since_tizen>
391 public Task ConnectAsync(bool autoConnect)
393 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
395 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
397 _taskForConnection = new TaskCompletionSource<bool>();
398 _impl.Connect(_remoteAddress, autoConnect);
399 return _taskForConnection.Task;
403 /// Disconnects to the remote GATT server asynchronously.
405 /// <returns> A task indicating whether the method is done or not.</returns>
406 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
407 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
408 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
409 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
410 /// <since_tizen> 6 </since_tizen>
411 public Task DisconnectAsync()
413 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
415 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
417 _taskForDisconnection = new TaskCompletionSource<bool>();
418 _impl.Disconnect(_remoteAddress);
419 return _taskForDisconnection.Task;
423 /// Destroy Bluetooth GATT client
425 /// <since_tizen> 3 </since_tizen>
426 [Obsolete("Deprecated since API level 6. Please use Dispose() method on BluetoothGattClient.")]
427 public void DestroyClient()
429 _impl.GetHandle().Dispose();
433 /// The address of the remote device.
435 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
436 /// or when the remote device is disconnected.</exception>
437 /// <since_tizen> 3 </since_tizen>
438 public string RemoteAddress
442 if (string.IsNullOrEmpty(_remoteAddress))
444 _remoteAddress = _impl.GetRemoteAddress();
446 return _remoteAddress;
451 /// Gets the service with the given UUID that belongs to the remote device.
453 /// <param name="uuid">The UUID for the service to get.</param>
454 /// <returns>The service with the given UUID if it exists, null otherwise.</returns>
455 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
456 /// or when the remote device is disconnected, or when the get service fails.</exception>
457 /// <since_tizen> 3 </since_tizen>
458 public BluetoothGattService GetService(string uuid)
460 return _impl.GetService(this, uuid);
464 /// Gets list of services that belongs to the remote device.
466 /// <returns>The list of services that belongs to the remote device.</returns>
467 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
468 /// or when the remote device is disconnected, or when the get service fails.</exception>
469 /// <since_tizen> 3 </since_tizen>
470 public IEnumerable<BluetoothGattService> GetServices()
472 return _impl.GetServices(this);
476 /// Reads the value of a given characteristic from the remote device asynchronously.
478 /// <param name="characteristic">The characteristic to be read.</param>
479 /// <returns>true on success, false otherwise.</returns>
480 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
481 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
482 /// <since_tizen> 3 </since_tizen>
483 public async Task<bool> ReadValueAsync(BluetoothGattCharacteristic characteristic)
485 return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
489 /// Reads the value of the given descriptor from the remote device asynchronously.
491 /// <param name="descriptor">The descriptor to be read.</param>
492 /// <returns>true on success, false otherwise.</returns>
493 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
494 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
495 /// <since_tizen> 3 </since_tizen>
496 public async Task<bool> ReadValueAsync(BluetoothGattDescriptor descriptor)
498 return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
502 /// Writes the value of a given characteristic to the remote device asynchronously.
504 /// <param name="characteristic">The characteristic to be written.</param>
505 /// <returns>true on success, false otherwise.</returns>
506 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
507 /// or when the remote device is disconnected or when the write attribute value fails.</exception>
508 /// <since_tizen> 3 </since_tizen>
509 public async Task<bool> WriteValueAsync(BluetoothGattCharacteristic characteristic)
511 return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
515 /// Writes the value of the given descriptor to the remote device asynchronously.
517 /// <param name="descriptor">The descriptor to be written.</param>
518 /// <returns>true on success, false otherwise.</returns>
519 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
520 /// or when the remote device is disconnected, or when the write attribute value fails.</exception>
521 /// <since_tizen> 3 </since_tizen>
522 public async Task<bool> WriteValueAsync(BluetoothGattDescriptor descriptor)
524 return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
528 /// Gets the value of the ATT MTU(Maximum Transmission Unit) for the connection.
530 /// <returns>The MTU value</returns>
531 /// <exception cref="NotSupportedException">Thrown when the BT/BLE is not supported.</exception>
532 /// <exception cref="InvalidOperationException">Thrown when the BT/BLE is not enabled
533 /// or when the remote device is disconnected, or when other specific error occurs.</exception>
534 /// <since_tizen> 8 </since_tizen>
535 [EditorBrowsable(EditorBrowsableState.Never)]
536 public int GetAttMtu()
538 return _impl.GetAttMtu();
542 /// Sets the value of the ATT MTU(Maximum Transmission Unit) for the connection.
544 /// <param name="mtu">The MTU value</param>
545 /// <exception cref="NotSupportedException">Thrown when the BT/BLE is not supported.</exception>
546 /// <exception cref="InvalidOperationException">Thrown when the BT/BLE is not enabled
547 /// or when the remote device is disconnected, or when other specific error occurs.</exception>
548 /// <since_tizen> 8 </since_tizen>
549 [EditorBrowsable(EditorBrowsableState.Never)]
550 public void SetAttMtu(int mtu)
552 _impl.SetAttMtu(mtu);
556 /// The AttMtuChanged event is raised when the MTU value changed.
558 /// <since_tizen> 8 </since_tizen>
559 [EditorBrowsable(EditorBrowsableState.Never)]
560 public event EventHandler<AttMtuChangedEventArgs> AttMtuChanged;
562 internal bool Isvalid()
564 return _impl.GetHandle().IsInvalid == false;
568 /// Destroys the current object.
570 ~BluetoothGattClient()
576 /// Destroys the current object.
578 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
579 /// <since_tizen> 6 </since_tizen>
580 public void Dispose()
583 GC.SuppressFinalize(this);
587 /// Releases all the resources currently used by this instance.
589 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
590 /// <since_tizen> 6 </since_tizen>
591 protected virtual void Dispose(bool disposing)
595 _impl?.GetHandle()?.Dispose();
597 StaticConnectionStateChanged -= OnConnectionStateChanged;
603 /// The Bluetooth GATT service.
605 /// <since_tizen> 3 </since_tizen>
606 public class BluetoothGattService
608 private BluetoothGattServiceImpl _impl;
609 private BluetoothGattClient _parentClient = null;
610 private BluetoothGattServer _parentServer = null;
611 private BluetoothGattService _parentService = null;
616 /// <param name="uuid">The UUID of the service.</param>
617 /// <param name="type">The type of service.</param>
618 /// <exception cref="InvalidOperationException">Thrown when the create GATT service procedure fails.</exception>
619 /// <since_tizen> 3 </since_tizen>
620 public BluetoothGattService(string uuid, BluetoothGattServiceType type)
623 _impl = new BluetoothGattServiceImpl(uuid, type);
626 internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
633 /// Specification name from the UUID.
635 /// <since_tizen> 3 </since_tizen>
636 public string Uuid { get; }
639 /// Adds a characteristic to this service.
641 /// <param name="characteristic">The characteristic to be added.</param>
642 /// <returns>true on success, false otherwise.</returns>
643 /// <exception cref="InvalidOperationException">Thrown when the add GATT characteristic procedure fails.</exception>
644 /// <since_tizen> 3 </since_tizen>
645 public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
647 if (GetGattClient() != null)
649 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
652 if (characteristic.GetService() != null)
654 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
657 _impl.AddCharacteristic(characteristic);
658 characteristic.SetParent(this);
662 /// Gets the characteristic with the given UUID that belongs to this service.
664 /// <param name="uuid">The UUID for the characteristic to get.</param>
665 /// <returns>The characteristic with a given UUID if it exists, null otherwise.</returns>
666 /// <since_tizen> 3 </since_tizen>
667 public BluetoothGattCharacteristic GetCharacteristic(string uuid)
669 return _impl.GetCharacteristic(this, uuid);
673 /// Gets list of the characteristic that belongs to this service.
675 /// <returns>The list of the characteristic that belongs to this service.</returns>
676 /// <since_tizen> 3 </since_tizen>
677 public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
679 return _impl.GetCharacteristics(this);
683 /// Includes a service to this service.
685 /// <param name="service">The service to be included.</param>
686 /// <returns>true on success, false otherwise</returns>
687 /// <exception cref="InvalidOperationException">Thrown when the add GATT service procedure fails.</exception>///
688 /// <since_tizen> 3 </since_tizen>
689 public void AddService(BluetoothGattService service)
691 if (GetGattClient() != null)
693 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
696 if (service.IsRegistered())
698 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
701 _impl.AddIncludeService(service);
702 service.SetParent(this);
706 /// Gets the included service.
708 /// <param name="uuid">The UUID for the service to get.</param>
709 /// <returns>The service with a given UUID if it exists, null otherwise.</returns>
710 /// <since_tizen> 3 </since_tizen>
711 public BluetoothGattService GetIncludeService(string uuid)
713 return _impl.GetIncludeService(this, uuid);
717 /// Gets the included service list of this service.
719 /// <returns>The included service list of this service.</returns>
720 /// <since_tizen> 3 </since_tizen>
721 public IEnumerable<BluetoothGattService> GetIncludeServices()
723 return _impl.GetIncludeServices(this);
727 /// Gets the server instance which the specified service belongs to.
729 /// <returns>The server instance which the specified service belongs to.</returns>
730 /// <since_tizen> 3 </since_tizen>
731 public BluetoothGattServer GetGattServer()
733 return _parentServer;
737 /// Gets the client instance which the specified service belongs to.
739 /// <returns>The client instance which the specified service belongs to.</returns>
740 /// <since_tizen> 3 </since_tizen>
741 public BluetoothGattClient GetGattClient()
743 return _parentClient;
746 internal BluetoothGattAttributeHandle GetHandle()
748 return _impl.GetHandle();
751 internal void SetParent(BluetoothGattService parent)
755 _parentService = parent;
756 _impl.ReleaseHandleOwnership();
760 internal void SetParent(BluetoothGattClient parent)
764 _parentClient = parent;
765 _impl.ReleaseHandleOwnership();
769 internal void SetParent(BluetoothGattServer parent)
773 _parentServer = parent;
774 _impl.ReleaseHandleOwnership();
778 internal void UnregisterService()
780 _parentServer = null;
781 _parentClient = null;
782 _parentService = null;
785 internal bool IsRegistered()
787 return _parentClient != null || _parentServer != null || _parentService != null;
792 /// The Bluetooth GATT characteristic.
794 /// <since_tizen> 3 </since_tizen>
795 public class BluetoothGattCharacteristic : BluetoothGattAttribute
797 private BluetoothGattCharacteristicImpl _impl;
798 private BluetoothGattService _parent = null;
800 private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
801 private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
803 private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
804 internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
809 /// <param name="uuid">The UUID of the characterstic.</param>
810 /// <param name="permissions">Permissions for the characterstic.</param>
811 /// <param name="properties">Properties set for the characterstic.</param>
812 /// <param name="value">The value associated with the characterstic.</param>
813 /// <remarks>throws in case of internal error.</remarks>
814 /// <exception cref="InvalidOperationException">Thrown when the create GATT characteristics procedure fails.</exception>
815 /// <since_tizen> 3 </since_tizen>
816 public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
818 _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
821 internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
827 /// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
830 /// Adding the event handle on characteristic on the server side will not have any effect.
832 /// <since_tizen> 3 </since_tizen>
833 public event EventHandler<ValueChangedEventArgs> ValueChanged
839 if (_characteristicValueChanged == null)
841 _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
843 _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
846 _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
848 _characteristicValueChanged = value;
855 _characteristicValueChanged = null;
856 if (_characteristicValueChanged == null)
858 _impl.UnsetCharacteristicValueChangedEvent();
866 /// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
869 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
870 /// Adding event handle on the characteristic on the client side will not have any effect.
872 /// <since_tizen> 3 </since_tizen>
873 public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
879 if (_notificationStateChangedCallback == null)
881 _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
883 _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
886 _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
889 _notificationStateChanged = value;
896 _notificationStateChanged = null;
897 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
903 /// The property for this characteristic.
905 /// <since_tizen> 3 </since_tizen>
906 public BluetoothGattProperty Properties
910 return _impl.GetProperties();
916 _impl.SetProperties(value);
922 /// The write type to be used for write operations.
924 /// <since_tizen> 3 </since_tizen>
925 public BluetoothGattWriteType WriteType
929 return _impl.GetWriteType();
933 _impl.SetWriteType(value);
937 internal override BluetoothGattClient Client
941 return _parent?.GetGattClient();
945 internal override BluetoothGattServer Server
949 return _parent?.GetGattServer();
953 internal override BluetoothGattAttributeImpl Impl
962 /// Adds a descriptor to this characteristic.
964 /// <param name="descriptor">The descriptor to be added.</param>
965 /// <returns>true on success, false otherwise.</returns>
966 /// <exception cref="InvalidOperationException">Thrown when the add GATT descriptor procedure fails.</exception>
967 /// <since_tizen> 3 </since_tizen>
968 public void AddDescriptor(BluetoothGattDescriptor descriptor)
972 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
975 if (descriptor.GetCharacteristic() != null)
977 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
980 _impl.AddDescriptor(descriptor);
981 descriptor.SetParent(this);
985 /// Gets the descriptor with the given UUID that belongs to this characteristic.
987 /// <param name="uuid">The UUID for the descriptor to get.</param>
988 /// <returns>The descriptor with a given UUID if it exists, null otherwise.</returns>
989 /// <since_tizen> 3 </since_tizen>
990 public BluetoothGattDescriptor GetDescriptor(string uuid)
992 return _impl.GetDescriptor(this, uuid);
996 /// Gets the list of descriptors that belongs to this characteristic.
998 /// <returns>The list of descriptors that belongs to this characteristic.</returns>
999 /// <since_tizen> 3 </since_tizen>
1000 public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
1002 return _impl.GetDescriptors(this);
1006 /// Gets the service instance, which the specified characterstic belongs to.
1008 /// <returns>The characteristic instance, the specified characterstic belongs to.</returns>
1009 /// <since_tizen> 3 </since_tizen>
1010 public BluetoothGattService GetService()
1015 internal void SetParent(BluetoothGattService parent)
1017 if (_parent == null)
1020 ReleaseHandleOwnership();
1026 /// The Bluetooth GATT descriptor.
1028 /// <since_tizen> 3 </since_tizen>
1029 public class BluetoothGattDescriptor : BluetoothGattAttribute
1031 private BluetoothGattCharacteristic _parent = null;
1032 private BluetoothGattDescriptorImpl _impl;
1035 /// The constructor.
1037 /// <param name="uuid">The UUID of the descriptor.</param>
1038 /// <param name="permisions">Permissions for the descriptor.</param>
1039 /// <param name="value">The value associated with the descriptor.</param>
1040 /// <remarks>throws in case of internal error.</remarks>
1041 /// <exception cref="InvalidOperationException">Thrown when the create GATT descriptor procedure fails.</exception>
1042 /// <since_tizen> 3 </since_tizen>
1043 public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
1045 _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
1048 internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
1053 internal override BluetoothGattClient Client
1057 return _parent?.Client;
1061 internal override BluetoothGattServer Server
1065 return _parent?.Server;
1069 internal override BluetoothGattAttributeImpl Impl
1078 /// Gets the characteristic instance, which the specified descriptor belongs to.
1080 /// <returns>The characteristic instance, the specified descriptor belongs to.</returns>
1081 /// <since_tizen> 3 </since_tizen>
1082 public BluetoothGattCharacteristic GetCharacteristic()
1087 internal void SetParent(BluetoothGattCharacteristic parent)
1089 if (_parent == null)
1092 ReleaseHandleOwnership();
1098 /// The Bluetooth GATT attribute.
1100 /// <since_tizen> 3 </since_tizen>
1101 public abstract class BluetoothGattAttribute
1103 private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
1104 private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
1106 private EventHandler<ReadRequestedEventArgs> _readValueRequested;
1107 private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
1110 /// The constructor.
1112 /// <param name="uuid">The UUID of the GATT attribute.</param>
1113 /// <param name="permission">Permission for the GATT attribute.</param>
1114 /// <since_tizen> 3 </since_tizen>
1115 public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
1118 Permissions = permission;
1124 /// This event is called when the client request to read the value of a characteristic or a descriptor.
1127 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
1129 /// <exception cref="InvalidOperationException">Thrown when the set read value requested callback procedure fails.</exception>
1130 /// <since_tizen> 3 </since_tizen>
1131 public event EventHandler<ReadRequestedEventArgs> ReadRequested
1135 if (Server == null) return;
1136 if (_readValueRequestedCallback == null)
1138 _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
1140 _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
1142 Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
1144 _readValueRequested = value;
1148 if (Server == null) return;
1149 _readValueRequested = null;
1150 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1155 /// This event is called when a value of a characteristic or a descriptor has been changed by a client.
1158 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
1160 /// <exception cref="InvalidOperationException">Thrown when the set write value requested callback procedure fails.</exception>
1161 /// <since_tizen> 3 </since_tizen>
1162 public event EventHandler<WriteRequestedEventArgs> WriteRequested
1166 if (Server == null) return;
1167 if (_writeValueRequested == null)
1169 _writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, response_needed, offset, valueToWrite, len, userData) =>
1171 byte[] writeValue = new byte[len];
1172 Marshal.Copy(valueToWrite, writeValue, 0, len);
1173 _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, writeValue, offset, response_needed));
1175 Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
1177 _writeValueRequested = value;
1181 if (Server == null) return;
1182 _writeValueRequested = null;
1183 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1188 /// The attribute's UUID.
1190 /// <since_tizen> 3 </since_tizen>
1191 public string Uuid { get; }
1194 /// Permissions for this attribute.
1196 /// <since_tizen> 3 </since_tizen>
1197 public BluetoothGattPermission Permissions { get; }
1200 /// The value of this descriptor.
1202 /// <since_tizen> 3 </since_tizen>
1207 return Impl.GetValue();
1211 Impl.SetValue(value);
1215 internal abstract BluetoothGattClient Client { get; }
1216 internal abstract BluetoothGattServer Server { get; }
1217 internal abstract BluetoothGattAttributeImpl Impl { get; }
1220 /// Returns a string value at the specified offset.
1222 /// <param name="offset">An offset in the attribute value buffer.</param>
1223 /// <returns>The string value at specified offset.</returns>
1224 /// <since_tizen> 3 </since_tizen>
1225 public string GetValue(int offset)
1227 return Impl.GetValue(offset);
1231 /// Sets the string value as a specified offset.
1233 /// <param name="value">value to set</param>
1234 /// <exception cref="InvalidOperationException">Throws exception if the value is null.</exception>
1235 /// <since_tizen> 3 </since_tizen>
1236 public void SetValue(string value)
1238 if (string.IsNullOrEmpty(value))
1239 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
1241 byte[] val = Encoding.UTF8.GetBytes(value);
1246 /// Returns a value at specified offset as the int value of the specified type.
1248 /// <param name="type">The type of the int value.</param>
1249 /// <param name="offset">An offset in the attribute value buffer.</param>
1250 /// <returns>The int value at given offset.</returns>
1251 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1252 /// <since_tizen> 3 </since_tizen>
1253 public int GetValue(IntDataType type, int offset)
1255 return Impl.GetValue(type, offset);
1259 /// Updates a value at the specified offset by the int value of the specified type.
1261 /// <param name="type">The type of the int value.</param>
1262 /// <param name="value">The value to set.</param>
1263 /// <param name="offset">An offset in the attribute value buffer.</param>
1264 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1265 /// <since_tizen> 3 </since_tizen>
1266 public void SetValue(IntDataType type, int value, int offset)
1268 Impl.SetValue(type, value, offset);
1272 /// Returns a value at the specified offset as the float value of the specified type.
1274 /// <param name="type">The type of the float value.</param>
1275 /// <param name="offset">An offset in the attribute value buffer.</param>
1276 /// <returns>The float value at given offset.</returns>
1277 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1278 /// <since_tizen> 3 </since_tizen>
1279 public float GetValue(FloatDataType type, int offset)
1281 return Impl.GetValue(type, offset);
1285 /// Updates the value at the specified offset by the float value of the specified type.
1287 /// <param name="type">The type of the float value.</param>
1288 /// <param name="mantissa">The mantissa of the float value.</param>
1289 /// <param name="exponent">An exponent of the float value.</param>
1290 /// <param name="offset">An offset in the attribute value buffer.</param>
1291 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1292 /// <since_tizen> 3 </since_tizen>
1293 public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
1295 Impl.SetValue(type, mantissa, exponent, offset);
1298 internal void ReleaseHandleOwnership()
1300 Impl.ReleaseHandleOwnership();
1303 internal BluetoothGattAttributeHandle GetHandle()
1305 return Impl.GetHandle();