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 CalibrationService and CalibrationServicePrivate classes. 7 : */ 8 : 9 : #include <qtpokit/calibrationservice.h> 10 : #include "calibrationservice_p.h" 11 : 12 : #include <QtEndian> 13 : 14 : /*! 15 : * \class CalibrationService 16 : * 17 : * The CalibrationService class accesses the `Calibrartion` service of Pokit devices. 18 : */ 19 : 20 : 21 : /*! 22 : * Constructs a new Pokit service with \a parent. 23 : */ 24 95 : CalibrationService::CalibrationService(QLowEnergyController * const controller, QObject * parent) 25 95 : : AbstractPokitService(new CalibrationServicePrivate(controller, this), parent) 26 : { 27 : 28 95 : } 29 : 30 : /*! 31 : * \cond internal 32 : * Constructs a new Pokit service with \a parent, and private implementation \a d. 33 : */ 34 0 : CalibrationService::CalibrationService( 35 0 : CalibrationServicePrivate * const d, QObject * const parent) 36 0 : : AbstractPokitService(d, parent) 37 : { 38 : 39 0 : } 40 : /// \endcond 41 : 42 : /*! 43 : * Destroys this CalibrationService object. 44 : */ 45 76 : CalibrationService::~CalibrationService() 46 : { 47 : 48 76 : } 49 : 50 : /*! 51 : * \copybrief AbstractPokitService::readCharacteristics 52 : * 53 : * This implementation always returns `true`, since the Calibration service provides no *readable* 54 : * characteristics (they're all write-only). 55 : */ 56 19 : bool CalibrationService::readCharacteristics() 57 : { 58 : Q_D(CalibrationService); 59 21 : qCDebug(d->lc).noquote() << tr("Ignoring read request; the Calibration service is write-only."); 60 19 : return true; 61 : } 62 : 63 : /*! 64 : * Set's the Pokit device's name to \a name. 65 : * 66 : * Returns `true` if the write request was successfully queued, `false` otherwise. 67 : * 68 : * Emits deviceNameWritten() if/when the \a name has been set. 69 : */ 70 38 : bool CalibrationService::calibrateTemperature(const float ambientTemperature) 71 : { 72 : static_assert(sizeof(float) == 4, "Pokit devices expect 32-bit floats"); 73 : Q_D(const CalibrationService); 74 : const QLowEnergyCharacteristic characteristic = 75 38 : d->getCharacteristic(CharacteristicUuids::temperature); 76 38 : if (!characteristic.isValid()) { 77 : return false; 78 : } 79 : 80 0 : const QByteArray newValue = CalibrationServicePrivate::encodeTemperature(ambientTemperature); 81 0 : qCDebug(d->lc).noquote() << tr("Writing new temperature %1 (0x%2).") 82 0 : .arg(ambientTemperature).arg(QLatin1String(newValue.toHex())); 83 0 : d->service->writeCharacteristic(characteristic, newValue); 84 0 : return (d->service->error() != QLowEnergyService::ServiceError::CharacteristicWriteError); 85 38 : } 86 : 87 : /*! 88 : * \fn CalibrationService::temperatureCalibrated 89 : * 90 : * This signal is emitted when the `Temperature` characteristic has been written succesfully. 91 : * 92 : * \see calibrateTemperature 93 : */ 94 : 95 : /*! 96 : * \cond internal 97 : * \class CalibrationServicePrivate 98 : * 99 : * The CalibrationServicePrivate class provides private implementation for CalibrationService. 100 : */ 101 : 102 : /*! 103 : * \internal 104 : * Constructs a new CalibrationServicePrivate object with public implementation \a q. 105 : */ 106 65 : CalibrationServicePrivate::CalibrationServicePrivate( 107 95 : QLowEnergyController * controller, CalibrationService * const q) 108 95 : : AbstractPokitServicePrivate(CalibrationService::serviceUuid, controller, q) 109 : { 110 : 111 65 : } 112 : 113 : /*! 114 : * Returns \a value in a format Pokit devices expect. Specifically, this just enocdes \a value as 115 : * a 32-bit float in litte-endian byte order. 116 : */ 117 95 : QByteArray CalibrationServicePrivate::encodeTemperature(const float value) 118 : { 119 : static_assert(sizeof(value) == 4, "Pokit devices expect 32-bit floats"); 120 95 : QByteArray bytes(sizeof(float), '\0'); 121 : qToLittleEndian<float>(value, bytes.data()); 122 95 : return bytes; 123 0 : } 124 : 125 : /*! 126 : * Implements AbstractPokitServicePrivate::characteristicWritten to parse \a newValue, then emit a 127 : * specialised signal, for each supported \a characteristic. 128 : */ 129 19 : void CalibrationServicePrivate::characteristicWritten(const QLowEnergyCharacteristic &characteristic, 130 : const QByteArray &newValue) 131 : { 132 19 : AbstractPokitServicePrivate::characteristicWritten(characteristic, newValue); 133 : 134 : Q_Q(CalibrationService); 135 19 : if (characteristic.uuid() == CalibrationService::CharacteristicUuids::temperature) { 136 0 : emit q->temperatureCalibrated(); 137 0 : return; 138 : } 139 : 140 59 : qCWarning(lc).noquote() << tr("Unknown characteristic written for Calibration service") 141 25 : << serviceUuid << characteristic.name() << characteristic.uuid(); 142 : } 143 : 144 : /// \endcond