Line data Source code
1 : // SPDX-FileCopyrightText: 2022-2026 Paul Colby <git@colby.id.au>
2 : // SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 : #include "statuscommand.h"
5 : #include "../stringliterals_p.h"
6 :
7 : #include <qtpokit/pokitdevice.h>
8 :
9 : #include <QJsonDocument>
10 : #include <QJsonObject>
11 :
12 : #include <iostream>
13 :
14 : DOKIT_USE_STRINGLITERALS
15 :
16 : /*!
17 : * \class StatusCommand
18 : *
19 : * The StatusCommand class implements the `status` CLI command.
20 : */
21 :
22 : /*!
23 : * Construct a new StatusCommand object with \a parent.
24 : */
25 2514 : StatusCommand::StatusCommand(QObject * const parent) : DeviceCommand(parent)
26 1072 : {
27 :
28 2514 : }
29 :
30 515 : QStringList StatusCommand::requiredOptions(const QCommandLineParser &parser) const
31 640 : {
32 1590 : return DeviceCommand::requiredOptions(parser) + QStringList{
33 1395 : };
34 640 : }
35 :
36 206 : QStringList StatusCommand::supportedOptions(const QCommandLineParser &parser) const
37 256 : {
38 462 : return DeviceCommand::supportedOptions(parser);
39 256 : }
40 :
41 : /*!
42 : * \copybrief DeviceCommand::processOptions
43 : *
44 : * This implementation extends DeviceCommand::processOptions to process additional CLI options
45 : * supported (or required) by this command.
46 : */
47 103 : QStringList StatusCommand::processOptions(const QCommandLineParser &parser)
48 128 : {
49 231 : QStringList errors = DeviceCommand::processOptions(parser);
50 128 : if (!errors.isEmpty()) {
51 0 : return errors;
52 0 : }
53 :
54 128 : return errors;
55 128 : }
56 :
57 : /*!
58 : * \copybrief DeviceCommand::getService
59 : *
60 : * This override returns a pointer to a StatusService object.
61 : */
62 0 : AbstractPokitService * StatusCommand::getService()
63 0 : {
64 0 : Q_ASSERT(device);
65 0 : if (!service) {
66 0 : service = device->status();
67 0 : Q_ASSERT(service);
68 0 : }
69 0 : return service;
70 0 : }
71 :
72 : /*!
73 : * \copybrief DeviceCommand::serviceDetailsDiscovered
74 : *
75 : * This override fetches the current device's status, and outputs it in the selected format.
76 : */
77 103 : void StatusCommand::serviceDetailsDiscovered()
78 56 : {
79 159 : DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently.
80 159 : const StatusService::DeviceCharacteristics chrs = service->deviceCharacteristics();
81 159 : if (chrs.firmwareVersion.isNull()) {
82 387 : qCWarning(lc).noquote() << tr("Failed to parse device information");
83 159 : QCoreApplication::exit(EXIT_FAILURE);
84 56 : return;
85 56 : }
86 0 : outputDeviceStatus(chrs);
87 0 : }
88 :
89 : /*!
90 : * Outputs the Pokit device's details, including \a chrs, in the selected format.
91 : */
92 927 : void StatusCommand::outputDeviceStatus(const StatusService::DeviceCharacteristics &chrs)
93 504 : {
94 1431 : const QString deviceName = service->deviceName();
95 1431 : const StatusService::Status status = service->status();
96 1431 : const std::optional<StatusService::TorchStatus> torchStatus = service->torchStatus();
97 1431 : const std::optional<StatusService::ButtonStatus> buttonStatus = service->buttonPress();
98 1431 : const QString statusLabel = StatusService::toString(status.deviceStatus);
99 1431 : const QString batteryLabel = StatusService::toString(status.batteryStatus);
100 1431 : const QString switchLabel = status.switchPosition ? StatusService::toString(*status.switchPosition) : QString();
101 1431 : const QString chargingLabel = status.chargingStatus ? StatusService::toString(*status.chargingStatus) : QString();
102 1431 : const QString torchLabel = (torchStatus) ? StatusService::toString(*torchStatus) : QString();
103 1431 : const QString buttonLabel = (buttonStatus) ? StatusService::toString(*buttonStatus) : QString();
104 :
105 1431 : switch (format) {
106 477 : case OutputFormat::Csv:
107 687 : std::cout << qUtf8Printable(tr("device_name,device_status,firmware_version,maximum_voltage,"
108 168 : "maximum_current,maximum_resistance,maximum_sampling_rate,"
109 168 : "sampling_buffer_size,capability_mask,mac_address,battery_voltage,"
110 168 : "battery_status,torch_status,button_status,switch_position,charging_status\n"));
111 2025 : std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16\n")
112 168 : .arg(escapeCsvField(deviceName),statusLabel.toLower(),chrs.firmwareVersion.toString())
113 168 : .arg(chrs.maximumVoltage).arg(chrs.maximumCurrent).arg(chrs.maximumResistance)
114 168 : .arg(chrs.maximumSamplingRate).arg(chrs.samplingBufferSize).arg(chrs.capabilityMask)
115 168 : .arg(chrs.macAddress.toString()).arg(status.batteryVoltage)
116 168 : .arg(batteryLabel.toLower(), torchLabel.toLower(), buttonLabel.toLower(), switchLabel.toLower(),
117 168 : chargingLabel.toLower()));
118 477 : break;
119 477 : case OutputFormat::Json: {
120 168 : QJsonObject battery{
121 594 : { u"level"_s, status.batteryVoltage },
122 1251 : };
123 477 : if (!batteryLabel.isNull()) {
124 891 : battery.insert(u"status"_s, batteryLabel);
125 168 : }
126 168 : QJsonObject object{
127 549 : { u"deviceName"_s, deviceName },
128 1311 : { u"firmwareVersion"_s, QJsonObject{
129 705 : { u"major"_s, chrs.firmwareVersion.majorVersion() },
130 591 : { u"minor"_s, chrs.firmwareVersion.minorVersion() },
131 1062 : }},
132 594 : { u"maximumVoltage"_s, chrs.maximumVoltage },
133 594 : { u"maximumCurrent"_s, chrs.maximumCurrent },
134 594 : { u"maximumResistance"_s, chrs.maximumResistance },
135 594 : { u"maximumSamplingRate"_s, chrs.maximumSamplingRate },
136 594 : { u"samplingBufferSize"_s, chrs.samplingBufferSize },
137 594 : { u"capabilityMask"_s, chrs.capabilityMask },
138 786 : { u"macAddress"_s, chrs.macAddress.toString() },
139 1353 : { u"deviceStatus"_s, QJsonObject{
140 777 : { u"code"_s, (quint8)status.deviceStatus },
141 549 : { u"label"_s, statusLabel },
142 1062 : }},
143 549 : { u"battery"_s, battery },
144 5313 : };
145 477 : if (torchStatus) {
146 0 : object.insert(u"torchStatus"_s, QJsonObject{
147 0 : { u"code"_s, (quint8)*torchStatus },
148 0 : { u"label"_s, torchLabel },
149 0 : });
150 0 : }
151 477 : if (buttonStatus) {
152 0 : object.insert(u"buttonStatus"_s, QJsonObject{
153 0 : { u"code"_s, (quint8)*buttonStatus },
154 0 : { u"label"_s, buttonLabel },
155 0 : });
156 0 : }
157 477 : if (status.switchPosition) {
158 0 : object.insert(u"switchStatus"_s, QJsonObject{
159 0 : { u"code"_s, (quint8)*status.switchPosition },
160 0 : { u"label"_s, switchLabel },
161 0 : });
162 0 : }
163 477 : if (status.chargingStatus) {
164 0 : object.insert(u"chargingStatus"_s, QJsonObject{
165 0 : { u"code"_s, (quint8)*status.chargingStatus },
166 0 : { u"label"_s, chargingLabel },
167 0 : });
168 0 : }
169 786 : std::cout << QJsonDocument(object).toJson().toStdString();
170 477 : } break;
171 477 : case OutputFormat::Text:
172 996 : std::cout << qUtf8Printable(tr("Device name: %1\n").arg(deviceName));
173 1086 : std::cout << qUtf8Printable(tr("Firmware version: %1\n").arg(chrs.firmwareVersion.toString()));
174 897 : std::cout << qUtf8Printable(tr("Maximum voltage: %1\n").arg(chrs.maximumVoltage));
175 897 : std::cout << qUtf8Printable(tr("Maximum current: %1\n").arg(chrs.maximumCurrent));
176 897 : std::cout << qUtf8Printable(tr("Maximum resistance: %1\n").arg(chrs.maximumResistance));
177 897 : std::cout << qUtf8Printable(tr("Maximum sampling rate: %1\n").arg(chrs.maximumSamplingRate));
178 897 : std::cout << qUtf8Printable(tr("Sampling buffer size: %1\n").arg(chrs.samplingBufferSize));
179 897 : std::cout << qUtf8Printable(tr("Capability mask: %1\n").arg(chrs.capabilityMask));
180 1086 : std::cout << qUtf8Printable(tr("MAC address: %1\n").arg(chrs.macAddress.toString()));
181 897 : std::cout << qUtf8Printable(tr("Device status: %1 (%2)\n").arg(statusLabel)
182 168 : .arg((quint8)status.deviceStatus));
183 996 : std::cout << qUtf8Printable(tr("Battery voltage: %1\n").arg(status.batteryVoltage));
184 1206 : std::cout << qUtf8Printable(tr("Battery status: %1 (%2)\n")
185 168 : .arg(batteryLabel.isNull() ? QString::fromLatin1("N/A") : batteryLabel)
186 168 : .arg((quint8)status.batteryStatus));
187 477 : if (status.switchPosition) {
188 0 : std::cout << qUtf8Printable(tr("Switch position: %1 (%2)\n")
189 0 : .arg(switchLabel).arg((quint8)*status.switchPosition));
190 0 : }
191 477 : if (status.chargingStatus) {
192 0 : std::cout << qUtf8Printable(tr("Charging status: %1 (%2)\n")
193 0 : .arg(chargingLabel).arg((quint8)*status.chargingStatus));
194 0 : }
195 168 : break;
196 504 : }
197 1431 : if (device) disconnect(); // Will exit the application once disconnected.
198 5142 : }
|