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:" << service->toString(data.range, data.mode) << data.range; 68 1368 : qCDebug(lc) << "updateInterval:" << (int)data.updateInterval; 69 1368 : qCDebug(lc) << "numberOfSamples:" << data.numberOfSamples; 70 1368 : qCDebug(lc) << "timestamp:" << data.timestamp << QDateTime::fromSecsSinceEpoch(data.timestamp, Qt::UTC); 71 1368 : this->metadata = data; 72 1368 : this->samplesToGo = data.numberOfSamples; 73 1368 : this->timestamp = (quint64)data.timestamp * (quint64)1000; 74 2736 : qCInfo(lc).noquote() << tr("Fetching %Ln logger sample/s...", nullptr, data.numberOfSamples); 75 1368 : } 76 : 77 : /*! 78 : * Outputs logger \a samples in the selected ouput format. 79 : */ 80 1620 : void LoggerFetchCommand::outputSamples(const DataLoggerService::Samples &samples) 81 : { 82 360 : QString unit; 83 1620 : switch (metadata.mode) { 84 324 : case DataLoggerService::Mode::DcVoltage: unit = QLatin1String("Vdc"); break; 85 324 : case DataLoggerService::Mode::AcVoltage: unit = QLatin1String("Vac"); break; 86 324 : case DataLoggerService::Mode::DcCurrent: unit = QLatin1String("Adc"); break; 87 324 : case DataLoggerService::Mode::AcCurrent: unit = QLatin1String("Aac"); break; 88 396 : case DataLoggerService::Mode::Temperature: unit = QString::fromUtf8("°C"); break; 89 0 : default: 90 0 : qCDebug(lc).noquote() << tr(R"(No known unit for mode %1 "%2".)").arg((int)metadata.mode) 91 0 : .arg(DataLoggerService::toString(metadata.mode)); 92 : } 93 2880 : const QString range = service->toString(metadata.range, metadata.mode); 94 : 95 9180 : for (const qint16 &sample: samples) { 96 7560 : const QString timeString = (metadata.timestamp == 0) ? QString::number(timestamp) 97 7560 : : QDateTime::fromMSecsSinceEpoch(timestamp, Qt::UTC).toString(Qt::ISODateWithMs); 98 7560 : const float value = sample * metadata.scale; 99 7560 : switch (format) { 100 : case OutputFormat::Csv: 101 2880 : for (; showCsvHeader; showCsvHeader = false) { 102 440 : std::cout << qUtf8Printable(tr("timestamp,value,unit,range\n")); 103 : } 104 5600 : std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4\n") 105 : .arg(timeString).arg(value).arg(unit, range)); 106 2520 : break; 107 840 : case OutputFormat::Json: { 108 : QJsonObject object{ 109 560 : { QLatin1String("timestamp"), timeString }, 110 560 : { QLatin1String("value"), value }, 111 560 : { QLatin1String("unit"), unit }, 112 5040 : { QLatin1String("mode"), DataLoggerService::toString(metadata.mode) }, 113 20160 : }; 114 2520 : if (!range.isEmpty()) { 115 3024 : object.insert(QLatin1String("range"), range); 116 : } 117 5040 : std::cout << QJsonDocument(object).toJson().toStdString(); 118 2520 : } break; 119 2520 : case OutputFormat::Text: 120 5600 : std::cout << qUtf8Printable(tr("%1 %2 %3\n").arg(timeString).arg(value).arg(unit)); 121 2520 : break; 122 : } 123 7560 : timestamp += metadata.updateInterval; 124 7560 : --samplesToGo; 125 5880 : } 126 1620 : if (samplesToGo <= 0) { 127 3780 : qCInfo(lc).noquote() << tr("Finished fetching %Ln sample/s (with %L1 remaining).", 128 2520 : nullptr, metadata.numberOfSamples).arg(samplesToGo); 129 1620 : if (device) disconnect(); // Will exit the application once disconnected. 130 : } 131 6660 : }