LCOV - code coverage report
Current view: top level - src/cli - loggerfetchcommand.cpp (source / functions) Coverage Total Hit
Project: Dokit Lines: 75.3 % 89 67
Version: Functions: 66.7 % 6 4

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2022-2025 Paul Colby <git@colby.id.au>
       2              : // SPDX-License-Identifier: LGPL-3.0-or-later
       3              : 
       4              : #include "loggerfetchcommand.h"
       5              : #include "../stringliterals_p.h"
       6              : 
       7              : #include <qtpokit/pokitdevice.h>
       8              : 
       9              : #include <QDateTime>
      10              : #include <QJsonDocument>
      11              : #include <QJsonObject>
      12              : 
      13              : #include <iostream>
      14              : 
      15              : // Qt 6.5.0 added new QDateTime::fromSecsSinceEpoch() and fromMSecsSinceEpoch()
      16              : // overloads, then Qt 6.6.0 deprecated some of of the older ones.
      17              : #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 0))
      18         4704 :     #define DOKIT_QT_UTC Qt::UTC
      19              : #else
      20              :     #include <QTimeZone>
      21         2688 :     #define DOKIT_QT_UTC QTimeZone::UTC
      22              : #endif
      23              : 
      24              : DOKIT_USE_STRINGLITERALS
      25              : 
      26              : /*!
      27              :  * \class LoggerFetchCommand
      28              :  *
      29              :  * The LoggerFetchCommand class implements the `logger` CLI command.
      30              :  */
      31              : 
      32              : /*!
      33              :  * Construct a new LoggerFetchCommand object with \a parent.
      34              :  */
      35         5189 : LoggerFetchCommand::LoggerFetchCommand(QObject * const parent) : DeviceCommand(parent)
      36         1754 : {
      37              : 
      38         5219 : }
      39              : 
      40              : /*!
      41              :  * \copybrief DeviceCommand::getService
      42              :  *
      43              :  * This override returns a pointer to a DataLoggerService object.
      44              :  */
      45            0 : AbstractPokitService * LoggerFetchCommand::getService()
      46            0 : {
      47            0 :     Q_ASSERT(device);
      48            0 :     if (!service) {
      49            0 :         service = device->dataLogger();
      50            0 :         Q_ASSERT(service);
      51            0 :         connect(service, &DataLoggerService::metadataRead, this, &LoggerFetchCommand::metadataRead);
      52            0 :         connect(service, &DataLoggerService::samplesRead, this, &LoggerFetchCommand::outputSamples);
      53            0 :     }
      54            0 :     return service;
      55            0 : }
      56              : 
      57              : /*!
      58              :  * \copybrief DeviceCommand::serviceDetailsDiscovered
      59              :  *
      60              :  * This override fetches the current device's status, and outputs it in the selected format.
      61              :  */
      62            0 : void LoggerFetchCommand::serviceDetailsDiscovered()
      63            0 : {
      64            0 :     DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently.
      65            0 :     qCInfo(lc).noquote() << tr("Fetching logger samples...");
      66            0 :     service->enableMetadataNotifications();
      67            0 :     service->enableReadingNotifications();
      68            0 :     service->fetchSamples();
      69            0 : }
      70              : 
      71              : /*!
      72              :  * Invoked when \a metadata has been received from the data logger.
      73              :  */
      74         3420 : void LoggerFetchCommand::metadataRead(const DataLoggerService::Metadata &data)
      75         1702 : {
      76         6110 :     qCDebug(lc) << "status:"          << (int)(data.status);
      77         6110 :     qCDebug(lc) << "scale:"           << data.scale;
      78         6110 :     qCDebug(lc) << "mode:"            << DataLoggerService::toString(data.mode) << (quint8)data.mode;
      79         6110 :     qCDebug(lc) << "range:"           << service->toString(data.range, data.mode) << data.range;
      80         6110 :     qCDebug(lc) << "updateInterval:"  << (int)data.updateInterval;
      81         6110 :     qCDebug(lc) << "numberOfSamples:" << data.numberOfSamples;
      82         6110 :     qCDebug(lc) << "timestamp:"       << data.timestamp << QDateTime::fromSecsSinceEpoch(data.timestamp, DOKIT_QT_UTC);
      83         5122 :     this->metadata = data;
      84         5122 :     this->samplesToGo = data.numberOfSamples;
      85         5122 :     this->timestamp = (quint64)data.timestamp * (quint64)1000;
      86         9530 :     qCInfo(lc).noquote() << tr("Fetching %Ln logger sample/s...", nullptr, data.numberOfSamples);
      87         5122 : }
      88              : 
      89              : /*!
      90              :  * Outputs logger \a samples in the selected output format.
      91              :  */
      92         4050 : void LoggerFetchCommand::outputSamples(const DataLoggerService::Samples &samples)
      93         1980 : {
      94         3870 :     QString unit;
      95         6030 :     switch (metadata.mode) {
      96         1584 :     case DataLoggerService::Mode::DcVoltage: unit = u"Vdc"_s; break;
      97         1584 :     case DataLoggerService::Mode::AcVoltage: unit = u"Vac"_s; break;
      98         1584 :     case DataLoggerService::Mode::DcCurrent: unit = u"Adc"_s; break;
      99         1584 :     case DataLoggerService::Mode::AcCurrent: unit = u"Aac"_s; break;
     100         1584 :     case DataLoggerService::Mode::Temperature: unit = QString::fromUtf8("°C"); break;
     101            0 :     default:
     102            0 :         qCDebug(lc).noquote() << tr(R"(No known unit for mode %1 "%2".)").arg((int)metadata.mode)
     103            0 :             .arg(DataLoggerService::toString(metadata.mode));
     104         1980 :     }
     105         8190 :     const QString range = service->toString(metadata.range, metadata.mode);
     106              : 
     107        32190 :     for (const qint16 &sample: samples) {
     108        28140 :         const QString timeString = (metadata.timestamp == 0) ? QString::number(timestamp)
     109        28140 :             : QDateTime::fromMSecsSinceEpoch(timestamp, DOKIT_QT_UTC).toString(Qt::ISODateWithMs);
     110        28140 :         const float value = sample * metadata.scale;
     111        28140 :         switch (format) {
     112         3080 :         case OutputFormat::Csv:
     113        10720 :             for (; showCsvHeader; showCsvHeader = false) {
     114         1760 :                 std::cout << qUtf8Printable(tr("timestamp,value,unit,range\n"));
     115          440 :             }
     116        18620 :             std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4\n")
     117         3080 :                 .arg(timeString).arg(value).arg(unit, range));
     118         9380 :             break;
     119         9380 :         case OutputFormat::Json: {
     120         3080 :             QJsonObject object{
     121        12740 :                 { u"timestamp"_s, timeString },
     122        12740 :                 { u"value"_s,     value },
     123        12740 :                 { u"unit"_s,      unit },
     124        15680 :                 { u"mode"_s,      DataLoggerService::toString(metadata.mode) },
     125        46760 :             };
     126         9380 :             if (!range.isEmpty()) {
     127        13888 :                 object.insert(u"range"_s, range);
     128         2464 :             }
     129        15680 :             std::cout << QJsonDocument(object).toJson().toStdString();
     130         9380 :         }   break;
     131         9380 :         case OutputFormat::Text:
     132        18200 :             std::cout << qUtf8Printable(tr("%1 %2 %3\n").arg(timeString).arg(value).arg(unit));
     133         9380 :             break;
     134         9240 :         }
     135        28140 :         timestamp += metadata.updateInterval;
     136        28140 :         --samplesToGo;
     137        19320 :     }
     138         6030 :     if (samplesToGo <= 0) {
     139        13410 :         qCInfo(lc).noquote() << tr("Finished fetching %Ln sample/s (with %L1 remaining).",
     140        10080 :             nullptr, metadata.numberOfSamples).arg(samplesToGo);
     141         6030 :         if (device) disconnect(); // Will exit the application once disconnected.
     142         1980 :     }
     143        36830 : }
        

Generated by: LCOV version 2.3.1-1