LCOV - code coverage report
Current view: top level - src/lib - deviceinfoservice.cpp (source / functions) Coverage Total Hit
Project: Dokit Lines: 75.0 % 140 105
Version: Functions: 94.1 % 17 16

            Line data    Source code
       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              : 
       9              : #include <qtpokit/deviceinfoservice.h>
      10              : #include "deviceinfoservice_p.h"
      11              : #include "../stringliterals_p.h"
      12              : 
      13              : #include <QtEndian>
      14              : 
      15              : QTPOKIT_BEGIN_NAMESPACE
      16              : DOKIT_USE_STRINGLITERALS
      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              :  */
      27         3200 : DeviceInfoService::DeviceInfoService(QLowEnergyController * const controller, QObject * parent)
      28         4416 :     : AbstractPokitService(new DeviceInfoServicePrivate(controller, this), parent)
      29         1472 : {
      30              : 
      31         4672 : }
      32              : 
      33              : /*!
      34              :  * \cond internal
      35              :  * Constructs a new Pokit service with \a parent, and private implementation \a d.
      36              :  */
      37            0 : DeviceInfoService::DeviceInfoService(
      38            0 :     DeviceInfoServicePrivate * const d, QObject * const parent)
      39            0 :     : AbstractPokitService(d, parent)
      40            0 : {
      41              : 
      42            0 : }
      43              : /// \endcond
      44              : 
      45           80 : bool DeviceInfoService::readCharacteristics()
      46           56 : {
      47          101 :     const bool r1 = readFirmwareRevisionCharacteristic();
      48          101 :     const bool r2 = readHardwareRevisionCharacteristic();
      49          101 :     const bool r3 = readSoftwareRevisionCharacteristic();
      50          101 :     const bool r4 = readManufacturerCharacteristics();
      51          101 :     const bool r5 = readModelNumberCharacteristic();
      52          157 :     const bool r6 = ((service() != nullptr) && (service()->characteristic(CharacteristicUuids::serialNumber).isValid()))
      53          136 :         ? readSerialNumberCharacteristic() : true;
      54          157 :     return (r1 && r2 && r3 && r4 && r5 && r6);
      55           56 : }
      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              :  */
      66          125 : bool DeviceInfoService::readFirmwareRevisionCharacteristic()
      67          112 : {
      68          112 :     Q_D(DeviceInfoService);
      69          272 :     return d->readCharacteristic(CharacteristicUuids::firmwareRevision);
      70          112 : }
      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              :  */
      81          125 : bool DeviceInfoService::readHardwareRevisionCharacteristic()
      82          112 : {
      83          112 :     Q_D(DeviceInfoService);
      84          272 :     return d->readCharacteristic(CharacteristicUuids::hardwareRevision);
      85          112 : }
      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              :  */
      96          125 : bool DeviceInfoService::readManufacturerCharacteristics()
      97          112 : {
      98          112 :     Q_D(DeviceInfoService);
      99          272 :     return d->readCharacteristic(CharacteristicUuids::manufacturerName);
     100          112 : }
     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              :  */
     111          125 : bool DeviceInfoService::readModelNumberCharacteristic()
     112          112 : {
     113          112 :     Q_D(DeviceInfoService);
     114          272 :     return d->readCharacteristic(CharacteristicUuids::modelNumber);
     115          112 : }
     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              :  */
     126          125 : bool DeviceInfoService::readSoftwareRevisionCharacteristic()
     127          112 : {
     128          112 :     Q_D(DeviceInfoService);
     129          272 :     return d->readCharacteristic(CharacteristicUuids::softwareRevision);
     130          112 : }
     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              :  */
     141           80 : bool DeviceInfoService::readSerialNumberCharacteristic()
     142           56 : {
     143           56 :     Q_D(DeviceInfoService);
     144          136 :     return d->readCharacteristic(CharacteristicUuids::serialNumber);
     145           56 : }
     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              :  */
     154         2000 : QString DeviceInfoService::manufacturer() const
     155          632 : {
     156          632 :     Q_D(const DeviceInfoService);
     157          632 :     const QLowEnergyCharacteristic characteristic =
     158         2632 :         d->getCharacteristic(CharacteristicUuids::manufacturerName);
     159         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     160         2632 : }
     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              :  */
     169         2000 : QString DeviceInfoService::modelNumber() const
     170          632 : {
     171          632 :     Q_D(const DeviceInfoService);
     172          632 :     const QLowEnergyCharacteristic characteristic =
     173         2632 :         d->getCharacteristic(CharacteristicUuids::modelNumber);
     174         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     175         2632 : }
     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              :  */
     184         2000 : QString DeviceInfoService::hardwareRevision() const
     185          632 : {
     186          632 :     Q_D(const DeviceInfoService);
     187          632 :     const QLowEnergyCharacteristic characteristic =
     188         2632 :         d->getCharacteristic(CharacteristicUuids::hardwareRevision);
     189         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     190         2632 : }
     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              :  */
     199         2000 : QString DeviceInfoService::firmwareRevision() const
     200          632 : {
     201          632 :     Q_D(const DeviceInfoService);
     202          632 :     const QLowEnergyCharacteristic characteristic =
     203         2632 :         d->getCharacteristic(CharacteristicUuids::firmwareRevision);
     204         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     205         2632 : }
     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              :  */
     214         2000 : QString DeviceInfoService::softwareRevision() const
     215          632 : {
     216          632 :     Q_D(const DeviceInfoService);
     217          632 :     const QLowEnergyCharacteristic characteristic =
     218         2632 :         d->getCharacteristic(CharacteristicUuids::softwareRevision);
     219         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     220         2632 : }
     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              :  */
     230         2000 : QString DeviceInfoService::serialNumber() const
     231          632 : {
     232          632 :     Q_D(const DeviceInfoService);
     233          632 :     const QLowEnergyCharacteristic characteristic =
     234         2632 :         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         4632 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()).remove('\0'_L1) : QString();
     242         2632 : }
     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              :  */
     309         1800 : DeviceInfoServicePrivate::DeviceInfoServicePrivate(
     310         3200 :     QLowEnergyController * controller, DeviceInfoService * const q)
     311         4416 :     : AbstractPokitServicePrivate(DeviceInfoService::serviceUuid, controller, q)
     312         1472 : {
     313              : 
     314         3272 : }
     315              : 
     316              : /*!
     317              :  * Implements AbstractPokitServicePrivate::characteristicRead to parse \a value, then emit a
     318              :  * specialised signal, for each supported \a characteristic.
     319              :  */
     320           80 : void DeviceInfoServicePrivate::characteristicRead(const QLowEnergyCharacteristic &characteristic,
     321              :                                               const QByteArray &value)
     322           56 : {
     323          136 :     AbstractPokitServicePrivate::characteristicRead(characteristic, value);
     324              : 
     325           56 :     Q_Q(DeviceInfoService);
     326          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::manufacturerName) {
     327            0 :         const QString name = QString::fromUtf8(value);
     328            0 :         qCDebug(lc).noquote() << tr(R"(Manufacturer name: "%1")").arg(name);
     329            0 :         Q_EMIT q->manufacturerRead(name);
     330            0 :         return;
     331            0 :     }
     332              : 
     333          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::modelNumber) {
     334            0 :         const QString model = QString::fromUtf8(value);
     335            0 :         qCDebug(lc).noquote() << tr(R"(Model number: "%1")").arg(model);
     336            0 :         Q_EMIT q->modelNumberRead(model);
     337            0 :         return;
     338            0 :     }
     339              : 
     340          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::hardwareRevision) {
     341            0 :         const QString revision = QString::fromUtf8(value);
     342            0 :         qCDebug(lc).noquote() << tr(R"(Hardware revision: "%1")").arg(revision);
     343            0 :         Q_EMIT q->hardwareRevisionRead(revision);
     344            0 :         return;
     345            0 :     }
     346              : 
     347          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::firmwareRevision) {
     348            0 :         const QString revision = QString::fromUtf8(value);
     349            0 :         qCDebug(lc).noquote() << tr(R"(Firmware revision: "%1")").arg(revision);
     350            0 :         Q_EMIT q->firmwareRevisionRead(revision);
     351            0 :         return;
     352            0 :     }
     353              : 
     354          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::softwareRevision) {
     355            0 :         const QString revision = QString::fromUtf8(value);
     356            0 :         qCDebug(lc).noquote() << tr(R"(Software revision: "%1")").arg(revision);
     357            0 :         Q_EMIT q->softwareRevisionRead(revision);
     358            0 :         return;
     359            0 :     }
     360              : 
     361          136 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::serialNumber) {
     362            0 :         const QString serialNumber = QString::fromUtf8(value);
     363            0 :         qCDebug(lc).noquote() << tr(R"(Serial number: "%1")").arg(serialNumber);
     364            0 :         Q_EMIT q->serialNumberRead(serialNumber);
     365            0 :         return;
     366            0 :     }
     367              : 
     368          354 :     qCWarning(lc).noquote() << tr("Unknown characteristic read for Device Info service")
     369          226 :         << serviceUuid << characteristic.name() << characteristic.uuid();
     370           56 : }
     371              : 
     372              : /// \endcond
     373              : 
     374              : QTPOKIT_END_NAMESPACE
        

Generated by: LCOV version 2.3.1-1