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();
37 _impl._notificationSent += (s, e) =>
40 NotificationSent?.Invoke(this, e);
45 /// (event) This event is called when the indication acknowledgement is received for each notified client.
47 /// <since_tizen> 3 </since_tizen>
48 public event EventHandler<NotificationSentEventArg> NotificationSent;
51 /// Creates the Bluetooth GATT server.
53 /// <returns>The BluetoothGattServer instance.</returns>
54 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
55 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
56 /// <exception cref="InvalidOperationException">Thrown when the create GATT server fails.</exception>
57 /// <since_tizen> 3 </since_tizen>
58 public static BluetoothGattServer CreateServer()
60 if (_instance == null)
62 BluetoothGattServer server = new BluetoothGattServer();
72 /// Registers the server along with the GATT services of the application it is hosting.
74 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
75 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
76 /// <exception cref="InvalidOperationException">Thrown when the register server application fails.</exception>
77 /// <since_tizen> 3 </since_tizen>
84 /// Registers a specified service to this server.
86 /// <param name="service">The service, which needs to be registered with this server.</param>
87 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
88 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
89 /// <exception cref="InvalidOperationException">Thrown when the register service fails.</exception>
90 /// <since_tizen> 3 </since_tizen>
91 public void RegisterGattService(BluetoothGattService service)
93 if (service.IsRegistered())
95 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
97 _impl.RegisterGattService(this, service);
101 /// Unregisters a specified service from this server.
103 /// <param name="service">The service, which needs to be unregistered from this server.</param>
105 /// Once unregistered, the service object will become invalid and should not be used to access sevices or any children attribute's methods/members.
107 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
108 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
109 /// <exception cref="InvalidOperationException">Thrown when the unregister service fails.</exception>
110 /// <since_tizen> 3 </since_tizen>
111 public void UnregisterGattService(BluetoothGattService service)
113 if (service.GetGattServer() != this)
115 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
118 _impl.UnregisterGattService(service);
122 /// Unregisters all services from this server.
125 /// Once unregistered, servicees will become invalid and should not be used to access sevices or any children attribute's methods/members.
127 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
128 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
129 /// <exception cref="InvalidOperationException">Thrown when the unregister all services fail.</exception>
130 /// <since_tizen> 3 </since_tizen>
131 public void UnregisterGattServices()
133 _impl.UnregisterAllGattServices(this);
137 /// Gets service with given UUID that belongs to this server.
139 /// <param name="uuid">The UUID for the service to get.</param>
140 /// <returns>The Service with the given UUID if it exists, null otherwise.</returns>
141 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
142 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
143 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
144 /// <since_tizen> 3 </since_tizen>
145 public BluetoothGattService GetService(string uuid)
147 return _impl.GetService(this, uuid);
151 /// Gets the list of services that belongs to this server.
153 /// <returns>The list of services that belongs to this server.</returns>
154 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
155 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
156 /// <exception cref="InvalidOperationException">Thrown when the service is not registered.</exception>
157 /// <since_tizen> 3 </since_tizen>
158 public IEnumerable<BluetoothGattService> GetServices()
160 return _impl.GetServices(this);
164 /// Sends indication for the value change of the characteristic to the remote devices.
166 /// <param name="characteristic">The characteristic whose the value is changed.</param>
167 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
168 /// <returns>true on success, false otherwise.</returns>
169 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
170 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
171 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
172 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
173 /// <since_tizen> 3 </since_tizen>
174 public async Task<bool> SendIndicationAsync(BluetoothGattCharacteristic characteristic, string clientAddress)
176 return await _impl.SendIndicationAsync(this, characteristic, clientAddress);
180 /// Sends the notification for the value change of the characteristic to the remote devices.
182 /// <param name="characteristic">The characteristic, which has a changed value.</param>
183 /// <param name="clientAddress">The remote device address to send, notify, or indicate and if set to NULL, then notify/indicate all is enabled.</param>
184 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
185 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
186 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
187 /// or when the remote device is disconnected, or when service is not registered, or when the CCCD is not enabled.</exception>
188 /// <since_tizen> 3 </since_tizen>
189 public void SendNotification(BluetoothGattCharacteristic characteristic, string clientAddress)
191 _ = _impl.SendIndicationAsync(this, characteristic, clientAddress);
195 /// Sends a response to the remote device as a result of a read/write request.
197 /// <param name="requestId">The identification of a read/write request.</param>
198 /// <param name="type">The request type for read/write.</param>
199 /// <param name="status">The error value in case of failure, 0 for success.</param>
200 /// <param name="value">The value to be sent.</param>
201 /// <param name="offset">The offset from where the value is read.</param>
202 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
203 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
204 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
205 /// or when the remote device is disconnected, or the send response procedure fails.</exception>
206 /// <since_tizen> 3 </since_tizen>
207 public void SendResponse(int requestId, BluetoothGattRequestType type, int status, byte[] value, int offset)
209 _impl.SendResponse(requestId, (int)type, status, value, offset);
212 internal bool IsValid()
214 return _impl.GetHandle().IsInvalid == false;
218 /// Destroys the current object.
220 ~BluetoothGattServer()
226 /// Destroys the current object.
228 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.server</feature>
229 /// <since_tizen> 6 </since_tizen>
230 public void Dispose()
233 GC.SuppressFinalize(this);
237 /// Releases all the resources currently used by this instance.
239 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
240 /// <since_tizen> 6 </since_tizen>
241 protected virtual void Dispose(bool disposing)
245 _impl?.GetHandle()?.Dispose();
252 /// The Bluetooth GATT client.
254 /// <since_tizen> 3 </since_tizen>
255 public class BluetoothGattClient : IDisposable
257 private BluetoothGattClientImpl _impl;
258 private string _remoteAddress = string.Empty;
259 private TaskCompletionSource<bool> _taskForConnection;
260 private TaskCompletionSource<bool> _taskForDisconnection;
261 private static event EventHandler<GattConnectionStateChangedEventArgs> s_connectionStateChanged;
262 private static Interop.Bluetooth.GattConnectionStateChangedCallBack s_connectionStateChangeCallback;
264 internal BluetoothGattClient(string remoteAddress)
266 _impl = new BluetoothGattClientImpl(remoteAddress);
267 _remoteAddress = remoteAddress;
268 StaticConnectionStateChanged += OnConnectionStateChanged;
272 /// Creates the Bluetooth GATT client.
274 /// <param name="remoteAddress">The remote device address.</param>
275 /// <returns>The BluetoothGattClient instance.</returns>
276 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
277 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
278 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
279 /// <since_tizen> 6 </since_tizen>
280 public static BluetoothGattClient CreateClient(string remoteAddress)
282 BluetoothGattClient client = new BluetoothGattClient(remoteAddress);
283 return client.Isvalid() ? client : null;
287 /// The ConnectionStateChanged event is raised when the gatt connection state is changed.
289 /// <since_tizen> 6 </since_tizen>
290 public event EventHandler<GattConnectionStateChangedEventArgs> ConnectionStateChanged;
292 private void OnConnectionStateChanged(Object s, GattConnectionStateChangedEventArgs e)
294 if (e.RemoteAddress == _remoteAddress)
296 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
298 if (e.Result == (int)BluetoothError.None)
300 _taskForConnection.SetResult(true);
304 _taskForConnection.SetException(BluetoothErrorFactory.CreateBluetoothException((int)e.Result));
306 _taskForConnection = null;
309 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
311 if (e.Result == (int)BluetoothError.None)
313 _taskForDisconnection.SetResult(true);
317 _taskForDisconnection.SetException(BluetoothErrorFactory.CreateBluetoothException(e.Result));
319 _taskForDisconnection = null;
322 if (e.Result == (int)BluetoothError.None)
324 ConnectionStateChanged?.Invoke(this, e);
329 internal static event EventHandler<GattConnectionStateChangedEventArgs> StaticConnectionStateChanged
333 if (s_connectionStateChanged == null)
335 RegisterConnectionStateChangedEvent();
337 s_connectionStateChanged += value;
341 s_connectionStateChanged -= value;
342 if (s_connectionStateChanged == null)
344 UnregisterConnectionStateChangedEvent();
349 private static void RegisterConnectionStateChangedEvent()
351 s_connectionStateChangeCallback = (int result, bool connected, string remoteDeviceAddress, IntPtr userData) =>
353 Log.Info(Globals.LogTag, "Setting gatt connection state changed callback");
354 GattConnectionStateChangedEventArgs e = new GattConnectionStateChangedEventArgs(result, connected, remoteDeviceAddress);
355 s_connectionStateChanged?.Invoke(null, e);
358 int ret = Interop.Bluetooth.SetGattConnectionStateChangedCallback(s_connectionStateChangeCallback, IntPtr.Zero);
359 if (ret != (int)BluetoothError.None)
361 Log.Error(Globals.LogTag, "Failed to set gatt connection state changed callback, Error - " + (BluetoothError)ret);
365 private static void UnregisterConnectionStateChangedEvent()
367 int ret = Interop.Bluetooth.UnsetGattConnectionStateChangedCallback();
368 if (ret != (int)BluetoothError.None)
370 Log.Error(Globals.LogTag, "Failed to unset gatt connection state changed callback, Error - " + (BluetoothError)ret);
375 /// Connects to the remote GATT server asynchronously.
377 /// <param name="autoConnect">The flag for reconnecting when the connection is disconnceted.</param>
378 /// <returns> A task indicating whether the method is done or not.</returns>
379 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
380 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
381 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
382 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
383 /// <since_tizen> 6 </since_tizen>
384 public Task ConnectAsync(bool autoConnect)
386 if (_taskForConnection != null && !_taskForConnection.Task.IsCompleted)
388 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
390 _taskForConnection = new TaskCompletionSource<bool>();
391 _impl.Connect(_remoteAddress, autoConnect);
392 return _taskForConnection.Task;
396 /// Disconnects to the remote GATT server asynchronously.
398 /// <returns> A task indicating whether the method is done or not.</returns>
399 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
400 /// <privilege>http://tizen.org/privilege/bluetooth</privilege>
401 /// <exception cref="NotSupportedException">Thrown when the BT/BTLE is not supported.</exception>
402 /// <exception cref="InvalidOperationException">Thrown when the create GATT client fails.</exception>
403 /// <since_tizen> 6 </since_tizen>
404 public Task DisconnectAsync()
406 if (_taskForDisconnection != null && !_taskForDisconnection.Task.IsCompleted)
408 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NowInProgress);
410 _taskForDisconnection = new TaskCompletionSource<bool>();
411 _impl.Disconnect(_remoteAddress);
412 return _taskForDisconnection.Task;
416 /// Destroy Bluetooth GATT client
418 /// <since_tizen> 3 </since_tizen>
419 [Obsolete("Deprecated since API level 6. Please use Dispose() method on BluetoothGattClient.")]
420 public void DestroyClient()
422 _impl.GetHandle().Dispose();
426 /// The address of the remote device.
428 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
429 /// or when the remote device is disconnected.</exception>
430 /// <since_tizen> 3 </since_tizen>
431 public string RemoteAddress
435 if (string.IsNullOrEmpty(_remoteAddress))
437 _remoteAddress = _impl.GetRemoteAddress();
439 return _remoteAddress;
444 /// Gets the service with the given UUID that belongs to the remote device.
446 /// <param name="uuid">The UUID for the service to get.</param>
447 /// <returns>The service with the given UUID if it exists, null otherwise.</returns>
448 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
449 /// or when the remote device is disconnected, or when the get service fails.</exception>
450 /// <since_tizen> 3 </since_tizen>
451 public BluetoothGattService GetService(string uuid)
453 return _impl.GetService(this, uuid);
457 /// Gets list of services that belongs to the remote device.
459 /// <returns>The list of services that belongs to the remote device.</returns>
460 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
461 /// or when the remote device is disconnected, or when the get service fails.</exception>
462 /// <since_tizen> 3 </since_tizen>
463 public IEnumerable<BluetoothGattService> GetServices()
465 return _impl.GetServices(this);
469 /// Reads the value of a given characteristic from the remote device asynchronously.
471 /// <param name="characteristic">The characteristic to be read.</param>
472 /// <returns>true on success, false otherwise.</returns>
473 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
474 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
475 /// <since_tizen> 3 </since_tizen>
476 public async Task<bool> ReadValueAsync(BluetoothGattCharacteristic characteristic)
478 return await _impl.ReadValueAsyncTask(characteristic.GetHandle());
482 /// Reads the value of the given descriptor from the remote device asynchronously.
484 /// <param name="descriptor">The descriptor to be read.</param>
485 /// <returns>true on success, false otherwise.</returns>
486 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
487 /// or when the remote device is disconnected, or when the read attribute value fails.</exception>
488 /// <since_tizen> 3 </since_tizen>
489 public async Task<bool> ReadValueAsync(BluetoothGattDescriptor descriptor)
491 return await _impl.ReadValueAsyncTask(descriptor.GetHandle());
495 /// Writes the value of a given characteristic to the remote device asynchronously.
497 /// <param name="characteristic">The characteristic to be written.</param>
498 /// <returns>true on success, false otherwise.</returns>
499 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
500 /// or when the remote device is disconnected or when the write attribute value fails.</exception>
501 /// <since_tizen> 3 </since_tizen>
502 public async Task<bool> WriteValueAsync(BluetoothGattCharacteristic characteristic)
504 return await _impl.WriteValueAsyncTask(characteristic.GetHandle());
508 /// Writes the value of the given descriptor to the remote device asynchronously.
510 /// <param name="descriptor">The descriptor to be written.</param>
511 /// <returns>true on success, false otherwise.</returns>
512 /// <exception cref="InvalidOperationException">Thrown when the BT/BTLE is not enabled
513 /// or when the remote device is disconnected, or when the write attribute value fails.</exception>
514 /// <since_tizen> 3 </since_tizen>
515 public async Task<bool> WriteValueAsync(BluetoothGattDescriptor descriptor)
517 return await _impl.WriteValueAsyncTask(descriptor.GetHandle());
520 internal bool Isvalid()
522 return _impl.GetHandle().IsInvalid == false;
526 /// Destroys the current object.
528 ~BluetoothGattClient()
534 /// Destroys the current object.
536 /// <feature>http://tizen.org/feature/network.bluetooth.le.gatt.client</feature>
537 /// <since_tizen> 6 </since_tizen>
538 public void Dispose()
541 GC.SuppressFinalize(this);
545 /// Releases all the resources currently used by this instance.
547 /// <param name="disposing">true if the managed resources should be disposed, otherwise false.</param>
548 /// <since_tizen> 6 </since_tizen>
549 protected virtual void Dispose(bool disposing)
553 _impl?.GetHandle()?.Dispose();
555 StaticConnectionStateChanged -= OnConnectionStateChanged;
561 /// The Bluetooth GATT service.
563 /// <since_tizen> 3 </since_tizen>
564 public class BluetoothGattService
566 private BluetoothGattServiceImpl _impl;
567 private BluetoothGattClient _parentClient = null;
568 private BluetoothGattServer _parentServer = null;
569 private BluetoothGattService _parentService = null;
574 /// <param name="uuid">The UUID of the service.</param>
575 /// <param name="type">The type of service.</param>
576 /// <exception cref="InvalidOperationException">Thrown when the create GATT service procedure fails.</exception>
577 /// <since_tizen> 3 </since_tizen>
578 public BluetoothGattService(string uuid, BluetoothGattServiceType type)
581 _impl = new BluetoothGattServiceImpl(uuid, type);
584 internal BluetoothGattService(BluetoothGattServiceImpl impl, string uuid)
591 /// Specification name from the UUID.
593 /// <since_tizen> 3 </since_tizen>
594 public string Uuid { get; }
597 /// Adds a characteristic to this service.
599 /// <param name="characteristic">The characteristic to be added.</param>
600 /// <returns>true on success, false otherwise.</returns>
601 /// <exception cref="InvalidOperationException">Thrown when the add GATT characteristic procedure fails.</exception>
602 /// <since_tizen> 3 </since_tizen>
603 public void AddCharacteristic(BluetoothGattCharacteristic characteristic)
605 if (GetGattClient() != null)
607 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
610 if (characteristic.GetService() != null)
612 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
615 _impl.AddCharacteristic(characteristic);
616 characteristic.SetParent(this);
620 /// Gets the characteristic with the given UUID that belongs to this service.
622 /// <param name="uuid">The UUID for the characteristic to get.</param>
623 /// <returns>The characteristic with a given UUID if it exists, null otherwise.</returns>
624 /// <since_tizen> 3 </since_tizen>
625 public BluetoothGattCharacteristic GetCharacteristic(string uuid)
627 return _impl.GetCharacteristic(this, uuid);
631 /// Gets list of the characteristic that belongs to this service.
633 /// <returns>The list of the characteristic that belongs to this service.</returns>
634 /// <since_tizen> 3 </since_tizen>
635 public IEnumerable<BluetoothGattCharacteristic> GetCharacteristics()
637 return _impl.GetCharacteristics(this);
641 /// Includes a service to this service.
643 /// <param name="service">The service to be included.</param>
644 /// <returns>true on success, false otherwise</returns>
645 /// <exception cref="InvalidOperationException">Thrown when the add GATT service procedure fails.</exception>///
646 /// <since_tizen> 3 </since_tizen>
647 public void AddService(BluetoothGattService service)
649 if (GetGattClient() != null)
651 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
654 if (service.IsRegistered())
656 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
659 _impl.AddIncludeService(service);
660 service.SetParent(this);
664 /// Gets the included service.
666 /// <param name="uuid">The UUID for the service to get.</param>
667 /// <returns>The service with a given UUID if it exists, null otherwise.</returns>
668 /// <since_tizen> 3 </since_tizen>
669 public BluetoothGattService GetIncludeService(string uuid)
671 return _impl.GetIncludeService(this, uuid);
675 /// Gets the included service list of this service.
677 /// <returns>The included service list of this service.</returns>
678 /// <since_tizen> 3 </since_tizen>
679 public IEnumerable<BluetoothGattService> GetIncludeServices()
681 return _impl.GetIncludeServices(this);
685 /// Gets the server instance which the specified service belongs to.
687 /// <returns>The server instance which the specified service belongs to.</returns>
688 /// <since_tizen> 3 </since_tizen>
689 public BluetoothGattServer GetGattServer()
691 return _parentServer;
695 /// Gets the client instance which the specified service belongs to.
697 /// <returns>The client instance which the specified service belongs to.</returns>
698 /// <since_tizen> 3 </since_tizen>
699 public BluetoothGattClient GetGattClient()
701 return _parentClient;
704 internal BluetoothGattAttributeHandle GetHandle()
706 return _impl.GetHandle();
709 internal void SetParent(BluetoothGattService parent)
713 _parentService = parent;
714 _impl.ReleaseHandleOwnership();
718 internal void SetParent(BluetoothGattClient parent)
722 _parentClient = parent;
723 _impl.ReleaseHandleOwnership();
727 internal void SetParent(BluetoothGattServer parent)
731 _parentServer = parent;
732 _impl.ReleaseHandleOwnership();
736 internal void UnregisterService()
738 _parentServer = null;
739 _parentClient = null;
740 _parentService = null;
743 internal bool IsRegistered()
745 return _parentClient != null || _parentServer != null || _parentService != null;
750 /// The Bluetooth GATT characteristic.
752 /// <since_tizen> 3 </since_tizen>
753 public class BluetoothGattCharacteristic : BluetoothGattAttribute
755 private BluetoothGattCharacteristicImpl _impl;
756 private BluetoothGattService _parent = null;
758 private Interop.Bluetooth.BtClientCharacteristicValueChangedCallback _characteristicValueChangedCallback;
759 private Interop.Bluetooth.BtGattServerNotificationStateChangeCallback _notificationStateChangedCallback;
761 private EventHandler<ValueChangedEventArgs> _characteristicValueChanged;
762 internal EventHandler<NotificationStateChangedEventArg> _notificationStateChanged;
767 /// <param name="uuid">The UUID of the characterstic.</param>
768 /// <param name="permissions">Permissions for the characterstic.</param>
769 /// <param name="properties">Properties set for the characterstic.</param>
770 /// <param name="value">The value associated with the characterstic.</param>
771 /// <remarks>throws in case of internal error.</remarks>
772 /// <exception cref="InvalidOperationException">Thrown when the create GATT characteristics procedure fails.</exception>
773 /// <since_tizen> 3 </since_tizen>
774 public BluetoothGattCharacteristic(string uuid, BluetoothGattPermission permissions, BluetoothGattProperty properties, byte[] value) : base(uuid, permissions)
776 _impl = new BluetoothGattCharacteristicImpl(uuid, permissions, properties, value);
779 internal BluetoothGattCharacteristic(BluetoothGattCharacteristicImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
785 /// The CharacteristicValueChanged event is raised when the server notifies for change in this characteristic value.
788 /// Adding the event handle on characteristic on the server side will not have any effect.
790 /// <since_tizen> 3 </since_tizen>
791 public event EventHandler<ValueChangedEventArgs> ValueChanged
797 if (_characteristicValueChanged == null)
799 _characteristicValueChangedCallback = (gattHandle, characteristicValue, len, userData) =>
801 _characteristicValueChanged?.Invoke(this, new ValueChangedEventArgs(characteristicValue, len));
804 _impl.SetCharacteristicValueChangedEvent(_characteristicValueChangedCallback);
806 _characteristicValueChanged = value;
813 _characteristicValueChanged = null;
814 if (_characteristicValueChanged == null)
816 _impl.UnsetCharacteristicValueChangedEvent();
824 /// The NotificationStateChanged event is called when the client enables or disables the Notification/Indication for particular characteristics.
827 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
828 /// Adding event handle on the characteristic on the client side will not have any effect.
830 /// <since_tizen> 3 </since_tizen>
831 public event EventHandler<NotificationStateChangedEventArg> NotificationStateChanged
837 if (_notificationStateChangedCallback == null)
839 _notificationStateChangedCallback = (notify, serverHandle, characteristicHandle, userData) =>
841 _notificationStateChanged?.Invoke(this, new NotificationStateChangedEventArg(Server, notify));
844 _impl.SetNotificationStateChangedEvent(_notificationStateChangedCallback);
847 _notificationStateChanged = value;
854 _notificationStateChanged = null;
855 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
861 /// The property for this characteristic.
863 /// <since_tizen> 3 </since_tizen>
864 public BluetoothGattProperty Properties
868 return _impl.GetProperties();
874 _impl.SetProperties(value);
880 /// The write type to be used for write operations.
882 /// <since_tizen> 3 </since_tizen>
883 public BluetoothGattWriteType WriteType
887 return _impl.GetWriteType();
891 _impl.SetWriteType(value);
895 internal override BluetoothGattClient Client
899 return _parent?.GetGattClient();
903 internal override BluetoothGattServer Server
907 return _parent?.GetGattServer();
911 internal override BluetoothGattAttributeImpl Impl
920 /// Adds a descriptor to this characteristic.
922 /// <param name="descriptor">The descriptor to be added.</param>
923 /// <returns>true on success, false otherwise.</returns>
924 /// <exception cref="InvalidOperationException">Thrown when the add GATT descriptor procedure fails.</exception>
925 /// <since_tizen> 3 </since_tizen>
926 public void AddDescriptor(BluetoothGattDescriptor descriptor)
930 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotSupported);
933 if (descriptor.GetCharacteristic() != null)
935 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.InvalidParameter);
938 _impl.AddDescriptor(descriptor);
939 descriptor.SetParent(this);
943 /// Gets the descriptor with the given UUID that belongs to this characteristic.
945 /// <param name="uuid">The UUID for the descriptor to get.</param>
946 /// <returns>The descriptor with a given UUID if it exists, null otherwise.</returns>
947 /// <since_tizen> 3 </since_tizen>
948 public BluetoothGattDescriptor GetDescriptor(string uuid)
950 return _impl.GetDescriptor(this, uuid);
954 /// Gets the list of descriptors that belongs to this characteristic.
956 /// <returns>The list of descriptors that belongs to this characteristic.</returns>
957 /// <since_tizen> 3 </since_tizen>
958 public IEnumerable<BluetoothGattDescriptor> GetDescriptors()
960 return _impl.GetDescriptors(this);
964 /// Gets the service instance, which the specified characterstic belongs to.
966 /// <returns>The characteristic instance, the specified characterstic belongs to.</returns>
967 /// <since_tizen> 3 </since_tizen>
968 public BluetoothGattService GetService()
973 internal void SetParent(BluetoothGattService parent)
978 ReleaseHandleOwnership();
984 /// The Bluetooth GATT descriptor.
986 /// <since_tizen> 3 </since_tizen>
987 public class BluetoothGattDescriptor : BluetoothGattAttribute
989 private BluetoothGattCharacteristic _parent = null;
990 private BluetoothGattDescriptorImpl _impl;
995 /// <param name="uuid">The UUID of the descriptor.</param>
996 /// <param name="permisions">Permissions for the descriptor.</param>
997 /// <param name="value">The value associated with the descriptor.</param>
998 /// <remarks>throws in case of internal error.</remarks>
999 /// <exception cref="InvalidOperationException">Thrown when the create GATT descriptor procedure fails.</exception>
1000 /// <since_tizen> 3 </since_tizen>
1001 public BluetoothGattDescriptor(string uuid, BluetoothGattPermission permisions, byte[] value) : base (uuid, permisions)
1003 _impl = new BluetoothGattDescriptorImpl(uuid, permisions, value);
1006 internal BluetoothGattDescriptor(BluetoothGattDescriptorImpl impl, string uuid, BluetoothGattPermission permission) : base(uuid, permission)
1011 internal override BluetoothGattClient Client
1015 return _parent?.Client;
1019 internal override BluetoothGattServer Server
1023 return _parent?.Server;
1027 internal override BluetoothGattAttributeImpl Impl
1036 /// Gets the characteristic instance, which the specified descriptor belongs to.
1038 /// <returns>The characteristic instance, the specified descriptor belongs to.</returns>
1039 /// <since_tizen> 3 </since_tizen>
1040 public BluetoothGattCharacteristic GetCharacteristic()
1045 internal void SetParent(BluetoothGattCharacteristic parent)
1047 if (_parent == null)
1050 ReleaseHandleOwnership();
1056 /// The Bluetooth GATT attribute.
1058 /// <since_tizen> 3 </since_tizen>
1059 public abstract class BluetoothGattAttribute
1061 private Interop.Bluetooth.BtGattServerReadValueRequestedCallback _readValueRequestedCallback;
1062 private Interop.Bluetooth.BtGattServerWriteValueRequestedCallback _writeValueRequestedCallback;
1064 private EventHandler<ReadRequestedEventArgs> _readValueRequested;
1065 private EventHandler<WriteRequestedEventArgs> _writeValueRequested;
1068 /// The constructor.
1070 /// <param name="uuid">The UUID of the GATT attribute.</param>
1071 /// <param name="permission">Permission for the GATT attribute.</param>
1072 /// <since_tizen> 3 </since_tizen>
1073 public BluetoothGattAttribute(string uuid, BluetoothGattPermission permission)
1076 Permissions = permission;
1082 /// This event is called when the client request to read the value of a characteristic or a descriptor.
1085 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
1087 /// <exception cref="InvalidOperationException">Thrown when the set read value requested callback procedure fails.</exception>
1088 /// <since_tizen> 3 </since_tizen>
1089 public event EventHandler<ReadRequestedEventArgs> ReadRequested
1093 if (Server == null) return;
1094 if (_readValueRequestedCallback == null)
1096 _readValueRequestedCallback = (clientAddress, requestId, serverHandle, gattHandle, offset, userData) =>
1098 _readValueRequested?.Invoke(this, new ReadRequestedEventArgs(Server, clientAddress, requestId, offset));
1100 Impl.SetReadValueRequestedEventCallback(_readValueRequestedCallback);
1102 _readValueRequested = value;
1106 if (Server == null) return;
1107 _readValueRequested = null;
1108 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1113 /// This event is called when a value of a characteristic or a descriptor has been changed by a client.
1116 /// BluetoothGattServer.RegisterGattService() should be called before adding/removing this EventHandler.
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 byte[] writeValue = new byte[len];
1130 Marshal.Copy(valueToWrite, writeValue, 0, len);
1131 _writeValueRequested?.Invoke(this, new WriteRequestedEventArgs(Server, clientAddress, requestId, writeValue, offset, response_needed));
1133 Impl.SetWriteValueRequestedEventCallback(_writeValueRequestedCallback);
1135 _writeValueRequested = value;
1139 if (Server == null) return;
1140 _writeValueRequested = null;
1141 // CAPI does not allow unsetting ReadValueRequestedEventCallback.
1146 /// The attribute's UUID.
1148 /// <since_tizen> 3 </since_tizen>
1149 public string Uuid { get; }
1152 /// Permissions for this attribute.
1154 /// <since_tizen> 3 </since_tizen>
1155 public BluetoothGattPermission Permissions { get; }
1158 /// The value of this descriptor.
1160 /// <since_tizen> 3 </since_tizen>
1165 return Impl.GetValue();
1169 Impl.SetValue(value);
1173 internal abstract BluetoothGattClient Client { get; }
1174 internal abstract BluetoothGattServer Server { get; }
1175 internal abstract BluetoothGattAttributeImpl Impl { get; }
1178 /// Returns a string value at the specified offset.
1180 /// <param name="offset">An offset in the attribute value buffer.</param>
1181 /// <returns>The string value at specified offset.</returns>
1182 /// <since_tizen> 3 </since_tizen>
1183 public string GetValue(int offset)
1185 return Impl.GetValue(offset);
1189 /// Sets the string value as a specified offset.
1191 /// <param name="value">value to set</param>
1192 /// <exception cref="InvalidOperationException">Throws exception if the value is null.</exception>
1193 /// <since_tizen> 3 </since_tizen>
1194 public void SetValue(string value)
1196 if (string.IsNullOrEmpty(value))
1197 GattUtil.ThrowForError((int)BluetoothError.InvalidParameter, "value should not be null");
1199 byte[] val = Encoding.UTF8.GetBytes(value);
1204 /// Returns a value at specified offset as the int value of the specified type.
1206 /// <param name="type">The type of the int value.</param>
1207 /// <param name="offset">An offset in the attribute value buffer.</param>
1208 /// <returns>The int value at given offset.</returns>
1209 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1210 /// <since_tizen> 3 </since_tizen>
1211 public int GetValue(IntDataType type, int offset)
1213 return Impl.GetValue(type, offset);
1217 /// Updates a value at the specified offset by the int value of the specified type.
1219 /// <param name="type">The type of the int value.</param>
1220 /// <param name="value">The value to set.</param>
1221 /// <param name="offset">An offset in the attribute value buffer.</param>
1222 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of int value) is greater than the length of the value buffer.</exception>
1223 /// <since_tizen> 3 </since_tizen>
1224 public void SetValue(IntDataType type, int value, int offset)
1226 Impl.SetValue(type, value, offset);
1230 /// Returns a value at the specified offset as the float value of the specified type.
1232 /// <param name="type">The type of the float value.</param>
1233 /// <param name="offset">An offset in the attribute value buffer.</param>
1234 /// <returns>The float value at given offset.</returns>
1235 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1236 /// <since_tizen> 3 </since_tizen>
1237 public float GetValue(FloatDataType type, int offset)
1239 return Impl.GetValue(type, offset);
1243 /// Updates the value at the specified offset by the float value of the specified type.
1245 /// <param name="type">The type of the float value.</param>
1246 /// <param name="mantissa">The mantissa of the float value.</param>
1247 /// <param name="exponent">An exponent of the float value.</param>
1248 /// <param name="offset">An offset in the attribute value buffer.</param>
1249 /// <exception cref="InvalidOperationException">Throws exception if (offset + size of float value) is greater than the length of the value buffer.</exception>
1250 /// <since_tizen> 3 </since_tizen>
1251 public void SetValue(FloatDataType type, int mantissa, int exponent, int offset)
1253 Impl.SetValue(type, mantissa, exponent, offset);
1256 internal void ReleaseHandleOwnership()
1258 Impl.ReleaseHandleOwnership();
1261 internal BluetoothGattAttributeHandle GetHandle()
1263 return Impl.GetHandle();