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