Dokit
Internal development documentation
Loading...
Searching...
No Matches
statuscommand.cpp
1// SPDX-FileCopyrightText: 2022-2024 Paul Colby <git@colby.id.au>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#include "statuscommand.h"
5
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 */
23{
24
25}
26
32
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 */
45{
47 if (!errors.isEmpty()) {
48 return errors;
49 }
50
51 return errors;
52}
53
54/*!
55 * \copybrief DeviceCommand::getService
56 *
57 * This override returns a pointer to a StatusService object.
58 */
60{
61 Q_ASSERT(device);
62 if (!service) {
64 Q_ASSERT(service);
65 }
66 return service;
67}
68
69/*!
70 * \copybrief DeviceCommand::serviceDetailsDiscovered
71 *
72 * This override fetches the current device's status, and outputs it in the selected format.
73 */
75{
76 DeviceCommand::serviceDetailsDiscovered(); // Just logs consistently.
78 if (chrs.firmwareVersion.isNull()) {
79 qCWarning(lc).noquote() << tr("Failed to parse device information");
80 QCoreApplication::exit(EXIT_FAILURE);
81 return;
82 }
84}
85
86/*!
87 * Outputs the Pokit device's details, including \a chrs, in the selected format.
88 */
90{
91 const QString deviceName = service->deviceName();
92 const StatusService::Status status = service->status();
93 const std::optional<StatusService::TorchStatus> torchStatus = service->torchStatus();
94 const std::optional<StatusService::ButtonStatus> buttonStatus = service->buttonPress();
95 const QString statusLabel = StatusService::toString(status.deviceStatus);
96 const QString batteryLabel = StatusService::toString(status.batteryStatus);
97 const QString switchLabel = status.switchPosition ? StatusService::toString(*status.switchPosition) : QString();
98 const QString chargingLabel = status.chargingStatus ? StatusService::toString(*status.chargingStatus) : QString();
99 const QString torchLabel = (torchStatus) ? StatusService::toString(*torchStatus) : QString();
100 const QString buttonLabel = (buttonStatus) ? StatusService::toString(*buttonStatus) : QString();
101
102 switch (format) {
104 std::cout << qUtf8Printable(tr("device_name,device_status,firmware_version,maximum_voltage,"
105 "maximum_current,maximum_resistance,maximum_sampling_rate,"
106 "sampling_buffer_size,capability_mask,mac_address,battery_voltage,"
107 "battery_status,torch_status,button_status,switch_position,charging_status\n"));
108 std::cout << qUtf8Printable(QString::fromLatin1("%1,%2,%3,%4,%5,%6,%7,%8,%9,%10,%11,%12,%13,%14,%15,%16\n")
109 .arg(escapeCsvField(deviceName),statusLabel.toLower(),chrs.firmwareVersion.toString())
112 .arg(chrs.macAddress.toString()).arg(status.batteryVoltage)
113 .arg(batteryLabel.toLower(), torchLabel.toLower(), buttonLabel.toLower(), switchLabel.toLower(),
114 chargingLabel.toLower()));
115 break;
116 case OutputFormat::Json: {
117 QJsonObject battery{
118 { QLatin1String("level"), status.batteryVoltage },
119 };
120 if (!batteryLabel.isNull()) {
121 battery.insert(QLatin1String("status"), batteryLabel);
122 }
123 QJsonObject object{
124 { QLatin1String("deviceName"), deviceName },
125 { QLatin1String("firmwareVersion"), QJsonObject{
126 { QLatin1String("major"), chrs.firmwareVersion.majorVersion() },
127 { QLatin1String("minor"), chrs.firmwareVersion.minorVersion() },
128 }},
129 { QLatin1String("maximumVoltage"), chrs.maximumVoltage },
130 { QLatin1String("maximumCurrent"), chrs.maximumCurrent },
131 { QLatin1String("maximumResistance"), chrs.maximumResistance },
132 { QLatin1String("maximumSamplingRate"), chrs.maximumSamplingRate },
133 { QLatin1String("samplingBufferSize"), chrs.samplingBufferSize },
134 { QLatin1String("capabilityMask"), chrs.capabilityMask },
135 { QLatin1String("macAddress"), chrs.macAddress.toString() },
136 { QLatin1String("deviceStatus"), QJsonObject{
137 { QLatin1String("code"), (quint8)status.deviceStatus },
138 { QLatin1String("label"), statusLabel },
139 }},
140 { QLatin1String("battery"), battery },
141 };
142 if (torchStatus) {
143 object.insert(QStringLiteral("torchStatus"), QJsonObject{
144 { QLatin1String("code"), (quint8)*torchStatus },
145 { QLatin1String("label"), torchLabel },
146 });
147 }
148 if (buttonStatus) {
149 object.insert(QStringLiteral("buttonStatus"), QJsonObject{
150 { QLatin1String("code"), (quint8)*buttonStatus },
151 { QLatin1String("label"), buttonLabel },
152 });
153 }
154 if (status.switchPosition) {
155 object.insert(QStringLiteral("switchStatus"), QJsonObject{
156 { QLatin1String("code"), (quint8)*status.switchPosition },
157 { QLatin1String("label"), switchLabel },
158 });
159 }
160 if (status.chargingStatus) {
161 object.insert(QStringLiteral("chargingStatus"), QJsonObject{
162 { QLatin1String("code"), (quint8)*status.chargingStatus },
163 { QLatin1String("label"), chargingLabel },
164 });
165 }
166 std::cout << QJsonDocument(object).toJson().toStdString();
167 } break;
169 std::cout << qUtf8Printable(tr("Device name: %1\n").arg(deviceName));
170 std::cout << qUtf8Printable(tr("Firmware version: %1\n").arg(chrs.firmwareVersion.toString()));
171 std::cout << qUtf8Printable(tr("Maximum voltage: %1\n").arg(chrs.maximumVoltage));
172 std::cout << qUtf8Printable(tr("Maximum current: %1\n").arg(chrs.maximumCurrent));
173 std::cout << qUtf8Printable(tr("Maximum resistance: %1\n").arg(chrs.maximumResistance));
174 std::cout << qUtf8Printable(tr("Maximum sampling rate: %1\n").arg(chrs.maximumSamplingRate));
175 std::cout << qUtf8Printable(tr("Sampling buffer size: %1\n").arg(chrs.samplingBufferSize));
176 std::cout << qUtf8Printable(tr("Capability mask: %1\n").arg(chrs.capabilityMask));
177 std::cout << qUtf8Printable(tr("MAC address: %1\n").arg(chrs.macAddress.toString()));
178 std::cout << qUtf8Printable(tr("Device status: %1 (%2)\n").arg(statusLabel)
179 .arg((quint8)status.deviceStatus));
180 std::cout << qUtf8Printable(tr("Battery voltage: %1\n").arg(status.batteryVoltage));
181 std::cout << qUtf8Printable(tr("Battery status: %1 (%2)\n")
182 .arg(batteryLabel.isNull() ? QString::fromLatin1("N/A") : batteryLabel)
183 .arg((quint8)status.batteryStatus));
184 if (status.switchPosition) {
185 std::cout << qUtf8Printable(tr("Switch position: %1 (%2)\n")
186 .arg(switchLabel).arg((quint8)*status.switchPosition));
187 }
188 if (status.chargingStatus) {
189 std::cout << qUtf8Printable(tr("Charging status: %1 (%2)\n")
190 .arg(chargingLabel).arg((quint8)*status.chargingStatus));
191 }
192 break;
193 }
194 if (device) disconnect(); // Will exit the application once disconnected.
195}
virtual QStringList supportedOptions(const QCommandLineParser &parser) const
Returns a list of CLI option names supported by this command.
OutputFormat format
Selected output format.
@ Text
Plain unstructured text.
@ Csv
RFC 4180 compliant CSV text.
@ Json
RFC 8259 compliant JSON text.
virtual QStringList processOptions(const QCommandLineParser &parser)
Processes the relevant options from the command line parser.
static QString escapeCsvField(const QString &field)
Returns an RFC 4180 compliant version of field.
virtual QStringList requiredOptions(const QCommandLineParser &parser) const
Returns a list of CLI option names required by this command.
The AbstractPokitService class provides a common base for Pokit services classes.
The AbstractCommand class extends AbstractCommand to add a PokitDevice instance.
PokitDevice * device
Pokit Bluetooth device (if any) this command interracts with.
virtual void serviceDetailsDiscovered()
Handles service detail discovery events.
void disconnect(int exitCode=EXIT_SUCCESS)
Disconnects the underlying Pokit device, and sets exitCode to be return to the OS once the disconnect...
StatusService * status()
Returns a pointer to StatusService instance that uses this device's controller for access.
QStringList supportedOptions(const QCommandLineParser &parser) const override
Returns a list of CLI option names supported by this command.
QStringList requiredOptions(const QCommandLineParser &parser) const override
Returns a list of CLI option names required by this command.
QStringList processOptions(const QCommandLineParser &parser) override
Processes the relevant options from the command line parser.
StatusService * service
Bluetooth service this command interracts with.
StatusCommand(QObject *const parent=nullptr)
Construct a new StatusCommand object with parent.
AbstractPokitService * getService() override
Returns a Pokit service object for the derived command class.
void outputDeviceStatus(const StatusService::DeviceCharacteristics &chrs)
Outputs the Pokit device's details, including chrs, in the selected format.
void serviceDetailsDiscovered() override
Handles service detail discovery events.
DeviceCharacteristics deviceCharacteristics() const
Returns the most recent value of the Status service's Device Characteristics characteristic.
QString deviceName() const
Returns the most recent value of the Status services's Device Name characteristic.
std::optional< ButtonStatus > buttonPress() const
Returns the most recent value of the Status services's Button Press characteristic.
static QString toString(const StatusService::DeviceStatus &status)
Returns a string version of the status enum label.
std::optional< TorchStatus > torchStatus() const
Returns the most recent value of the Status services's Torch characteristic.
Status status() const
Returns the most recent value of the Status service's Status characteristic.
Declares the PokitDevice class.
QString toString() const const
std::string toStdString() const const
void exit(int returnCode)
QByteArray toJson() const const
bool isEmpty() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromLatin1(const char *str, int size)
bool isNull() const const
QString toLower() const const
bool isNull() const const
int majorVersion() const const
int minorVersion() const const
QString toString() const const
Attributes included in the Device Characteristics characterstic.
quint16 maximumCurrent
Device's maximum input current.
quint16 maximumSamplingRate
Device's maximum sampling rate.
quint16 samplingBufferSize
Device's sampling buffer size.
quint16 maximumVoltage
Device's maximum input voltage.
QBluetoothAddress macAddress
Device's MAC address.
quint16 maximumResistance
Device's maximum input resistance.
QVersionNumber firmwareVersion
Device's major and minor firmware version.
Attributes included in the Status characterstic.
float batteryVoltage
Current battery voltage level.
std::optional< ChargingStatus > chargingStatus
Current charging status, if supported by the device.
DeviceStatus deviceStatus
Current Pokit device status.
BatteryStatus batteryStatus
Logical interpretation the battery voltage level.
std::optional< SwitchPosition > switchPosition
Position of the Pokit device's physical mode switch.