1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qsensorbackend.h"
5#include "qsensorbackend_p.h"
6#include "qsensor_p.h"
7#include <QDebug>
8
9QT_BEGIN_NAMESPACE
10
11/*!
12 \class QSensorBackend
13 \ingroup sensors_backend
14 \inmodule QtSensors
15 \since 5.1
16
17 \brief The QSensorBackend class is a sensor implementation.
18
19 Sensors on a device will be represented by sub-classes of
20 QSensorBackend.
21*/
22
23/*!
24 \internal
25*/
26QSensorBackend::QSensorBackend(QSensor *sensor, QObject *parent)
27 : QObject(*new QSensorBackendPrivate(sensor), parent)
28{
29}
30
31/*!
32 \internal
33*/
34QSensorBackend::~QSensorBackend()
35{
36}
37
38/*!
39 Checks whether a feature is supported by this sensor backend.
40
41 This is the backend side of QSensor::isFeatureSupported(). Reimplement this function if the
42 backend supports one of the additional sensor features of QSensor::Feature.
43
44 Returns whether the feature \a feature is supported by this backend. The default implementation returns false.
45 \since 5.0
46 */
47bool QSensorBackend::isFeatureSupported(QSensor::Feature feature) const
48{
49 Q_UNUSED(feature);
50 return false;
51}
52
53/*!
54 Notify the QSensor class that a new reading is available.
55*/
56void QSensorBackend::newReadingAvailable()
57{
58 Q_D(QSensorBackend);
59 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
60
61 // Copy the values from the device reading to the filter reading
62 sensorPrivate->filter_reading->copyValuesFrom(other: sensorPrivate->device_reading);
63
64 for (QFilterList::const_iterator it = sensorPrivate->filters.constBegin(); it != sensorPrivate->filters.constEnd(); ++it) {
65 QSensorFilter *filter = (*it);
66 if (!filter->filter(reading: sensorPrivate->filter_reading))
67 return;
68 }
69
70 // Copy the values from the filter reading to the cached reading
71 sensorPrivate->cache_reading->copyValuesFrom(other: sensorPrivate->filter_reading);
72
73 Q_EMIT d->m_sensor->readingChanged();
74}
75
76/*!
77 \fn QSensorBackend::start()
78
79 Start reporting values.
80*/
81
82/*!
83 \fn QSensorBackend::stop()
84
85 Stop reporting values.
86*/
87
88/*!
89 If the backend has lost its reference to the reading
90 it can call this method to get the address.
91
92 Note that you will need to down-cast to the appropriate
93 type.
94
95 \sa setReading()
96*/
97QSensorReading *QSensorBackend::reading() const
98{
99 Q_D(const QSensorBackend);
100 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
101 return sensorPrivate->device_reading;
102}
103
104/*!
105 Returns the sensor front end associated with this backend.
106*/
107QSensor *QSensorBackend::sensor() const
108{
109 Q_D(const QSensorBackend);
110 return d->m_sensor;
111}
112
113/*!
114 \fn template <typename T> T *QSensorBackend::setReading(T *reading)
115
116 This function is called to initialize the \a reading
117 classes used for a sensor.
118
119 If your backend has already allocated a reading you
120 should pass the address of this to the function.
121 Otherwise you should pass 0 and the function will
122 return the address of the reading your backend
123 should use when it wants to notify the sensor API
124 of new readings.
125
126 Note that this is a template function so it should
127 be called with the appropriate type.
128
129 \code
130 class MyBackend : public QSensorBackend
131 {
132 QAccelerometerReading m_reading;
133 public:
134 MyBackend(QSensor *sensor)
135 : QSensorBackend(sensor)
136 {
137 setReading<QAccelerometerReading>(&m_reading);
138 }
139
140 ...
141 \endcode
142
143 Note that this function must be called or you will
144 not be able to send readings to the front end.
145
146 If you do not wish to store the address of the reading
147 you may use the reading() method to get it again later.
148
149 \code
150 class MyBackend : public QSensorBackend
151 {
152 public:
153 MyBackend(QSensor *sensor)
154 : QSensorBackend(sensor)
155 {
156 setReading<QAccelerometerReading>(0);
157 }
158
159 void poll()
160 {
161 quint64 timestamp;
162 qreal x, y, z;
163 ...
164 QAccelerometerReading *reading = static_cast<QAccelerometerReading*>(reading());
165 reading->setTimestamp(timestamp);
166 reading->setX(x);
167 reading->setY(y);
168 reading->setZ(z);
169 }
170
171 ...
172 \endcode
173
174 \sa reading()
175*/
176
177/*!
178 \internal
179*/
180void QSensorBackend::setReadings(QSensorReading *device, QSensorReading *filter, QSensorReading *cache)
181{
182 Q_D(QSensorBackend);
183 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
184 sensorPrivate->device_reading = device;
185 sensorPrivate->filter_reading = filter;
186 sensorPrivate->cache_reading = cache;
187}
188
189/*!
190 Add a data rate (consisting of \a min and \a max values) for the sensor.
191
192 Note that this function should be called from the constructor so that the information
193 is available immediately.
194
195 \sa QSensor::availableDataRates
196*/
197void QSensorBackend::addDataRate(qreal min, qreal max)
198{
199 Q_D(QSensorBackend);
200 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
201 sensorPrivate->availableDataRates << qrange(min, max);
202}
203
204/*!
205 Set the data rates for the sensor based on \a otherSensor.
206
207 This is designed for sensors that are based on other sensors.
208
209 \code
210 setDataRates(otherSensor);
211 \endcode
212
213 Note that this function must be called from the constructor.
214
215 \sa QSensor::availableDataRates, addDataRate()
216*/
217void QSensorBackend::setDataRates(const QSensor *otherSensor)
218{
219 Q_D(QSensorBackend);
220 if (!otherSensor) {
221 qWarning() << "ERROR: Cannot call QSensorBackend::setDataRates with 0";
222 return;
223 }
224 if (otherSensor->identifier().isEmpty()) {
225 qWarning() << "ERROR: Cannot call QSensorBackend::setDataRates with an invalid sensor";
226 return;
227 }
228 if (d->m_sensor->isConnectedToBackend()) {
229 qWarning() << "ERROR: Cannot call QSensorBackend::setDataRates outside of the constructor";
230 return;
231 }
232 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
233 sensorPrivate->availableDataRates = otherSensor->availableDataRates();
234}
235
236/*!
237 Add an output range (consisting of \a min, \a max values and \a accuracy) for the sensor.
238
239 Note that this function should be called from the constructor so that the information
240 is available immediately.
241
242 \sa QSensor::outputRange, QSensor::outputRanges
243*/
244void QSensorBackend::addOutputRange(qreal min, qreal max, qreal accuracy)
245{
246 Q_D(QSensorBackend);
247 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
248
249 qoutputrange details = {.minimum: min, .maximum: max, .accuracy: accuracy};
250
251 sensorPrivate->outputRanges << details;
252}
253
254/*!
255 Set the \a description for the sensor.
256
257 Note that this function should be called from the constructor so that the information
258 is available immediately.
259*/
260void QSensorBackend::setDescription(const QString &description)
261{
262 Q_D(QSensorBackend);
263 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
264 sensorPrivate->description = description;
265}
266
267/*!
268 Inform the front end that the sensor has stopped.
269 This can be due to start() failing or for some
270 unexpected reason (eg. hardware failure).
271
272 Note that the front end must call QSensor::isActive() to see if
273 the sensor has stopped. If the sensor has stopped due to an error
274 the sensorError() function should be called to notify the class
275 of the error condition.
276*/
277void QSensorBackend::sensorStopped()
278{
279 Q_D(QSensorBackend);
280 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
281 sensorPrivate->active = false;
282}
283
284/*!
285 Inform the front end of the sensor's busy state according
286 to the provided \a busy parameter.
287
288 If the sensor is set \e busy this implicitly calls sensorStopped().
289 Busy indication is typically done in start().
290
291 Note that the front end must call QSensor::isBusy() to see if
292 the sensor is busy. If the sensor has stopped due to an error
293 the sensorError() function should be called to notify the class
294 of the error condition.
295*/
296void QSensorBackend::sensorBusy(bool busy)
297{
298 Q_D(QSensorBackend);
299 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
300 if (sensorPrivate->busy == busy)
301 return;
302 if (busy)
303 sensorPrivate->active = false;
304 sensorPrivate->busy = busy;
305 emit d->m_sensor->busyChanged();
306}
307
308/*!
309 Inform the front end that a sensor error occurred.
310 Note that this only reports an \a error code. It does
311 not stop the sensor.
312
313 \sa sensorStopped()
314*/
315void QSensorBackend::sensorError(int error)
316{
317 Q_D(QSensorBackend);
318 QSensorPrivate *sensorPrivate = d->m_sensor->d_func();
319 sensorPrivate->error = error;
320 Q_EMIT d->m_sensor->sensorError(error);
321}
322
323QT_END_NAMESPACE
324
325#include "moc_qsensorbackend.cpp"
326

source code of qtsensors/src/sensors/qsensorbackend.cpp