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 1386 : LoggerFetchCommand::LoggerFetchCommand(QObject * const parent) : DeviceCommand(parent) 24 : { 25 : 26 1386 : } 27 : 28 : /*! 29 : * \copybrief DeviceCommand::getService 30 : * 31 : * This override returns a pointer to a DataLoggerService object. 32 : */ 33 0 : AbstractPokitService * LoggerFetchCommand::getService() 34 : { 35 : Q_ASSERT(device); 36 0 : if (!service) { 37 0 : service = device->dataLogger(); 38 : Q_ASSERT(service); 39 0 : connect(service, &DataLoggerService::metadataRead, this, &LoggerFetchCommand::metadataRead); 40 0 : connect(service, &DataLoggerService::samplesRead, this, &LoggerFetchCommand::outputSamples); 41 : } 42 0 : return service; 43 : } 44 : 45 : /*! 46 : * \copybrief DeviceCommand::serviceDetailsDiscovered 47 : * 48 : * This override fetches the current device's status, and outputs it in the selected format. 49 : */ 50 0 : void LoggerFetchCommand::serviceDetailsDiscovered() 51 : { 52 0 : DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently. 53 0 : qCInfo(lc).noquote() << tr("Fetching logger samples..."); 54 0 : service->enableMetadataNotifications(); 55 0 : service->enableReadingNotifications(); 56 0 : service->fetchSamples(); 57 0 : } 58 : 59 : /*! 60 : * Invoked when \a metadata has been received from the data logger. 61 : */ 62 1368 : void LoggerFetchCommand::metadataRead(const DataLoggerService::Metadata &data) 63 : { 64 1368 : qCDebug(lc) << "status:" << (int)(data.status); 65 1368 : qCDebug(lc) << "scale:" << data.scale; 66 1368 : qCDebug(lc) << "mode:" << DataLoggerService::toString(data.mode) << (quint8)data.mode; 67 1368 : qCDebug(lc) << "range:" << DataLoggerService::toString(data.range, data.mode) 68 0 : << (quint8)data.range.voltageRange; 69 1368 : qCDebug(lc) << "updateInterval:" << (int)data.updateInterval; 70 1368 : qCDebug(lc) << "numberOfSamples:" << data.numberOfSamples; 71 1368 : qCDebug(lc) << "timestamp:" << data.timestamp 72 0 : << QDateTime::fromSecsSinceEpoch(data.timestamp, Qt::UTC); 73 1368 : this->metadata = data; 74 1368 : this->samplesToGo = data.numberOfSamples; 75 1368 : this->timestamp = (quint64)data.timestamp * (quint64)1000; 76 2736 : qCInfo(lc).noquote() << tr("Fetching %Ln logger sample/s...", nullptr, data.numberOfSamples); 77 1368 : } 78 : 79 : /*! 80 : * Outputs logger \a samples in the selected ouput format. 81 : */ 82 1620 : void LoggerFetchCommand::outputSamples(const DataLoggerService::Samples &samples) 83 : { 84 360 : QString unit; 85 1620 : switch (metadata.mode) { 86 324 : case DataLoggerService::Mode::DcVoltage: unit = QLatin1String("Vdc"); break; 87 324 : case DataLoggerService::Mode::AcVoltage: unit = QLatin1String("Vac"); break; 88 324 : case DataLoggerService::Mode::DcCurrent: unit = QLatin1String("Adc"); break; 89 324 : case DataLoggerService::Mode::AcCurrent: unit = QLatin1String("Aac"); break; 90 396 : case DataLoggerService::Mode::Temperature: unit = QString::fromUtf8("°C"); 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 2880 : const QString range = DataLoggerService::toString(metadata.range, metadata.mode); 96 : 97 9180 : for (const qint16 &sample: samples) { 98 7560 : const QString timeString = (metadata.timestamp == 0) ? QString::number(timestamp) 99 7560 : : QDateTime::fromMSecsSinceEpoch(timestamp, Qt::UTC).toString(Qt::ISODateWithMs); 100 7560 : const float value = sample * metadata.scale; 101 7560 : switch (format) { 102 : case OutputFormat::Csv: 103 2880 : for (; showCsvHeader; showCsvHeader = false) { 104 440 : std::cout << qUtf8Printable(tr("timestamp,value,unit,range\n")); 105 : } 106 5600 : std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4\n") 107 : .arg(timeString).arg(value).arg(unit, range)); 108 2520 : break; 109 840 : case OutputFormat::Json: { 110 : QJsonObject object{ 111 560 : { QLatin1String("timestamp"), timeString }, 112 560 : { QLatin1String("value"), value }, 113 560 : { QLatin1String("unit"), unit }, 114 5040 : { QLatin1String("mode"), DataLoggerService::toString(metadata.mode) }, 115 20160 : }; 116 2520 : if (!range.isEmpty()) { 117 3024 : object.insert(QLatin1String("range"), range); 118 : } 119 5040 : std::cout << QJsonDocument(object).toJson().toStdString(); 120 2520 : } break; 121 2520 : case OutputFormat::Text: 122 5600 : std::cout << qUtf8Printable(tr("%1 %2 %3\n").arg(timeString).arg(value).arg(unit)); 123 2520 : break; 124 : } 125 7560 : timestamp += metadata.updateInterval; 126 7560 : --samplesToGo; 127 5880 : } 128 1620 : if (samplesToGo <= 0) { 129 3780 : qCInfo(lc).noquote() << tr("Finished fetching %Ln sample/s (with %L1 remaining).", 130 2520 : nullptr, metadata.numberOfSamples).arg(samplesToGo); 131 1620 : if (device) disconnect(); // Will exit the application once disconnected. 132 : } 133 6660 : }