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: 71.4 % 7 5

            Line data    Source code
       1              : // SPDX-FileCopyrightText: 2022-2024 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              : // Qt 6.5.0 added new QDateTime::fromSecsSinceEpoch() and fromMSecsSinceEpoch()
      15              : // overloads, then Qt 6.6.0 deprectated some of of the older ones.
      16              : #if (QT_VERSION < QT_VERSION_CHECK(6, 5, 0))
      17         4032 :     #define DOKIT_QT_UTC Qt::UTC
      18              : #else
      19              :     #include <QTimeZone>
      20         1344 :     #define DOKIT_QT_UTC QTimeZone::UTC
      21              : #endif
      22              : 
      23              : /*!
      24              :  * \class LoggerFetchCommand
      25              :  *
      26              :  * The LoggerFetchCommand class implements the `logger` CLI command.
      27              :  */
      28              : 
      29              : /*!
      30              :  * Construct a new LoggerFetchCommand object with \a parent.
      31              :  */
      32         4158 : LoggerFetchCommand::LoggerFetchCommand(QObject * const parent) : DeviceCommand(parent)
      33         1288 : {
      34              : 
      35         4214 : }
      36              : 
      37              : /*!
      38              :  * \copybrief DeviceCommand::getService
      39              :  *
      40              :  * This override returns a pointer to a DataLoggerService object.
      41              :  */
      42            0 : AbstractPokitService * LoggerFetchCommand::getService()
      43            0 : {
      44            0 :     Q_ASSERT(device);
      45            0 :     if (!service) {
      46            0 :         service = device->dataLogger();
      47            0 :         Q_ASSERT(service);
      48            0 :         connect(service, &DataLoggerService::metadataRead, this, &LoggerFetchCommand::metadataRead);
      49            0 :         connect(service, &DataLoggerService::samplesRead, this, &LoggerFetchCommand::outputSamples);
      50            0 :     }
      51            0 :     return service;
      52            0 : }
      53              : 
      54              : /*!
      55              :  * \copybrief DeviceCommand::serviceDetailsDiscovered
      56              :  *
      57              :  * This override fetches the current device's status, and outputs it in the selected format.
      58              :  */
      59            0 : void LoggerFetchCommand::serviceDetailsDiscovered()
      60            0 : {
      61            0 :     DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently.
      62            0 :     qCInfo(lc).noquote() << tr("Fetching logger samples...");
      63            0 :     service->enableMetadataNotifications();
      64            0 :     service->enableReadingNotifications();
      65            0 :     service->fetchSamples();
      66            0 : }
      67              : 
      68              : /*!
      69              :  * Invoked when \a metadata has been received from the data logger.
      70              :  */
      71         2888 : void LoggerFetchCommand::metadataRead(const DataLoggerService::Metadata &data)
      72         1244 : {
      73         4740 :     qCDebug(lc) << "status:"          << (int)(data.status);
      74         4740 :     qCDebug(lc) << "scale:"           << data.scale;
      75         4740 :     qCDebug(lc) << "mode:"            << DataLoggerService::toString(data.mode) << (quint8)data.mode;
      76         4740 :     qCDebug(lc) << "range:"           << service->toString(data.range, data.mode) << data.range;
      77         4740 :     qCDebug(lc) << "updateInterval:"  << (int)data.updateInterval;
      78         4740 :     qCDebug(lc) << "numberOfSamples:" << data.numberOfSamples;
      79         4740 :     qCDebug(lc) << "timestamp:"       << data.timestamp << QDateTime::fromSecsSinceEpoch(data.timestamp, DOKIT_QT_UTC);
      80         4132 :     this->metadata = data;
      81         4132 :     this->samplesToGo = data.numberOfSamples;
      82         4132 :     this->timestamp = (quint64)data.timestamp * (quint64)1000;
      83         7628 :     qCInfo(lc).noquote() << tr("Fetching %Ln logger sample/s...", nullptr, data.numberOfSamples);
      84         4132 : }
      85              : 
      86              : /*!
      87              :  * Outputs logger \a samples in the selected ouput format.
      88              :  */
      89         3420 : void LoggerFetchCommand::outputSamples(const DataLoggerService::Samples &samples)
      90         1440 : {
      91         2790 :     QString unit;
      92         4860 :     switch (metadata.mode) {
      93          972 :     case DataLoggerService::Mode::DcVoltage: unit = QLatin1String("Vdc"); break;
      94          972 :     case DataLoggerService::Mode::AcVoltage: unit = QLatin1String("Vac"); break;
      95          972 :     case DataLoggerService::Mode::DcCurrent: unit = QLatin1String("Adc"); break;
      96          972 :     case DataLoggerService::Mode::AcCurrent: unit = QLatin1String("Aac"); break;
      97         1242 :     case DataLoggerService::Mode::Temperature: unit = QString::fromUtf8("°C"); break;
      98            0 :     default:
      99            0 :         qCDebug(lc).noquote() << tr(R"(No known unit for mode %1 "%2".)").arg((int)metadata.mode)
     100            0 :             .arg(DataLoggerService::toString(metadata.mode));
     101         1440 :     }
     102         6930 :     const QString range = service->toString(metadata.range, metadata.mode);
     103              : 
     104        26100 :     for (const qint16 &sample: samples) {
     105        22680 :         const QString timeString = (metadata.timestamp == 0) ? QString::number(timestamp)
     106        22680 :             : QDateTime::fromMSecsSinceEpoch(timestamp, DOKIT_QT_UTC).toString(Qt::ISODateWithMs);
     107        22680 :         const float value = sample * metadata.scale;
     108        22680 :         switch (format) {
     109         2240 :         case OutputFormat::Csv:
     110         8640 :             for (; showCsvHeader; showCsvHeader = false) {
     111         1380 :                 std::cout << qUtf8Printable(tr("timestamp,value,unit,range\n"));
     112          320 :             }
     113        14980 :             std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4\n")
     114         2240 :                 .arg(timeString).arg(value).arg(unit, range));
     115         7560 :             break;
     116         7560 :         case OutputFormat::Json: {
     117         2240 :             QJsonObject object{
     118         4340 :                 { QLatin1String("timestamp"), timeString },
     119         4340 :                 { QLatin1String("value"),     value },
     120         4340 :                 { QLatin1String("unit"),      unit },
     121        10780 :                 { QLatin1String("mode"),      DataLoggerService::toString(metadata.mode) },
     122        37240 :             };
     123         7560 :             if (!range.isEmpty()) {
     124         8064 :                 object.insert(QLatin1String("range"), range);
     125         1792 :             }
     126        12880 :             std::cout << QJsonDocument(object).toJson().toStdString();
     127         7560 :         }   break;
     128         7560 :         case OutputFormat::Text:
     129        14980 :             std::cout << qUtf8Printable(tr("%1 %2 %3\n").arg(timeString).arg(value).arg(unit));
     130         7560 :             break;
     131         6720 :         }
     132        22680 :         timestamp += metadata.updateInterval;
     133        22680 :         --samplesToGo;
     134        16380 :     }
     135         4860 :     if (samplesToGo <= 0) {
     136        11070 :         qCInfo(lc).noquote() << tr("Finished fetching %Ln sample/s (with %L1 remaining).",
     137         8280 :             nullptr, metadata.numberOfSamples).arg(samplesToGo);
     138         4860 :         if (device) disconnect(); // Will exit the application once disconnected.
     139         1440 :     }
     140        28380 : }
        

Generated by: LCOV version 2.0-1