From 1c95fb26f1e45500cd03875ebde498f85b350406 Mon Sep 17 00:00:00 2001 From: DonLakeFlyer Date: Wed, 1 Jul 2020 15:46:44 -0700 Subject: [PATCH] Support param meta data and gzip json --- qgroundcontrol.qrc | 2 + src/Vehicle/ComponentInformationManager.cc | 110 +++++++++++++++++++-- src/Vehicle/ComponentInformationManager.h | 14 ++- src/Vehicle/StateMachine.cc | 9 ++ src/Vehicle/StateMachine.h | 2 + 5 files changed, 128 insertions(+), 9 deletions(-) diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index d5a550e2f..9373f9dc5 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -337,5 +337,7 @@ src/comm/APMArduSubMockLink.params src/comm/PX4MockLink.params src/comm/MockLink.Version.MetaData.json + src/comm/MockLink.Version.MetaData.json.gz + src/comm/MockLink.Parameter.MetaData.json diff --git a/src/Vehicle/ComponentInformationManager.cc b/src/Vehicle/ComponentInformationManager.cc index d3d3c5206..f811313c3 100644 --- a/src/Vehicle/ComponentInformationManager.cc +++ b/src/Vehicle/ComponentInformationManager.cc @@ -10,14 +10,21 @@ #include "ComponentInformationManager.h" #include "Vehicle.h" #include "FTPManager.h" +#include "QGCZlib.h" +#include "JsonHelper.h" #include +#include +#include QGC_LOGGING_CATEGORY(ComponentInformationManagerLog, "ComponentInformationManagerLog") +const char* ComponentInformationManager::_jsonVersionKey = "version"; +const char* ComponentInformationManager::_jsonSupportedCompMetadataTypesKey = "supportedCompMetadataTypes"; + ComponentInformationManager::StateFn ComponentInformationManager::_rgStates[]= { ComponentInformationManager::_stateRequestCompInfoVersion, - //ComponentInformationManager::_stateRequestCompInfoParam, + ComponentInformationManager::_stateRequestCompInfoParam, ComponentInformationManager::_stateRequestAllCompInfoComplete }; @@ -27,6 +34,7 @@ RequestMetaDataTypeStateMachine::StateFn RequestMetaDataTypeStateMachine::_rgSta RequestMetaDataTypeStateMachine::_stateRequestCompInfo, RequestMetaDataTypeStateMachine::_stateRequestMetaDataJson, RequestMetaDataTypeStateMachine::_stateRequestTranslationJson, + RequestMetaDataTypeStateMachine::_stateRequestComplete, }; int RequestMetaDataTypeStateMachine::_cStates = sizeof(RequestMetaDataTypeStateMachine::_rgStates) / sizeof(RequestMetaDataTypeStateMachine::_rgStates[0]); @@ -69,7 +77,12 @@ void ComponentInformationManager::_stateRequestCompInfoComplete(void) void ComponentInformationManager::_stateRequestCompInfoParam(StateMachine* stateMachine) { ComponentInformationManager* compMgr = static_cast(stateMachine); - compMgr->_requestTypeStateMachine.request(COMP_METADATA_TYPE_PARAMETER); + + if (compMgr->_isCompTypeSupported(COMP_METADATA_TYPE_PARAMETER)) { + compMgr->_requestTypeStateMachine.request(COMP_METADATA_TYPE_PARAMETER); + } else { + + } } void ComponentInformationManager::_stateRequestAllCompInfoComplete(StateMachine* stateMachine) @@ -80,6 +93,41 @@ void ComponentInformationManager::_stateRequestAllCompInfoComplete(StateMachine* compMgr->_requestAllCompleteFnData = nullptr; } +void ComponentInformationManager::_compInfoJsonAvailable(const QString& metadataJsonFileName, const QString& translationsJsonFileName) +{ + qCDebug(ComponentInformationManagerLog) << "_compInfoJsonAvailable metadata:translation" << metadataJsonFileName << translationsJsonFileName; + + if (!metadataJsonFileName.isEmpty()) { + QString errorString; + QJsonDocument jsonDoc; + if (!JsonHelper::isJsonFile(metadataJsonFileName, jsonDoc, errorString)) { + qCWarning(ComponentInformationManagerLog) << "Version json file read failed" << errorString; + return; + } + QJsonObject jsonObj = jsonDoc.object(); + + if (currentState() == _stateRequestCompInfoVersion) { + QList keyInfoList = { + { _jsonVersionKey, QJsonValue::Double, true }, + { _jsonSupportedCompMetadataTypesKey, QJsonValue::Array, true }, + }; + if (!JsonHelper::validateKeys(jsonObj, keyInfoList, errorString)) { + qCWarning(ComponentInformationManagerLog) << "Version json validation failed:" << errorString; + return; + } + + for (const QJsonValue& idValue: jsonObj[_jsonSupportedCompMetadataTypesKey].toArray()) { + _supportedMetaDataTypes.append(static_cast(idValue.toInt())); + } + } + } +} + +bool ComponentInformationManager::_isCompTypeSupported(COMP_METADATA_TYPE type) +{ + return _supportedMetaDataTypes.contains(type); +} + RequestMetaDataTypeStateMachine::RequestMetaDataTypeStateMachine(ComponentInformationManager* compMgr) : _compMgr(compMgr) { @@ -91,6 +139,8 @@ void RequestMetaDataTypeStateMachine::request(COMP_METADATA_TYPE type) _compInfoAvailable = false; _type = type; _stateIndex = -1; + _jsonMetadataFileName.clear(); + _jsonTranslationFileName.clear(); start(); } @@ -171,9 +221,47 @@ void RequestMetaDataTypeStateMachine::_stateRequestCompInfo(StateMachine* stateM } } -void RequestMetaDataTypeStateMachine::_downloadComplete(const QString& file, const QString& errorMsg) +QString RequestMetaDataTypeStateMachine::_downloadCompleteJsonWorker(const QString& fileName, const QString& inflatedFileName) { - qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_downloadComplete" << file << errorMsg; + QString outputFileName = fileName; + + if (fileName.endsWith(".gz", Qt::CaseInsensitive)) { + outputFileName = (QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)).absoluteFilePath(inflatedFileName)); + if (QGCZlib::inflateGzipFile(fileName, outputFileName)) { + QFile(fileName).remove(); + } else { + qCWarning(ComponentInformationManagerLog) << "Inflate of compressed json failed" << inflatedFileName; + outputFileName.clear(); + } + } else { + outputFileName = fileName; + } + + return outputFileName; +} + +void RequestMetaDataTypeStateMachine::_downloadCompleteMetaDataJson(const QString& fileName, const QString& errorMsg) +{ + qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_downloadCompleteMetaDataJson fileName:errorMsg" << fileName << errorMsg; + + if (errorMsg.isEmpty()) { + _jsonMetadataFileName = _downloadCompleteJsonWorker(fileName, "metadata.json"); + } + + advance(); +} + +void RequestMetaDataTypeStateMachine::_downloadCompleteTranslationJson(const QString& fileName, const QString& errorMsg) +{ + qCDebug(ComponentInformationManagerLog) << "RequestMetaDataTypeStateMachine::_downloadCompleteTranslationJson fileName:errorMsg" << fileName << errorMsg; + + QString jsonTranslationFileName; + if (errorMsg.isEmpty()) { + jsonTranslationFileName = _downloadCompleteJsonWorker(fileName, "translation.json"); + } + + _compMgr->_compInfoJsonAvailable(_jsonMetadataFileName, jsonTranslationFileName); + advance(); } @@ -186,9 +274,9 @@ void RequestMetaDataTypeStateMachine::_stateRequestMetaDataJson(StateMachine* st if (requestMachine->_compInfoAvailable) { ComponentInformation_t& compInfo = requestMachine->_compInfo; - qCDebug(ComponentInformationManagerLog) << "Downloading metadata json" << compInfo.translationURI; + qCDebug(ComponentInformationManagerLog) << "Downloading metadata json" << compInfo.metadataURI; if (_uriIsFTP(compInfo.metadataURI)) { - connect(ftpManager, &FTPManager::downloadComplete, requestMachine, &RequestMetaDataTypeStateMachine::_downloadComplete); + connect(ftpManager, &FTPManager::downloadComplete, requestMachine, &RequestMetaDataTypeStateMachine::_downloadCompleteMetaDataJson); ftpManager->download(compInfo.metadataURI, QStandardPaths::writableLocation(QStandardPaths::TempLocation)); } else { // FIXME: NYI @@ -214,7 +302,7 @@ void RequestMetaDataTypeStateMachine::_stateRequestTranslationJson(StateMachine* } else { qCDebug(ComponentInformationManagerLog) << "Downloading translation json" << compInfo.translationURI; if (_uriIsFTP(compInfo.translationURI)) { - connect(ftpManager, &FTPManager::downloadComplete, requestMachine, &RequestMetaDataTypeStateMachine::_downloadComplete); + connect(ftpManager, &FTPManager::downloadComplete, requestMachine, &RequestMetaDataTypeStateMachine::_downloadCompleteTranslationJson); ftpManager->download(compInfo.metadataURI, QStandardPaths::writableLocation(QStandardPaths::TempLocation)); } else { // FIXME: NYI @@ -227,6 +315,14 @@ void RequestMetaDataTypeStateMachine::_stateRequestTranslationJson(StateMachine* } } +void RequestMetaDataTypeStateMachine::_stateRequestComplete(StateMachine* stateMachine) +{ + RequestMetaDataTypeStateMachine* requestMachine = static_cast(stateMachine); + + requestMachine->compMgr()->_compInfoJsonAvailable(requestMachine->_jsonMetadataFileName, requestMachine->_jsonTranslationFileName); + requestMachine->advance(); +} + bool RequestMetaDataTypeStateMachine::_uriIsFTP(const QString& uri) { return uri.startsWith("mavlinkftp", Qt::CaseInsensitive); diff --git a/src/Vehicle/ComponentInformationManager.h b/src/Vehicle/ComponentInformationManager.h index 356c1bbc4..5112ddbf6 100644 --- a/src/Vehicle/ComponentInformationManager.h +++ b/src/Vehicle/ComponentInformationManager.h @@ -43,12 +43,15 @@ public: void statesCompleted (void) const final; private slots: - void _downloadComplete(const QString& file, const QString& errorMsg); + void _downloadCompleteMetaDataJson (const QString& file, const QString& errorMsg); + void _downloadCompleteTranslationJson(const QString& file, const QString& errorMsg); + QString _downloadCompleteJsonWorker (const QString& jsonFileName, const QString& inflatedFileName); private: static void _stateRequestCompInfo (StateMachine* stateMachine); static void _stateRequestMetaDataJson (StateMachine* stateMachine); static void _stateRequestTranslationJson (StateMachine* stateMachine); + static void _stateRequestComplete (StateMachine* stateMachine); static bool _uriIsFTP (const QString& uri); @@ -56,6 +59,8 @@ private: COMP_METADATA_TYPE _type = COMP_METADATA_TYPE_VERSION; bool _compInfoAvailable = false; ComponentInformation_t _compInfo; + QString _jsonMetadataFileName; + QString _jsonTranslationFileName; static StateFn _rgStates[]; static int _cStates; @@ -78,7 +83,9 @@ public: const StateFn* rgStates (void) const final; private: - void _stateRequestCompInfoComplete(void); + void _stateRequestCompInfoComplete (void); + void _compInfoJsonAvailable (const QString& metadataJsonFileName, const QString& translationsJsonFileName); + bool _isCompTypeSupported (COMP_METADATA_TYPE type); static void _stateRequestCompInfoVersion (StateMachine* stateMachine); static void _stateRequestCompInfoParam (StateMachine* stateMachine); @@ -97,5 +104,8 @@ private: static StateFn _rgStates[]; static int _cStates; + static const char* _jsonVersionKey; + static const char* _jsonSupportedCompMetadataTypesKey; + friend class RequestMetaDataTypeStateMachine; }; diff --git a/src/Vehicle/StateMachine.cc b/src/Vehicle/StateMachine.cc index a9df89935..2cbc7dfbf 100644 --- a/src/Vehicle/StateMachine.cc +++ b/src/Vehicle/StateMachine.cc @@ -50,3 +50,12 @@ void StateMachine::statesCompleted(void) const { } + +StateMachine::StateFn StateMachine::currentState(void) +{ + if (_active) { + return rgStates()[_stateIndex]; + } else { + return nullptr; + } +} diff --git a/src/Vehicle/StateMachine.h b/src/Vehicle/StateMachine.h index 738c19576..771057437 100644 --- a/src/Vehicle/StateMachine.h +++ b/src/Vehicle/StateMachine.h @@ -29,6 +29,8 @@ public: /// Move the state machine to the specified state and call the state function void move(StateFn stateFn); + StateFn currentState(void); + /// @return The number of states in the rgStates array virtual int stateCount(void) const = 0; -- 2.22.0