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 847 : 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 57 : QString toString(const PokitProduct product)
27 : {
28 57 : switch (product) {
29 19 : case PokitProduct::PokitMeter: return QStringLiteral("Pokit Meter");
30 19 : case PokitProduct::PokitPro: return QStringLiteral("Pokit Pro");
31 : }
32 60 : qCWarning(lc).noquote() << QCoreApplication::translate("PokitProducts",
33 30 : "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 521 : bool isPokitProduct(const QBluetoothDeviceInfo &info)
44 : {
45 666 : 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 95 : PokitProduct pokitProduct(const QBluetoothDeviceInfo &info)
56 : {
57 120 : 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 863 : bool isPokitProduct(const QList<QBluetoothUuid> &serviceUuids)
74 : {
75 1389 : return (serviceUuids.contains(StatusService::ServiceUuids::pokitMeter) ||
76 863 : 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 114 : bool isPokitProduct(const QLowEnergyController &controller)
89 : {
90 144 : 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 285 : PokitProduct pokitProduct(const QList<QBluetoothUuid> &serviceUuids)
102 : {
103 285 : if (serviceUuids.contains(StatusService::ServiceUuids::pokitMeter)) {
104 : return PokitProduct::PokitMeter;
105 209 : } else if (serviceUuids.contains(StatusService::ServiceUuids::pokitPro)) {
106 : return PokitProduct::PokitPro;
107 : } else {
108 280 : qCWarning(lc).noquote()
109 168 : << QCoreApplication::translate("PokitProducts", "Device is not a Pokit product", "pokitProduct");
110 147 : qCDebug(lc).noquote() << "Service UUIDs:" << serviceUuids;
111 119 : 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 95 : PokitProduct pokitProduct(const QLowEnergyController &controller)
124 : {
125 120 : 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 209 : QString toString(const PokitProduct product, const quint8 range)
141 : {
142 209 : switch (product) {
143 76 : case PokitProduct::PokitMeter:
144 160 : qCWarning(lc).noquote()
145 96 : << QCoreApplication::translate("PokitProducts", "Pokit Meter has no capacitance support", "toString");
146 : return QString();
147 114 : case PokitProduct::PokitPro:
148 114 : return PokitPro::toString(static_cast<PokitPro::CapacitanceRange>(range));
149 : }
150 60 : qCWarning(lc).noquote() << QCoreApplication::translate("CapacitanceRange",
151 30 : "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 95 : QVariant maxValue(const PokitProduct product, const quint8 range)
164 : {
165 95 : switch (product) {
166 19 : case PokitProduct::PokitMeter:
167 40 : qCWarning(lc).noquote()
168 24 : << QCoreApplication::translate("PokitProducts", "Pokit Meter has no capacitance support", "toString");
169 : return QVariant();
170 57 : case PokitProduct::PokitPro:
171 57 : return PokitPro::maxValue(static_cast<PokitPro::CapacitanceRange>(range));
172 : }
173 60 : qCWarning(lc).noquote() << QCoreApplication::translate("CapacitanceRange",
174 30 : "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 1881 : QString toString(const PokitProduct product, const quint8 range)
190 : {
191 1881 : switch (product) {
192 1729 : case PokitProduct::PokitMeter:
193 1729 : return PokitMeter::toString(static_cast<PokitMeter::CurrentRange>(range));
194 133 : case PokitProduct::PokitPro:
195 133 : return PokitPro::toString(static_cast<PokitPro::CurrentRange>(range));
196 : }
197 60 : qCWarning(lc).noquote() << QCoreApplication::translate("CurrentRange",
198 30 : "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 285 : QVariant maxValue(const PokitProduct product, const quint8 range)
210 : {
211 285 : switch (product) {
212 133 : case PokitProduct::PokitMeter:
213 133 : return PokitMeter::maxValue(static_cast<PokitMeter::CurrentRange>(range));
214 133 : case PokitProduct::PokitPro:
215 133 : return PokitPro::maxValue(static_cast<PokitPro::CurrentRange>(range));
216 : }
217 60 : qCWarning(lc).noquote() << QCoreApplication::translate("CurrentRange",
218 30 : "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 247 : QString toString(const PokitProduct product, const quint8 range)
234 : {
235 247 : switch (product) {
236 171 : case PokitProduct::PokitMeter:
237 171 : return PokitMeter::toString(static_cast<PokitMeter::ResistanceRange>(range));
238 57 : case PokitProduct::PokitPro:
239 57 : return PokitPro::toString(static_cast<PokitPro::ResistanceRange>(range));
240 : }
241 60 : qCWarning(lc).noquote() << QCoreApplication::translate("ResistanceRange",
242 30 : "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 133 : QVariant maxValue(const PokitProduct product, const quint8 range)
254 : {
255 133 : switch (product) {
256 57 : case PokitProduct::PokitMeter:
257 57 : return PokitMeter::maxValue(static_cast<PokitMeter::ResistanceRange>(range));
258 57 : case PokitProduct::PokitPro:
259 57 : return PokitPro::maxValue(static_cast<PokitPro::ResistanceRange>(range));
260 : }
261 60 : qCWarning(lc).noquote() << QCoreApplication::translate("ResistanceRange",
262 30 : "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 1881 : QString toString(const PokitProduct product, const quint8 range)
278 : {
279 1881 : switch (product) {
280 1729 : case PokitProduct::PokitMeter:
281 1729 : return PokitMeter::toString(static_cast<PokitMeter::VoltageRange>(range));
282 133 : case PokitProduct::PokitPro:
283 133 : return PokitPro::toString(static_cast<PokitPro::VoltageRange>(range));
284 : }
285 60 : qCWarning(lc).noquote() << QCoreApplication::translate("VoltageRange",
286 30 : "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 285 : QVariant maxValue(const PokitProduct product, const quint8 range)
298 : {
299 285 : switch (product) {
300 133 : case PokitProduct::PokitMeter:
301 133 : return PokitMeter::maxValue(static_cast<PokitMeter::VoltageRange>(range));
302 133 : case PokitProduct::PokitPro:
303 133 : return PokitPro::maxValue(static_cast<PokitPro::VoltageRange>(range));
304 : }
305 60 : qCWarning(lc).noquote() << QCoreApplication::translate("VoltageRange",
306 30 : "Unknown PokitProduct value: %1", "maxValue").arg((int)product);
307 : return QVariant();
308 : }
309 :
310 : }
311 :
312 : /// \endcond
|