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