Line data Source code
1 : // SPDX-FileCopyrightText: 2022 Paul Colby <git@colby.id.au>
2 : // SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 : /*!
5 : * \file
6 : * Defines the PokitDiscoveryAgent and PokitDiscoveryAgentPrivate classes.
7 : */
8 :
9 : #include <qtpokit/pokitdiscoveryagent.h>
10 : #include "pokitdiscoveryagent_p.h"
11 :
12 : #include <qtpokit/statusservice.h>
13 :
14 : #include <QBluetoothUuid>
15 :
16 : /*!
17 : * \class PokitDiscoveryAgent
18 : *
19 : * The PokitDiscoveryAgent class discovers nearby Pokit devices.
20 : *
21 : * After constructing a PokitDiscoveryAgent object, and subscribing to the relevant signals,
22 : * invoke start() to begin discovery.
23 : */
24 :
25 : /*!
26 : * Constructs a new Pokit device discovery agent with \a parent, using \a deviceAdapter for the
27 : * search device.
28 : */
29 0 : PokitDiscoveryAgent::PokitDiscoveryAgent(
30 0 : const QBluetoothAddress &deviceAdapter, QObject *parent)
31 : : QBluetoothDeviceDiscoveryAgent(deviceAdapter, parent),
32 0 : d_ptr(new PokitDiscoveryAgentPrivate(this))
33 : {
34 :
35 0 : }
36 :
37 : /*!
38 : * Constructs a new Pokit device discovery agent with \a parent.
39 : */
40 7530 : PokitDiscoveryAgent::PokitDiscoveryAgent(QObject * parent)
41 : : QBluetoothDeviceDiscoveryAgent(parent),
42 7530 : d_ptr(new PokitDiscoveryAgentPrivate(this))
43 : {
44 :
45 7530 : }
46 :
47 : /*!
48 : * \cond internal
49 : * Constructs a new Pokit device discovery agent with \a parent, using \a deviceAdapter for the
50 : * search device, and private implementation \a d.
51 : */
52 0 : PokitDiscoveryAgent::PokitDiscoveryAgent(
53 : PokitDiscoveryAgentPrivate * const d, const QBluetoothAddress &deviceAdapter,
54 0 : QObject * const parent)
55 0 : : QBluetoothDeviceDiscoveryAgent(deviceAdapter, parent), d_ptr(d)
56 : {
57 :
58 0 : }
59 :
60 : /*!
61 : * Constructs a new Pokit device discovery agent with \a parent, and private implementation \a d.
62 : */
63 0 : PokitDiscoveryAgent::PokitDiscoveryAgent(
64 0 : PokitDiscoveryAgentPrivate * const d, QObject * const parent)
65 0 : : QBluetoothDeviceDiscoveryAgent(parent), d_ptr(d)
66 : {
67 :
68 0 : }
69 : /// \endcond
70 :
71 : /*!
72 : * Destroys this PokitDiscoveryAgent object.
73 : */
74 14760 : PokitDiscoveryAgent::~PokitDiscoveryAgent()
75 : {
76 7530 : delete d_ptr;
77 14760 : }
78 :
79 : /*!
80 : * Returns \c true if \a info describes a Pokit device.
81 : *
82 : * Currently, this is based on whether or not \a info's service UUIDs includes a known Pokit
83 : * service, but this test criteria might be swapped for something else sometime.
84 : */
85 368 : bool PokitDiscoveryAgent::isPokitDevice(const QBluetoothDeviceInfo &info)
86 : {
87 368 : return (isPokitMeter(info) || isPokitPro(info));
88 : }
89 :
90 : /*!
91 : * Returns \c true if \a info describes a Pokit Meter device.
92 : *
93 : * Currently, this is based on whether or not \a info's service UUIDs includes a known Pokit
94 : * service, but this test criteria might be swapped for something else sometime.
95 : */
96 504 : bool PokitDiscoveryAgent::isPokitMeter(const QBluetoothDeviceInfo &info)
97 : {
98 912 : return info.serviceUuids().contains(StatusService::ServiceUuids::pokitMeter);
99 : }
100 :
101 : /*!
102 : * Returns \c true if \a info describes a Pokit Pro device.
103 : *
104 : * Currently, this is based on whether or not \a info's service UUIDs includes a known Pokit
105 : * service, but this test criteria might be swapped for something else sometime.
106 : */
107 412 : bool PokitDiscoveryAgent::isPokitPro(const QBluetoothDeviceInfo &info)
108 : {
109 746 : return info.serviceUuids().contains(StatusService::ServiceUuids::pokitPro);
110 : }
111 :
112 : /*!
113 : * Starts Pokit device discovery.
114 : *
115 : * This override simply enforces that \a method must be \c LowEnergyMethod, as all Pokit devices
116 : * used Bluetooth Low Energy (BLE).
117 : */
118 0 : void PokitDiscoveryAgent::start(QBluetoothDeviceDiscoveryAgent::DiscoveryMethods methods)
119 : {
120 : Q_D(PokitDiscoveryAgent);
121 : Q_ASSERT(methods == QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
122 0 : qCDebug(d->lc).noquote() << tr("Scanning for Bluetooth Low Energy devices.");
123 0 : QBluetoothDeviceDiscoveryAgent::start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
124 0 : }
125 :
126 : /*!
127 : * Starts Pokit device discovery.
128 : */
129 51 : void PokitDiscoveryAgent::start()
130 : {
131 : Q_D(PokitDiscoveryAgent);
132 51 : qCDebug(d->lc).noquote() << tr("Scanning for Bluetooth Low Energy devices.");
133 51 : QBluetoothDeviceDiscoveryAgent::start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
134 51 : }
135 :
136 : /*!
137 : * \fn void PokitDiscoveryAgent::pokitDeviceDiscovered(const QBluetoothDeviceInfo &info)
138 : *
139 : * This signal is emitted when the Pokit device described by \a info is discovered.
140 : */
141 :
142 : /*!
143 : * \fn void PokitDiscoveryAgent::pokitDeviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields)
144 : *
145 : * This signal is emitted when the Pokit device described by \a info is updated. The
146 : * \a updatedFields flags tell which information has been updated.
147 : */
148 :
149 : /*!
150 : * \cond internal
151 : * \class PokitDiscoveryAgentPrivate
152 : *
153 : * The PokitDiscoveryAgentPrivate class provides private implementation for
154 : * PokitDiscoveryAgent.
155 : */
156 :
157 : /*!
158 : * \internal
159 : * Constructs a new PokitDiscoveryAgentPrivate object with public implementation \a q.
160 : */
161 7530 : PokitDiscoveryAgentPrivate::PokitDiscoveryAgentPrivate(PokitDiscoveryAgent * const q)
162 7530 : : q_ptr(q)
163 : {
164 7530 : connect(q, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,
165 : this, &PokitDiscoveryAgentPrivate::deviceDiscovered);
166 :
167 : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Signal added in Qt 5.12.
168 5466 : connect(q, &QBluetoothDeviceDiscoveryAgent::deviceUpdated,
169 : this, &PokitDiscoveryAgentPrivate::deviceUpdated);
170 : #endif
171 7530 : }
172 :
173 : /*!
174 : * Handle scan canceled signals, by simply logging the event for diagnostic purposes.
175 : */
176 17 : void PokitDiscoveryAgentPrivate::canceled()
177 : {
178 17 : qCDebug(lc).noquote() << tr("Pokit device scan cancelled.");
179 17 : }
180 :
181 : /*!
182 : * Handle deviceDiscovered signals.
183 : *
184 : * Here we simply check if \a info describes a Pokit device, and if so, emit pokitDeviceDiscovered().
185 : */
186 136 : void PokitDiscoveryAgentPrivate::deviceDiscovered(const QBluetoothDeviceInfo &info)
187 : {
188 88 : Q_Q(PokitDiscoveryAgent);
189 136 : if (!q->isPokitDevice(info)) return;
190 51 : qCDebug(lc).noquote() << tr("Discovered Pokit device \"%1\" at %2.")
191 0 : .arg(info.name(), info.address().toString());
192 51 : emit q->pokitDeviceDiscovered(info);
193 : }
194 :
195 : #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) // Required signal, and Fields, added in Qt 5.12.
196 : /*!
197 : * Handle deviceUpdated signals.
198 : *
199 : * Here we simply check if \a info describes a Pokit device, and if so, emit pokitDeviceUpdated().
200 : *
201 : * \since Qt 5.12.0
202 : */
203 96 : void PokitDiscoveryAgentPrivate::deviceUpdated(
204 : const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields)
205 : {
206 64 : Q_Q(PokitDiscoveryAgent);
207 96 : if (!q->isPokitDevice(info)) return;
208 36 : qCDebug(lc).noquote() << tr("Pokit device \"%1\" at %2 updated with RSSI %3.")
209 0 : .arg(info.name(), info.address().toString()).arg(info.rssi());
210 36 : emit q->pokitDeviceUpdated(info, updatedFields);
211 : }
212 : #endif
213 :
214 : /*!
215 : * Handle scan errors, by simply logging \a error for diagnostic purposes.
216 : */
217 17 : void PokitDiscoveryAgentPrivate::error(const QBluetoothDeviceDiscoveryAgent::Error error)
218 : {
219 51 : qCWarning(lc).noquote() << tr("Pokit device scan error:") << error;
220 17 : }
221 :
222 : /*!
223 : * Handle scan finished signals, by simply logging the event for diagnostic purposes.
224 : */
225 17 : void PokitDiscoveryAgentPrivate::finished()
226 : {
227 17 : qCDebug(lc).noquote() << tr("Pokit device scan finished.");
228 17 : }
229 :
230 : /// \endcond
|