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 #PokitProduct helper functions.
7 : */
8 :
9 : #include <qtpokit/pokitmeter.h>
10 : #include <qtpokit/pokitpro.h>
11 : #include <qtpokit/pokitproducts.h>
12 : #include <qtpokit/statusservice.h>
13 :
14 : #include "pokitproducts_p.h"
15 :
16 : #include <QCoreApplication>
17 : #include <QLoggingCategory>
18 :
19 819 : static Q_LOGGING_CATEGORY(lc, "dokit.pokit.products", QtInfoMsg); ///< Logging category for this file.
20 :
21 : QTPOKIT_BEGIN_NAMESPACE
22 :
23 : /*!
24 : * Returns \c product as user-friendly string.
25 : */
26 54 : QString toString(const PokitProduct product)
27 : {
28 54 : switch (product) {
29 18 : case PokitProduct::PokitMeter: return QStringLiteral("Pokit Meter");
30 18 : case PokitProduct::PokitPro: return QStringLiteral("Pokit Pro");
31 : }
32 56 : qCWarning(lc).noquote() << QCoreApplication::translate("PokitProducts",
33 28 : "Unknown PokitProduct value: %1", "toString").arg((int)product);
34 : return QString();
35 : }
36 :
37 : /*!
38 : * Returns \c true if \a info describes a Pokit device.
39 : *
40 : * Currently, this is based on whether or not \a info's service UUIDs includes a known Pokit
41 : * Status service, but this test criteria might be swapped for something else sometime.
42 : */
43 492 : bool isPokitProduct(const QBluetoothDeviceInfo &info)
44 : {
45 608 : return isPokitProduct(info.serviceUuids());
46 : }
47 :
48 : /*!
49 : * Returns the #PokitProduct corresponding the Bluetotoh device \a info.
50 : *
51 : * If \a info is not a Pokit device, then result is undefined.
52 : *
53 : * \see isPokitProduct
54 : */
55 90 : PokitProduct pokitProduct(const QBluetoothDeviceInfo &info)
56 : {
57 110 : return pokitProduct(info.serviceUuids());
58 : }
59 :
60 : /// \cond internal
61 :
62 : /*!
63 : * Returns \c true if \a serviceUuids contains a known Pokit Status service UUID.
64 : *
65 : * \todo The Pokit Android app does this by distinguishing between these two advertiserd services:
66 : * "00001800-0000-1000-8000-00805f9b34fb" Meter
67 : * "0000180a-0000-1000-8000-00805f9b34fb" Pro
68 : * Of course, these are the QBluetoothUuid::ServiceClassUuid::GenericAccess and
69 : * QBluetoothUuid::ServiceClassUuid::GenericAttribute services.
70 : *
71 : * Currently, this is the only known way to detect a Pokit device.
72 : */
73 816 : bool isPokitProduct(const QList<QBluetoothUuid> &serviceUuids)
74 : {
75 1342 : return (serviceUuids.contains(StatusService::ServiceUuids::pokitMeter) ||
76 816 : serviceUuids.contains(StatusService::ServiceUuids::pokitPro));
77 : }
78 :
79 :
80 : /*!
81 : * Returns \c true if \a controller describes a Pokit device.
82 : *
83 : * Currently, this is based on whether or not \a controller's service UUIDs includes a known Pokit
84 : * Status service, but this test criteria might be swapped for something else sometime.
85 : *
86 : * \see isPokitProduct
87 : */
88 108 : bool isPokitProduct(const QLowEnergyController &controller)
89 : {
90 132 : return isPokitProduct(controller.services());
91 : }
92 :
93 : /*!
94 : * Returns the #PokitProduct corresponding to the Bluetooth \a serviceUuids.
95 : *
96 : * Currently, this is based on whether or not \a servceUuids includes a known Pokit
97 : * Status service, but this test criteria might be swapped for something else sometime.
98 : *
99 : * \see isPokitProduct
100 : */
101 270 : PokitProduct pokitProduct(const QList<QBluetoothUuid> &serviceUuids)
102 : {
103 270 : if (serviceUuids.contains(StatusService::ServiceUuids::pokitMeter)) {
104 : return PokitProduct::PokitMeter;
105 198 : } else if (serviceUuids.contains(StatusService::ServiceUuids::pokitPro)) {
106 : return PokitProduct::PokitPro;
107 : } else {
108 252 : qCWarning(lc).noquote()
109 154 : << QCoreApplication::translate("PokitProducts", "Device is not a Pokit product", "pokitProduct");
110 126 : qCDebug(lc).noquote() << "Service UUIDs:" << serviceUuids;
111 126 : return PokitProduct::PokitMeter; // Need to fallback to something; Pokit Meter is just the lowest product.
112 : }
113 : }
114 :
115 : /*!
116 : * Returns the #PokitProduct corresponding to the Bluetooth \a controller.
117 : *
118 : * Currently, this is based on whether or not \a controller's service UUIDs includes a known Pokit
119 : * Status service, but this test criteria might be swapped for something else sometime.
120 : *
121 : * \see isPokitProduct
122 : */
123 90 : PokitProduct pokitProduct(const QLowEnergyController &controller)
124 : {
125 110 : return pokitProduct(controller.services());
126 : }
127 :
128 : QTPOKIT_END_NAMESPACE
129 :
130 : /// Encapsulates convenience functions for working with capacitance ranges.
131 : namespace CapacitanceRange {
132 :
133 : /*!
134 : * Returns \a product's capacitance \a range as a human-friendly string.
135 : *
136 : * \note Since Pokit Meters do not support capacitance measurement, \a product should not be PokitProduct::PokitMeter.
137 : *
138 : * \see PokitPro::toString(const PokitPro::CapacitanceRange &range)
139 : */
140 198 : QString toString(const PokitProduct product, const quint8 range)
141 : {
142 198 : switch (product) {
143 72 : case PokitProduct::PokitMeter:
144 144 : qCWarning(lc).noquote()
145 88 : << QCoreApplication::translate("PokitProducts", "Pokit Meter has no capacitance support", "toString");
146 : return QString();
147 108 : case PokitProduct::PokitPro:
148 108 : return PokitPro::toString(static_cast<PokitPro::CapacitanceRange>(range));
149 : }
150 56 : qCWarning(lc).noquote() << QCoreApplication::translate("CapacitanceRange",
151 28 : "Unknown PokitProduct value: %1", "toString").arg((int)product);
152 : return QString();
153 : }
154 :
155 : /*!
156 : * Returns the maximum value for \a product's \a range in (integer) nanofarads, or the string "Auto".
157 : * If \a range is not a known valid value, then an null QVariant is returned.
158 : *
159 : * \note Since Pokit Meters do not support capacitance measurement, \a product should not be PokitProduct::PokitMeter.
160 : *
161 : * \see PokitPro::maxValue(const PokitPro::CapacitanceRange &range)
162 : */
163 90 : QVariant maxValue(const PokitProduct product, const quint8 range)
164 : {
165 90 : switch (product) {
166 18 : case PokitProduct::PokitMeter:
167 36 : qCWarning(lc).noquote()
168 22 : << QCoreApplication::translate("PokitProducts", "Pokit Meter has no capacitance support", "toString");
169 : return QVariant();
170 54 : case PokitProduct::PokitPro:
171 54 : return PokitPro::maxValue(static_cast<PokitPro::CapacitanceRange>(range));
172 : }
173 56 : qCWarning(lc).noquote() << QCoreApplication::translate("CapacitanceRange",
174 28 : "Unknown PokitProduct value: %1", "maxValue").arg((int)product);
175 : return QVariant();
176 : }
177 :
178 : }
179 :
180 : /// Encapsulates convenience functions for working with current ranges.
181 : namespace CurrentRange {
182 :
183 : /*!
184 : * Returns \a product's current \a range as a human-friendly string.
185 : *
186 : * \see PokitMeter::toString(const PokitMeter::CurrentRange &range)
187 : * \see PokitPro::toString(const PokitPro::CurrentRange &range)
188 : */
189 1782 : QString toString(const PokitProduct product, const quint8 range)
190 : {
191 1782 : switch (product) {
192 1638 : case PokitProduct::PokitMeter:
193 1638 : return PokitMeter::toString(static_cast<PokitMeter::CurrentRange>(range));
194 126 : case PokitProduct::PokitPro:
195 126 : return PokitPro::toString(static_cast<PokitPro::CurrentRange>(range));
196 : }
197 56 : qCWarning(lc).noquote() << QCoreApplication::translate("CurrentRange",
198 28 : "Unknown PokitProduct value: %1", "toString").arg((int)product);
199 : return QString();
200 : }
201 :
202 : /*!
203 : * Returns the maximum value for \a product's \a range in (integer) microamps, or the string "Auto".
204 : * If \a range is not a known valid value, then an null QVariant is returned.
205 : *
206 : * \see PokitMeter::maxValue(const PokitMeter::CurrentRange &range)
207 : * \see PokitPro::maxValue(const PokitPro::CurrentRange &range)
208 : */
209 270 : QVariant maxValue(const PokitProduct product, const quint8 range)
210 : {
211 270 : switch (product) {
212 126 : case PokitProduct::PokitMeter:
213 126 : return PokitMeter::maxValue(static_cast<PokitMeter::CurrentRange>(range));
214 126 : case PokitProduct::PokitPro:
215 126 : return PokitPro::maxValue(static_cast<PokitPro::CurrentRange>(range));
216 : }
217 56 : qCWarning(lc).noquote() << QCoreApplication::translate("CurrentRange",
218 28 : "Unknown PokitProduct value: %1", "maxValue").arg((int)product);
219 : return QVariant();
220 : }
221 :
222 : }
223 :
224 : /// Encapsulates convenience functions for working with resistance ranges.
225 : namespace ResistanceRange {
226 :
227 : /*!
228 : * Returns \a product's current \a range as a human-friendly string.
229 : *
230 : * \see PokitMeter::toString(const PokitMeter::ResistanceRange &range)
231 : * \see PokitPro::toString(const PokitPro::ResistanceRange &range)
232 : */
233 234 : QString toString(const PokitProduct product, const quint8 range)
234 : {
235 234 : switch (product) {
236 162 : case PokitProduct::PokitMeter:
237 162 : return PokitMeter::toString(static_cast<PokitMeter::ResistanceRange>(range));
238 54 : case PokitProduct::PokitPro:
239 54 : return PokitPro::toString(static_cast<PokitPro::ResistanceRange>(range));
240 : }
241 56 : qCWarning(lc).noquote() << QCoreApplication::translate("ResistanceRange",
242 28 : "Unknown PokitProduct value: %1", "toString").arg((int)product);
243 : return QString();
244 : }
245 :
246 : /*!
247 : * Returns the maximum value for \a product's \a range in (integer) ohms, or the string "Auto".
248 : * If \a range is not a known valid value, then an null QVariant is returned.
249 : *
250 : * \see PokitMeter::maxValue(const PokitMeter::ResistanceRange &range)
251 : * \see PokitPro::maxValue(const PokitPro::ResistanceRange &range)
252 : */
253 126 : QVariant maxValue(const PokitProduct product, const quint8 range)
254 : {
255 126 : switch (product) {
256 54 : case PokitProduct::PokitMeter:
257 54 : return PokitMeter::maxValue(static_cast<PokitMeter::ResistanceRange>(range));
258 54 : case PokitProduct::PokitPro:
259 54 : return PokitPro::maxValue(static_cast<PokitPro::ResistanceRange>(range));
260 : }
261 56 : qCWarning(lc).noquote() << QCoreApplication::translate("ResistanceRange",
262 28 : "Unknown PokitProduct value: %1", "maxValue").arg((int)product);
263 : return QVariant();
264 : }
265 :
266 : }
267 :
268 : /// Encapsulates convenience functions for working with voltage ranges.
269 : namespace VoltageRange {
270 :
271 : /*!
272 : * Returns \a product's current \a range as a human-friendly string.
273 : *
274 : * \see PokitMeter::toString(const PokitMeter::VoltageRange &range)
275 : * \see PokitPro::toString(const PokitPro::VoltageRange &range)
276 : */
277 1782 : QString toString(const PokitProduct product, const quint8 range)
278 : {
279 1782 : switch (product) {
280 1638 : case PokitProduct::PokitMeter:
281 1638 : return PokitMeter::toString(static_cast<PokitMeter::VoltageRange>(range));
282 126 : case PokitProduct::PokitPro:
283 126 : return PokitPro::toString(static_cast<PokitPro::VoltageRange>(range));
284 : }
285 56 : qCWarning(lc).noquote() << QCoreApplication::translate("VoltageRange",
286 28 : "Unknown PokitProduct value: %1", "toString").arg((int)product);
287 : return QString();
288 : }
289 :
290 : /*!
291 : * Returns the maximum value for \a product's \a range in (integer) millivolts, or the string "Auto".
292 : * If \a range is not a known valid value, then an null QVariant is returned.
293 : *
294 : * \see PokitMeter::maxValue(const PokitMeter::VoltageRange &range)
295 : * \see PokitPro::maxValue(const PokitPro::VoltageRange &range)
296 : */
297 270 : QVariant maxValue(const PokitProduct product, const quint8 range)
298 : {
299 270 : switch (product) {
300 126 : case PokitProduct::PokitMeter:
301 126 : return PokitMeter::maxValue(static_cast<PokitMeter::VoltageRange>(range));
302 126 : case PokitProduct::PokitPro:
303 126 : return PokitPro::maxValue(static_cast<PokitPro::VoltageRange>(range));
304 : }
305 56 : qCWarning(lc).noquote() << QCoreApplication::translate("VoltageRange",
306 28 : "Unknown PokitProduct value: %1", "maxValue").arg((int)product);
307 : return QVariant();
308 : }
309 :
310 : }
311 :
312 : /// \endcond
|