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: 85.0 % 20 17

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2022-2024 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              : 
      12              : #include <QtEndian>
      13              : 
      14              : /*!
      15              :  * \class DeviceInfoService
      16              :  *
      17              :  * The DeviceInfoService class accesses the `Device Info` service of Pokit devices.
      18              :  */
      19              : 
      20              : /*!
      21              :  * Constructs a new Pokit service with \a parent.
      22              :  */
      23         1346 : DeviceInfoService::DeviceInfoService(QLowEnergyController * const controller, QObject * parent)
      24         1926 :     : AbstractPokitService(new DeviceInfoServicePrivate(controller, this), parent)
      25         1028 : {
      26              : 
      27         2374 : }
      28              : 
      29              : /*!
      30              :  * \cond internal
      31              :  * Constructs a new Pokit service with \a parent, and private implementation \a d.
      32              :  */
      33            0 : DeviceInfoService::DeviceInfoService(
      34            0 :     DeviceInfoServicePrivate * const d, QObject * const parent)
      35            0 :     : AbstractPokitService(d, parent)
      36            0 : {
      37              : 
      38            0 : }
      39              : /// \endcond
      40              : 
      41           38 : bool DeviceInfoService::readCharacteristics()
      42           44 : {
      43           60 :     const bool r1 = readFirmwareRevisionCharacteristic();
      44           60 :     const bool r2 = readHardwareRevisionCharacteristic();
      45           60 :     const bool r3 = readSoftwareRevisionCharacteristic();
      46           60 :     const bool r4 = readManufacturerCharacteristics();
      47           60 :     const bool r5 = readModelNumberCharacteristic();
      48           82 :     const bool r6 = ((service() != nullptr) && (service()->characteristic(CharacteristicUuids::serialNumber).isValid()))
      49           82 :         ? readSerialNumberCharacteristic() : true;
      50           82 :     return (r1 && r2 && r3 && r4 && r5 && r6);
      51           44 : }
      52              : 
      53              : /*!
      54              :  * Read the `Device Info` service's `Firmware Revision` characteristic.
      55              :  *
      56              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
      57              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
      58              :  * not yet been discovered).
      59              :  *
      60              :  * Emits firmwareRevisionRead() if/when the characteristic has been read successfully.
      61              :  */
      62           54 : bool DeviceInfoService::readFirmwareRevisionCharacteristic()
      63           88 : {
      64           88 :     Q_D(DeviceInfoService);
      65          164 :     return d->readCharacteristic(CharacteristicUuids::firmwareRevision);
      66           88 : }
      67              : 
      68              : /*!
      69              :  * Read the `Device Info` service's `Hardware Revision` characteristic.
      70              :  *
      71              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
      72              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
      73              :  * not yet been discovered).
      74              :  *
      75              :  * Emits hardwareRevisionRead() if/when the characteristic has been read successfully.
      76              :  */
      77           54 : bool DeviceInfoService::readHardwareRevisionCharacteristic()
      78           88 : {
      79           88 :     Q_D(DeviceInfoService);
      80          164 :     return d->readCharacteristic(CharacteristicUuids::hardwareRevision);
      81           88 : }
      82              : 
      83              : /*!
      84              :  * Read the `Device Info` service's `Manufacturer Name` characteristic.
      85              :  *
      86              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
      87              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
      88              :  * not yet been discovered).
      89              :  *
      90              :  * Emits manufacturerNameRead() if/when the characteristic has been read successfully.
      91              :  */
      92           54 : bool DeviceInfoService::readManufacturerCharacteristics()
      93           88 : {
      94           88 :     Q_D(DeviceInfoService);
      95          164 :     return d->readCharacteristic(CharacteristicUuids::manufacturerName);
      96           88 : }
      97              : 
      98              : /*!
      99              :  * Read the `Device Info` service's `Model Number` characteristic.
     100              :  *
     101              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     102              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     103              :  * not yet been discovered).
     104              :  *
     105              :  * Emits modelNumberRead() if/when the characteristic has been read successfully.
     106              :  */
     107           54 : bool DeviceInfoService::readModelNumberCharacteristic()
     108           88 : {
     109           88 :     Q_D(DeviceInfoService);
     110          164 :     return d->readCharacteristic(CharacteristicUuids::modelNumber);
     111           88 : }
     112              : 
     113              : /*!
     114              :  * Read the `Device Info` service's `Software Revision` characteristic.
     115              :  *
     116              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     117              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     118              :  * not yet been discovered).
     119              :  *
     120              :  * Emits softwareRevisionRead() if/when the characteristic has been read successfully.
     121              :  */
     122           54 : bool DeviceInfoService::readSoftwareRevisionCharacteristic()
     123           88 : {
     124           88 :     Q_D(DeviceInfoService);
     125          164 :     return d->readCharacteristic(CharacteristicUuids::softwareRevision);
     126           88 : }
     127              : 
     128              : /*!
     129              :  * Read the `Device Info` service's (undocumented) `Serial Number` characteristic.
     130              :  *
     131              :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     132              :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     133              :  * not yet been discovered).
     134              :  *
     135              :  * Emits serialNumberRead() if/when the characteristic has been read successfully.
     136              :  */
     137           38 : bool DeviceInfoService::readSerialNumberCharacteristic()
     138           44 : {
     139           44 :     Q_D(DeviceInfoService);
     140           82 :     return d->readCharacteristic(CharacteristicUuids::serialNumber);
     141           44 : }
     142              : 
     143              : /*!
     144              :  * Returns the most recent value of the `Device Info` service's `Manufacturer Name` characteristic.
     145              :  *
     146              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     147              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     148              :  * null QString is returned.
     149              :  */
     150          776 : QString DeviceInfoService::manufacturer() const
     151          368 : {
     152          368 :     Q_D(const DeviceInfoService);
     153          368 :     const QLowEnergyCharacteristic characteristic =
     154         1144 :         d->getCharacteristic(CharacteristicUuids::manufacturerName);
     155         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     156         1144 : }
     157              : 
     158              : /*!
     159              :  * Returns the most recent value of the `Device Info` service's `Model Number` characteristic.
     160              :  *
     161              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     162              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     163              :  * null QString is returned.
     164              :  */
     165          776 : QString DeviceInfoService::modelNumber() const
     166          368 : {
     167          368 :     Q_D(const DeviceInfoService);
     168          368 :     const QLowEnergyCharacteristic characteristic =
     169         1144 :         d->getCharacteristic(CharacteristicUuids::modelNumber);
     170         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     171         1144 : }
     172              : 
     173              : /*!
     174              :  * Returns the most recent value of the `Device Info` service's `Hardware Revision` characteristic.
     175              :  *
     176              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     177              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     178              :  * null QString is returned.
     179              :  */
     180          776 : QString DeviceInfoService::hardwareRevision() const
     181          368 : {
     182          368 :     Q_D(const DeviceInfoService);
     183          368 :     const QLowEnergyCharacteristic characteristic =
     184         1144 :         d->getCharacteristic(CharacteristicUuids::hardwareRevision);
     185         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     186         1144 : }
     187              : 
     188              : /*!
     189              :  * Returns the most recent value of the `Device Info` service's `Firmware Revision` characteristic.
     190              :  *
     191              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     192              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     193              :  * null QString is returned.
     194              :  */
     195          776 : QString DeviceInfoService::firmwareRevision() const
     196          368 : {
     197          368 :     Q_D(const DeviceInfoService);
     198          368 :     const QLowEnergyCharacteristic characteristic =
     199         1144 :         d->getCharacteristic(CharacteristicUuids::firmwareRevision);
     200         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     201         1144 : }
     202              : 
     203              : /*!
     204              :  * Returns the most recent value of the `Device Info` service's `Software Revision` characteristic.
     205              :  *
     206              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     207              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     208              :  * null QString is returned.
     209              :  */
     210          776 : QString DeviceInfoService::softwareRevision() const
     211          368 : {
     212          368 :     Q_D(const DeviceInfoService);
     213          368 :     const QLowEnergyCharacteristic characteristic =
     214         1144 :         d->getCharacteristic(CharacteristicUuids::softwareRevision);
     215         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     216         1144 : }
     217              : 
     218              : /*!
     219              :  * Returns the most recent value of the `Device Info` service's (undocumented) `Serial Number`
     220              :  * characteristic.
     221              :  *
     222              :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     223              :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     224              :  * null QString is returned.
     225              :  */
     226          776 : QString DeviceInfoService::serialNumber() const
     227          368 : {
     228          368 :     Q_D(const DeviceInfoService);
     229          368 :     const QLowEnergyCharacteristic characteristic =
     230         1144 :         d->getCharacteristic(CharacteristicUuids::serialNumber);
     231              :     /*!
     232              :      * \cond internal
     233              :      * \pokitApi Unlike other string characteristics, Pokit (Pro) devices always appear to add a trailing
     234              :      * `null` byte to serial number strings. So here we strip any that are present.
     235              :      * \endcond
     236              :      */
     237         1920 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()).remove(QLatin1Char('\0')) : QString();
     238         1144 : }
     239              : 
     240              : /*!
     241              :  * \fn DeviceInfoService::manufacturerRead
     242              :  *
     243              :  * This signal is emitted when the `Manufacturer Name` characteristic has been read successfully.
     244              :  *
     245              :  * \see readManufacturerCharacteristic
     246              :  * \see manufacturer
     247              :  */
     248              : 
     249              : /*!
     250              :  * \fn DeviceInfoService::modelNumberRead
     251              :  *
     252              :  * This signal is emitted when the `Model Number` characteristic has been read successfully.
     253              :  *
     254              :  * \see readModelNumberCharacteristic
     255              :  * \see modelNumber
     256              :  */
     257              : 
     258              : /*!
     259              :  * \fn DeviceInfoService::hardwareRevisionRead
     260              :  *
     261              :  * This signal is emitted when the `Hardware Revision` characteristic has been read successfully.
     262              :  *
     263              :  * \see readHardwareRevisionCharacteristic
     264              :  * \see hardwareRevision
     265              :  */
     266              : 
     267              : /*!
     268              :  * \fn DeviceInfoService::firmwareRevisionRead
     269              :  *
     270              :  * This signal is emitted when the `Firmware Revision` characteristic has been read successfully.
     271              :  *
     272              :  * \see readFirmwareRevisionCharacteristic
     273              :  * \see firmwareRevision
     274              :  */
     275              : 
     276              : /*!
     277              :  * \fn DeviceInfoService::softwareRevisionRead
     278              :  *
     279              :  * This signal is emitted when the `Software Revision` characteristic has been read successfully.
     280              :  *
     281              :  * \see readSoftwareRevisionCharacteristic
     282              :  * \see softwareRevision
     283              :  */
     284              : 
     285              : /*!
     286              :  * \fn DeviceInfoService::serialNumberRead
     287              :  *
     288              :  * This signal is emitted when the `Serial Number` characteristic has been read successfully.
     289              :  *
     290              :  * \see readSerialNumberCharacteristic
     291              :  * \see serialNumber
     292              :  */
     293              : 
     294              : /*!
     295              :  * \cond internal
     296              :  * \class DeviceInfoServicePrivate
     297              :  *
     298              :  * The DeviceInfoServicePrivate class provides private implementation for DeviceInfoService.
     299              :  */
     300              : 
     301              : /*!
     302              :  * \internal
     303              :  * Constructs a new DeviceInfoServicePrivate object with public implementation \a q.
     304              :  */
     305          580 : DeviceInfoServicePrivate::DeviceInfoServicePrivate(
     306         1346 :     QLowEnergyController * controller, DeviceInfoService * const q)
     307         1926 :     : AbstractPokitServicePrivate(DeviceInfoService::serviceUuid, controller, q)
     308         1028 : {
     309              : 
     310         1608 : }
     311              : 
     312              : /*!
     313              :  * Implements AbstractPokitServicePrivate::characteristicRead to parse \a value, then emit a
     314              :  * specialised signal, for each supported \a characteristic.
     315              :  */
     316           38 : void DeviceInfoServicePrivate::characteristicRead(const QLowEnergyCharacteristic &characteristic,
     317              :                                               const QByteArray &value)
     318           44 : {
     319           82 :     AbstractPokitServicePrivate::characteristicRead(characteristic, value);
     320              : 
     321           44 :     Q_Q(DeviceInfoService);
     322           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::manufacturerName) {
     323            0 :         const QString name = QString::fromUtf8(value);
     324            0 :         qCDebug(lc).noquote() << tr(R"(Manufacturer name: "%1")").arg(name);
     325            0 :         Q_EMIT q->manufacturerRead(name);
     326            0 :         return;
     327            0 :     }
     328              : 
     329           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::modelNumber) {
     330            0 :         const QString model = QString::fromUtf8(value);
     331            0 :         qCDebug(lc).noquote() << tr(R"(Model number: "%1")").arg(model);
     332            0 :         Q_EMIT q->modelNumberRead(model);
     333            0 :         return;
     334            0 :     }
     335              : 
     336           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::hardwareRevision) {
     337            0 :         const QString revision = QString::fromUtf8(value);
     338            0 :         qCDebug(lc).noquote() << tr(R"(Hardware revision: "%1")").arg(revision);
     339            0 :         Q_EMIT q->hardwareRevisionRead(revision);
     340            0 :         return;
     341            0 :     }
     342              : 
     343           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::firmwareRevision) {
     344            0 :         const QString revision = QString::fromUtf8(value);
     345            0 :         qCDebug(lc).noquote() << tr(R"(Firmware revision: "%1")").arg(revision);
     346            0 :         Q_EMIT q->firmwareRevisionRead(revision);
     347            0 :         return;
     348            0 :     }
     349              : 
     350           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::softwareRevision) {
     351            0 :         const QString revision = QString::fromUtf8(value);
     352            0 :         qCDebug(lc).noquote() << tr(R"(Software revision: "%1")").arg(revision);
     353            0 :         Q_EMIT q->softwareRevisionRead(revision);
     354            0 :         return;
     355            0 :     }
     356              : 
     357           82 :     if (characteristic.uuid() == DeviceInfoService::CharacteristicUuids::serialNumber) {
     358            0 :         const QString serialNumber = QString::fromUtf8(value);
     359            0 :         qCDebug(lc).noquote() << tr(R"(Serial number: "%1")").arg(serialNumber);
     360            0 :         Q_EMIT q->serialNumberRead(serialNumber);
     361            0 :         return;
     362            0 :     }
     363              : 
     364          179 :     qCWarning(lc).noquote() << tr("Unknown characteristic read for Device Info service")
     365          135 :         << serviceUuid << characteristic.name() << characteristic.uuid();
     366           44 : }
     367              : 
     368              : /// \endcond
        

Generated by: LCOV version 2.0-1