QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
CompInfoParam.cc
Go to the documentation of this file.
1#include "CompInfoParam.h"
2#include "FirmwarePlugin.h"
3#include "JsonParsing.h"
4#include "ParameterMetaData.h"
6#include "Vehicle.h"
7
8#include <QtCore/QJsonArray>
9#include <QtCore/QJsonDocument>
10#include <QtCore/QRegularExpression>
11
12QGC_LOGGING_CATEGORY(CompInfoParamLog, "ComponentInformation.CompInfoParam")
13
14CompInfoParam::CompInfoParam(uint8_t compId_, Vehicle *vehicle_, QObject *parent)
15 : CompInfo(COMP_METADATA_TYPE_PARAMETER, compId_, vehicle_, parent)
16{
17}
18
19void CompInfoParam::setJson(const QString &metadataJsonFileName)
20{
21 if (metadataJsonFileName.isEmpty()) {
22 return;
23 }
24
25 QString errorString;
26 QJsonDocument jsonDoc;
27
28 if (!JsonParsing::isJsonFile(metadataJsonFileName, jsonDoc, errorString)) {
29 qCWarning(CompInfoParamLog) << "Metadata json file open failed: compid:" << compId << errorString;
30 return;
31 }
32
33 const QJsonObject jsonObj = jsonDoc.object();
34 const QList<JsonParsing::KeyValidateInfo> keyInfoList = {
35 {JsonParsing::jsonVersionKey, QJsonValue::Double, true},
36 {kJsonParametersKey, QJsonValue::Array, true},
37 };
38 if (!JsonParsing::validateKeys(jsonObj, keyInfoList, errorString)) {
39 qCWarning(CompInfoParamLog) << "Metadata json validation failed: compid:" << compId << errorString;
40 return;
41 }
42
43 if (jsonObj[JsonParsing::jsonVersionKey].toInt() != 1) {
44 qCWarning(CompInfoParamLog) << "Metadata json unsupported version" << jsonObj[JsonParsing::jsonVersionKey].toInt();
45 return;
46 }
47
48 _noJsonMetadata = false;
49
50 const QJsonArray parameters = jsonObj[kJsonParametersKey].toArray();
51 const QString escapedTag = QRegularExpression::escape(kIndexedNameTag);
52
53 for (const QJsonValue &parameterValue : parameters) {
54 if (!parameterValue.isObject()) {
55 qCWarning(CompInfoParamLog) << "Metadata json read failed: compid:" << compId << "parameters array contains non-object";
56 return;
57 }
58
59 FactMetaData *newMetaData = FactMetaData::createFromJsonObject(parameterValue.toObject(), ParameterMetaData::kEmptyDefines, this);
60
61 if (newMetaData->name().contains(kIndexedNameTag)) {
62 QString regexPattern = QRegularExpression::escape(newMetaData->name());
63 regexPattern.replace(escapedTag, QStringLiteral("(\\d+)"));
64 _indexedNameMetaDataList.append({QRegularExpression(QStringLiteral("^%1$").arg(regexPattern)), newMetaData});
65 } else {
66 _nameToMetaDataMap[newMetaData->name()] = newMetaData;
67 }
68 }
69}
70
72{
73 if (FactMetaData *cached = _nameToMetaDataMap.value(name)) {
74 return cached;
75 }
76
77 FactMetaData *factMetaData = _resolveMetaData(name, valueType);
78 _nameToMetaDataMap[name] = factMetaData;
79 return factMetaData;
80}
81
82FactMetaData *CompInfoParam::_resolveMetaData(const QString &name, FactMetaData::ValueType_t valueType)
83{
84 if (_noJsonMetadata) {
85 // No vehicle-provided metadata — use firmware-bundled metadata
86 if (ParameterMetaData *fwMeta = _getParameterMetaData()) {
87 return fwMeta->getMetaDataForFact(name, valueType);
88 }
89 } else {
90 // Vehicle provided JSON metadata — check exact match then indexed patterns
91 if (FactMetaData *found = _lookupJsonMetaData(name)) {
92 return found;
93 }
94 }
95
96 // Generic fallback
97 auto *factMetaData = new FactMetaData(valueType, this);
98 const int sep = name.indexOf('_');
99 if (sep > 0) {
100 factMetaData->setGroup(name.left(sep));
101 }
102 if (compId != MAV_COMP_ID_AUTOPILOT1) {
103 factMetaData->setCategory(tr("Component %1").arg(compId));
104 }
105 return factMetaData;
106}
107
108FactMetaData *CompInfoParam::_lookupJsonMetaData(const QString &name)
109{
110 // Try indexed name patterns (e.g. "CAL_GYRO{n}_ID" matches "CAL_GYRO0_ID")
111 for (const auto &[regex, templateMeta] : _indexedNameMetaDataList) {
112 const QRegularExpressionMatch match = regex.match(name);
113 if (match.hasMatch()) {
114 auto *factMetaData = new FactMetaData(*templateMeta, this);
115 factMetaData->setName(name);
116
117 const QString index = match.captured(1);
118 QString desc = factMetaData->shortDescription();
119 desc.replace(kIndexedNameTag, index);
120 factMetaData->setShortDescription(desc);
121
122 desc = factMetaData->longDescription();
123 desc.replace(kIndexedNameTag, index);
124 factMetaData->setLongDescription(desc);
125 return factMetaData;
126 }
127 }
128
129 return nullptr;
130}
131
132ParameterMetaData *CompInfoParam::_getParameterMetaData()
133{
134 if (!_parameterMetaData && compId == MAV_COMP_ID_AUTOPILOT1) {
135 _parameterMetaData = vehicle->firmwarePlugin()->loadParameterMetaData(vehicle);
136 if (_parameterMetaData) {
137 _parameterMetaData->setParent(this);
138 }
139 }
140
141 return _parameterMetaData;
142}
QString errorString
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void setJson(const QString &metadataJsonFileName) override
FactMetaData * factMetaDataForName(const QString &name, FactMetaData::ValueType_t valueType)
Base class for all CompInfo types.
Definition CompInfo.h:15
Vehicle *const vehicle
Definition CompInfo.h:37
const uint8_t compId
Definition CompInfo.h:38
Holds the meta data associated with a Fact.
static FactMetaData * createFromJsonObject(const QJsonObject &json, const QMap< QString, QString > &defineMap, QObject *metaDataParent)
QString name() const
ParameterMetaData * loadParameterMetaData(const Vehicle *vehicle)
static const FactMetaData::DefineMap_t kEmptyDefines
FirmwarePlugin * firmwarePlugin()
Provides access to the Firmware Plugin for this Vehicle.
Definition Vehicle.h:444
bool validateKeys(const QJsonObject &jsonObject, const QList< KeyValidateInfo > &keyInfo, QString &errorString)
Validates that all required keys are present and that listed keys have the expected type.
bool isJsonFile(const QByteArray &bytes, QJsonDocument &jsonDoc, QString &errorString)
Determines whether an in-memory byte buffer contains parseable JSON content.
constexpr const char * jsonVersionKey
Definition JsonParsing.h:12