Dokit
Internal development documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Pages
deviceinfoservice.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2022-2025 Paul Colby <git@colby.id.au>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4/*!
5 * \file
6 * Defines the DeviceInfoService and DeviceInfoServicePrivate classes.
7 */
8
10#include "deviceinfoservice_p.h"
11#include "../stringliterals_p.h"
12
13#include <QtEndian>
14
17
18/*!
19 * \class DeviceInfoService
20 *
21 * The DeviceInfoService class accesses the `Device Info` service of Pokit devices.
22 */
23
24/*!
25 * Constructs a new Pokit service with \a parent.
26 */
28 : AbstractPokitService(new DeviceInfoServicePrivate(controller, this), parent)
29{
30
31}
32
33/*!
34 * \cond internal
35 * Constructs a new Pokit service with \a parent, and private implementation \a d.
36 */
38 DeviceInfoServicePrivate * const d, QObject * const parent)
39 : AbstractPokitService(d, parent)
40{
41
42}
43/// \endcond
44
46{
47 const bool r1 = readFirmwareRevisionCharacteristic();
48 const bool r2 = readHardwareRevisionCharacteristic();
49 const bool r3 = readSoftwareRevisionCharacteristic();
50 const bool r4 = readManufacturerCharacteristics();
51 const bool r5 = readModelNumberCharacteristic();
52 const bool r6 = ((service() != nullptr) && (service()->characteristic(CharacteristicUuids::serialNumber).isValid()))
54 return (r1 && r2 && r3 && r4 && r5 && r6);
55}
56
57/*!
58 * Read the `Device Info` service's `Firmware Revision` characteristic.
59 *
60 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
61 * underlying controller it not yet connected to the Pokit device, or the device's services have
62 * not yet been discovered).
63 *
64 * Emits firmwareRevisionRead() if/when the characteristic has been read successfully.
65 */
71
72/*!
73 * Read the `Device Info` service's `Hardware Revision` characteristic.
74 *
75 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
76 * underlying controller it not yet connected to the Pokit device, or the device's services have
77 * not yet been discovered).
78 *
79 * Emits hardwareRevisionRead() if/when the characteristic has been read successfully.
80 */
86
87/*!
88 * Read the `Device Info` service's `Manufacturer Name` characteristic.
89 *
90 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
91 * underlying controller it not yet connected to the Pokit device, or the device's services have
92 * not yet been discovered).
93 *
94 * Emits manufacturerNameRead() if/when the characteristic has been read successfully.
95 */
101
102/*!
103 * Read the `Device Info` service's `Model Number` characteristic.
104 *
105 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
106 * underlying controller it not yet connected to the Pokit device, or the device's services have
107 * not yet been discovered).
108 *
109 * Emits modelNumberRead() if/when the characteristic has been read successfully.
110 */
116
117/*!
118 * Read the `Device Info` service's `Software Revision` characteristic.
119 *
120 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
121 * underlying controller it not yet connected to the Pokit device, or the device's services have
122 * not yet been discovered).
123 *
124 * Emits softwareRevisionRead() if/when the characteristic has been read successfully.
125 */
131
132/*!
133 * Read the `Device Info` service's (undocumented) `Serial Number` characteristic.
134 *
135 * Returns `true` is the read request is successfully queued, `false` otherwise (ie if the
136 * underlying controller it not yet connected to the Pokit device, or the device's services have
137 * not yet been discovered).
138 *
139 * Emits serialNumberRead() if/when the characteristic has been read successfully.
140 */
146
147/*!
148 * Returns the most recent value of the `Device Info` service's `Manufacturer Name` characteristic.
149 *
150 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
151 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
152 * null QString is returned.
153 */
155{
156 Q_D(const DeviceInfoService);
157 const QLowEnergyCharacteristic characteristic =
158 d->getCharacteristic(CharacteristicUuids::manufacturerName);
159 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
160}
161
162/*!
163 * Returns the most recent value of the `Device Info` service's `Model Number` characteristic.
164 *
165 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
166 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
167 * null QString is returned.
168 */
170{
171 Q_D(const DeviceInfoService);
172 const QLowEnergyCharacteristic characteristic =
173 d->getCharacteristic(CharacteristicUuids::modelNumber);
174 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
175}
176
177/*!
178 * Returns the most recent value of the `Device Info` service's `Hardware Revision` characteristic.
179 *
180 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
181 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
182 * null QString is returned.
183 */
185{
186 Q_D(const DeviceInfoService);
187 const QLowEnergyCharacteristic characteristic =
188 d->getCharacteristic(CharacteristicUuids::hardwareRevision);
189 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
190}
191
192/*!
193 * Returns the most recent value of the `Device Info` service's `Firmware Revision` characteristic.
194 *
195 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
196 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
197 * null QString is returned.
198 */
200{
201 Q_D(const DeviceInfoService);
202 const QLowEnergyCharacteristic characteristic =
203 d->getCharacteristic(CharacteristicUuids::firmwareRevision);
204 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
205}
206
207/*!
208 * Returns the most recent value of the `Device Info` service's `Software Revision` characteristic.
209 *
210 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
211 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
212 * null QString is returned.
213 */
215{
216 Q_D(const DeviceInfoService);
217 const QLowEnergyCharacteristic characteristic =
218 d->getCharacteristic(CharacteristicUuids::softwareRevision);
219 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
220}
221
222/*!
223 * Returns the most recent value of the `Device Info` service's (undocumented) `Serial Number`
224 * characteristic.
225 *
226 * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
227 * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
228 * null QString is returned.
229 */
231{
232 Q_D(const DeviceInfoService);
233 const QLowEnergyCharacteristic characteristic =
234 d->getCharacteristic(CharacteristicUuids::serialNumber);
235 /*!
236 * \cond internal
237 * \pokitApi Unlike other string characteristics, Pokit (Pro) devices always appear to add a trailing
238 * `null` byte to serial number strings. So here we strip any that are present.
239 * \endcond
240 */
241 return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()).remove('\0'_L1) : QString();
242}
243
244/*!
245 * \fn DeviceInfoService::manufacturerRead
246 *
247 * This signal is emitted when the `Manufacturer Name` characteristic has been read successfully.
248 *
249 * \see readManufacturerCharacteristic
250 * \see manufacturer
251 */
252
253/*!
254 * \fn DeviceInfoService::modelNumberRead
255 *
256 * This signal is emitted when the `Model Number` characteristic has been read successfully.
257 *
258 * \see readModelNumberCharacteristic
259 * \see modelNumber
260 */
261
262/*!
263 * \fn DeviceInfoService::hardwareRevisionRead
264 *
265 * This signal is emitted when the `Hardware Revision` characteristic has been read successfully.
266 *
267 * \see readHardwareRevisionCharacteristic
268 * \see hardwareRevision
269 */
270
271/*!
272 * \fn DeviceInfoService::firmwareRevisionRead
273 *
274 * This signal is emitted when the `Firmware Revision` characteristic has been read successfully.
275 *
276 * \see readFirmwareRevisionCharacteristic
277 * \see firmwareRevision
278 */
279
280/*!
281 * \fn DeviceInfoService::softwareRevisionRead
282 *
283 * This signal is emitted when the `Software Revision` characteristic has been read successfully.
284 *
285 * \see readSoftwareRevisionCharacteristic
286 * \see softwareRevision
287 */
288
289/*!
290 * \fn DeviceInfoService::serialNumberRead
291 *
292 * This signal is emitted when the `Serial Number` characteristic has been read successfully.
293 *
294 * \see readSerialNumberCharacteristic
295 * \see serialNumber
296 */
297
298/*!
299 * \cond internal
300 * \class DeviceInfoServicePrivate
301 *
302 * The DeviceInfoServicePrivate class provides private implementation for DeviceInfoService.
303 */
304
305/*!
306 * \internal
307 * Constructs a new DeviceInfoServicePrivate object with public implementation \a q.
308 */
315
316/*!
317 * Implements AbstractPokitServicePrivate::characteristicRead to parse \a value, then emit a
318 * specialised signal, for each supported \a characteristic.
319 */
321 const QByteArray &value)
322{
324
327 const QString name = QString::fromUtf8(value);
328 qCDebug(lc).noquote() << tr(R"(Manufacturer name: "%1")").arg(name);
329 Q_EMIT q->manufacturerRead(name);
330 return;
331 }
332
334 const QString model = QString::fromUtf8(value);
335 qCDebug(lc).noquote() << tr(R"(Model number: "%1")").arg(model);
336 Q_EMIT q->modelNumberRead(model);
337 return;
338 }
339
341 const QString revision = QString::fromUtf8(value);
342 qCDebug(lc).noquote() << tr(R"(Hardware revision: "%1")").arg(revision);
343 Q_EMIT q->hardwareRevisionRead(revision);
344 return;
345 }
346
348 const QString revision = QString::fromUtf8(value);
349 qCDebug(lc).noquote() << tr(R"(Firmware revision: "%1")").arg(revision);
350 Q_EMIT q->firmwareRevisionRead(revision);
351 return;
352 }
353
355 const QString revision = QString::fromUtf8(value);
356 qCDebug(lc).noquote() << tr(R"(Software revision: "%1")").arg(revision);
357 Q_EMIT q->softwareRevisionRead(revision);
358 return;
359 }
360
362 const QString serialNumber = QString::fromUtf8(value);
363 qCDebug(lc).noquote() << tr(R"(Serial number: "%1")").arg(serialNumber);
364 Q_EMIT q->serialNumberRead(serialNumber);
365 return;
366 }
367
368 qCWarning(lc).noquote() << tr("Unknown characteristic read for Device Info service")
369 << serviceUuid << characteristic.name() << characteristic.uuid();
370}
371
372/// \endcond
373
QBluetoothUuid serviceUuid
UUIDs for service.
AbstractPokitServicePrivate(const QBluetoothUuid &serviceUuid, QLowEnergyController *controller, AbstractPokitService *const q)
virtual void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
Handles QLowEnergyService::characteristicRead events.
QLowEnergyController * controller
BLE controller to fetch the service from.
QLowEnergyService * service()
Returns a non-const pointer to the internal service object, if any.
The DeviceInfoServicePrivate class provides private implementation for DeviceInfoService.
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) override
Implements AbstractPokitServicePrivate::characteristicRead to parse value, then emit a specialised si...
DeviceInfoServicePrivate(QLowEnergyController *controller, DeviceInfoService *const q)
The DeviceInfoService class accesses the Device Info service of Pokit devices.
QString serialNumber() const
Returns the most recent value of the Device Info service's (undocumented) Serial Number characteristi...
bool readSerialNumberCharacteristic()
Read the Device Info service's (undocumented) Serial Number characteristic.
bool readHardwareRevisionCharacteristic()
Read the Device Info service's Hardware Revision characteristic.
bool readSoftwareRevisionCharacteristic()
Read the Device Info service's Software Revision characteristic.
QString softwareRevision() const
Returns the most recent value of the Device Info service's Software Revision characteristic.
bool readFirmwareRevisionCharacteristic()
Read the Device Info service's Firmware Revision characteristic.
QString hardwareRevision() const
Returns the most recent value of the Device Info service's Hardware Revision characteristic.
bool readManufacturerCharacteristics()
Read the Device Info service's Manufacturer Name characteristic.
QString modelNumber() const
Returns the most recent value of the Device Info service's Model Number characteristic.
bool readModelNumberCharacteristic()
Read the Device Info service's Model Number characteristic.
bool readCharacteristics() override
Read all characteristics.
QString manufacturer() const
Returns the most recent value of the Device Info service's Manufacturer Name characteristic.
QString firmwareRevision() const
Returns the most recent value of the Device Info service's Firmware Revision characteristic.
DeviceInfoService(QLowEnergyController *const pokitDevice, QObject *parent=nullptr)
Constructs a new Pokit service with parent.
Declares the DeviceInfoService class.
Declares the DeviceInfoServicePrivate class.
bool isValid() const const
QString name() const const
QBluetoothUuid uuid() const const
QByteArray value() const const
QLowEnergyCharacteristic characteristic(const QBluetoothUuid &uuid) const const
QObject(QObject *parent)
Q_EMITQ_EMIT
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromUtf8(const char *str, int size)
QString & remove(int position, int n)
#define QTPOKIT_BEGIN_NAMESPACE
Macro for starting the QtPokit library's top-most namespace (if one is defined).
#define QTPOKIT_END_NAMESPACE
Macro for ending the QtPokit library's top-most namespace (if one is defined).
Declares the DOKIT_USE_STRINGLITERALS macro, and related functions.
#define DOKIT_USE_STRINGLITERALS
Internal macro for using either official Qt string literals (added in Qt 6.4), or our own equivalent ...
static const QBluetoothUuid manufacturerName
UUID of the Device Info service's Manufacturer Name String characteristic.
static const QBluetoothUuid hardwareRevision
UUID of the Device Info service's Hardware Revision String characteristic.
static const QBluetoothUuid softwareRevision
UUID of the Device Info service's Software Revision String characteristic.
static const QBluetoothUuid serialNumber
UUID of the Device Info service's Serial Number String characteristic.
static const QBluetoothUuid firmwareRevision
UUID of the Device Info service's Firmware Revision String characteristic.
static const QBluetoothUuid modelNumber
UUID of the Device Info service's Model Number String characteristic.