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 : #include "loggerfetchcommand.h" 5 : 6 : #include <qtpokit/pokitdevice.h> 7 : 8 : #include <QDateTime> 9 : #include <QJsonDocument> 10 : #include <QJsonObject> 11 : 12 : #include <iostream> 13 : 14 : /*! 15 : * \class LoggerFetchCommand 16 : * 17 : * The LoggerFetchCommand class implements the `logger` CLI command. 18 : */ 19 : 20 : /*! 21 : * Construct a new LoggerFetchCommand object with \a parent. 22 : */ 23 1054 : LoggerFetchCommand::LoggerFetchCommand(QObject * const parent) 24 1054 : : DeviceCommand(parent), service(nullptr), showCsvHeader(true) 25 : { 26 : 27 1054 : } 28 : 29 : /*! 30 : * \copybrief DeviceCommand::getService 31 : * 32 : * This override returns a pointer to a DataLoggerService object. 33 : */ 34 0 : AbstractPokitService * LoggerFetchCommand::getService() 35 : { 36 : Q_ASSERT(device); 37 0 : if (!service) { 38 0 : service = device->dataLogger(); 39 : Q_ASSERT(service); 40 0 : connect(service, &DataLoggerService::metadataRead, this, &LoggerFetchCommand::metadataRead); 41 0 : connect(service, &DataLoggerService::samplesRead, this, &LoggerFetchCommand::outputSamples); 42 : } 43 0 : return service; 44 : } 45 : 46 : /*! 47 : * \copybrief DeviceCommand::serviceDetailsDiscovered 48 : * 49 : * This override fetches the current device's status, and outputs it in the selected format. 50 : */ 51 0 : void LoggerFetchCommand::serviceDetailsDiscovered() 52 : { 53 0 : DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently. 54 0 : qCInfo(lc).noquote() << tr("Fetching logger samples..."); 55 0 : service->enableMetadataNotifications(); 56 0 : service->enableReadingNotifications(); 57 0 : service->fetchSamples(); 58 0 : } 59 : 60 : /*! 61 : * Invoked when \a metadata has been received from the data logger. 62 : */ 63 1037 : void LoggerFetchCommand::metadataRead(const DataLoggerService::Metadata &metadata) 64 : { 65 1037 : qCDebug(lc) << "status:" << (int)(metadata.status); 66 1037 : qCDebug(lc) << "scale:" << metadata.scale; 67 1037 : qCDebug(lc) << "mode:" << DataLoggerService::toString(metadata.mode) << (quint8)metadata.mode; 68 1037 : qCDebug(lc) << "range:" << DataLoggerService::toString(metadata.range.voltageRange) 69 0 : << (quint8)metadata.range.voltageRange; 70 1037 : qCDebug(lc) << "updateInterval:" << (int)metadata.updateInterval; 71 1037 : qCDebug(lc) << "numberOfSamples:" << metadata.numberOfSamples; 72 1037 : qCDebug(lc) << "timestamp:" << metadata.timestamp 73 0 : << QDateTime::fromSecsSinceEpoch(metadata.timestamp, Qt::UTC); 74 1037 : this->metadata = metadata; 75 1037 : this->samplesToGo = metadata.numberOfSamples; 76 1037 : this->timestamp = (quint64)metadata.timestamp * (quint64)1000; 77 2257 : qCInfo(lc).noquote() << tr("Fetching %L1 logger samples...").arg(metadata.numberOfSamples); 78 1037 : } 79 : 80 : /*! 81 : * Outputs logger \a samples in the selected ouput format. 82 : */ 83 1224 : void LoggerFetchCommand::outputSamples(const DataLoggerService::Samples &samples) 84 : { 85 216 : QString unit; 86 1224 : switch (metadata.mode) { 87 306 : case DataLoggerService::Mode::DcVoltage: unit = QLatin1String("Vdc"); break; 88 306 : case DataLoggerService::Mode::AcVoltage: unit = QLatin1String("Vac"); break; 89 306 : case DataLoggerService::Mode::DcCurrent: unit = QLatin1String("Adc"); break; 90 306 : case DataLoggerService::Mode::AcCurrent: unit = QLatin1String("Aac"); break; 91 0 : default: 92 0 : qCDebug(lc).noquote() << tr("No known unit for mode %1 \"%2\".").arg((int)metadata.mode) 93 0 : .arg(DataLoggerService::toString(metadata.mode)); 94 : } 95 2232 : const QString range = DataLoggerService::toString(metadata.range, metadata.mode); 96 : 97 6936 : for (const qint16 &sample: samples) { 98 5712 : const QString timeString = (metadata.timestamp == 0) ? QString::number(timestamp) 99 5712 : : QDateTime::fromMSecsSinceEpoch(timestamp, Qt::UTC).toString(Qt::ISODateWithMs); 100 5712 : const float value = sample * metadata.scale; 101 5712 : switch (format) { 102 : case OutputFormat::Csv: 103 2176 : for (; showCsvHeader; showCsvHeader = false) { 104 320 : std::cout << qUtf8Printable(tr("timestamp,value,unit,range\n")); 105 : } 106 4144 : std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4\n") 107 : .arg(timeString).arg(value).arg(unit, range)); 108 1904 : break; 109 : case OutputFormat::Json: 110 21504 : std::cout << QJsonDocument(QJsonObject{ 111 336 : { QLatin1String("timestamp"), timeString }, 112 336 : { QLatin1String("value"), value }, 113 336 : { QLatin1String("unit"), unit }, 114 336 : { QLatin1String("range"), range }, 115 3472 : { QLatin1String("mode"), DataLoggerService::toString(metadata.mode) }, 116 13328 : }).toJson().toStdString(); 117 1904 : break; 118 1904 : case OutputFormat::Text: 119 4144 : std::cout << qUtf8Printable(tr("%1 %2 %3\n").arg(timeString).arg(value).arg(unit)); 120 1904 : break; 121 : } 122 5712 : timestamp += metadata.updateInterval; 123 5712 : --samplesToGo; 124 4704 : } 125 1224 : if (samplesToGo <= 0) { 126 2448 : qCInfo(lc).noquote() << tr("Finished fetching %L1 samples (with %L2 to remaining).") 127 1440 : .arg(metadata.numberOfSamples).arg(samplesToGo); 128 1224 : if (device) disconnect(); // Will exit the application once disconnected. 129 : } 130 1224 : }