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 /// <param name="remoteAddress">The remote device address.</param>
280 /// <returns>The BluetoothGattClient instance.</returns>
281 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
282 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
283 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
284 /// <since_tizen> 6 </since_tizen>
285 public static BluetoothGattClient CreateClient(string remoteAddress)
287 BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
288 return client.Isvalid() ? client : null;
292 /// The ConnectionStateChanged event is raised when the gatt connection state is changed.
294 /// <since_tizen> 6 </since_tizen>
295 public event EventHandler<GattConnectionStateChangedEventArgs> ConnectionStateChanged;
297 private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
299 if (e.RemoteAddress == _remoteAddress)
301 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
303 if (e.Result == (int)BluetoothError.None)
305 _taskForConnection.SetResult(true);
309 _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
311 _taskForConnection = null;
314 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
316 if (e.Result == (int)BluetoothError.None)
318 _taskForDisconnection.SetResult(true);
322 _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
324 _taskForDisconnection = null;
327 if (e.Result == (int)BluetoothError.None)
329 ConnectionStateChanged?.Invoke(this, e);
334 private static event EventHandler<GattConnectionStateChangedEventArgs> StaticConnectionStateChanged
338 if (s_connectionStateChanged == null)
340 RegisterConnectionStateChangedEvent();
342 s_connectionStateChanged += value;
346 s_connectionStateChanged -= value;
347 if (s_connectionStateChanged == null)
349 UnregisterConnectionStateChangedEvent();
354 private static void RegisterConnectionStateChangedEvent()
356 s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
358 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
359 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
360 s_connectionStateChanged?.Invoke(null, e);
363 int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
364 if (ret != (int)BluetoothError.None)
366 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
367 BluetoothErrorFactory.ThrowBluetoothException(ret);
371 private static void UnregisterConnectionStateChangedEvent()
373 int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
374 if (ret != (int)BluetoothError.None)
376 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
377 BluetoothErrorFactory.ThrowBluetoothException(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());
527 internal bool Isvalid()
529 return _impl.GetHandle().IsInvalid == false;
533 /// Destroys the current object.
535 ~BluetoothGattClient()
541 /// Destroys the current object.
543 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
544 /// <since_tizen> 6 </since_tizen>
545 public void Dispose()
548 GC.SuppressFinalize(this);
552 /// Releases all the resources currently used by this instance.
554 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
555 /// <since_tizen> 6 </since_tizen>
556 protected virtual void Dispose(bool disposing)
560 _impl?.GetHandle()?.Dispose();
562 StaticConnectionStateChanged -= OnConnectionStateChanged;
568 /// The Bluetooth GATT service.
570 /// <since_tizen> 3 </since_tizen>
571 public class BluetoothGattService
573 private BluetoothGattServiceImpl _impl;
574 private BluetoothGattClient _parentClient = null;
575 private BluetoothGattServer _parentServer = null;
576 private BluetoothGattService _parentService = null;
581 /// <param name="uuid">The UUID of the service.</param>
582 /// <param name="type">The type of service.</param>
583 /// <exception cref="InvalidOperationException">Thrown when the create GATT service procedure fails.</exception>
584 /// <since_tizen> 3 </since_tizen>
585 public BluetoothGattService(string uuid, BluetoothGattServiceType type)
588 _impl = new BluetoothGattServiceImpl(uuid, type);
591 internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
598 /// Specification name from the UUID.
600 /// <since_tizen> 3 </since_tizen>
601 public string Uuid { get; }
604 /// Adds a characteristic to this service.
606 /// <param name="characteristic">The characteristic to be added.</param>
607 /// <returns>true on success, false otherwise.</returns>
608 /// <exception cref="InvalidOperationException">Thrown when the add GATT characteristic procedure fails.</exception>
609 /// <since_tizen> 3 </since_tizen>
610 public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
612 if (GetGattClient() != null)
614 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
617 if (characteristic.GetService() != null)
619 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
622 _impl.AddCharacteristic(characteristic);
623 characteristic.SetParent(this);
627 /// Gets the characteristic with the given UUID that belongs to this service.
629 /// <param name="uuid">The UUID for the characteristic to get.</param>
630 /// <returns>The characteristic with a given UUID if it exists, null otherwise.</returns>
631 /// <since_tizen> 3 </since_tizen>
632 public BluetoothGattCharacteristic GetCharacteristic(string uuid)
634 return _impl.GetCharacteristic(this, uuid);
638 /// Gets list of the characteristic that belongs to this service.
640 /// <returns>The list of the characteristic that belongs to this service.</returns>
641 /// <since_tizen> 3 </since_tizen>
642 public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
644 return _impl.GetCharacteristics(this);
648 /// Includes a service to this service.
650 /// <param name="service">The service to be included.</param>
651 /// <returns>true on success, false otherwise</returns>
652 /// <exception cref="InvalidOperationException">Thrown when the add GATT service procedure fails.</exception>///
653 /// <since_tizen> 3 </since_tizen>
654 public void AddService(BluetoothGattService service)
656 if (GetGattClient() != null)
658 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
661 if (service.IsRegistered())
663 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
666 _impl.AddIncludeService(service);
667 service.SetParent(this);
671 /// Gets the included service.
673 /// <param name="uuid">The UUID for the service to get.</param>
674 /// <returns>The service with a given UUID if it exists, null otherwise.</returns>
675 /// <since_tizen> 3 </since_tizen>
676 public BluetoothGattService GetIncludeService(string uuid)
678 return _impl.GetIncludeService(this, uuid);
682 /// Gets the included service list of this service.
684 /// <returns>The included service list of this service.</returns>
685 /// <since_tizen> 3 </since_tizen>
686 public IEnumerable<BluetoothGattService> GetIncludeServices()
688 return _impl.GetIncludeServices(this);
692 /// Gets the server instance which the specified service belongs to.
694 /// <returns>The server instance which the specified service belongs to.</returns>
695 /// <since_tizen> 3 </since_tizen>
696 public BluetoothGattServer GetGattServer()
698 return _parentServer;
702 /// Gets the client instance which the specified service belongs to.
704 /// <returns>The client instance which the specified service belongs to.</returns>
705 /// <since_tizen> 3 </since_tizen>
706 public BluetoothGattClient GetGattClient()
708 return _parentClient;
711 internal BluetoothGattAttributeHandle GetHandle()
713 return _impl.GetHandle();
716 internal void SetParent(BluetoothGattService parent)
720 _parentService = parent;
721 _impl.ReleaseHandleOwnership();
725 internal void SetParent(BluetoothGattClient parent)
729 _parentClient = parent;
730 _impl.ReleaseHandleOwnership();
734 internal void SetParent(BluetoothGattServer parent)
738 _parentServer = parent;
739 _impl.ReleaseHandleOwnership();
743 internal void UnregisterService()
745 _parentServer = null;
746 _parentClient = null;
747 _parentService = null;
750 internal bool IsRegistered()
752 return _parentClient != null || _parentServer != null || _parentService != null;
757 /// The Bluetooth GATT characteristic.
759 /// <since_tizen> 3 </since_tizen>
760 public class BluetoothGattCharacteristic : BluetoothGattAttribute
762 private BluetoothGattCharacteristicImpl _impl;
763 private BluetoothGattService _parent = null;
765 private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
766 private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
768 private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
769 internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
774 /// <param name="uuid">The UUID of the characterstic.</param>
775 /// <param name="permissions">Permissions for the characterstic.</param>
776 /// <param name="properties">Properties set for the characterstic.</param>
777 /// <param name="value">The value associated with the characterstic.</param>
778 /// <remarks>throws in case of internal error.</remarks>
779 /// <exception cref="InvalidOperationException">Thrown when the create GATT characteristics procedure fails.</exception>
780 /// <since_tizen> 3 </since_tizen>
781 public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
783 _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
786 internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
792 /// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
795 /// Adding the event handle on characteristic on the server side will not have any effect.
797 /// <since_tizen> 3 </since_tizen>
798 public event EventHandler<ValueChangedEventArgs> ValueChanged
804 if (_characteristicValueChanged == null)
806 _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
808 _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
811 _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
813 _characteristicValueChanged = value;
820 _characteristicValueChanged = null;
821 if (_characteristicValueChanged == null)
823 _impl.UnsetCharacteristicValueChangedEvent();
831 /// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
834 /// Adding event handle on the characteristic on the client side will not have any effect.
836 /// <since_tizen> 3 </since_tizen>
837 public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
843 if (_notificationStateChangedCallback == null)
845 _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
847 _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
850 _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
853 _notificationStateChanged = value;
860 _notificationStateChanged = null;
861 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
867 /// The property for this characteristic.
869 /// <since_tizen> 3 </since_tizen>
870 public BluetoothGattProperty Properties
874 return _impl.GetProperties();
880 _impl.SetProperties(value);
886 /// The write type to be used for write operations.
888 /// <since_tizen> 3 </since_tizen>
889 public BluetoothGattWriteType WriteType
893 return _impl.GetWriteType();
897 _impl.SetWriteType(value);
901 internal override BluetoothGattClient Client
905 return _parent?.GetGattClient();
909 internal override BluetoothGattServer Server
913 return _parent?.GetGattServer();
917 internal override BluetoothGattAttributeImpl Impl
926 /// Adds a descriptor to this characteristic.
928 /// <param name="descriptor">The descriptor to be added.</param>
929 /// <returns>true on success, false otherwise.</returns>
930 /// <exception cref="InvalidOperationException">Thrown when the add GATT descriptor procedure fails.</exception>
931 /// <since_tizen> 3 </since_tizen>
932 public void AddDescriptor(BluetoothGattDescriptor descriptor)
936 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
939 if (descriptor.GetCharacteristic() != null)
941 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
944 _impl.AddDescriptor(descriptor);
945 descriptor.SetParent(this);
949 /// Gets the descriptor with the given UUID that belongs to this characteristic.
951 /// <param name="uuid">The UUID for the descriptor to get.</param>
952 /// <returns>The descriptor with a given UUID if it exists, null otherwise.</returns>
953 /// <since_tizen> 3 </since_tizen>
954 public BluetoothGattDescriptor GetDescriptor(string uuid)
956 return _impl.GetDescriptor(this, uuid);
960 /// Gets the list of descriptors that belongs to this characteristic.
962 /// <returns>The list of descriptors that belongs to this characteristic.</returns>
963 /// <since_tizen> 3 </since_tizen>
964 public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
966 return _impl.GetDescriptors(this);
970 /// Gets the service instance, which the specified characterstic belongs to.
972 /// <returns>The characteristic instance, the specified characterstic belongs to.</returns>
973 /// <since_tizen> 3 </since_tizen>
974 public BluetoothGattService GetService()
979 internal void SetParent(BluetoothGattService parent)
984 ReleaseHandleOwnership();
990 /// The Bluetooth GATT descriptor.
992 /// <since_tizen> 3 </since_tizen>
993 public class BluetoothGattDescriptor : BluetoothGattAttribute
995 private BluetoothGattCharacteristic _parent = null;
996 private BluetoothGattDescriptorImpl _impl;
1001 /// <param name="uuid">The UUID of the descriptor.</param>
1002 /// <param name="permisions">Permissions for the descriptor.</param>
1003 /// <param name="value">The value associated with the descriptor.</param>
1004 /// <remarks>throws in case of internal error.</remarks>
1005 /// <exception cref="InvalidOperationException">Thrown when the create GATT descriptor procedure fails.</exception>
1006 /// <since_tizen> 3 </since_tizen>
1007 public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
1009 _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
1012 internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
1017 internal override BluetoothGattClient Client
1021 return _parent?.Client;
1025 internal override BluetoothGattServer Server
1029 return _parent?.Server;
1033 internal override BluetoothGattAttributeImpl Impl
1042 /// Gets the characteristic instance, which the specified descriptor belongs to.
1044 /// <returns>The characteristic instance, the specified descriptor belongs to.</returns>
1045 /// <since_tizen> 3 </since_tizen>
1046 public BluetoothGattCharacteristic GetCharacteristic()
1051 internal void SetParent(BluetoothGattCharacteristic parent)
1053 if (_parent == null)
1056 ReleaseHandleOwnership();
1062 /// The Bluetooth GATT attribute.
1064 /// <since_tizen> 3 </since_tizen>
1065 public abstract class BluetoothGattAttribute
1067 private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
1068 private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
1070 private EventHandler<ReadRequestedEventArgs> _readValueRequested;
1071 private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
1074 /// The constructor.
1076 /// <param name="uuid">The UUID of the GATT attribute.</param>
1077 /// <param name="permission">Permission for the GATT attribute.</param>
1078 /// <since_tizen> 3 </since_tizen>
1079 public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
1082 Permissions = permission;
1088 /// This event is called when the client request to read the value of a characteristic or a descriptor.
1090 /// <exception cref="InvalidOperationException">Thrown when the set read value requested callback procedure fails.</exception>
1091 /// <since_tizen> 3 </since_tizen>
1092 public event EventHandler<ReadRequestedEventArgs> ReadRequested
1096 if (Server == null) return;
1097 if (_readValueRequestedCallback == null)
1099 _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
1101 _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
1103 Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
1105 _readValueRequested = value;
1109 if (Server == null) return;
1110 _readValueRequested = null;
1111 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1116 /// This event is called when a value of a characteristic or a descriptor has been changed by a client.
1118 /// <exception cref="InvalidOperationException">Thrown when the set write value requested callback procedure fails.</exception>
1119 /// <since_tizen> 3 </since_tizen>
1120 public event EventHandler<WriteRequestedEventArgs> WriteRequested
1124 if (Server == null) return;
1125 if (_writeValueRequested == null)
1127 _writeValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, response_needed, offset, valueToWrite, len, userData) =>
1129 _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, valueToWrite, offset, response_needed));
1131 Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
1133 _writeValueRequested = value;
1137 if (Server == null) return;
1138 _writeValueRequested = null;
1139 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1144 /// The attribute's UUID.
1146 /// <since_tizen> 3 </since_tizen>
1147 public string Uuid { get; }
1150 /// Permissions for this attribute.
1152 /// <since_tizen> 3 </since_tizen>
1153 public BluetoothGattPermission Permissions { get; }
1156 /// The value of this descriptor.
1158 /// <since_tizen> 3 </since_tizen>
1163 return Impl.GetValue();
1167 Impl.SetValue(value);
1171 internal abstract BluetoothGattClient Client { get; }
1172 internal abstract BluetoothGattServer Server { get; }
1173 internal abstract BluetoothGattAttributeImpl Impl { get; }
1176 /// Returns a string value at the specified offset.
1178 /// <param name="offset">An offset in the attribute value buffer.</param>
1179 /// <returns>The string value at specified offset.</returns>
1180 /// <since_tizen> 3 </since_tizen>
1181 public string GetValue(int offset)
1183 return Impl.GetValue(offset);
1187 /// Sets the string value as a specified offset.
1189 /// <param name="value">value to set</param>
1190 /// <exception cref="InvalidOperationException">Throws exception if the value is null.</exception>
1191 /// <since_tizen> 3 </since_tizen>
1192 public void SetValue(string value)
1194 if (string.IsNullOrEmpty(value))
1195 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
1197 byte[] val = Encoding.UTF8.GetBytes(value);
1202 /// Returns a value at specified offset as the int value of the specified type.
1204 /// <param name="type">The type of the int value.</param>
1205 /// <param name="offset">An offset in the attribute value buffer.</param>
1206 /// <returns>The int value at given offset.</returns>
1207 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1208 /// <since_tizen> 3 </since_tizen>
1209 public int GetValue(IntDataType type, int offset)
1211 return Impl.GetValue(type, offset);
1215 /// Updates a value at the specified offset by the int value of the specified type.
1217 /// <param name="type">The type of the int value.</param>
1218 /// <param name="value">The value to set.</param>
1219 /// <param name="offset">An offset in the attribute value buffer.</param>
1220 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1221 /// <since_tizen> 3 </since_tizen>
1222 public void SetValue(IntDataType type, int value, int offset)
1224 Impl.SetValue(type, value, offset);
1228 /// Returns a value at the specified offset as the float value of the specified type.
1230 /// <param name="type">The type of the float value.</param>
1231 /// <param name="offset">An offset in the attribute value buffer.</param>
1232 /// <returns>The float value at given offset.</returns>
1233 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1234 /// <since_tizen> 3 </since_tizen>
1235 public float GetValue(FloatDataType type, int offset)
1237 return Impl.GetValue(type, offset);
1241 /// Updates the value at the specified offset by the float value of the specified type.
1243 /// <param name="type">The type of the float value.</param>
1244 /// <param name="mantissa">The mantissa of the float value.</param>
1245 /// <param name="exponent">An exponent of the float value.</param>
1246 /// <param name="offset">An offset in the attribute value buffer.</param>
1247 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1248 /// <since_tizen> 3 </since_tizen>
1249 public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
1251 Impl.SetValue(type, mantissa, exponent, offset);
1254 internal void ReleaseHandleOwnership()
1256 Impl.ReleaseHandleOwnership();
1259 internal BluetoothGattAttributeHandle GetHandle()
1261 return Impl.GetHandle();