11#include "pokitproducts_p.h"
17#include <QLowEnergyController>
120 : AbstractPokitService(d,
parent)
158 if (!characteristic.
isValid()) {
162 const bool updateIntervalIs32bit =
169 d->service->writeCharacteristic(characteristic, value);
170 return (d->service->error() != QLowEnergyService::ServiceError::CharacteristicWriteError);
184 qCWarning(d->lc).noquote() <<
tr(
"Settings command must be 'Start'.");
346 const bool updateIntervalIs32bit)
348 static_assert(
sizeof(settings.
command) == 1,
"Expected to be 1 byte.");
349 static_assert(
sizeof(settings.
arguments) == 2,
"Expected to be 2 bytes.");
350 static_assert(
sizeof(settings.
mode) == 1,
"Expected to be 1 byte.");
351 static_assert(
sizeof(settings.
range) == 1,
"Expected to be 1 byte.");
352 static_assert(
sizeof(settings.
updateInterval) == 4,
"Expected to be 4 bytes.");
353 static_assert(
sizeof(settings.
timestamp) == 4,
"Expected to be 4 bytes.");
367 if (!updateIntervalIs32bit) {
369 Q_ASSERT(value.
size() == 11);
372 Q_ASSERT(value.
size() == 13);
392 qCDebug(lc) << value.
mid(7,12).
toHex(
',');
394 metadata.scale = qFromLittleEndian<float>(value.
mid(1,4).
constData());
396 metadata.range =
static_cast<quint8
>(value.
at(6));
405 if (value.
size() == 15) {
406 metadata.updateInterval = qFromLittleEndian<quint16>(value.
mid(7,2).
constData())*1000;
407 metadata.numberOfSamples = qFromLittleEndian<quint16>(value.
mid(9,2).
constData());
408 metadata.timestamp = qFromLittleEndian<quint32>(value.
mid(11,4).
constData());
409 }
else if (value.
size() == 23) {
410 metadata.updateInterval = qFromLittleEndian<quint32>(value.
mid(7,4).
constData());
411 metadata.numberOfSamples = qFromLittleEndian<quint16>(value.
mid(11,2).
constData());
412 metadata.timestamp = qFromLittleEndian<quint32>(value.
mid(19,4).
constData());
414 qCWarning(lc).noquote() <<
tr(
"Cannot decode metadata of %n byte/s: %1",
nullptr, value.
size())
426 if ((value.
size()%2) != 0) {
427 qCWarning(lc).noquote() <<
tr(
"Samples value has odd size %1 (should be even): %2")
431 while ((samples.
size()*2) < value.
size()) {
434 qCDebug(lc).noquote() <<
tr(
"Read %n sample/s from %1-bytes.",
nullptr, samples.
size()).
arg(value.
size());
448 qCWarning(lc).noquote() <<
tr(
"Settings characteristic is write-only, but somehow read")
460 qCWarning(lc).noquote() <<
tr(
"Reading characteristic is notify-only")
465 qCWarning(lc).noquote() <<
tr(
"Unknown characteristic read for Data Logger service")
480 Q_EMIT q->settingsWritten();
485 qCWarning(lc).noquote() <<
tr(
"Metadata characteristic is read/notify, but somehow written")
491 qCWarning(lc).noquote() <<
tr(
"Reading characteristic is notify-only, but somehow written")
496 qCWarning(lc).noquote() <<
tr(
"Unknown characteristic written for Data Logger service")
511 qCWarning(lc).noquote() <<
tr(
"Settings characteristic is write-only, but somehow updated")
526 qCWarning(lc).noquote() <<
tr(
"Unknown characteristic notified for Data Logger service")
QBluetoothUuid serviceUuid
UUIDs for service.
virtual void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue)
Handles QLowEnergyService::characteristicChanged events.
AbstractPokitServicePrivate(const QBluetoothUuid &serviceUuid, QLowEnergyController *controller, AbstractPokitService *const q)
virtual void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
Handles QLowEnergyService::characteristicRead events.
virtual void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue)
Handles QLowEnergyService::characteristicWritten events.
QLowEnergyController * controller
BLE controller to fetch the service from.
static QString toHexString(const QByteArray &data, const int maxSize=20)
Returns up to maxSize bytes of data as a human readable hexadecimal string.
static bool checkSize(const QString &label, const QByteArray &data, const int minSize, const int maxSize=-1, const bool failOnMax=false)
Returns false if data is smaller than minSize, otherwise returns failOnMax if data is bigger than max...
std::optional< PokitProduct > pokitProduct() const
Returns the Pokit product this service is attached to.
The DataLoggerServicePrivate class provides private implementation for DataLoggerService.
void characteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) override
Implements AbstractPokitServicePrivate::characteristicChanged to parse newValue, then emit a speciali...
void characteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &newValue) override
Implements AbstractPokitServicePrivate::characteristicWritten to parse newValue, then emit a speciali...
static QByteArray encodeSettings(const DataLoggerService::Settings &settings, const bool updateIntervalIs32bit)
Returns settings in the format Pokit devices expect.
void characteristicRead(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) override
Implements AbstractPokitServicePrivate::characteristicRead to parse value, then emit a specialised si...
static DataLoggerService::Samples parseSamples(const QByteArray &value)
Parses the Reading value into a DataLoggerService::Samples vector.
static DataLoggerService::Metadata parseMetadata(const QByteArray &value)
Parses the Metadata value into a DataLoggerService::Metatdata struct.
DataLoggerServicePrivate(QLowEnergyController *controller, DataLoggerService *const q)
The DataLoggerService class accesses the Data Logger service of Pokit devices.
bool readMetadataCharacteristic()
Reads the DataLogger service's Metadata characteristic.
bool enableMetadataNotifications()
Enables client-side notifications of Data Logger metadata changes.
LoggerStatus
Values supported by the Status attribute of the Metadata characteristic.
@ Error
An error has occurred.
DataLoggerService(QLowEnergyController *const pokitDevice, QObject *parent=nullptr)
Constructs a new Pokit service with parent.
bool disableMetadataNotifications()
Disables client-side notifications of Data Logger metadata changes.
bool enableReadingNotifications()
Enables client-side notifications of Data Logger readings.
bool setSettings(const Settings &settings)
Configures the Pokit device's data logger mode.
bool startLogger(const Settings &settings)
Start the data logger with settings.
QVector< qint16 > Samples
Raw samples from the Reading characteristic.
static QString toString(const Mode &mode)
Returns mode as a user-friendly string.
bool fetchSamples()
Start the data logger.
static quint32 maxValue(const PokitProduct product, const quint8 range, const Mode mode)
Returns the maximum value for range, or 0 if range is not a known value for product's mode.
bool readCharacteristics() override
Read all characteristics.
QString toString(const quint8 range, const Mode mode) const
Returns range as a user-friendly string, or a null QString if mode has no ranges.
@ Stop
Stop the Data Logger.
@ Refresh
Refresh the Data Logger.
@ Start
Start the Data Logger.
bool disableReadingNotifications()
Disables client-side notifications of Data Logger readings.
bool stopLogger()
Stop the data logger.
Metadata metadata() const
Returns the most recent value of the DataLogger service's Metadata characteristic.
Mode
Values supported by the Mode attribute of the Settings and Metadata characteristics.
@ DcVoltage
Measure DC voltage.
@ AcCurrent
Measure AC current.
@ AcVoltage
Measure AC voltage.
@ Temperature
Measure temperature.
@ DcCurrent
Measure DC current.
Declares the DataLoggerService class.
Declares the DataLoggerServicePrivate class.
QString toString(const PokitProduct product, const quint8 range)
Returns product's current range as a human-friendly string.
quint32 maxValue(const PokitProduct product, const quint8 range)
Returns the maximum value for range in microamps, or 0 if range is not a known value for product.
quint32 maxValue(const PokitProduct product, const quint8 range)
Returns the maximum value for range in millivolts, or 0 if range is not a known value for product.
QString toString(const PokitProduct product, const quint8 range)
Returns product's current range as a human-friendly string.
PokitProduct
Pokit products known to, and supported by, the QtPokit library.
char at(int i) const const
const char * constData() const const
bool isNull() const const
QByteArray mid(int pos, int len) const const
QByteArray toHex() const const
void setByteOrder(QDataStream::ByteOrder bo)
void setFloatingPointPrecision(QDataStream::FloatingPointPrecision precision)
bool isValid() const const
QString name() const const
QBluetoothUuid uuid() const const
QByteArray value() const const
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void append(const T &value)
Declares the StatusService class.
static const QBluetoothUuid metadata
UUID of the DataLogger service's Metadata characterstic.
static const QBluetoothUuid settings
UUID of the DataLogger service's Settings characterstic.
static const QBluetoothUuid reading
UUID of the DataLogger service's Reading characterstic.
Attributes included in the Settings characterstic.
quint32 timestamp
Custom timestamp for start time in retrieved metadata.
quint16 arguments
Reserved to used along with command in future.
Command command
Custom operation request.
quint8 range
Desired range.
Mode mode
Desired operation mode.
quint32 updateInterval
Desired update interval in milliseconds.