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 /// The Bluetooth GATT server.
28 /// <since_tizen> 3 </since_tizen>
29 public class BluetoothGattServer : IDisposable
31 private static BluetoothGattServer _instance;
32 private BluetoothGattServerImpl _impl;
34 private BluetoothGattServer()
36 _impl = new BluetoothGattServerImpl();
40 /// (event) This event is called when the indication acknowledgement is received for each notified client.
42 /// <since_tizen> 3 </since_tizen>
43 public event EventHandler<NotificationSentEventArg> NotificationSent
47 _impl._notificationSent += value;
51 _impl._notificationSent -= value;
56 /// Creates the Bluetooth GATT server.
58 /// <returns>The BluetoothGattServer instance.</returns>
59 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
60 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
61 /// <exception cref="InvalidOperationException">Thrown when the create GATT server fails.</exception>
62 /// <since_tizen> 3 </since_tizen>
63 public static BluetoothGattServer CreateServer()
65 if (_instance == null)
67 BluetoothGattServer server = new BluetoothGattServer();
77 /// Registers the server along with the GATT services of the application it is hosting.
79 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
80 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
81 /// <exception cref="InvalidOperationException">Thrown when the register server application fails.</exception>
82 /// <since_tizen> 3 </since_tizen>
89 /// Registers a specified service to this server.
91 /// <param name="service">The service, which needs to be registered with this server.</param>
92 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
93 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
94 /// <exception cref="InvalidOperationException">Thrown when the register service fails.</exception>
95 /// <since_tizen> 3 </since_tizen>
96 public void RegisterGattService(BluetoothGattService service)
98 if (service.IsRegistered())
100 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
102 _impl.RegisterGattService(this, service);
106 /// Unregisters a specified service from this server.
108 /// <param name="service">The service, which needs to be unregistered from this server.</param>
110 /// Once unregistered, the service object will become invalid and should not be used to access sevices or any children attribute's methods/members.
112 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
113 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
114 /// <exception cref="InvalidOperationException">Thrown when the unregister service fails.</exception>
115 /// <since_tizen> 3 </since_tizen>
116 public void UnregisterGattService(BluetoothGattService service)
118 if (service.GetGattServer() != this)
120 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
123 _impl.UnregisterGattService(service);
127 /// Unregisters all services from this server.
130 /// Once unregistered, servicees will become invalid and should not be used to access sevices or any children attribute's methods/members.
132 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
133 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
134 /// <exception cref="InvalidOperationException">Thrown when the unregister all services fail.</exception>
135 /// <since_tizen> 3 </since_tizen>
136 public void UnregisterGattServices()
138 _impl.UnregisterAllGattServices(this);
142 /// Gets service with given UUID that belongs to this server.
144 /// <param name="uuid">The UUID for the service to get.</param>
145 /// <returns>The Service with the given UUID if it exists, null otherwise.</returns>
146 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
147 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
148 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
149 /// <since_tizen> 3 </since_tizen>
150 public BluetoothGattService GetService(string uuid)
152 return _impl.GetService(this, uuid);
156 /// Gets the list of services that belongs to this server.
158 /// <returns>The list of services that belongs to this server.</returns>
159 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
160 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
161 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
162 /// <since_tizen> 3 </since_tizen>
163 public IEnumerable<BluetoothGattService> GetServices()
165 return _impl.GetServices(this);
169 /// Sends indication for the value change of the characteristic to the remote devices.
171 /// <param name="characteristic">The characteristic whose the value is changed.</param>
172 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
173 /// <returns>true on success, false otherwise.</returns>
174 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
175 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
176 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
177 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
178 /// <since_tizen> 3 </since_tizen>
179 public async Task<bool> SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
181 return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
185 /// Sends the notification for the value change of the characteristic to the remote devices.
187 /// <param name="characteristic">The characteristic, which has a changed value.</param>
188 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
189 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
190 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
191 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
192 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
193 /// <since_tizen> 3 </since_tizen>
194 public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
196 _impl.SendNotification(characteristic, clientAddress);
200 /// Sends a response to the remote device as a result of a read/write request.
202 /// <param name="requestId">The identification of a read/write request.</param>
203 /// <param name="type">The request type for read/write.</param>
204 /// <param name="status">The error value in case of failure, 0 for success.</param>
205 /// <param name="value">The value to be sent.</param>
206 /// <param name="offset">The offset from where the value is read.</param>
207 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
208 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
209 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
210 /// or when the remote device is disconnected, or the send response procedure fails.</exception>
211 /// <since_tizen> 3 </since_tizen>
212 public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
214 _impl.SendResponse(requestId, (int)type, status, value, offset);
217 internal bool IsValid()
219 return _impl.GetHandle().IsInvalid == false;
223 /// Destroys the current object.
225 ~BluetoothGattServer()
231 /// Destroys the current object.
233 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
234 /// <since_tizen> 6 </since_tizen>
235 public void Dispose()
238 GC.SuppressFinalize(this);
242 /// Releases all the resources currently used by this instance.
244 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
245 /// <since_tizen> 6 </since_tizen>
246 protected virtual void Dispose(bool disposing)
250 _impl?.GetHandle()?.Dispose();
257 /// The Bluetooth GATT client.
259 /// <since_tizen> 3 </since_tizen>
260 public class BluetoothGattClient : IDisposable
262 private BluetoothGattClientImpl _impl;
263 private string _remoteAddress = string.Empty;
264 private TaskCompletionSource<bool> _taskForConnection;
265 private TaskCompletionSource<bool> _taskForDisconnection;
266 private static event EventHandler<GattConnectionStateChangedEventArgs> s_connectionStateChanged;
267 private static Interop.Bluetooth.GattConnectionStateChangedCallBack s_connectionStateChangeCallback;
269 internal BluetoothGattClient(string remoteAddress)
271 _impl = new BluetoothGattClientImpl(remoteAddress);
272 _remoteAddress = remoteAddress;
273 StaticConnectionStateChanged += OnConnectionStateChanged;
277 /// Creates the Bluetooth GATT client.
279 /// <returns>The BluetoothGattClient instance.</returns>
280 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
281 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
282 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
283 /// <since_tizen> 6 </since_tizen>
284 public static BluetoothGattClient CreateClient(string remoteAddress)
286 BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
287 return client.Isvalid() ? client : null;
291 /// The ConnectionStateChanged event is raised when the gatt connection state is changed.
293 /// <since_tizen> 6 </since_tizen>
294 public event EventHandler<GattConnectionStateChangedEventArgs> ConnectionStateChanged;
296 private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
298 if (e.RemoteAddress == _remoteAddress)
300 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
302 if (e.Result == (int)BluetoothError.None)
304 _taskForConnection.SetResult(true);
308 _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
310 _taskForConnection = null;
313 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
315 if (e.Result == (int)BluetoothError.None)
317 _taskForDisconnection.SetResult(true);
321 _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
323 _taskForDisconnection = null;
326 if (e.Result == (int)BluetoothError.None)
328 ConnectionStateChanged?.Invoke(this, e);
333 private static event EventHandler<GattConnectionStateChangedEventArgs> StaticConnectionStateChanged
337 if (s_connectionStateChanged == null)
339 RegisterConnectionStateChangedEvent();
341 s_connectionStateChanged += value;
345 s_connectionStateChanged -= value;
346 if (s_connectionStateChanged == null)
348 UnregisterConnectionStateChangedEvent();
353 private static void RegisterConnectionStateChangedEvent()
355 s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
357 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
358 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
359 s_connectionStateChanged?.Invoke(null, e);
362 int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
363 if (ret != (int)BluetoothError.None)
365 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
366 BluetoothErrorFactory.ThrowBluetoothException(ret);
370 private static void UnregisterConnectionStateChangedEvent()
372 int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
373 if (ret != (int)BluetoothError.None)
375 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
376 BluetoothErrorFactory.ThrowBluetoothException(ret);
381 /// Connects to the remote GATT server asynchronously.
383 /// <param name="autoConnect">The flag for reconnecting when the connection is disconnceted.</param>
384 /// <returns> A task indicating whether the method is done or not.</returns>
385 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
386 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
387 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
388 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
389 /// <since_tizen> 6 </since_tizen>
390 public Task ConnectAsync(bool autoConnect)
392 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
394 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
396 _taskForConnection = new TaskCompletionSource<bool>();
397 _impl.Connect(_remoteAddress, autoConnect);
398 return _taskForConnection.Task;
402 /// Disconnects to the remote GATT server asynchronously.
404 /// <returns> A task indicating whether the method is done or not.</returns>
405 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
406 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
407 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
408 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
409 /// <since_tizen> 6 </since_tizen>
410 public Task DisconnectAsync()
412 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
414 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
416 _taskForDisconnection = new TaskCompletionSource<bool>();
417 _impl.Disconnect(_remoteAddress);
418 return _taskForDisconnection.Task;
422 /// Destroy Bluetooth GATT client
424 /// <since_tizen> 3 </since_tizen>
425 public void DestroyClient()
427 _impl.GetHandle().Dispose();
431 /// The address of the remote device.
433 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
434 /// or when the remote device is disconnected.</exception>
435 /// <since_tizen> 3 </since_tizen>
436 public string RemoteAddress
440 if (string.IsNullOrEmpty(_remoteAddress))
442 _remoteAddress = _impl.GetRemoteAddress();
444 return _remoteAddress;
449 /// Gets the service with the given UUID that belongs to the remote device.
451 /// <param name="uuid">The UUID for the service to get.</param>
452 /// <returns>The service with the given UUID if it exists, null otherwise.</returns>
453 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
454 /// or when the remote device is disconnected, or when the get service fails.</exception>
455 /// <since_tizen> 3 </since_tizen>
456 public BluetoothGattService GetService(string uuid)
458 return _impl.GetService(this, uuid);
462 /// Gets list of services that belongs to the remote device.
464 /// <returns>The list of services that belongs to the remote device.</returns>
465 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
466 /// or when the remote device is disconnected, or when the get service fails.</exception>
467 /// <since_tizen> 3 </since_tizen>
468 public IEnumerable<BluetoothGattService> GetServices()
470 return _impl.GetServices(this);
474 /// Reads the value of a given characteristic from the remote device asynchronously.
476 /// <param name="characteristic">The characteristic to be read.</param>
477 /// <returns>true on success, false otherwise.</returns>
478 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
479 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
480 /// <since_tizen> 3 </since_tizen>
481 public async Task<bool> ReadValueAsync(BluetoothGattCharacteristic characteristic)
483 return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
487 /// Reads the value of the given descriptor from the remote device asynchronously.
489 /// <param name="descriptor">The descriptor to be read.</param>
490 /// <returns>true on success, false otherwise.</returns>
491 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
492 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
493 /// <since_tizen> 3 </since_tizen>
494 public async Task<bool> ReadValueAsync(BluetoothGattDescriptor descriptor)
496 return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
500 /// Writes the value of a given characteristic to the remote device asynchronously.
502 /// <param name="characteristic">The characteristic to be written.</param>
503 /// <returns>true on success, false otherwise.</returns>
504 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
505 /// or when the remote device is disconnected or when the write attribute value fails.</exception>
506 /// <since_tizen> 3 </since_tizen>
507 public async Task<bool> WriteValueAsync(BluetoothGattCharacteristic characteristic)
509 return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
513 /// Writes the value of the given descriptor to the remote device asynchronously.
515 /// <param name="descriptor">The descriptor to be written.</param>
516 /// <returns>true on success, false otherwise.</returns>
517 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
518 /// or when the remote device is disconnected, or when the write attribute value fails.</exception>
519 /// <since_tizen> 3 </since_tizen>
520 public async Task<bool> WriteValueAsync(BluetoothGattDescriptor descriptor)
522 return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
525 internal bool Isvalid()
527 return _impl.GetHandle().IsInvalid == false;
531 /// Destroys the current object.
533 ~BluetoothGattClient()
539 /// Destroys the current object.
541 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
542 /// <since_tizen> 6 </since_tizen>
543 public void Dispose()
546 GC.SuppressFinalize(this);
550 /// Releases all the resources currently used by this instance.
552 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
553 /// <since_tizen> 6 </since_tizen>
554 protected virtual void Dispose(bool disposing)
558 _impl?.GetHandle()?.Dispose();
560 StaticConnectionStateChanged -= OnConnectionStateChanged;
566 /// The Bluetooth GATT service.
568 /// <since_tizen> 3 </since_tizen>
569 public class BluetoothGattService
571 private BluetoothGattServiceImpl _impl;
572 private BluetoothGattClient _parentClient = null;
573 private BluetoothGattServer _parentServer = null;
574 private BluetoothGattService _parentService = null;
579 /// <param name="uuid">The UUID of the service.</param>
580 /// <param name="type">The type of service.</param>
581 /// <exception cref="InvalidOperationException">Thrown when the create GATT service procedure fails.</exception>
582 /// <since_tizen> 3 </since_tizen>
583 public BluetoothGattService(string uuid, BluetoothGattServiceType type)
586 _impl = new BluetoothGattServiceImpl(uuid, type);
589 internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
596 /// Specification name from the UUID.
598 /// <since_tizen> 3 </since_tizen>
599 public string Uuid { get; }
602 /// Adds a characteristic to this service.
604 /// <param name="characteristic">The characteristic to be added.</param>
605 /// <returns>true on success, false otherwise.</returns>
606 /// <exception cref="InvalidOperationException">Thrown when the add GATT characteristic procedure fails.</exception>
607 /// <since_tizen> 3 </since_tizen>
608 public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
610 if (GetGattClient() != null)
612 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
615 if (characteristic.GetService() != null)
617 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
620 _impl.AddCharacteristic(characteristic);
621 characteristic.SetParent(this);
625 /// Gets the characteristic with the given UUID that belongs to this service.
627 /// <param name="uuid">The UUID for the characteristic to get.</param>
628 /// <returns>The characteristic with a given UUID if it exists, null otherwise.</returns>
629 /// <since_tizen> 3 </since_tizen>
630 public BluetoothGattCharacteristic GetCharacteristic(string uuid)
632 return _impl.GetCharacteristic(this, uuid);
636 /// Gets list of the characteristic that belongs to this service.
638 /// <returns>The list of the characteristic that belongs to this service.</returns>
639 /// <since_tizen> 3 </since_tizen>
640 public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
642 return _impl.GetCharacteristics(this);
646 /// Includes a service to this service.
648 /// <param name="service">The service to be included.</param>
649 /// <returns>true on success, false otherwise</returns>
650 /// <exception cref="InvalidOperationException">Thrown when the add GATT service procedure fails.</exception>///
651 /// <since_tizen> 3 </since_tizen>
652 public void AddService(BluetoothGattService service)
654 if (GetGattClient() != null)
656 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
659 if (service.IsRegistered())
661 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
664 _impl.AddIncludeService(service);
665 service.SetParent(this);
669 /// Gets the included service.
671 /// <param name="uuid">The UUID for the service to get.</param>
672 /// <returns>The service with a given UUID if it exists, null otherwise.</returns>
673 /// <since_tizen> 3 </since_tizen>
674 public BluetoothGattService GetIncludeService(string uuid)
676 return _impl.GetIncludeService(this, uuid);
680 /// Gets the included service list of this service.
682 /// <returns>The included service list of this service.</returns>
683 /// <since_tizen> 3 </since_tizen>
684 public IEnumerable<BluetoothGattService> GetIncludeServices()
686 return _impl.GetIncludeServices(this);
690 /// Gets the server instance which the specified service belongs to.
692 /// <returns>The server instance which the specified service belongs to.</returns>
693 /// <since_tizen> 3 </since_tizen>
694 public BluetoothGattServer GetGattServer()
696 return _parentServer;
700 /// Gets the client instance which the specified service belongs to.
702 /// <returns>The client instance which the specified service belongs to.</returns>
703 /// <since_tizen> 3 </since_tizen>
704 public BluetoothGattClient GetGattClient()
706 return _parentClient;
709 internal BluetoothGattAttributeHandle GetHandle()
711 return _impl.GetHandle();
714 internal void SetParent(BluetoothGattService parent)
718 _parentService = parent;
719 _impl.ReleaseHandleOwnership();
723 internal void SetParent(BluetoothGattClient parent)
727 _parentClient = parent;
728 _impl.ReleaseHandleOwnership();
732 internal void SetParent(BluetoothGattServer parent)
736 _parentServer = parent;
737 _impl.ReleaseHandleOwnership();
741 internal void UnregisterService()
743 _parentServer = null;
744 _parentClient = null;
745 _parentService = null;
748 internal bool IsRegistered()
750 return _parentClient != null || _parentServer != null || _parentService != null;
755 /// The Bluetooth GATT characteristic.
757 /// <since_tizen> 3 </since_tizen>
758 public class BluetoothGattCharacteristic : BluetoothGattAttribute
760 private BluetoothGattCharacteristicImpl _impl;
761 private BluetoothGattService _parent = null;
763 private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
764 private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
766 private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
767 internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
772 /// <param name="uuid">The UUID of the characterstic.</param>
773 /// <param name="permissions">Permissions for the characterstic.</param>
774 /// <param name="properties">Properties set for the characterstic.</param>
775 /// <param name="value">The value associated with the characterstic.</param>
776 /// <remarks>throws in case of internal error.</remarks>
777 /// <exception cref="InvalidOperationException">Thrown when the create GATT characteristics procedure fails.</exception>
778 /// <since_tizen> 3 </since_tizen>
779 public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
781 _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
784 internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
790 /// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
793 /// Adding the event handle on characteristic on the server side will not have any effect.
795 /// <since_tizen> 3 </since_tizen>
796 public event EventHandler<ValueChangedEventArgs> ValueChanged
802 if (_characteristicValueChanged == null)
804 _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
806 _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
809 _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
811 _characteristicValueChanged = value;
818 _characteristicValueChanged = null;
819 if (_characteristicValueChanged == null)
821 _impl.UnsetCharacteristicValueChangedEvent();
829 /// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
832 /// Adding event handle on the characteristic on the client side will not have any effect.
834 /// <since_tizen> 3 </since_tizen>
835 public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
841 if (_notificationStateChangedCallback == null)
843 _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
845 _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
848 _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
851 _notificationStateChanged = value;
858 _notificationStateChanged = null;
859 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
865 /// The property for this characteristic.
867 /// <since_tizen> 3 </since_tizen>
868 public BluetoothGattProperty Properties
872 return _impl.GetProperties();
878 _impl.SetProperties(value);
884 /// The write type to be used for write operations.
886 /// <since_tizen> 3 </since_tizen>
887 public BluetoothGattWriteType WriteType
891 return _impl.GetWriteType();
895 _impl.SetWriteType(value);
899 internal override BluetoothGattClient Client
903 return _parent?.GetGattClient();
907 internal override BluetoothGattServer Server
911 return _parent?.GetGattServer();
915 internal override BluetoothGattAttributeImpl Impl
924 /// Adds a descriptor to this characteristic.
926 /// <param name="descriptor">The descriptor to be added.</param>
927 /// <returns>true on success, false otherwise.</returns>
928 /// <exception cref="InvalidOperationException">Thrown when the add GATT descriptor procedure fails.</exception>
929 /// <since_tizen> 3 </since_tizen>
930 public void AddDescriptor(BluetoothGattDescriptor descriptor)
934 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
937 if (descriptor.GetCharacteristic() != null)
939 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
942 _impl.AddDescriptor(descriptor);
943 descriptor.SetParent(this);
947 /// Gets the descriptor with the given UUID that belongs to this characteristic.
949 /// <param name="uuid">The UUID for the descriptor to get.</param>
950 /// <returns>The descriptor with a given UUID if it exists, null otherwise.</returns>
951 /// <since_tizen> 3 </since_tizen>
952 public BluetoothGattDescriptor GetDescriptor(string uuid)
954 return _impl.GetDescriptor(this, uuid);
958 /// Gets the list of descriptors that belongs to this characteristic.
960 /// <returns>The list of descriptors that belongs to this characteristic.</returns>
961 /// <since_tizen> 3 </since_tizen>
962 public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
964 return _impl.GetDescriptors(this);
968 /// Gets the service instance, which the specified characterstic belongs to.
970 /// <returns>The characteristic instance, the specified characterstic belongs to.</returns>
971 /// <since_tizen> 3 </since_tizen>
972 public BluetoothGattService GetService()
977 internal void SetParent(BluetoothGattService parent)
982 ReleaseHandleOwnership();
988 /// The Bluetooth GATT descriptor.
990 /// <since_tizen> 3 </since_tizen>
991 public class BluetoothGattDescriptor : BluetoothGattAttribute
993 private BluetoothGattCharacteristic _parent = null;
994 private BluetoothGattDescriptorImpl _impl;
999 /// <param name="uuid">The UUID of the descriptor.</param>
1000 /// <param name="permisions">Permissions for the descriptor.</param>
1001 /// <param name="value">The value associated with the descriptor.</param>
1002 /// <remarks>throws in case of internal error.</remarks>
1003 /// <exception cref="InvalidOperationException">Thrown when the create GATT descriptor procedure fails.</exception>
1004 /// <since_tizen> 3 </since_tizen>
1005 public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
1007 _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
1010 internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
1015 internal override BluetoothGattClient Client
1019 return _parent?.Client;
1023 internal override BluetoothGattServer Server
1027 return _parent?.Server;
1031 internal override BluetoothGattAttributeImpl Impl
1040 /// Gets the characteristic instance, which the specified descriptor belongs to.
1042 /// <returns>The characteristic instance, the specified descriptor belongs to.</returns>
1043 /// <since_tizen> 3 </since_tizen>
1044 public BluetoothGattCharacteristic GetCharacteristic()
1049 internal void SetParent(BluetoothGattCharacteristic parent)
1051 if (_parent == null)
1054 ReleaseHandleOwnership();
1060 /// The Bluetooth GATT attribute.
1062 /// <since_tizen> 3 </since_tizen>
1063 public abstract class BluetoothGattAttribute
1065 private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
1066 private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
1068 private EventHandler<ReadRequestedEventArgs> _readValueRequested;
1069 private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
1072 /// The constructor.
1074 /// <param name="uuid">The UUID of the GATT attribute.</param>
1075 /// <param name="permission">Permission for the GATT attribute.</param>
1076 /// <since_tizen> 3 </since_tizen>
1077 public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
1080 Permissions = permission;
1086 /// This event is called when the client request to read the value of a characteristic or a descriptor.
1088 /// <exception cref="InvalidOperationException">Thrown when the set read value requested callback procedure fails.</exception>
1089 /// <since_tizen> 3 </since_tizen>
1090 public event EventHandler<ReadRequestedEventArgs> ReadRequested
1094 if (Server == null) return;
1095 if (_readValueRequestedCallback == null)
1097 _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
1099 _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
1101 Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
1103 _readValueRequested = value;
1107 if (Server == null) return;
1108 _readValueRequested = null;
1109 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1114 /// This event is called when a value of a characteristic or a descriptor has been changed by a client.
1116 /// <exception cref="InvalidOperationException">Thrown when the set write value requested callback procedure fails.</exception>
1117 /// <since_tizen> 3 </since_tizen>
1118 public event EventHandler<WriteRequestedEventArgs> WriteRequested
1122 if (Server == null) return;
1123 if (_writeValueRequested == null)
1125 _writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, response_needed, offset, valueToWrite, len, userData) =>
1127 _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, valueToWrite, offset, response_needed));
1129 Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
1131 _writeValueRequested = value;
1135 if (Server == null) return;
1136 _writeValueRequested = null;
1137 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1142 /// The attribute's UUID.
1144 /// <since_tizen> 3 </since_tizen>
1145 public string Uuid { get; }
1148 /// Permissions for this attribute.
1150 /// <since_tizen> 3 </since_tizen>
1151 public BluetoothGattPermission Permissions { get; }
1154 /// The value of this descriptor.
1156 /// <since_tizen> 3 </since_tizen>
1161 return Impl.GetValue();
1165 Impl.SetValue(value);
1169 internal abstract BluetoothGattClient Client { get; }
1170 internal abstract BluetoothGattServer Server { get; }
1171 internal abstract BluetoothGattAttributeImpl Impl { get; }
1174 /// Returns a string value at the specified offset.
1176 /// <param name="offset">An offset in the attribute value buffer.</param>
1177 /// <returns>The string value at specified offset.</returns>
1178 /// <since_tizen> 3 </since_tizen>
1179 public string GetValue(int offset)
1181 return Impl.GetValue(offset);
1185 /// Sets the string value as a specified offset.
1187 /// <param name="value">value to set</param>
1188 /// <exception cref="InvalidOperationException">Throws exception if the value is null.</exception>
1189 /// <since_tizen> 3 </since_tizen>
1190 public void SetValue(string value)
1192 if (string.IsNullOrEmpty(value))
1193 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
1195 byte[] val = Encoding.UTF8.GetBytes(value);
1200 /// Returns a value at specified offset as the int value of the specified type.
1202 /// <param name="type">The type of the int value.</param>
1203 /// <param name="offset">An offset in the attribute value buffer.</param>
1204 /// <returns>The int value at given offset.</returns>
1205 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1206 /// <since_tizen> 3 </since_tizen>
1207 public int GetValue(IntDataType type, int offset)
1209 return Impl.GetValue(type, offset);
1213 /// Updates a value at the specified offset by the int value of the specified type.
1215 /// <param name="type">The type of the int value.</param>
1216 /// <param name="value">The value to set.</param>
1217 /// <param name="offset">An offset in the attribute value buffer.</param>
1218 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1219 /// <since_tizen> 3 </since_tizen>
1220 public void SetValue(IntDataType type, int value, int offset)
1222 Impl.SetValue(type, value, offset);
1226 /// Returns a value at the specified offset as the float value of the specified type.
1228 /// <param name="type">The type of the float value.</param>
1229 /// <param name="offset">An offset in the attribute value buffer.</param>
1230 /// <returns>The float value at given offset.</returns>
1231 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1232 /// <since_tizen> 3 </since_tizen>
1233 public float GetValue(FloatDataType type, int offset)
1235 return Impl.GetValue(type, offset);
1239 /// Updates the value at the specified offset by the float value of the specified type.
1241 /// <param name="type">The type of the float value.</param>
1242 /// <param name="mantissa">The mantissa of the float value.</param>
1243 /// <param name="exponent">An exponent of the float value.</param>
1244 /// <param name="offset">An offset in the attribute value buffer.</param>
1245 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1246 /// <since_tizen> 3 </since_tizen>
1247 public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
1249 Impl.SetValue(type, mantissa, exponent, offset);
1252 internal void ReleaseHandleOwnership()
1254 Impl.ReleaseHandleOwnership();
1257 internal BluetoothGattAttributeHandle GetHandle()
1259 return Impl.GetHandle();