Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
BTGattHandler.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2020 ZAFENA AB
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef BT_GATT_HANDLER_HPP_
27#define BT_GATT_HANDLER_HPP_
28
29#include <cstring>
30#include <string>
31#include <memory>
32#include <cstdint>
33
34#include <mutex>
35#include <atomic>
36#include <thread>
37
38#include <jau/environment.hpp>
39#include <jau/ringbuffer.hpp>
40#include <jau/cow_darray.hpp>
41#include <jau/uuid.hpp>
43
44#include "BTTypes0.hpp"
45#include "L2CAPComm.hpp"
46#include "ATTPDUTypes.hpp"
47#include "GattNumbers.hpp"
48#include "DBGattServer.hpp"
49#include "jau/int_types.hpp"
50
51/**
52 * - - - - - - - - - - - - - - -
53 *
54 * Module BTGattHandler:
55 *
56 * - BT Core Spec v5.2: Vol 3, Part G Generic Attribute Protocol (GATT)
57 * - BT Core Spec v5.2: Vol 3, Part G GATT: 2.6 GATT Profile Hierarchy
58 * - BT Core Spec v5.2: Vol 3, Part G GATT: 3.4 Summary of GATT Profile Attribute Types
59 */
60namespace direct_bt {
61
62 class BTDevice; // forward
63 typedef std::shared_ptr<BTDevice> BTDeviceRef;
64
65 /** \addtogroup DBTSystemAPI
66 *
67 * @{
68 */
69
70 /**
71 * GATT Singleton runtime environment properties
72 * <p>
73 * Also see {@link DBTEnv::getExplodingProperties(const std::string & prefixDomain)}.
74 * </p>
75 */
77 private:
78 BTGattEnv() noexcept; // NOLINT(modernize-use-equals-delete)
79
80 const bool exploding; // just to trigger exploding properties
81
82 public:
83 /**
84 * Timeout for GATT read command replies, defaults to 550ms minimum,
85 * where 500ms is the minimum supervising timeout HCIConstInt::LE_CONN_MIN_TIMEOUT_MS.
86 *
87 * Environment variable is 'direct_bt.gatt.cmd.read.timeout'.
88 *
89 * Actually used timeout will be `max(connection_supervisor_timeout + 50ms, GATT_READ_COMMAND_REPLY_TIMEOUT)`,
90 * additional 50ms to allow L2CAP timeout hit first.
91 */
93
94 /**
95 * Timeout for GATT write command replies, defaults to 550ms minimum,
96 * where 500ms is the minimum supervising timeout HCIConstInt::LE_CONN_MIN_TIMEOUT_MS.
97 *
98 * Environment variable is 'direct_bt.gatt.cmd.write.timeout'.
99 *
100 * Actually used timeout will be `max(connection_supervisor_timeout + 50ms, GATT_WRITE_COMMAND_REPLY_TIMEOUT)`,
101 * additional 50ms to allow L2CAP timeout hit first.
102 */
104
105 /**
106 * Timeout for l2cap _initial_ command reply, defaults to 2500ms (2000ms minimum).
107 *
108 * Environment variable is 'direct_bt.gatt.cmd.init.timeout'.
109 *
110 * Actually used timeout will be `min(10000, max(2 * connection_supervisor_timeout, GATT_INITIAL_COMMAND_REPLY_TIMEOUT))`,
111 * double of connection_supervisor_timeout, to make sure L2CAP timeout hits first.
112 */
114
115 /**
116 * Medium ringbuffer capacity, defaults to 128 messages.
117 * <p>
118 * Environment variable is 'direct_bt.gatt.ringsize'.
119 * </p>
120 */
121 const int32_t ATTPDU_RING_CAPACITY;
122
123 /**
124 * Debug all GATT Data communication
125 * <p>
126 * Environment variable is 'direct_bt.debug.gatt.data'.
127 * </p>
128 */
129 const bool DEBUG_DATA;
130
131 public:
132 static BTGattEnv& get() noexcept {
133 /**
134 * Thread safe starting with C++11 6.7:
135 *
136 * If control enters the declaration concurrently while the variable is being initialized,
137 * the concurrent execution shall wait for completion of the initialization.
138 *
139 * (Magic Statics)
140 *
141 * Avoiding non-working double checked locking.
142 */
143 static BTGattEnv e;
144 return e;
145 }
146 };
147
148 /**
149 * A thread safe GATT handler associated to one device via one L2CAP connection.
150 *
151 * Implementation utilizes a lock free ringbuffer receiving data within its separate thread.
152 *
153 * Controlling Environment variables, see {@link BTGattEnv}.
154 *
155 * @anchor BTGattHandlerRoles
156 * Local GATTRole to a remote BTDevice, (see getRole()):
157 *
158 * - {@link GATTRole::Server}: The remote device in ::BTRole::Master role running a ::GATTRole::Client. We acts as a ::GATTRole::Server.
159 * - {@link GATTRole::Client}: The remote device in ::BTRole::Slave role running a ::GATTRole::Server. We acts as a ::GATTRole::Client.
160 *
161 * See [BTDevice roles](@ref BTDeviceRoles) and [BTAdapter roles](@ref BTAdapterRoles).
162 *
163 * @see GATTRole
164 * @see [BTAdapter roles](@ref BTAdapterRoles).
165 * @see [BTDevice roles](@ref BTDeviceRoles).
166 * @see [BTGattHandler roles](@ref BTGattHandlerRoles).
167 * @see [Bluetooth Specification](https://www.bluetooth.com/specifications/bluetooth-core-specification/)
168 */
170 public:
171 enum class Defaults : uint16_t {
172 /**
173 * BT Core Spec v5.2: Vol 3, Part F 3.2.8: Maximum length of an attribute value.
174 *
175 * We add +1 for opcode, but don't add for different PDU type's parameter
176 * upfront the attribute value.
177 */
178 MAX_ATT_MTU = 512 + 1,
179
180 /* BT Core Spec v5.2: Vol 3, Part G GATT: 5.2.1 ATT_MTU */
181 MIN_ATT_MTU = 23
182 };
183 static constexpr uint16_t number(const Defaults d) { return static_cast<uint16_t>(d); }
184
185 /** Supervison timeout of the connection. */
186 const int32_t supervision_timeout;
187 /** Environment runtime configuration, usually used internally only. */
188 const BTGattEnv & env;
189 /** Derived environment runtime configuration, usually used internally only. */
191 /** Derived environment runtime configuration, usually used internally only. */
193
194 /**
195 * Internal handler implementation for given DBGattServer instance
196 * matching its DBGattServer::Mode.
197 *
198 * The specific implementation acts upon GATT requests from a connected client
199 * according to DBGattServer::Mode.
200 */
202 public:
203 virtual ~GattServerHandler() = default;
204
205 /**
206 * Close and clear this handler, i.e. release all resources.
207 *
208 * Usually called when disconnected or destructed.
209 */
210 virtual void close() noexcept {}
211
212 virtual DBGattServer::Mode getMode() noexcept = 0;
213
214 /**
215 * Reply to an exchange MTU request
216 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.3.1 Exchange MTU (Server configuration)
217 * @param pdu
218 * @return true if transmission was successful, otherwise false
219 */
220 virtual bool replyExchangeMTUReq(const AttExchangeMTU * pdu) noexcept = 0;
221
222 /**
223 * Reply to a read request
224 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.1 Read Characteristic Value
225 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.3 Read Long Characteristic Value
226 * - For any follow up request, which previous request reply couldn't fit in ATT_MTU (Long Write)
227 * @param pdu
228 * @return true if transmission was successful, otherwise false
229 */
230 virtual bool replyReadReq(const AttPDUMsg * pdu) noexcept = 0;
231
232 /**
233 * Reply to a write request.
234 *
235 * Without Response:
236 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.5.3 ATT_WRITE_CMD
237 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.1 Write Characteristic Value without Response
238 *
239 * With Response:
240 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.5.1 ATT_WRITE_REQ
241 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value
242 * - BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration
243 *
244 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.5.2 ATT_WRITE_RSP
245 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value
246 *
247 * @param pdu
248 * @return true if transmission was successful, otherwise false
249 */
250 virtual bool replyWriteReq(const AttPDUMsg * pdu) noexcept = 0;
251
252 /**
253 * Reply to a find info request
254 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.1 ATT_FIND_INFORMATION_REQ
255 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.2 ATT_FIND_INFORMATION_RSP
256 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.7.1 Discover All Characteristic Descriptors
257 *
258 * @param pdu
259 * @return true if transmission was successful, otherwise false
260 */
261 virtual bool replyFindInfoReq(const AttFindInfoReq * pdu) noexcept = 0;
262
263 /**
264 * Reply to a find by type value request
265 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.3 ATT_FIND_BY_TYPE_VALUE_REQ
266 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.4 ATT_FIND_BY_TYPE_VALUE_RSP
267 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.2 Discover Primary Service by Service UUID
268 * @param pdu
269 * @return true if transmission was successful, otherwise false
270 */
271 virtual bool replyFindByTypeValueReq(const AttFindByTypeValueReq * pdu) noexcept = 0;
272
273 /**
274 * Reply to a read by type request
275 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.4.1 ATT_READ_BY_TYPE_REQ
276 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.4.2 ATT_READ_BY_TYPE_RSP
277 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.6.1 Discover All Characteristics of a Service
278 *
279 * @param pdu
280 * @return true if transmission was successful, otherwise false
281 */
282 virtual bool replyReadByTypeReq(const AttReadByNTypeReq * pdu) noexcept = 0;
283
284 /**
285 * Reply to a read by group type request
286 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.4.9 ATT_READ_BY_GROUP_TYPE_REQ
287 * - BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.4.10 ATT_READ_BY_GROUP_TYPE_RSP
288 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.1 Discover All Primary Services
289 *
290 * @param pdu
291 * @return true if transmission was successful, otherwise false
292 */
293 virtual bool replyReadByGroupTypeReq(const AttReadByNTypeReq * pdu) noexcept = 0;
294 };
295
296 /**
297 * Native GATT characteristic event listener for notification and indication events received from a GATT server.
298 */
300 public:
301 struct Section {
302 /** start point, inclusive */
303 uint16_t start;
304 /** end point, exclusive */
305 uint16_t end;
306
307 Section(uint16_t s, uint16_t e) : start(s), end(e) {}
308
309 std::string toString() { return "["+std::to_string(start)+".."+std::to_string(end-1)+"]"; }
310 };
311
312 /**
313 * Called from native BLE stack, initiated by a received notification.
314 * @param source BTDevice origin of this notification
315 * @param charHandle the GATT characteristic handle related to this notification
316 * @param charValue the notification value
317 * @param timestamp monotonic timestamp at reception, see jau::getCurrentMilliseconds()
318 */
319 virtual void notificationReceived(const BTDeviceRef& source, const uint16_t charHandle,
320 const jau::TROOctets& charValue, const uint64_t timestamp) = 0;
321
322 /**
323 * Called from native BLE stack, initiated by a received indication.
324 * @param source BTDevice origin of this indication
325 * @param charHandle the GATT characteristic handle related to this indication
326 * @param charValue the indication value
327 * @param timestamp monotonic timestamp at reception, see jau::getCurrentMilliseconds()
328 * @param confirmationSent if true, the native stack has sent the confirmation, otherwise user is required to do so.
329 */
330 virtual void indicationReceived(const BTDeviceRef&, const uint16_t charHandle,
331 const jau::TROOctets& charValue, const uint64_t timestamp,
332 const bool confirmationSent) = 0;
333
334 /**
335 * Informal low-level notification of AttPDUMsg requests to this GATTRole::Server, optional
336 *
337 * @param pduRequest the request
338 * @param serverDest the GATTRole::Server receiver device, never null
339 * @param clientSource the GATTRole::Client source device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
340 */
341 virtual void requestSent([[maybe_unused]] const AttPDUMsg& pduRequest,
342 [[maybe_unused]] const BTDeviceRef& serverDest,
343 [[maybe_unused]] const BTDeviceRef& clientSource) { }
344
345 /**
346 * Informal low-level notification of AttPDUMsg responses from this GATTRole::Server, optional.
347 *
348 * @param pduReply the response
349 * @param serverSource the GATTRole::Server source device, never null
350 * @param clientDest the GATTRole::Client receiver device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
351 */
352 virtual void replyReceived([[maybe_unused]] const AttPDUMsg& pduReply,
353 [[maybe_unused]] const BTDeviceRef& serverSource,
354 [[maybe_unused]] const BTDeviceRef& clientDest) { }
355
356 /**
357 * Informal notification about a complete MTU exchange request and response to and from this GATTRole::Server, optional.
358 *
359 * @param clientMTU the client MTU request
360 * @param pduReply the response
361 * @param error_reply in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
362 * @param serverMTU the replied server MTU, passed for convenience
363 * @param usedMTU the MTU minimum of client and server to be used, passed for convenience
364 * @param serverReplier the GATTRole::Server replier device, never null
365 * @param clientRequester the GATTRole::Client requester device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
366 */
367 virtual void mtuResponse([[maybe_unused]] const uint16_t clientMTU,
368 [[maybe_unused]] const AttPDUMsg& pduReply,
369 [[maybe_unused]] const AttErrorRsp::ErrorCode error_reply,
370 [[maybe_unused]] const uint16_t serverMTU,
371 [[maybe_unused]] const uint16_t usedMTU,
372 [[maybe_unused]] const BTDeviceRef& serverReplier,
373 [[maybe_unused]] const BTDeviceRef& clientRequester) { }
374 /**
375 * Informal notification about a completed write request sent to this GATTRole::Server, optional.
376 *
377 * @param handle the GATT characteristic or descriptor handle, requested to be written
378 * @param data the data requested to be written
379 * @param sections list of NativeGattCharListener::Section within given data, requested to be written. Overlapping consecutive sections have already been merged.
380 * @param with_response true if the write requests expects a response, i.e. via AttPDUMsg::Opcode::WRITE_REQ or AttPDUMsg::Opcode::EXECUTE_WRITE_REQ
381 * @param serverDest the GATTRole::Server receiver device, never null
382 * @param clientSource the GATTRole::Client source device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
383 */
384 virtual void writeRequest([[maybe_unused]] const uint16_t handle,
385 [[maybe_unused]] const jau::TROOctets& data,
386 [[maybe_unused]] const jau::darray<Section>& sections,
387 [[maybe_unused]] const bool with_response,
388 [[maybe_unused]] const BTDeviceRef& serverDest,
389 [[maybe_unused]] const BTDeviceRef& clientSource) { }
390
391 /**
392 * Informal notification about a write response received from this GATTRole::Server, optional.
393 *
394 * @param pduReply the write response
395 * @param error_code in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
396 * @param serverSource the GATTRole::Server source device, never null
397 * @param clientDest the GATTRole::Client receiver device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
398 */
399 virtual void writeResponse([[maybe_unused]] const AttPDUMsg& pduReply,
400 [[maybe_unused]] const AttErrorRsp::ErrorCode error_code,
401 [[maybe_unused]] const BTDeviceRef& serverSource,
402 [[maybe_unused]] const BTDeviceRef& clientDest) { }
403
404
405 /**
406 * Informal notification about a complete read request and response to and from this GATTRole::Server, optional.
407 *
408 * @param handle the GATT characteristic or descriptor handle, requested to be written
409 * @param value_offset the value offset of the data to be read
410 * @param pduReply the response
411 * @param error_reply in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
412 * @param data_reply the replied read data at given value_offset, passed for convenience
413 * @param serverReplier the GATTRole::Server replier device, never null
414 * @param clientRequester the GATTRole::Client requester device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
415 */
416 virtual void readResponse([[maybe_unused]] const uint16_t handle,
417 [[maybe_unused]] const uint16_t value_offset,
418 [[maybe_unused]] const AttPDUMsg& pduReply,
419 [[maybe_unused]] const AttErrorRsp::ErrorCode error_reply,
420 [[maybe_unused]] const jau::TROOctets& data_reply,
421 [[maybe_unused]] const BTDeviceRef& serverReplier,
422 [[maybe_unused]] const BTDeviceRef& clientRequester) { }
423
424 virtual ~NativeGattCharListener() noexcept = default;
425
426 /** Return a simple description about this instance. */
427 virtual std::string toString() {
428 return "NativeGattCharListener["+jau::to_string(this)+"]";
429 }
430
431 /**
432 * Default comparison operator, merely testing for same memory reference.
433 * <p>
434 * Specializations may override.
435 * </p>
436 */
437 virtual bool operator==(const NativeGattCharListener& rhs) const noexcept
438 { return this == &rhs; }
439
440 bool operator!=(const NativeGattCharListener& rhs) const noexcept
441 { return !(*this == rhs); }
442 };
445
446 typedef std::shared_ptr<NativeGattCharListener> NativeGattCharListenerRef;
450
451 private:
452 /** BTGattHandler's device weak back-reference */
453 std::weak_ptr<BTDevice> wbr_device;
454 GATTRole role;
455 L2CAPClient& l2cap;
456
457 const std::string deviceString;
458 mutable std::recursive_mutex mtx_command;
459 jau::POctets rbuffer;
460
461 jau::sc_atomic_bool is_connected; // reflects state
462 jau::relaxed_atomic_bool has_ioerror; // reflects state
463
464 jau::service_runner l2cap_reader_service;
466
467 jau::relaxed_atomic_uint16 serverMTU; // set in initClientGatt()
468 jau::relaxed_atomic_uint16 usedMTU; // concurrent use in initClientGatt(set), send and l2capReaderThreadImpl
469 jau::relaxed_atomic_bool clientMTUExchanged; // set in initClientGatt()
470
471 /** send immediate confirmation of indication events from device, defaults to true. */
472 jau::relaxed_atomic_bool sendIndicationConfirmation = true;
473
474 struct GattCharListenerPair {
475 /** The actual listener */
476 BTGattCharListenerRef listener;
477 /** The optional weak device reference. Weak, b/c it shall not block destruction */
478 std::weak_ptr<BTGattChar> wbr_characteristic;
479
480 bool match(const BTGattChar& characteristic) const noexcept {
481 BTGattCharRef sda = wbr_characteristic.lock();
482 if( nullptr != sda ) {
483 return *sda == characteristic;
484 } else {
485 return true;
486 }
487 }
488 };
489 typedef jau::cow_darray<GattCharListenerPair, size_type> gattCharListenerList_t;
490 static gattCharListenerList_t::equal_comparator gattCharListenerRefEqComparator;
491 gattCharListenerList_t gattCharListenerList;
492
493 NativeGattCharListenerList_t nativeGattCharListenerList;
494
495 /** Pass through user Gatt-Server database, non-nullptr if ::GATTRole::Server */
496 DBGattServerRef gattServerData;
497 /** Always set, never nullptr */
498 std::unique_ptr<GattServerHandler> gattServerHandler;
499 static std::unique_ptr<GattServerHandler> selectGattServerHandler(BTGattHandler& gh, const DBGattServerRef& gattServerData) noexcept;
500
501 GattServiceList_t services;
502 std::shared_ptr<GattGenericAccessSvc> genericAccess = nullptr;
503
504 bool validateConnected() noexcept;
505
506 DBGattCharRef findServerGattCharByValueHandle(const uint16_t char_value_handle) noexcept;
507
508 /**
509 * Reply given ATT message using the installed GattServerHandler gattServerHandler
510 * @param pdu the message
511 * @return true if transmission was successful, otherwise false
512 */
513 bool replyAttPDUReq(std::unique_ptr<const AttPDUMsg> && pdu) noexcept;
514
515 void l2capReaderWork(jau::service_runner& sr) noexcept;
516 void l2capReaderEndLocked(jau::service_runner& sr) noexcept;
517
518 bool l2capReaderInterrupted(int dummy=0) /* const */ noexcept;
519
520 /**
521 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.4.2 MTU Exchange
522 *
523 * Returns the server-mtu if successful, otherwise 0.
524 *
525 * Method usually called via initClientGatt() and is only exposed special applications.
526 *
527 * @see initClientGatt()
528 */
529 uint16_t clientMTUExchange(const jau::fraction_i64& timeout) noexcept;
530
531 /**
532 * Discover all primary services _only_.
533 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.1 Discover All Primary Services
534 *
535 * @param shared_this shared pointer of this instance, used to forward a weak_ptr to BTGattService for back-reference. Reference is validated.
536 * @param result vector containing all discovered primary services
537 * @return true on success, otherwise false
538 * @see initClientGatt()
539 * @see discoverCompletePrimaryServices()
540 */
541 bool discoverPrimaryServices(const std::shared_ptr<BTGattHandler>& shared_this, GattServiceList_t& result) noexcept;
542
543 /**
544 * Discover all characteristics of a service and declaration attributes _only_.
545 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.6.1 Discover All Characteristics of a Service
546 * - BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.1 Characterisic Declaration Attribute Value
547 *
548 * @see initClientGatt()
549 * @see discoverCompletePrimaryServices()
550 */
551 bool discoverCharacteristics(BTGattServiceRef & service) noexcept;
552
553 /**
554 * Discover all descriptors of a service _only_.
555 * - BT Core Spec v5.2: Vol 3, Part G GATT: 4.7.1 Discover All Characteristic Descriptors
556 *
557 * @see initClientGatt()
558 * @see discoverCompletePrimaryServices()
559 */
560 bool discoverDescriptors(BTGattServiceRef & service) noexcept;
561
562 /**
563 * Discover all primary services _and_ all its characteristics declarations
564 * including their client config.
565 * <p>
566 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.4.1 Discover All Primary Services
567 * </p>
568 * Populates the internal internal BTGattService vector of discovered services.
569 *
570 * Service discovery may consume 500ms - 2000ms, depending on bandwidth.
571 *
572 * Method called from initClientGatt().
573 *
574 * @param shared_this shared pointer of this instance, used to forward a weak_ptr to BTGattService for back-reference. Reference is validated.
575 * @return true if successful, otherwise false
576 * @see initClientGatt()
577 */
578 bool discoverCompletePrimaryServices(const std::shared_ptr<BTGattHandler>& shared_this) noexcept;
579
580 public:
581 /**
582 * Constructing a new BTGattHandler instance with its opened and connected L2CAP channel.
583 * <p>
584 * After successful l2cap connection, the MTU will be exchanged.
585 * See getServerMTU() and getUsedMTU(), the latter is in use.
586 * </p>
587 * @param device the connected remote device
588 * @param l2cap_att the underlying used L2CAP
589 * @param supervision_timeout the connection supervising timeout in [ms]
590 */
591 BTGattHandler(const BTDeviceRef & device, L2CAPClient& l2cap_att, const int32_t supervision_timeout) noexcept;
592
593 BTGattHandler(const BTGattHandler&) = delete;
594 void operator=(const BTGattHandler&) = delete;
595
596 /** Destructor closing this instance including L2CAP channel, see {@link #disconnect()}. */
597 ~BTGattHandler() noexcept;
598
599 BTDeviceRef getDeviceUnchecked() const noexcept { return wbr_device.lock(); }
601
602 /**
603 * Return the local GATTRole to the remote BTDevice.
604 * @see GATTRole
605 * @see [BTGattHandler roles](@ref BTGattHandlerRoles).
606 * @since 2.4.0
607 */
608 GATTRole getRole() const noexcept { return role; }
609
610 bool isConnected() const noexcept { return is_connected ; }
611 bool hasIOError() const noexcept { return has_ioerror; }
612 std::string getStateString() const noexcept;
613
614 /**
615 * Disconnect this BTGattHandler and optionally the associated device
616 * @param disconnect_device if true, associated device will also be disconnected, otherwise not.
617 * @param ioerr_cause if true, reason for disconnection is an IO error
618 * @return true if successful, otherwise false
619 */
620 bool disconnect(const bool disconnect_device, const bool ioerr_cause) noexcept;
621
622 inline uint16_t getServerMTU() const noexcept { return serverMTU; }
623 inline uint16_t getUsedMTU() const noexcept { return usedMTU; }
624 void setUsedMTU(const uint16_t mtu) noexcept { usedMTU = mtu; }
625
626 /**
627 * Find and return the BTGattChar within given list of primary services
628 * via given characteristic value handle.
629 * <p>
630 * Returns nullptr if not found.
631 * </p>
632 */
633 BTGattCharRef findCharacterisicsByValueHandle(const GattServiceList_t&services_, const uint16_t charValueHandle) noexcept;
634
635 /**
636 * Find and return the BTGattChar within given primary service
637 * via given characteristic value handle.
638 * <p>
639 * Returns nullptr if not found.
640 * </p>
641 */
642 BTGattCharRef findCharacterisicsByValueHandle(const BTGattServiceRef& service, const uint16_t charValueHandle) noexcept;
643
644 /**
645 * Initialize the connection and internal data set for GATT client operations:
646 * - Exchange MTU
647 * - Discover all primary services, its characteristics and its descriptors
648 * - Extracts the GattGenericAccessSvc from the services, see getGenericAccess()
649 *
650 * Service discovery may consume 500ms - 2000ms, depending on bandwidth.
651 *
652 * @param shared_this the shared BTGattHandler reference
653 * @param already_init if already initialized true, will hold true, otherwise false
654 * @return true if already initialized or successfully newly initialized with at least GattGenericAccessSvc available, otherwise false
655 * @see clientMTUExchange()
656 * @see discoverCompletePrimaryServices()
657 */
658 bool initClientGatt(const std::shared_ptr<BTGattHandler>& shared_this, bool& already_init) noexcept;
659
660 /**
661 * Returns a reference of the internal kept BTGattService list.
662 *
663 * The internal list should have been populated via initClientGatt() once.
664 *
665 * @see initClientGatt()
666 */
667 inline GattServiceList_t& getServices() noexcept { return services; }
668
669 /**
670 * Returns the internal kept shared GattGenericAccessSvc instance.
671 *
672 * This instance is created via initClientGatt().
673 *
674 * @see initClientGatt()
675 */
676 inline std::shared_ptr<GattGenericAccessSvc> getGenericAccess() noexcept { return genericAccess; }
677
678 /**
679 * Sends the given AttPDUMsg to the connected device via l2cap.
680 *
681 * ATT_MTU range
682 * - ATT_MTU minimum is 23 bytes (Vol 3, Part G: 5.2.1)
683 * - ATT_MTU is negotiated, maximum attribute value length is 512 bytes (Vol 3, Part F: 3.2.8-9)
684 * - ATT Value sent: [1 .. ATT_MTU-1] (Vol 3, Part F: 3.2.8-9)
685 *
686 * Implementation disconnect() and returns false if an unexpected l2cap write errors occurs.
687 *
688 * @param msg the message to be send
689 * @return true if successful otherwise false if write error, not connected or if message size exceeds usedMTU-1.
690 */
691 bool send(const AttPDUMsg & msg) noexcept;
692
693 /**
694 * Sends the given AttPDUMsg to the connected device via l2cap using {@link #send()}.
695 *
696 * Implementation waits for timeout milliseconds receiving the response
697 * from the ringbuffer, filled from the reader-thread.
698 *
699 * Implementation disconnect() and returns nullptr
700 * if no matching reply has been received within timeout milliseconds.
701 *
702 * In case method completes successfully,
703 * the message has been send out and a reply has also been received and is returned as the result.
704 *
705 * @param msg the message to be send
706 * @param timeout fractions of seconds to wait for a reply
707 * @return non nullptr for a valid reply, otherwise nullptr
708 */
709 std::unique_ptr<const AttPDUMsg> sendWithReply(const AttPDUMsg & msg, const jau::fraction_i64& timeout) noexcept;
710
711 /**
712 * Generic read GATT value and long value
713 * <p>
714 * If expectedLength = 0, then only one ATT_READ_REQ/RSP will be used.
715 * </p>
716 * <p>
717 * If expectedLength < 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used until
718 * the response returns zero. This is the default parameter.
719 * </p>
720 * <p>
721 * If expectedLength > 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used
722 * if required until the response returns zero.
723 * </p>
724 */
725 bool readValue(const uint16_t handle, jau::POctets & res, ssize_type expectedLength=-1) noexcept;
726
727 /**
728 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.1 Read Characteristic Value
729 * <p>
730 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.3 Read Long Characteristic Value
731 * </p>
732 * <p>
733 * If expectedLength = 0, then only one ATT_READ_REQ/RSP will be used.
734 * </p>
735 * <p>
736 * If expectedLength < 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used until
737 * the response returns zero. This is the default parameter.
738 * </p>
739 * <p>
740 * If expectedLength > 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used
741 * if required until the response returns zero.
742 * </p>
743 */
744 bool readCharacteristicValue(const BTGattChar & c, jau::POctets & res, ssize_type expectedLength=-1) noexcept;
745
746 /**
747 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.1 Read Characteristic Descriptor
748 * <p>
749 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.2 Read Long Characteristic Descriptor
750 * </p>
751 * <p>
752 * If expectedLength = 0, then only one ATT_READ_REQ/RSP will be used.
753 * </p>
754 * <p>
755 * If expectedLength < 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used until
756 * the response returns zero. This is the default parameter.
757 * </p>
758 * <p>
759 * If expectedLength > 0, then long values using multiple ATT_READ_BLOB_REQ/RSP will be used
760 * if required until the response returns zero.
761 * </p>
762 */
763 bool readDescriptorValue(BTGattDesc & cd, ssize_type expectedLength=-1) noexcept;
764
765 /**
766 * Generic write GATT value and long value
767 */
768 bool writeValue(const uint16_t handle, const jau::TROOctets & value, const bool withResponse) noexcept;
769
770 /**
771 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.3 Write Characteristic Descriptors
772 * <p>
773 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3 Characteristic Descriptor
774 * </p>
775 * <p>
776 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration
777 * </p>
778 */
779 bool writeDescriptorValue(const BTGattDesc & cd) noexcept;
780
781 /**
782 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value
783 */
784 bool writeCharacteristicValue(const BTGattChar & c, const jau::TROOctets & value) noexcept;
785
786 /**
787 * BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.1 Write Characteristic Value Without Response
788 */
789 bool writeCharacteristicValueNoResp(const BTGattChar & c, const jau::TROOctets & value) noexcept;
790
791 /**
792 * BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration
793 * <p>
794 * Method enables notification and/or indication for the corresponding characteristic at BLE level.
795 * </p>
796 * <p>
797 * It is recommended to utilize notification over indication, as its link-layer handshake
798 * and higher potential bandwidth may deliver material higher performance.
799 * </p>
800 * <p>
801 * Throws an IllegalArgumentException if the given BTGattDesc is not a ClientCharacteristicConfiguration.
802 * </p>
803 */
804 bool configNotificationIndication(BTGattDesc & cd, const bool enableNotification, const bool enableIndication) noexcept;
805
806 /**
807 * Send a notification event consisting out of the given `value` representing the given characteristic value handle
808 * to the connected BTRole::Master.
809 *
810 * This command is only valid if this BTGattHandler is in role GATTRole::Server.
811 *
812 * Implementation is not receiving any reply after sending out the indication and returns immediately.
813 *
814 * @param char_value_handle valid characteristic value handle, must be sourced from referenced DBGattServer
815 * @return true if successful, otherwise false
816 */
817 bool sendNotification(const uint16_t char_value_handle, const jau::TROOctets & value) noexcept;
818
819 /**
820 * Send an indication event consisting out of the given `value` representing the given characteristic value handle
821 * to the connected BTRole::Master.
822 *
823 * This command is only valid if this BTGattHandler is in role GATTRole::Server.
824 *
825 * Implementation awaits the indication reply after sending out the indication.
826 *
827 * @param char_value_handle valid characteristic value handle, must be sourced from referenced DBGattServer
828 * @return true if successful, otherwise false
829 */
830 bool sendIndication(const uint16_t char_value_handle, const jau::TROOctets & value) noexcept;
831
832 /**
833 * Add the given listener to the list if not already present.
834 * <p>
835 * Returns true if the given listener is not element of the list and has been newly added,
836 * otherwise false.
837 * </p>
838 */
839 bool addCharListener(const BTGattCharListenerRef& l) noexcept;
840
841 /**
842 * Please use BTGattChar::addCharListener() for clarity, merely existing here to allow JNI access.
843 */
844 bool addCharListener(const BTGattCharListenerRef& l, const BTGattCharRef& d) noexcept;
845
846 /**
847 * Remove the given listener from the list.
848 * <p>
849 * Returns true if the given listener is an element of the list and has been removed,
850 * otherwise false.
851 * </p>
852 */
853 bool removeCharListener(const BTGattCharListenerRef& l) noexcept;
854
855 /**
856 * Remove the given listener from the list.
857 * <p>
858 * Returns true if the given listener is an element of the list and has been removed,
859 * otherwise false.
860 * </p>
861 */
862 bool removeCharListener(const BTGattCharListener * l) noexcept;
863
864 /**
865 * Remove all {@link BTGattCharListener} from the list, which are associated to the given {@link BTGattChar}
866 * when added via BTGattChar::addCharListener().
867 *
868 * @param associatedCharacteristic the match criteria to remove any BTGattCharListener from the list
869 * @return number of removed listener.
870 */
871 size_type removeAllAssociatedCharListener(const BTGattCharRef& associatedChar) noexcept;
872
873 size_type removeAllAssociatedCharListener(const BTGattChar * associatedChar) noexcept;
874
875 /**
876 * Add the given listener to the list if not already present.
877 * <p>
878 * Returns true if the given listener is not element of the list and has been newly added,
879 * otherwise false.
880 * </p>
881 */
882 bool addCharListener(const NativeGattCharListenerRef& l) noexcept;
883
884 /**
885 * Remove the given listener from the list.
886 * <p>
887 * Returns true if the given listener is an element of the list and has been removed,
888 * otherwise false.
889 * </p>
890 */
891 bool removeCharListener(const NativeGattCharListenerRef& l) noexcept;
892
893 /**
894 * Remove all event listener from the list.
895 * <p>
896 * Returns the number of removed event listener.
897 * </p>
898 */
900
901 /**
902 * Return event listener count.
903 */
904 jau::nsize_t getCharListenerCount() const noexcept { return gattCharListenerList.size() + nativeGattCharListenerList.size(); }
905
906 /**
907 * Print a list of all BTGattCharListener and NativeGattCharListener.
908 *
909 * This is merely a facility for debug and analysis.
910 */
911 void printCharListener() noexcept;
912
913 /**
914 * Notify all NativeGattCharListener about a low-level AttPDUMsg request being sent to this GATTRole::Server.
915 *
916 * This functionality has an informal character only.
917 *
918 * @param pduRequest the request
919 * @param clientSource the GATTRole::Client source device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
920 */
921 void notifyNativeRequestSent(const AttPDUMsg& pduRequest, const BTDeviceRef& clientSource) noexcept;
922
923 /**
924 * Notify all NativeGattCharListener about a low-level AttPDUMsg reply being received from this GATTRole::Server.
925 *
926 * @param pduReply the response
927 * @param clientDest the GATTRole::Client receiver device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
928 */
929 void notifyNativeReplyReceived(const AttPDUMsg& pduReply, const BTDeviceRef& clientDest) noexcept;
930
931 /**
932 * Notify all NativeGattCharListener about a completed MTU exchange request and response to and from this GATTRole::Server.
933 *
934 * This functionality has an informal character only.
935 *
936 * @param clientMTU the client MTU request
937 * @param pduReply the response
938 * @param error_reply in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
939 * @param serverMTU the replied server MTU, passed for convenience
940 * @param usedMTU the MTU minimum of client and server to be used, passed for convenience
941 * @param clientRequester the GATTRole::Client requester device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
942 */
943 void notifyNativeMTUResponse(const uint16_t clientMTU,
944 const AttPDUMsg& pduReply, const AttErrorRsp::ErrorCode error_reply,
945 const uint16_t serverMTU, const uint16_t usedMTU,
946 const BTDeviceRef& clientRequester) noexcept;
947
948 /**
949 * Notify all NativeGattCharListener about a completed write request sent to this GATTRole::Server.
950 *
951 * This functionality has an informal character only.
952 *
953 * @param handle the GATT characteristic or descriptor handle, requested to be written
954 * @param data the data requested to be written
955 * @param sections list of NativeGattCharListener::Section within given data, requested to be written. Overlapping consecutive sections have already been merged.
956 * @param with_response true if the write requests expects a response, i.e. via AttPDUMsg::Opcode::WRITE_REQ or AttPDUMsg::Opcode::EXECUTE_WRITE_REQ
957 * @param clientSource the GATTRole::Client source device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
958 */
959 void notifyNativeWriteRequest(const uint16_t handle, const jau::TROOctets& data, const NativeGattCharSections_t& sections, const bool with_response, const BTDeviceRef& clientSource) noexcept;
960
961 /**
962 * Notify all NativeGattCharListener about a write response received from this GATTRole::Server.
963 *
964 * This functionality has an informal character only.
965 *
966 * @param pduReply the response
967 * @param error_code in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
968 * @param clientDest the GATTRole::Client receiver device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
969 */
970 void notifyNativeWriteResponse(const AttPDUMsg& pduReply, const AttErrorRsp::ErrorCode error_code, const BTDeviceRef& clientDest) noexcept;
971
972 /**
973 * Notify all NativeGattCharListener about a completed read request and response to and from this GATTRole::Server.
974 *
975 * This functionality has an informal character only.
976 *
977 * @param handle the GATT characteristic or descriptor handle, requested to be written
978 * @param value_offset the value offset of the data to be read
979 * @param pduReply the response
980 * @param error_reply in case of an AttErrorRsp reply, the AttErrorRsp::ErrorCode is passed for convenience, otherwise AttErrorRsp::ErrorCode::NO_ERROR.
981 * @param data_reply the replied read data at given value_offset, passed for convenience
982 * @param clientRequester the GATTRole::Client requester device, only known and not nullptr for DBGattServer::Mode:FWD GattServerHandler
983 */
984 void notifyNativeReadResponse(const uint16_t handle, const uint16_t value_offset,
985 const AttPDUMsg& pduReply, const AttErrorRsp::ErrorCode error_reply, const jau::TROOctets& data_reply,
986 const BTDeviceRef& clientRequester) noexcept;
987
988 /**
989 * Enable or disable sending an immediate confirmation for received indication events from the device.
990 * <p>
991 * Default value is true.
992 * </p>
993 * <p>
994 * This setting is per BTGattHandler and hence per BTDevice.
995 * </p>
996 */
997 void setSendIndicationConfirmation(const bool v) noexcept;
998
999 /**
1000 * Returns whether sending an immediate confirmation for received indication events from the device is enabled.
1001 * <p>
1002 * Default value is true.
1003 * </p>
1004 * <p>
1005 * This setting is per BTGattHandler and hence per BTDevice.
1006 * </p>
1007 */
1008 bool getSendIndicationConfirmation() noexcept;
1009
1010 /*****************************************************/
1011 /** Higher level semantic functionality **/
1012 /*****************************************************/
1013
1014 std::shared_ptr<GattGenericAccessSvc> getGenericAccess(GattServiceList_t& primServices) noexcept;
1015 std::shared_ptr<GattGenericAccessSvc> getGenericAccess(jau::darray<BTGattCharRef> & genericAccessCharDeclList) noexcept;
1016
1018 std::shared_ptr<GattDeviceInformationSvc> getDeviceInformation(jau::darray<BTGattCharRef> & deviceInfoCharDeclList) noexcept;
1019
1020 /**
1021 * Issues a ping to the device, validating whether it is still reachable.
1022 * <p>
1023 * This method could be periodically utilized to shorten the underlying OS disconnect period
1024 * after turning the device off, which lies within 7-13s.
1025 * </p>
1026 * <p>
1027 * In case the device is no more reachable, disconnect will be initiated due to the occurring IO error.
1028 * </p>
1029 * @return `true` if successful, otherwise false in case no GATT services exists etc.
1030 */
1031 bool ping() noexcept;
1032
1033 std::string toString() const noexcept;
1034 };
1035 typedef std::shared_ptr<BTGattHandler> BTGattHandlerRef;
1036
1037 /**@}*/
1038
1039} // namespace direct_bt
1040
1041#endif /* BT_GATT_HANDLER_HPP_ */
BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.1.1 ATT_ERROR_RSP.
BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.2.1 ATT_EXCHANGE_MTU_REQ BT Core Spec v5....
BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.3 ATT_FIND_BY_TYPE_VALUE_REQ.
BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.3.1 ATT_FIND_INFORMATION_REQ.
Handles the Attribute Protocol (ATT) using Protocol Data Unit (PDU) encoded messages over L2CAP chann...
BT Core Spec v5.2: Vol 3, Part F ATT: 3.4.4.1 ATT_READ_BY_TYPE_REQ.
BTGattChar event listener for notification and indication events.
Definition: BTGattChar.hpp:450
Representing a Gatt Characteristic object from the GATTRole::Client perspective.
Definition: BTGattChar.hpp:94
Representing a Gatt Characteristic Descriptor object from the GATTRole::Client perspective.
Definition: BTGattDesc.hpp:74
GATT Singleton runtime environment properties.
const jau::fraction_i64 GATT_READ_COMMAND_REPLY_TIMEOUT
Timeout for GATT read command replies, defaults to 550ms minimum, where 500ms is the minimum supervis...
const int32_t ATTPDU_RING_CAPACITY
Medium ringbuffer capacity, defaults to 128 messages.
const jau::fraction_i64 GATT_INITIAL_COMMAND_REPLY_TIMEOUT
Timeout for l2cap initial command reply, defaults to 2500ms (2000ms minimum).
const bool DEBUG_DATA
Debug all GATT Data communication.
static BTGattEnv & get() noexcept
const jau::fraction_i64 GATT_WRITE_COMMAND_REPLY_TIMEOUT
Timeout for GATT write command replies, defaults to 550ms minimum, where 500ms is the minimum supervi...
Internal handler implementation for given DBGattServer instance matching its DBGattServer::Mode.
virtual bool replyFindInfoReq(const AttFindInfoReq *pdu) noexcept=0
Reply to a find info request.
virtual bool replyWriteReq(const AttPDUMsg *pdu) noexcept=0
Reply to a write request.
virtual DBGattServer::Mode getMode() noexcept=0
virtual bool replyExchangeMTUReq(const AttExchangeMTU *pdu) noexcept=0
Reply to an exchange MTU request.
virtual bool replyReadReq(const AttPDUMsg *pdu) noexcept=0
Reply to a read request.
virtual bool replyFindByTypeValueReq(const AttFindByTypeValueReq *pdu) noexcept=0
Reply to a find by type value request.
virtual bool replyReadByGroupTypeReq(const AttReadByNTypeReq *pdu) noexcept=0
Reply to a read by group type request.
virtual bool replyReadByTypeReq(const AttReadByNTypeReq *pdu) noexcept=0
Reply to a read by type request.
virtual void close() noexcept
Close and clear this handler, i.e.
Native GATT characteristic event listener for notification and indication events received from a GATT...
bool operator!=(const NativeGattCharListener &rhs) const noexcept
virtual ~NativeGattCharListener() noexcept=default
virtual void replyReceived(const AttPDUMsg &pduReply, const BTDeviceRef &serverSource, const BTDeviceRef &clientDest)
Informal low-level notification of AttPDUMsg responses from this GATTRole::Server,...
virtual bool operator==(const NativeGattCharListener &rhs) const noexcept
Default comparison operator, merely testing for same memory reference.
virtual void notificationReceived(const BTDeviceRef &source, const uint16_t charHandle, const jau::TROOctets &charValue, const uint64_t timestamp)=0
Called from native BLE stack, initiated by a received notification.
virtual void writeResponse(const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_code, const BTDeviceRef &serverSource, const BTDeviceRef &clientDest)
Informal notification about a write response received from this GATTRole::Server, optional.
virtual void mtuResponse(const uint16_t clientMTU, const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_reply, const uint16_t serverMTU, const uint16_t usedMTU, const BTDeviceRef &serverReplier, const BTDeviceRef &clientRequester)
Informal notification about a complete MTU exchange request and response to and from this GATTRole::S...
virtual void readResponse(const uint16_t handle, const uint16_t value_offset, const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_reply, const jau::TROOctets &data_reply, const BTDeviceRef &serverReplier, const BTDeviceRef &clientRequester)
Informal notification about a complete read request and response to and from this GATTRole::Server,...
virtual void indicationReceived(const BTDeviceRef &, const uint16_t charHandle, const jau::TROOctets &charValue, const uint64_t timestamp, const bool confirmationSent)=0
Called from native BLE stack, initiated by a received indication.
virtual void writeRequest(const uint16_t handle, const jau::TROOctets &data, const jau::darray< Section > &sections, const bool with_response, const BTDeviceRef &serverDest, const BTDeviceRef &clientSource)
Informal notification about a completed write request sent to this GATTRole::Server,...
virtual void requestSent(const AttPDUMsg &pduRequest, const BTDeviceRef &serverDest, const BTDeviceRef &clientSource)
Informal low-level notification of AttPDUMsg requests to this GATTRole::Server, optional.
A thread safe GATT handler associated to one device via one L2CAP connection.
bool readDescriptorValue(BTGattDesc &cd, ssize_type expectedLength=-1) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.1 Read Characteristic Descriptor.
bool disconnect(const bool disconnect_device, const bool ioerr_cause) noexcept
Disconnect this BTGattHandler and optionally the associated device.
bool send(const AttPDUMsg &msg) noexcept
Sends the given AttPDUMsg to the connected device via l2cap.
BTDeviceRef getDeviceUnchecked() const noexcept
const int32_t supervision_timeout
Supervison timeout of the connection.
bool writeValue(const uint16_t handle, const jau::TROOctets &value, const bool withResponse) noexcept
Generic write GATT value and long value.
void notifyNativeReplyReceived(const AttPDUMsg &pduReply, const BTDeviceRef &clientDest) noexcept
Notify all NativeGattCharListener about a low-level AttPDUMsg reply being received from this GATTRole...
bool addCharListener(const BTGattCharListenerRef &l) noexcept
Add the given listener to the list if not already present.
bool getSendIndicationConfirmation() noexcept
Returns whether sending an immediate confirmation for received indication events from the device is e...
void notifyNativeMTUResponse(const uint16_t clientMTU, const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_reply, const uint16_t serverMTU, const uint16_t usedMTU, const BTDeviceRef &clientRequester) noexcept
Notify all NativeGattCharListener about a completed MTU exchange request and response to and from thi...
uint16_t getUsedMTU() const noexcept
std::string toString() const noexcept
void setUsedMTU(const uint16_t mtu) noexcept
GattServiceList_t & getServices() noexcept
Returns a reference of the internal kept BTGattService list.
bool readValue(const uint16_t handle, jau::POctets &res, ssize_type expectedLength=-1) noexcept
Generic read GATT value and long value.
bool writeCharacteristicValueNoResp(const BTGattChar &c, const jau::TROOctets &value) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.1 Write Characteristic Value Without Response.
void setSendIndicationConfirmation(const bool v) noexcept
Enable or disable sending an immediate confirmation for received indication events from the device.
bool readCharacteristicValue(const BTGattChar &c, jau::POctets &res, ssize_type expectedLength=-1) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 4.8.1 Read Characteristic Value.
uint16_t getServerMTU() const noexcept
void notifyNativeWriteResponse(const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_code, const BTDeviceRef &clientDest) noexcept
Notify all NativeGattCharListener about a write response received from this GATTRole::Server.
bool sendIndication(const uint16_t char_value_handle, const jau::TROOctets &value) noexcept
Send an indication event consisting out of the given value representing the given characteristic valu...
static constexpr uint16_t number(const Defaults d)
void notifyNativeReadResponse(const uint16_t handle, const uint16_t value_offset, const AttPDUMsg &pduReply, const AttErrorRsp::ErrorCode error_reply, const jau::TROOctets &data_reply, const BTDeviceRef &clientRequester) noexcept
Notify all NativeGattCharListener about a completed read request and response to and from this GATTRo...
bool configNotificationIndication(BTGattDesc &cd, const bool enableNotification, const bool enableIndication) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 3.3.3.3 Client Characteristic Configuration.
jau::darray< BTGattServiceRef, size_type > GattServiceList_t
const BTGattEnv & env
Environment runtime configuration, usually used internally only.
bool initClientGatt(const std::shared_ptr< BTGattHandler > &shared_this, bool &already_init) noexcept
Initialize the connection and internal data set for GATT client operations:
bool writeDescriptorValue(const BTGattDesc &cd) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 4.12.3 Write Characteristic Descriptors.
std::string getStateString() const noexcept
bool sendNotification(const uint16_t char_value_handle, const jau::TROOctets &value) noexcept
Send a notification event consisting out of the given value representing the given characteristic val...
bool hasIOError() const noexcept
const jau::fraction_i64 read_cmd_reply_timeout
Derived environment runtime configuration, usually used internally only.
size_type removeAllAssociatedCharListener(const BTGattCharRef &associatedChar) noexcept
Remove all BTGattCharListener from the list, which are associated to the given BTGattChar when added ...
bool isConnected() const noexcept
jau::darray< NativeGattCharListener::Section, size_type > NativeGattCharSections_t
jau::nsize_t getCharListenerCount() const noexcept
Return event listener count.
bool removeCharListener(const BTGattCharListenerRef &l) noexcept
Remove the given listener from the list.
bool writeCharacteristicValue(const BTGattChar &c, const jau::TROOctets &value) noexcept
BT Core Spec v5.2: Vol 3, Part G GATT: 4.9.3 Write Characteristic Value.
std::unique_ptr< const AttPDUMsg > sendWithReply(const AttPDUMsg &msg, const jau::fraction_i64 &timeout) noexcept
Sends the given AttPDUMsg to the connected device via l2cap using send().
jau::cow_darray< NativeGattCharListenerRef, size_type > NativeGattCharListenerList_t
std::shared_ptr< GattGenericAccessSvc > getGenericAccess() noexcept
Returns the internal kept shared GattGenericAccessSvc instance.
BTGattCharRef findCharacterisicsByValueHandle(const GattServiceList_t &services_, const uint16_t charValueHandle) noexcept
Find and return the BTGattChar within given list of primary services via given characteristic value h...
bool ping() noexcept
Issues a ping to the device, validating whether it is still reachable.
std::shared_ptr< NativeGattCharListener > NativeGattCharListenerRef
BTDeviceRef getDeviceChecked() const
size_type removeAllCharListener() noexcept
Remove all event listener from the list.
std::shared_ptr< GattDeviceInformationSvc > getDeviceInformation(GattServiceList_t &primServices) noexcept
void printCharListener() noexcept
Print a list of all BTGattCharListener and NativeGattCharListener.
void notifyNativeRequestSent(const AttPDUMsg &pduRequest, const BTDeviceRef &clientSource) noexcept
Notify all NativeGattCharListener about a low-level AttPDUMsg request being sent to this GATTRole::Se...
void notifyNativeWriteRequest(const uint16_t handle, const jau::TROOctets &data, const NativeGattCharSections_t &sections, const bool with_response, const BTDeviceRef &clientSource) noexcept
Notify all NativeGattCharListener about a completed write request sent to this GATTRole::Server.
GATTRole getRole() const noexcept
Return the local GATTRole to the remote BTDevice.
const jau::fraction_i64 write_cmd_reply_timeout
Derived environment runtime configuration, usually used internally only.
Mode
Operating mode of a DBGattServer instance.
Device Information is a GATT service.
Generic Access Service is a mandatory GATT service all peripherals are required to implement.
L2CAP read/write communication channel to remote device.
Definition: L2CAPComm.hpp:195
Persistent endian aware octet data, i.e.
Definition: octets.hpp:560
Transient read only and endian aware octet data, i.e.
Definition: octets.hpp:67
bool(* equal_comparator)(const value_type &a, const value_type &b)
Generic value_type equal comparator to be user defined for e.g.
Definition: cow_darray.hpp:989
Implementation of a dynamic linear array storage, aka vector.
Definition: darray.hpp:148
Ring buffer implementation, a.k.a circular buffer, exposing lock-free get*(..) and put*(....
Definition: ringbuffer.hpp:182
Base jau environment class, merely to tag all environment settings by inheritance and hence documenta...
Definition: environment.hpp:57
Service runner, a reusable dedicated thread performing custom user services.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::shared_ptr< BTGattHandler > BTGattHandlerRef
Definition: BTGattChar.hpp:61
std::shared_ptr< BTDevice > BTDeviceRef
Definition: BTDevice.hpp:1347
GATTRole
Bluetooth GATT roles.
Definition: BTTypes0.hpp:96
std::shared_ptr< BTGattCharListener > BTGattCharListenerRef
Definition: BTGattChar.hpp:70
std::shared_ptr< BTGattChar > BTGattCharRef
Definition: BTGattChar.hpp:410
std::shared_ptr< BTGattService > BTGattServiceRef
Definition: BTGattChar.hpp:67
std::shared_ptr< DBGattServer > DBGattServerRef
std::shared_ptr< DBGattChar > DBGattCharRef
fraction< int64_t > fraction_i64
fraction using int64_t as integral type
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
int_fast32_t snsize_t
Natural 'ssize_t' alternative using int_fast32_t as its natural sized type.
Definition: int_types.hpp:65
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition: backtrace.hpp:32
STL namespace.