Direct-BT v3.3.0-1-gc2d430c
Direct-BT - Direct Bluetooth Programming.
GATTNumbers.cpp
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#include <cstring>
27#include <string>
28#include <memory>
29#include <cstdint>
30#include <cstdio>
31
32#include <algorithm>
33
34#include <jau/darray.hpp>
35#include <jau/debug.hpp>
36
37#include "GattNumbers.hpp"
38
39using namespace direct_bt;
40
41#if defined(DIRECTBT_BUILDIN_GATT_SERVICE_CHARACTERISTIC_SPEC)
42
43
44#if 0
45// Testing jau::make_darray compliance ..
46struct Lala0 { int a; int b; };
47
50 GCPS{ Read, Mandatory },
51 GCPS{ Notify, Excluded } );
52
55 Lala0{ 0, 1 },
56 Lala0{ 1, 2 } );
57
60 GCPS{ Read, Mandatory },
61 Lala0{ 1, 2 } );
62#endif
63
64typedef GattCharacteristicSpec GCS;
66
67/** https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.generic_access.xml */
69 jau::make_darray( // GattCharacteristicSpec
71 // jau::make_darray<GattCharacteristicPropertySpec, GattCharacteristicPropertySpec...>( // GattCharacteristicPropertySpec [9]:
72 jau::make_darray( // GattCharacteristicPropertySpec [9]:
73 GCPS{ Read, Mandatory },
75 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
76 // GattClientCharacteristicConfigSpec:
78 },
80 jau::make_darray( // [9]:
81 GCPS{ Read, Mandatory },
83 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
84 // GattClientCharacteristicConfigSpec:
86 },
88 jau::make_darray( // [9]:
89 GCPS{ Read, Mandatory },
91 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
92 // GattClientCharacteristicConfigSpec:
94 },
96 jau::make_darray( // [9]:
97 GCPS{ Read, Excluded },
99 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
100 // GattClientCharacteristicConfigSpec:
102 },
104 jau::make_darray( // [9]:
105 GCPS{ Read, Mandatory },
107 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
108 // GattClientCharacteristicConfigSpec:
110 }
111 ) };
112
113/** https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org.bluetooth.service.health_thermometer.xml */
115 jau::make_darray( // GattCharacteristicSpec
117 jau::make_darray( // [9]:
118 GCPS{ Read, Excluded },
120 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
121 // GattClientCharacteristicConfigSpec:
123 },
125 jau::make_darray( // [9]:
126 GCPS{ Read, Mandatory },
128 GCPS{ Notify, Excluded }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
129 // GattClientCharacteristicConfigSpec:
131 },
133 jau::make_darray( // [9]:
134 GCPS{ Read, Excluded },
136 GCPS{ Notify, Mandatory }, GCPS{ Indicate, Excluded }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
137 // GattClientCharacteristicConfigSpec:
139 },
141 jau::make_darray( // [9]:
142 GCPS{ Read, Mandatory },
144 GCPS{ Notify, Excluded }, GCPS{ Indicate, Optional }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
145 // GattClientCharacteristicConfigSpec:
147 }
148 ) };
149
151 jau::make_darray( // GattCharacteristicSpec
153 jau::make_darray( // [9]:
154 GCPS{ Read, Mandatory },
156 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
157 // GattClientCharacteristicConfigSpec:
159 },
161 jau::make_darray( // [9]:
162 GCPS{ Read, Mandatory },
164 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
165 // GattClientCharacteristicConfigSpec:
167 },
169 jau::make_darray( // [9]:
170 GCPS{ Read, Mandatory },
172 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
173 // GattClientCharacteristicConfigSpec:
175 },
177 jau::make_darray( // [9]:
178 GCPS{ Read, Mandatory },
180 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
181 // GattClientCharacteristicConfigSpec:
183 },
185 jau::make_darray( // [9]:
186 GCPS{ Read, Mandatory },
188 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
189 // GattClientCharacteristicConfigSpec:
191 },
193 jau::make_darray( // [9]:
194 GCPS{ Read, Mandatory },
196 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
197 // GattClientCharacteristicConfigSpec:
199 },
200 GCS{ SYSTEM_ID, Optional,
201 jau::make_darray( // [9]:
202 GCPS{ Read, Mandatory },
204 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
205 // GattClientCharacteristicConfigSpec:
207 },
209 jau::make_darray( // [9]:
210 GCPS{ Read, Mandatory },
212 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
213 // GattClientCharacteristicConfigSpec:
215 },
216 GCS{ PNP_ID, Optional,
217 jau::make_darray( // [9]:
218 GCPS{ Read, Mandatory },
220 GCPS{ Notify, Excluded }, GCPS{ Indicate, Mandatory }, GCPS{ AuxWriteExt, Excluded }, GCPS{ Broadcast, Excluded } ),
221 // GattClientCharacteristicConfigSpec:
223 }
224 ) };
225
228
229const GattServiceCharacteristic * direct_bt::findGattServiceChar(const uint16_t uuid16) noexcept {
230 for(size_t i=0; i<GATT_SERVICES.size(); i++) {
231 const GattServiceCharacteristic & serviceChar = *GATT_SERVICES.at(i);
232 if( uuid16 == serviceChar.service ) {
233 return &serviceChar;
234 }
235 for(size_t j=0; j<serviceChar.characteristics.size(); j++) {
236 const GattCharacteristicSpec & charSpec = serviceChar.characteristics.at(i);
237 if( uuid16 == charSpec.characteristic ) {
238 return &serviceChar;
239 }
240 }
241 }
242 return nullptr;
243}
244
245const GattCharacteristicSpec * direct_bt::findGattCharSpec(const uint16_t uuid16) noexcept {
246 for(size_t i=0; i<GATT_SERVICES.size(); i++) {
247 const GattServiceCharacteristic & serviceChar = *GATT_SERVICES.at(i);
248 for(size_t j=0; j<serviceChar.characteristics.size(); j++) {
249 const GattCharacteristicSpec & charSpec = serviceChar.characteristics.at(i);
250 if( uuid16 == charSpec.characteristic ) {
251 return &charSpec;
252 }
253 }
254 }
255 return nullptr;
256}
257
258#endif /* DIRECTBT_BUILDIN_GATT_SERVICE_CHARACTERISTIC_SPEC */
259
260#define CASE_TO_STRING(V) case V: return #V;
261
262#define SERVICE_TYPE_ENUM(X) \
263 X(GENERIC_ACCESS) \
264 X(HEALTH_THERMOMETER) \
265 X(DEVICE_INFORMATION) \
266 X(BATTERY_SERVICE)
267
269 switch(v) {
271 default: ; // fall through intended
272 }
273 return "Unknown";
274}
275
276#define CHARACTERISTIC_TYPE_ENUM(X) \
277 X(DEVICE_NAME) \
278 X(APPEARANCE) \
279 X(PERIPHERAL_PRIVACY_FLAG) \
280 X(RECONNECTION_ADDRESS) \
281 X(PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS) \
282 X(TEMPERATURE) \
283 X(TEMPERATURE_CELSIUS) \
284 X(TEMPERATURE_FAHRENHEIT) \
285 X(TEMPERATURE_MEASUREMENT) \
286 X(TEMPERATURE_TYPE) \
287 X(INTERMEDIATE_TEMPERATURE) \
288 X(MEASUREMENT_INTERVAL) \
289 X(SYSTEM_ID) \
290 X(MODEL_NUMBER_STRING) \
291 X(SERIAL_NUMBER_STRING) \
292 X(FIRMWARE_REVISION_STRING) \
293 X(HARDWARE_REVISION_STRING) \
294 X(SOFTWARE_REVISION_STRING) \
295 X(MANUFACTURER_NAME_STRING) \
296 X(REGULATORY_CERT_DATA_LIST) \
297 X(PNP_ID)
298
299
301 switch(v) {
303 default: ; // fall through intended
304 }
305 return "Unknown";
306}
307
308#define CHARACTERISTIC_PROP_ENUM(X) \
309 X(Broadcast) \
310 X(Read) \
311 X(WriteNoAck) \
312 X(WriteWithAck) \
313 X(Notify) \
314 X(Indicate) \
315 X(AuthSignedWrite) \
316 X(ExtProps) \
317 X(ReliableWriteExt) \
318 X(AuxWriteExt)
319
321 switch(v) {
323 default: ; // fall through intended
324 }
325 return "Unknown";
326}
327
328#define REQUIREMENT_SPEC_ENUM(X) \
329 X(Excluded) \
330 X(Mandatory) \
331 X(Optional) \
332 X(Conditional) \
333 X(if_characteristic_supported) \
334 X(if_notify_or_indicate_supported) \
335 X(C1)
336
338 switch(v) {
340 default: ; // fall through intended
341 }
342 return "Unknown";
343}
344
345std::string GattCharacteristicPropertySpec::toString() const noexcept {
347}
348
350 return "ClientCharCfg["+GattRequirementSpecToString(requirement)+"["+read.toString()+", "+writeWithAck.toString()+"]]";
351}
352
353std::string GattCharacteristicSpec::toString() const noexcept {
355 for(size_t i=0; i<propertySpec.size(); i++) {
356 if(0<i) {
357 res += ", ";
358 }
359 res += propertySpec.at(i).toString();
360 }
361 res += "], "+clientConfig.toString();
362 return res;
363}
364
365std::string GattServiceCharacteristic::toString() const noexcept {
366 std::string res = GattServiceTypeToString(service)+": [";
367 for(size_t i=0; i<characteristics.size(); i++) {
368 if(0<i) {
369 res += ", ";
370 }
371 res.append("[").append(characteristics.at(i).toString()).append("]");
372 }
373 res += "]";
374 return res;
375}
376
377/********************************************************/
378/********************************************************/
379/********************************************************/
380
381std::string direct_bt::GattNameToString(const jau::TROOctets &v) noexcept {
382 const jau::nsize_t str_len = v.size();
383 if( 0 == str_len ) {
384 return std::string(); // empty
385 }
386 jau::POctets s(str_len+1, jau::lb_endian_t::little); // dtor releases chunk
387 {
388 // Prelim checking to avoid g++ 8.3 showing a warning: pointer overflow between offset 0 and size
389 uint8_t const * const v_p = v.get_ptr();
390 if( nullptr == v_p ) {
391 return std::string(); // emptylb_lb_lb_
392 }
393 uint8_t * const s_p = s.get_wptr();
394 if( nullptr == s_p ) {
395 return std::string(); // empty
396 }
397 memcpy(s_p, v_p, str_len);
398 }
399 s.put_uint8_nc(str_len, 0); // EOS
400 return std::string((const char*)s.get_ptr());
401}
402
404: minConnectionInterval(source.get_uint16(0)), maxConnectionInterval(source.get_uint16(2)),
405 slaveLatency(source.get_uint16(4)), connectionSupervisionTimeoutMultiplier(source.get_uint16(6))
406{
407}
408
409std::shared_ptr<GattPeriphalPreferredConnectionParameters> GattPeriphalPreferredConnectionParameters::get(const jau::TROOctets &source) noexcept {
410 const jau::nsize_t reqSize = 8;
411 if( source.size() < reqSize ) {
412 ERR_PRINT("GattPeriphalPreferredConnectionParameters: Insufficient data, less than %d bytes in %s", reqSize, source.toString().c_str());
413 return nullptr;
414 }
415 return std::make_shared<GattPeriphalPreferredConnectionParameters>(source);
416}
417
419 return "PrefConnectionParam[interval["+
421 "], slaveLatency "+std::to_string(slaveLatency)+
423}
424
425std::string GattGenericAccessSvc::toString() const noexcept {
426 std::string pcp(nullptr != prefConnParam ? prefConnParam->toString() : "");
427 return "'"+deviceName+"'[appearance "+jau::to_hexstring(static_cast<uint16_t>(appearance))+" ("+to_string(appearance)+"), "+pcp+"]";
428}
429
431: vendor_id_source(source.get_uint8(0)), vendor_id(source.get_uint16(1)),
432 product_id(source.get_uint16(3)), product_version(source.get_uint16(5)) {}
433
434std::shared_ptr<GattPnP_ID> GattPnP_ID::get(const jau::TROOctets &source) noexcept {
435 const jau::nsize_t reqSize = 7;
436 if( source.size() < reqSize ) {
437 ERR_PRINT("GattPnP_ID: Insufficient data, less than %d bytes in %s", reqSize, source.toString().c_str());
438 return nullptr;
439 }
440 return std::make_shared<GattPnP_ID>(source);
441}
442
443std::string GattPnP_ID::toString() const noexcept {
444 return "vendor_id[source "+jau::to_hexstring(vendor_id_source)+
446 "], product_id "+jau::to_hexstring(product_id)+
447 ", product_version "+jau::to_hexstring(product_version);
448}
449
450std::string GattDeviceInformationSvc::toString() const noexcept {
451 std::string pnp(nullptr != pnpID ? pnpID->toString() : "");
452 return "DeviceInfo[manufacturer '"+manufacturer+"', model '"+modelNumber+"', serial '"+serialNumber+"', systemID '"+systemID.toString()+
453 "', revisions[firmware '"+firmwareRevision+"', hardware '"+hardwareRevision+"', software '"+softwareRevision+
454 "'], pnpID["+pnp+"], regCertData '"+regulatoryCertDataList.toString()+"']";
455}
456
457std::shared_ptr<GattTemperatureMeasurement> GattTemperatureMeasurement::get(const jau::TROOctets &source) noexcept {
458 const jau::nsize_t size = source.size();
459 jau::nsize_t reqSize = 1 + 4; // max size = 13
460 if( reqSize > size ) {
461 // min size: flags + temperatureValue
462 ERR_PRINT("GattTemperatureMeasurement: Insufficient data, less than %d bytes in %s", reqSize, source.toString().c_str());
463 return nullptr;
464 }
465
466 uint8_t flags = source.get_uint8(0);
467 bool hasTimestamp = 0 != ( flags & Bits::HAS_TIMESTAMP );
468 if( hasTimestamp ) {
469 reqSize += 7;
470 }
471 bool hasTemperatureType = 0 != ( flags & Bits::HAS_TEMP_TYPE );
472 if( hasTemperatureType ) {
473 reqSize += 1;
474 }
475 if( reqSize > size ) {
476 return nullptr;
477 }
478
479 uint32_t raw_temp_value = source.get_uint32(1);
480 float temperatureValue = ieee11073::FloatTypes::float32_IEEE11073_to_IEEE754(raw_temp_value);
481
482 /** Timestamp, if HAS_TIMESTAMP is set. */
483 ieee11073::AbsoluteTime timestamp;
484 if( hasTemperatureType ) {
485 timestamp = ieee11073::AbsoluteTime(source.get_ptr(1+4), 7);
486 }
487
488 /** Temperature Type, if HAS_TEMP_TYPE is set: Format ???? */
489 uint8_t temperature_type=0;
490 if( hasTemperatureType ) {
491 temperature_type = source.get_uint8(1+4+7);
492 }
493 return std::make_shared<GattTemperatureMeasurement>(flags, temperatureValue, timestamp, temperature_type);
494}
495
496std::string GattTemperatureMeasurement::toString() const noexcept {
497 std::string res = std::to_string(temperatureValue);
498 res += isFahrenheit() ? " F" : " C";
499 if( hasTimestamp() ) {
500 res += ", "+timestamp.toString();
501 }
502 if( hasTemperatureType() ) {
503 res += ", type "+std::to_string(temperature_type);
504 }
505 return res;
506}
#define CASE_TO_STRING(V)
#define CHARACTERISTIC_TYPE_ENUM(X)
#define CHARACTERISTIC_PROP_ENUM(X)
#define SERVICE_TYPE_ENUM(X)
#define REQUIREMENT_SPEC_ENUM(X)
std::string toString() const noexcept
const std::string serialNumber
Optional.
const std::string firmwareRevision
Optional.
const std::string softwareRevision
Optional.
const std::shared_ptr< GattPnP_ID > pnpID
Optional.
const jau::POctets regulatoryCertDataList
Optional.
const jau::POctets systemID
Optional.
const std::string modelNumber
Optional.
const std::string manufacturer
Optional.
const std::string hardwareRevision
Optional.
const AppearanceCat appearance
Characteristic: Mandatory [Read: Mandatory; Write: Excluded; ...].
const std::string deviceName
Characteristic: Mandatory [Read: Mandatory; Write: Optional; ...].
const std::shared_ptr< GattPeriphalPreferredConnectionParameters > prefConnParam
Characteristic: Optional [Read: Mandatory; Write: Excluded; ...].
std::string toString() const noexcept
static std::shared_ptr< GattTemperatureMeasurement > get(const jau::TROOctets &source) noexcept
const ieee11073::AbsoluteTime timestamp
Timestamp, if HAS_TIMESTAMP is set.
std::string toString() const noexcept
const uint8_t temperature_type
Temperature Type, if HAS_TEMP_TYPE is set: Format ????.
bool hasTemperatureType() const noexcept
const float temperatureValue
In Celsius if IS_TEMP_FAHRENHEIT is set, otherwise Fahrenheit.
date / timestamp format
Definition: DataTypes.hpp:72
std::string toString() const
Definition: DataTypes.cpp:60
static float float32_IEEE11073_to_IEEE754(const uint32_t raw_bt_float32_le)
Converts a 'IEEE-11073 32-bit FLOAT' to std IEEE754 float.
Definition: DataTypes.cpp:99
Persistent endian aware octet data, i.e.
Definition: octets.hpp:560
std::string toString() const
Definition: octets.hpp:932
constexpr void put_uint8_nc(const nsize_t i, const uint8_t v) noexcept
Definition: octets.hpp:335
uint8_t * get_wptr() noexcept
Definition: octets.hpp:474
Transient read only and endian aware octet data, i.e.
Definition: octets.hpp:67
constexpr uint8_t const * get_ptr() const noexcept
Definition: octets.hpp:272
constexpr size_type size() const noexcept
Like std::vector::size().
Definition: darray.hpp:763
const_reference at(size_type i) const
Like std::vector::at(size_type), immutable reference.
Definition: darray.hpp:814
#define ERR_PRINT(...)
Use for unconditional error messages, prefix '[elapsed_time] Error @ FILE:LINE FUNC: '.
Definition: debug.hpp:109
@ little
Identifier for little endian, equivalent to endian::little.
std::string to_string(const alphabet &v) noexcept
Definition: base_codec.hpp:97
std::string GattRequirementSpecToString(const GattRequirementSpec v) noexcept
std::string GattNameToString(const jau::TROOctets &v) noexcept
Converts a GATT Name (not null-terminated) UTF8 to a null-terminated C++ string.
std::string to_string(const DiscoveryPolicy v) noexcept
Definition: BTAdapter.cpp:58
GattCharacteristicProperty
std::string GattCharacteristicTypeToString(const GattCharacteristicType v) noexcept
std::string GattCharacteristicPropertyToString(const GattCharacteristicProperty v) noexcept
std::string GattServiceTypeToString(const GattServiceType v) noexcept
GattServiceType
GATT Service Type, each encapsulating a set of Characteristics.
Definition: GattNumbers.hpp:84
GattCharacteristicType
GATT Assigned Characteristic Attribute Type for single logical value.
constexpr darray< First > make_darray(First &&arg1, Next &&... argsN)
Construct a darray<T> instance, initialized by move semantics from the variadic (template pack) argum...
Definition: darray.hpp:1373
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition: int_types.hpp:53
std::string to_hexstring(value_type const &v) noexcept
Produce a lower-case hexadecimal string representation of the given pointer.
std::string toString() const noexcept
std::string toString() const noexcept
GattCharacteristicProperty property
std::string toString() const noexcept
jau::darray< GattCharacteristicPropertySpec > propertySpec
Aggregated in PropertySpecIdx order.
GattClientCharacteristicConfigSpec clientConfig
GattCharacteristicType characteristic
std::string toString() const noexcept
GattCharacteristicPropertySpec writeWithAck
GattCharacteristicPropertySpec read
GattPeriphalPreferredConnectionParameters(const jau::TROOctets &source) noexcept
const uint16_t connectionSupervisionTimeoutMultiplier
mandatory [10..3200]
const uint16_t minConnectionInterval
mandatory [6..3200] x 1.25ms
static std::shared_ptr< GattPeriphalPreferredConnectionParameters > get(const jau::TROOctets &source) noexcept
const uint16_t maxConnectionInterval
mandatory [6..3200] x 1.25ms and >= minConnectionInterval
const uint16_t slaveLatency
mandatory [1..1000]
static std::shared_ptr< GattPnP_ID > get(const jau::TROOctets &source) noexcept
const uint16_t product_version
const uint8_t vendor_id_source
const uint16_t vendor_id
const uint16_t product_id
std::string toString() const noexcept
std::string toString() const noexcept
jau::darray< GattCharacteristicSpec > characteristics
@ GENERIC_ACCESS
This service contains generic information about the device.
@ HEALTH_THERMOMETER
This service exposes temperature and other data from a thermometer intended for healthcare and fitnes...
@ DEVICE_INFORMATION
This service exposes manufacturer and/or vendor information about a device.
const jau::darray< const GattServiceCharacteristic * > GATT_SERVICES
@ Notify
@ ReliableWriteExt
FIXME: extension?
@ Indicate
@ AuthSignedWrite
@ WriteNoAck
@ Read
@ Broadcast
@ AuxWriteExt
FIXME: extension?
@ WriteWithAck
@ Optional
@ if_characteristic_supported
@ Conditional
@ if_notify_or_indicate_supported
@ Mandatory
@ Excluded
const GattServiceCharacteristic GATT_HEALTH_THERMOMETER_SRVC
https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Services/org....
const GattServiceCharacteristic GATT_DEVICE_INFORMATION_SRVC
const GattServiceCharacteristic GATT_GENERIC_ACCESS_SRVC
@ SOFTWARE_REVISION_STRING
@ REGULATORY_CERT_DATA_LIST
@ SERIAL_NUMBER_STRING
@ MODEL_NUMBER_STRING
@ DEVICE_NAME
@ APPEARANCE
@ MANUFACTURER_NAME_STRING
@ PNP_ID
@ PERIPHERAL_PRIVACY_FLAG
@ PERIPHERAL_PREFERRED_CONNECTION_PARAMETERS
@ TEMPERATURE_MEASUREMENT
@ FIRMWARE_REVISION_STRING
@ TEMPERATURE_TYPE
Mandatory: 8bit: 1 armpit, 2 body (general), 3(ear), 4 (finger), ...
@ RECONNECTION_ADDRESS
@ SYSTEM_ID
Mandatory: uint40.
@ MEASUREMENT_INTERVAL
@ INTERMEDIATE_TEMPERATURE
@ HARDWARE_REVISION_STRING