LCOV - code coverage report
Current view: top level - src/lib - statusservice.cpp (source / functions) Hit Total Coverage
Project: QtPokit Lines: 120 157 76.4 %
Version: Functions: 22 25 88.0 %

          Line data    Source code
       1             : // SPDX-FileCopyrightText: 2022-2023 Paul Colby <git@colby.id.au>
       2             : // SPDX-License-Identifier: LGPL-3.0-or-later
       3             : 
       4             : /*!
       5             :  * \file
       6             :  * Defines the StatusService and StatusServicePrivate classes.
       7             :  */
       8             : 
       9             : #include <qtpokit/statusservice.h>
      10             : #include "statusservice_p.h"
      11             : 
      12             : #include <QtEndian>
      13             : 
      14             : /*!
      15             :  * \class StatusService
      16             :  *
      17             :  * The StatusService class accesses the `Pokit Status` service of Pokit devices.
      18             :  */
      19             : 
      20             : /*!
      21             :  * \struct StatusService::ServiceUuids
      22             :  *
      23             :  * UUIDs of the "Pokit Status" service.
      24             :  *
      25             :  * \cond internal
      26             :  * \pokitApi Pokit API 1.00 (and 0.02) states the Status Service UUID as
      27             :  * `57d3a771-267c-4394-8872-78223e92aec4` which is correct for the Pokit Meter, but Pokit Pro uses
      28             :  * `57d3a771-267c-4394-8872-78223e92aec5` instead, that is the last digit is a `5` not `4`.
      29             :  * \endcond
      30             :  */
      31             : 
      32             : /// UUID of the Pokit Meter's `Pokit Status` service.
      33             : const QBluetoothUuid StatusService::ServiceUuids::
      34             :     pokitMeter(QLatin1String("57d3a771-267c-4394-8872-78223e92aec4"));
      35             : 
      36             : /// UUID of the Pokit Pro's `Pokit Status` service.
      37             : const QBluetoothUuid StatusService::ServiceUuids::
      38             :     pokitPro(QLatin1String("57d3a771-267c-4394-8872-78223e92aec5"));
      39             : 
      40             : /// \struct StatusService::CharacteristicUuids
      41             : /// \brief Characteristics available via the `Pokit Status` service.
      42             : 
      43             : /// UUID of the `Pokit Status` service's `Device Characteristics` characterstic.
      44             : const QBluetoothUuid StatusService::CharacteristicUuids::
      45             :     deviceCharacteristics(QLatin1String("6974f5e5-0e54-45c3-97dd-29e4b5fb0849"));
      46             : 
      47             : /// UUID of the `Pokit Status` service's `Status` characterstic.
      48             : const QBluetoothUuid StatusService::CharacteristicUuids::
      49             :     status(QLatin1String("3dba36e1-6120-4706-8dfd-ed9c16e569b6"));
      50             : 
      51             : /// UUID of the `Pokit Status` service's `Device Name` characterstic.
      52             : const QBluetoothUuid StatusService::CharacteristicUuids::
      53             :     name(QLatin1String("7f0375de-077e-4555-8f78-800494509cc3"));
      54             : 
      55             : /// UUID of the `Pokit Status` service's `Flash LED` characterstic.
      56             : const QBluetoothUuid StatusService::CharacteristicUuids::
      57             :     flashLed(QLatin1String("ec9bb1f3-05a9-4277-8dd0-60a7896f0d6e"));
      58             : 
      59             : /// \struct StatusService::DeviceCharacteristics
      60             : /// \brief Attributes included in the `Device Characteristics` characterstic.
      61             : 
      62             : /// \enum StatusService::DeviceStatus
      63             : /// \brief Values supported by the `Status` attribute of the `Status` characteristic.
      64             : 
      65             : /*!
      66             :  * Returns a string version of the \a status enum label.
      67             :  */
      68         374 : QString StatusService::toString(const StatusService::DeviceStatus &status)
      69             : {
      70         374 :     switch (status) {
      71          30 :     case DeviceStatus::Idle:                 return  QLatin1String("Idle");
      72           3 :     case DeviceStatus::MultimeterDcVoltage:  return  QLatin1String("MultimeterDcVoltage");
      73           3 :     case DeviceStatus::MultimeterAcVoltage:  return  QLatin1String("MultimeterAcVoltage");
      74           3 :     case DeviceStatus::MultimeterDcCurrent:  return  QLatin1String("MultimeterDcCurrent");
      75           3 :     case DeviceStatus::MultimeterAcCurrent:  return  QLatin1String("MultimeterAcCurrent");
      76           3 :     case DeviceStatus::MultimeterResistance: return  QLatin1String("MultimeterResistance");
      77           3 :     case DeviceStatus::MultimeterDiode:      return  QLatin1String("MultimeterDiode");
      78           3 :     case DeviceStatus::MultimeterContinuity: return  QLatin1String("MultimeterContinuity");
      79           3 :     case DeviceStatus::MultimeterTemperature:return  QLatin1String("MultimeterTemperature");
      80           3 :     case DeviceStatus::DsoModeSampling:      return  QLatin1String("DsoModeSampling");
      81           3 :     case DeviceStatus::LoggerModeSampling:   return  QLatin1String("LoggerModeSampling");
      82             :     }
      83             :     return QString();
      84             : }
      85             : 
      86             : /// \enum StatusService::BatteryStatus
      87             : /// \brief Values supported by the `Battery Status` attribute of the `Status` characteristic.
      88             : 
      89             : /*!
      90             :  * Returns a string version of the \a status enum label.
      91             :  */
      92         221 : QString StatusService::toString(const StatusService::BatteryStatus &status)
      93             : {
      94         221 :     switch (status) {
      95          30 :     case BatteryStatus::Low:  return QLatin1String("Low");
      96           3 :     case BatteryStatus::Good: return QLatin1String("Good");
      97             :     }
      98             :     return QString();
      99             : }
     100             : 
     101             : /*!
     102             :  * \struct StatusService::Status
     103             :  * \brief Attributes included in the `Status` characterstic.
     104             :  *
     105             :  * \note Not all Pokit devices support the batteryStatus member, in which case the member will be
     106             :  * initilialised to the maximum value supported by the underlying type (ie `255`) to indicate "not
     107             :  * set".
     108             :  */
     109             : 
     110             : /*!
     111             :  * Constructs a new Pokit service with \a parent.
     112             :  */
     113         408 : StatusService::StatusService(QLowEnergyController * const controller, QObject * parent)
     114         408 :     : AbstractPokitService(new StatusServicePrivate(controller, this), parent)
     115             : {
     116             : 
     117         408 : }
     118             : 
     119             : /*!
     120             :  * \cond internal
     121             :  * Constructs a new Pokit service with \a parent, and private implementation \a d.
     122             :  */
     123           0 : StatusService::StatusService(
     124           0 :     StatusServicePrivate * const d, QObject * const parent)
     125           0 :     : AbstractPokitService(d, parent)
     126             : {
     127             : 
     128           0 : }
     129             : /// \endcond
     130             : 
     131             : /*!
     132             :  * Destroys this StatusService object.
     133             :  */
     134         221 : StatusService::~StatusService()
     135             : {
     136             : 
     137         221 : }
     138             : 
     139          17 : bool StatusService::readCharacteristics()
     140             : {
     141          11 :     const bool r1 = readDeviceCharacteristics();
     142          11 :     const bool r2 = readStatusCharacteristic();
     143          11 :     const bool r3 = readNameCharacteristic();
     144          17 :     return (r1 && r2 && r3);
     145             : }
     146             : 
     147             : /*!
     148             :  * Read the `Status` service's `Device Characteristics` characteristic.
     149             :  *
     150             :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     151             :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     152             :  * not yet been discovered).
     153             :  *
     154             :  * Emits deviceCharacteristicsRead() if/when the characteristic has been read successfully.
     155             :  */
     156          28 : bool StatusService::readDeviceCharacteristics()
     157             : {
     158             :     Q_D(StatusService);
     159          34 :     return d->readCharacteristic(CharacteristicUuids::deviceCharacteristics);
     160             : }
     161             : 
     162             : /*!
     163             :  * Read the `Status` service's `Status` characteristic.
     164             :  *
     165             :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     166             :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     167             :  * not yet been discovered).
     168             :  *
     169             :  * Emits deviceStatusRead() if/when the characteristic has been read successfully.
     170             :  */
     171          28 : bool StatusService::readStatusCharacteristic()
     172             : {
     173             :     Q_D(StatusService);
     174          34 :     return d->readCharacteristic(CharacteristicUuids::status);
     175             : }
     176             : 
     177             : /*!
     178             :  * Read the `Status` service's `Name` characteristic.
     179             :  *
     180             :  * Returns `true` is the read request is succesfully queued, `false` otherwise (ie if the
     181             :  * underlying controller it not yet connected to the Pokit device, or the device's services have
     182             :  * not yet been discovered).
     183             :  *
     184             :  * Emits deviceNameRead() if/when the characteristic has been read successfully.
     185             :  */
     186          28 : bool StatusService::readNameCharacteristic()
     187             : {
     188             :     Q_D(StatusService);
     189          34 :     return d->readCharacteristic(CharacteristicUuids::name);
     190             : }
     191             : 
     192             : /*!
     193             :  * Returns the most recent value of the `Status` service's `Device Characteristics` 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 result is returned, which can be checked via the returned
     198             :  * DeviceCharacteristics::firmwareVersion, like:
     199             :  *
     200             :  * ```
     201             :  * const DeviceCharacteristics characteristics = service->deviceCharacteristics();
     202             :  * if (!characteristics.firmwareVersion.isNull()) {
     203             :  *     ...
     204             :  * }
     205             :  * ```
     206             :  */
     207          34 : StatusService::DeviceCharacteristics StatusService::deviceCharacteristics() const
     208             : {
     209             :     Q_D(const StatusService);
     210             :     const QLowEnergyCharacteristic characteristic =
     211          34 :         d->getCharacteristic(CharacteristicUuids::deviceCharacteristics);
     212          34 :     return (characteristic.isValid())
     213           0 :         ? StatusServicePrivate::parseDeviceCharacteristics(characteristic.value())
     214          68 :         : StatusService::DeviceCharacteristics();
     215          34 : }
     216             : 
     217             : /*!
     218             :  * Returns the most recent value of the `Status` service's `Status` characteristic.
     219             :  *
     220             :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     221             :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then the
     222             :  * returned StatusService::Status::batteryLevel member will be a quiet NaN, which can be checked
     223             :  * like:
     224             :  *
     225             :  * ```
     226             :  * const StatusService::Status status = statusService->status();
     227             :  * if (qIsNaN(status.batteryVoltage)) {
     228             :  *     // Handle failure.
     229             :  * }
     230             :  * ```
     231             :  */
     232         170 : StatusService::Status StatusService::status() const
     233             : {
     234             :     Q_D(const StatusService);
     235             :     const QLowEnergyCharacteristic characteristic =
     236         170 :         d->getCharacteristic(CharacteristicUuids::status);
     237         170 :     return (characteristic.isValid()) ? StatusServicePrivate::parseStatus(characteristic.value())
     238             :         : StatusService::Status{ DeviceStatus::Idle, std::numeric_limits<float>::quiet_NaN(),
     239         340 :                                  BatteryStatus::Low };
     240         170 : }
     241             : 
     242             : /*!
     243             :  * Returns the most recent value of the `Status` services's `Device Name` characteristic.
     244             :  *
     245             :  * The returned value, if any, is from the underlying Bluetooth stack's cache. If no such value is
     246             :  * currently available (ie the serviceDetailsDiscovered signal has not been emitted yet), then a
     247             :  * null QString is returned.
     248             :  */
     249         170 : QString StatusService::deviceName() const
     250             : {
     251             :     Q_D(const StatusService);
     252             :     const QLowEnergyCharacteristic characteristic =
     253         170 :         d->getCharacteristic(CharacteristicUuids::name);
     254         340 :     return (characteristic.isValid()) ? QString::fromUtf8(characteristic.value()) : QString();
     255         170 : }
     256             : 
     257             : /*!
     258             :  * Set's the Pokit device's name to \a name.
     259             :  *
     260             :  * Returns `true` if the write request was successfully queued, `false` otherwise.
     261             :  *
     262             :  * Emits deviceNameWritten() if/when the \a name has been set.
     263             :  */
     264          17 : bool StatusService::setDeviceName(const QString &name)
     265             : {
     266             :     Q_D(const StatusService);
     267             :     const QLowEnergyCharacteristic characteristic =
     268          17 :         d->getCharacteristic(CharacteristicUuids::name);
     269          17 :     if (!characteristic.isValid()) {
     270             :         return false;
     271             :     }
     272             : 
     273             :     const QByteArray value = name.toUtf8();
     274           0 :     if (value.length() > 11) {
     275           0 :         qCWarning(d->lc).noquote() << tr("Device name \"%1\" is too long (%2 > 11 bytes): 0x3")
     276           0 :             .arg(name).arg(value.length()).arg(QLatin1String(value.toHex()));
     277           0 :         return false;
     278             :     }
     279             : 
     280           0 :     d->service->writeCharacteristic(characteristic, value);
     281           0 :     return (d->service->error() != QLowEnergyService::ServiceError::CharacteristicWriteError);
     282          17 : }
     283             : 
     284             : /*!
     285             :  * Flash the Pokit device's LED.
     286             :  *
     287             :  * Returns `true` if the flash request was successfully queued, `false` otherwise.
     288             :  *
     289             :  * Emits deviceLedFlashed() if/when the LED has flashed successfully.
     290             :  *
     291             :  * \note This operation is only supported by Pokit Meter devices. Pokit Pro devices will report an
     292             :  * Bluetooth ATT error `0x80`.
     293             :  *
     294             :  * \cond internal
     295             :  * \pokitApi The Android app can turn Pokit Pro LEDs on/off. Perhaps that is handled by an
     296             :  * undocumented use of this characteristic. Or perhaps its via some other service.
     297             :  * \endcond
     298             :  */
     299          17 : bool StatusService::flashLed()
     300             : {
     301             :     Q_D(const StatusService);
     302             :     const QLowEnergyCharacteristic characteristic =
     303          17 :         d->getCharacteristic(CharacteristicUuids::flashLed);
     304          17 :     if (!characteristic.isValid()) {
     305             :         return false;
     306             :     }
     307             : 
     308             :     // The Flash LED characeristic is write-only, and takes a single uint8 "LED" parameter, which
     309             :     // must always be 1. Presumably this is an index for which LED to flash, but the Pokit API docs
     310             :     // say that "any value other than 1 will be ignored", which makes sense given that all current
     311             :     // Pokit devices have only one LED.
     312           0 :     const QByteArray value(1, '\x01');
     313           0 :     d->service->writeCharacteristic(characteristic, value);
     314           0 :     return (d->service->error() != QLowEnergyService::ServiceError::CharacteristicWriteError);
     315          17 : }
     316             : 
     317             : /*!
     318             :  * \fn StatusService::deviceCharacteristicsRead
     319             :  *
     320             :  * This signal is emitted when the `Device Characteristics` characteristic has been read
     321             :  * successfully.
     322             :  *
     323             :  * \see readDeviceCharacteristics
     324             :  */
     325             : 
     326             : /*!
     327             :  * \fn StatusService::deviceNameRead
     328             :  *
     329             :  * This signal is emitted when the `Device Name` characteristic has been read successfully.
     330             :  *
     331             :  * \see readDeviceName
     332             :  */
     333             : 
     334             : /*!
     335             :  * \fn StatusService::deviceNameWritten
     336             :  *
     337             :  * This signal is emitted when the `Device Name` characteristic has been written successfully.
     338             :  *
     339             :  * \see setDeviceName
     340             :  */
     341             : 
     342             : /*!
     343             :  * \fn StatusService::deviceStatusRead
     344             :  *
     345             :  * This signal is emitted when the `Status` characteristic has been read successfully.
     346             :  *
     347             :  * \see readDeviceStatus
     348             :  */
     349             : 
     350             : /*!
     351             :  * \fn StatusService::deviceLedFlashed
     352             :  *
     353             :  * This signal is emitted when device's LED has flashed in response to a write of the `Flash LED`
     354             :  * characteristic.
     355             :  */
     356             : 
     357             : /*!
     358             :  * \cond internal
     359             :  * \class StatusServicePrivate
     360             :  *
     361             :  * The StatusServicePrivate class provides private implementation for StatusService.
     362             :  */
     363             : 
     364             : /*!
     365             :  * \internal
     366             :  * Constructs a new StatusServicePrivate object with public implementation \a q.
     367             :  */
     368         408 : StatusServicePrivate::StatusServicePrivate(
     369         408 :     QLowEnergyController * controller, StatusService * const q)
     370         408 :     : AbstractPokitServicePrivate(QBluetoothUuid(), controller, q)
     371             : {
     372             : 
     373         408 : }
     374             : 
     375             : /*!
     376             :  * Parses the `Device Characteristics` \a value into a DeviceCharacteristics struct.
     377             :  */
     378          68 : StatusService::DeviceCharacteristics StatusServicePrivate::parseDeviceCharacteristics(
     379             :     const QByteArray &value)
     380             : {
     381          68 :     StatusService::DeviceCharacteristics characteristics{
     382             :         QVersionNumber(), 0, 0, 0, 0, 0, 0, QBluetoothAddress()
     383          68 :     };
     384             :     Q_ASSERT(characteristics.firmwareVersion.isNull());  // How we indicate failure.
     385             : 
     386          80 :     if (!checkSize(QLatin1String("Device Characterisitcs"), value, 20, 20)) {
     387             :         return characteristics;
     388             :     }
     389             : 
     390          40 :     characteristics.firmwareVersion = QVersionNumber(
     391          68 :                                           qFromLittleEndian<quint8 >(value.mid(0,1)),
     392          62 :                                           qFromLittleEndian<quint8 >(value.mid(1,1)));
     393          40 :     characteristics.maximumVoltage      = qFromLittleEndian<quint16>(value.mid(2,2));
     394          40 :     characteristics.maximumCurrent      = qFromLittleEndian<quint16>(value.mid(4,2));
     395          40 :     characteristics.maximumResistance   = qFromLittleEndian<quint16>(value.mid(6,2));
     396          40 :     characteristics.maximumSamplingRate = qFromLittleEndian<quint16>(value.mid(8,2));
     397          40 :     characteristics.samplingBufferSize  = qFromLittleEndian<quint16>(value.mid(10,2));
     398          40 :     characteristics.capabilityMask      = qFromLittleEndian<quint16>(value.mid(12,2));
     399          62 :     characteristics.macAddress = QBluetoothAddress(qFromBigEndian<quint64>
     400         102 :                                                    (QByteArray(2, '\0') + value.mid(14,6)));
     401             : 
     402          34 :     qCDebug(lc).noquote() << tr("Firmware version:     ") << characteristics.firmwareVersion;
     403          34 :     qCDebug(lc).noquote() << tr("Maximum voltage:      ") << characteristics.maximumVoltage;
     404          34 :     qCDebug(lc).noquote() << tr("Maximum current:      ") << characteristics.maximumCurrent;
     405          34 :     qCDebug(lc).noquote() << tr("Maximum resistance:   ") << characteristics.maximumResistance;
     406          34 :     qCDebug(lc).noquote() << tr("Maximum sampling rate:") << characteristics.maximumSamplingRate;
     407          34 :     qCDebug(lc).noquote() << tr("Sampling buffer size: ") << characteristics.samplingBufferSize;
     408          34 :     qCDebug(lc).noquote() << tr("Capability mask:      ") << characteristics.capabilityMask;
     409          34 :     qCDebug(lc).noquote() << tr("MAC address:          ") << characteristics.macAddress;
     410             : 
     411             :     Q_ASSERT(!characteristics.firmwareVersion.isNull()); // How we indicate success.
     412           4 :     return characteristics;
     413             : }
     414             : 
     415             : /*!
     416             :  * Parses the `Status` \a value into Statu struct. Note, not all Pokit devices support all members
     417             :  * in Status. Specifically, the batteryStatus member is not usually set by Pokit Meter devices, so
     418             :  * will be an invlalid BatteryStatus enum value (`255`) in that case.
     419             :  */
     420          68 : StatusService::Status StatusServicePrivate::parseStatus(const QByteArray &value)
     421             : {
     422          68 :     StatusService::Status status{
     423             :         static_cast<StatusService::DeviceStatus>
     424             :             (std::numeric_limits<std::underlying_type<StatusService::DeviceStatus>::type>::max()),
     425             :         std::numeric_limits<float>::quiet_NaN(),
     426             :         static_cast<StatusService::BatteryStatus>
     427             :             (std::numeric_limits<std::underlying_type<StatusService::BatteryStatus>::type>::max()),
     428             :     };
     429             : 
     430             :     /*!
     431             :      * \pokitApi Pokit API 0.02 says the `Status` characteristic is 5 bytes. API 1.00 then added an
     432             :      * additional byte for `Battery Status`, for 6 bytes in total. However, Pokit Pro devices return
     433             :      * 8 bytes here. The purpose of those last 2 bytes are not currently known. Note also, Pokit
     434             :      * Meter only uses the first 5 bytes - ie `Battery Status` is not present.
     435             :      */
     436             : 
     437          80 :     if (!checkSize(QLatin1String("Status"), value, 5, 6)) {
     438          34 :         return status;
     439             :     }
     440             : 
     441          34 :     status.deviceStatus = static_cast<StatusService::DeviceStatus>(value.at(0));
     442          40 :     status.batteryVoltage = qFromLittleEndian<float>(value.mid(1,4));
     443          34 :     if (value.size() >= 6) { // Battery Status added to Pokit API docs v1.00.
     444          17 :         status.batteryStatus = static_cast<StatusService::BatteryStatus>(value.at(5));
     445             :     }
     446          34 :     qCDebug(lc).noquote() << tr("Device status:   %1 (%2)")
     447           0 :         .arg((quint8)status.deviceStatus).arg(StatusService::toString(status.deviceStatus));
     448          34 :     qCDebug(lc).noquote() << tr("Battery voltage: %1 volts").arg(status.batteryVoltage);
     449          34 :     qCDebug(lc).noquote() << tr("Battery status:  %1 (%2)")
     450           0 :         .arg((quint8)status.batteryStatus).arg(StatusService::toString(status.batteryStatus));
     451          34 :     return status;
     452             : }
     453             : 
     454             : /*!
     455             :  * Handles `QLowEnergyController::serviceDiscovered` events.
     456             :  *
     457             :  * Here we override the base implementation to detect if we're looking at a Pokit Meter, or Pokit
     458             :  * Pro device, as the two devices have very slightly different Status Service UUIDs.
     459             :  */
     460          68 : void StatusServicePrivate::serviceDiscovered(const QBluetoothUuid &newService)
     461             : {
     462          68 :     if (newService == StatusService::ServiceUuids::pokitMeter) {
     463          17 :         qCDebug(lc).noquote() << tr("Found Status Service for a Pokit Meter device.");
     464          17 :         serviceUuid = StatusService::ServiceUuids::pokitMeter;
     465          51 :     } else if (newService == StatusService::ServiceUuids::pokitPro) {
     466          17 :         qCDebug(lc).noquote() << tr("Found Status Service for a Pokit Pro device.");
     467          17 :         serviceUuid = StatusService::ServiceUuids::pokitPro;
     468             :     }
     469          68 :     AbstractPokitServicePrivate::serviceDiscovered(newService);
     470          68 : }
     471             : 
     472             : /*!
     473             :  * Implements AbstractPokitServicePrivate::characteristicRead to parse \a value, then emit a
     474             :  * specialised signal, for each supported \a characteristic.
     475             :  */
     476          17 : void StatusServicePrivate::characteristicRead(const QLowEnergyCharacteristic &characteristic,
     477             :                                               const QByteArray &value)
     478             : {
     479          17 :     AbstractPokitServicePrivate::characteristicRead(characteristic, value);
     480             : 
     481             :     Q_Q(StatusService);
     482          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::deviceCharacteristics) {
     483           0 :         emit q->deviceCharacteristicsRead(parseDeviceCharacteristics(value));
     484           0 :         return;
     485             :     }
     486             : 
     487          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::status) {
     488           0 :         emit q->deviceStatusRead(parseStatus(value));
     489           0 :         return;
     490             :     }
     491             : 
     492          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::name) {
     493           0 :         const QString deviceName = QString::fromUtf8(value);
     494           0 :         qCDebug(lc).noquote() << tr("Device name: \"%1\"").arg(deviceName);
     495           0 :         emit q->deviceNameRead(deviceName);
     496             :         return;
     497           0 :     }
     498             : 
     499          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::flashLed) {
     500           0 :         qCWarning(lc).noquote() << tr("Flash LED characteristic is write-only, but somehow read")
     501           0 :             << serviceUuid << characteristic.name() << characteristic.uuid();
     502           0 :         return;
     503             :     }
     504             : 
     505          51 :     qCWarning(lc).noquote() << tr("Unknown characteristic read for Status service")
     506          17 :         << serviceUuid << characteristic.name() << characteristic.uuid();
     507             : }
     508             : 
     509             : /*!
     510             :  * Implements AbstractPokitServicePrivate::characteristicWritten to parse \a newValue, then emit a
     511             :  * specialised signal, for each supported \a characteristic.
     512             :  */
     513          17 : void StatusServicePrivate::characteristicWritten(const QLowEnergyCharacteristic &characteristic,
     514             :                                                  const QByteArray &newValue)
     515             : {
     516          17 :     AbstractPokitServicePrivate::characteristicWritten(characteristic, newValue);
     517             : 
     518             :     Q_Q(StatusService);
     519          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::deviceCharacteristics) {
     520           0 :         qCWarning(lc).noquote() << tr("Device Characteristics is read-only, but somehow written")
     521           0 :             << serviceUuid << characteristic.name() << characteristic.uuid();
     522           0 :         return;
     523             :     }
     524             : 
     525          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::status) {
     526           0 :         qCWarning(lc).noquote() << tr("Status characteristic is read-only, but somehow written")
     527           0 :             << serviceUuid << characteristic.name() << characteristic.uuid();
     528           0 :         return;
     529             :     }
     530             : 
     531          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::name) {
     532           0 :         emit q->deviceNameWritten();
     533           0 :         return;
     534             :     }
     535             : 
     536          17 :     if (characteristic.uuid() == StatusService::CharacteristicUuids::flashLed) {
     537           0 :         emit q->deviceLedFlashed();
     538           0 :         return;
     539             :     }
     540             : 
     541          51 :     qCWarning(lc).noquote() << tr("Unknown characteristic written for Status service")
     542          17 :         << serviceUuid << characteristic.name() << characteristic.uuid();
     543             : }
     544             : 
     545             : /// \endcond

Generated by: LCOV version 1.14