WiP: write basic model data and models list
This commit is contained in:
@@ -42,7 +42,7 @@ static void writeYamlToByteArray(const YAML::Node& node, QByteArray& data)
|
||||
qDebug() << data_ostream.str().c_str();
|
||||
}
|
||||
|
||||
bool loadModelsListFromYaml(std::vector<CategoryData> categories,
|
||||
bool loadModelsListFromYaml(std::vector<CategoryData>& categories,
|
||||
EtxModelfiles& modelFiles,
|
||||
const QByteArray& data)
|
||||
{
|
||||
@@ -102,16 +102,42 @@ bool loadRadioSettingsFromYaml(GeneralSettings& settings, const QByteArray& data
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// 'modelFiles' should be ordered by Category index to avoid
|
||||
// turning the sequence into a map.
|
||||
//
|
||||
bool writeModelsListToYaml(const std::vector<CategoryData>& categories,
|
||||
const EtxModelfiles& modelFiles,
|
||||
QByteArray& data)
|
||||
{
|
||||
YAML::Node node;
|
||||
for (const auto& modelFile: modelFiles) {
|
||||
|
||||
YAML::Node cat_attrs;
|
||||
cat_attrs["filename"] = modelFile.first;
|
||||
|
||||
const std::string cat_name = categories[modelFile.second].name;
|
||||
node[modelFile.second][cat_name].push_back(cat_attrs);
|
||||
}
|
||||
|
||||
writeYamlToByteArray(node, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeModelToYaml(const ModelData& model, QByteArray& data)
|
||||
{
|
||||
return false;
|
||||
YAML::Node node;
|
||||
node = model;
|
||||
|
||||
writeYamlToByteArray(node, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeRadioSettingsToYaml(const GeneralSettings& settings, QByteArray& data)
|
||||
{
|
||||
YAML::Node node;
|
||||
node = settings;
|
||||
writeYamlToByteArray(node, data);
|
||||
|
||||
writeYamlToByteArray(node, data);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,12 +30,16 @@
|
||||
typedef std::pair<std::string, int> EtxModelfileCategoryPair;
|
||||
typedef std::list<EtxModelfileCategoryPair> EtxModelfiles;
|
||||
|
||||
bool loadModelsListFromYaml(std::vector<CategoryData> categories,
|
||||
bool loadModelsListFromYaml(std::vector<CategoryData>& categories,
|
||||
EtxModelfiles& modelFiles,
|
||||
const QByteArray& data);
|
||||
|
||||
bool loadModelFromYaml(ModelData& model, const QByteArray& data);
|
||||
bool loadRadioSettingsFromYaml(GeneralSettings& settings, const QByteArray& data);
|
||||
|
||||
bool writeModelsListToYaml(const std::vector<CategoryData>& categories,
|
||||
const EtxModelfiles& modelFiles,
|
||||
QByteArray& data);
|
||||
|
||||
bool writeModelToYaml(const ModelData& model, QByteArray& data);
|
||||
bool writeRadioSettingsToYaml(const GeneralSettings& settings, QByteArray& data);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "yaml_modeldata.h"
|
||||
#include "modeldata.h"
|
||||
|
||||
const YamlLookupTable timerModeLut = {
|
||||
static const YamlLookupTable timerModeLut = {
|
||||
{TimerData::TIMERMODE_OFF, "OFF"},
|
||||
{TimerData::TIMERMODE_ON, "ON"},
|
||||
{TimerData::TIMERMODE_START, "START"},
|
||||
@@ -30,7 +30,7 @@ const YamlLookupTable timerModeLut = {
|
||||
{TimerData::TIMERMODE_THR_START, "THR_START"},
|
||||
};
|
||||
|
||||
const YamlLookupTable trainerModeLut = {
|
||||
static const YamlLookupTable trainerModeLut = {
|
||||
{ TRAINER_MODE_OFF, "OFF" },
|
||||
{ TRAINER_MODE_MASTER_JACK, "MASTER_TRAINER_JACK" },
|
||||
{ TRAINER_MODE_SLAVE_JACK, "SLAVE" },
|
||||
@@ -41,3 +41,172 @@ const YamlLookupTable trainerModeLut = {
|
||||
{ TRAINER_MODE_SLAVE_BLUETOOTH, "SLAVE_BT" },
|
||||
{ TRAINER_MODE_MULTI, "MASTER_MULTI" },
|
||||
};
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
Node convert<TimerData>::encode(const TimerData& rhs)
|
||||
{
|
||||
Node node;
|
||||
node["swtch"] = rhs.swtch;
|
||||
node["mode"] = timerModeLut << rhs.mode;
|
||||
node["name"] = rhs.name;
|
||||
node["minuteBeep"] = rhs.minuteBeep;
|
||||
node["countdownBeep"] = rhs.countdownBeep;
|
||||
node["start"] = rhs.val;
|
||||
node["persistent"] = rhs.persistent;
|
||||
node["countdownStart"] = rhs.countdownStart;
|
||||
node["value"] = rhs.pvalue;
|
||||
return node;
|
||||
}
|
||||
|
||||
bool convert<TimerData>::decode(const Node& node, TimerData& rhs)
|
||||
{
|
||||
node["swtch"] >> rhs.swtch;
|
||||
node["mode"] >> timerModeLut >> rhs.mode;
|
||||
node["name"] >> rhs.name;
|
||||
node["minuteBeep"] >> rhs.minuteBeep;
|
||||
node["countdownBeep"] >> rhs.countdownBeep;
|
||||
node["start"] >> rhs.val;
|
||||
node["persistent"] >> rhs.persistent;
|
||||
node["countdownStart"] >> rhs.countdownStart;
|
||||
node["value"] >> rhs.pvalue;
|
||||
return true;
|
||||
}
|
||||
|
||||
Node convert<ModelData>::encode(const ModelData& rhs)
|
||||
{
|
||||
Node node;
|
||||
node["header"]["name"] = rhs.name;
|
||||
node["header"]["bitmap"] = rhs.bitmap;
|
||||
// TODO: modelId
|
||||
|
||||
for (int i=0; i<CPN_MAX_TIMERS; i++) {
|
||||
Node timer;
|
||||
timer = rhs.timers[i];
|
||||
node["timers"][std::to_string(i)] = timer;
|
||||
}
|
||||
|
||||
node["noGlobalFunctions"] = rhs.noGlobalFunctions;
|
||||
node["thrTrim"] = rhs.thrTrim;
|
||||
node["trimInc"] = rhs.trimInc;
|
||||
node["displayTrims"] = rhs.trimsDisplay;
|
||||
node["disableThrottleWarning"] = rhs.disableThrottleWarning;
|
||||
// node[] = rhs.beepANACenter;
|
||||
node["extendedLimits"] = rhs.extendedLimits;
|
||||
node["extendedTrims"] = rhs.extendedTrims;
|
||||
node["throttleReversed"] = rhs.throttleReversed;
|
||||
|
||||
// flightModeData[]
|
||||
// mixData[]
|
||||
// limitData[]
|
||||
// inputNames[]
|
||||
// expoData[]
|
||||
// curves[]
|
||||
// logicalSw[]
|
||||
// customFn[]
|
||||
|
||||
// swashRingData
|
||||
// thrTraceSrc
|
||||
// switchWarningStates
|
||||
// thrTrimSwitch
|
||||
// potsWarningMode
|
||||
// potsWarnEnabled[]
|
||||
// potsWarnPosition[]
|
||||
|
||||
node["displayChecklist"] = rhs.displayChecklist;
|
||||
|
||||
// gvarData[]
|
||||
// mavlink ???
|
||||
// telemetryProtocol ???
|
||||
// frsky
|
||||
// rssiSource
|
||||
// rssiAlarms
|
||||
|
||||
node["trainerMode"] = trainerModeLut << rhs.trainerMode;
|
||||
|
||||
// moduleData[]
|
||||
// scriptData[]
|
||||
// sensorData[]
|
||||
|
||||
node["toplcdTimer"] = rhs.toplcdTimer;
|
||||
|
||||
// customScreens
|
||||
// topBarData
|
||||
node["view"] = rhs.view;
|
||||
node["modelRegistrationID"] = rhs.registrationId;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool convert<ModelData>::decode(const Node& node, ModelData& rhs)
|
||||
{
|
||||
if (!node.IsMap()) return false;
|
||||
|
||||
if (node["header"]) {
|
||||
const auto& header = node["header"];
|
||||
if (!header.IsMap()) return false;
|
||||
|
||||
header["name"] >> rhs.name;
|
||||
header["bitmap"] >> rhs.bitmap;
|
||||
// TODO: modelId
|
||||
}
|
||||
|
||||
if (node["timers"]) {
|
||||
const auto& timers = node["timers"];
|
||||
if (!timers.IsMap()) return false;
|
||||
timers >> rhs.timers;
|
||||
}
|
||||
|
||||
node["noGlobalFunctions"] >> rhs.noGlobalFunctions;
|
||||
node["thrTrim"] >> rhs.thrTrim;
|
||||
node["trimInc"] >> rhs.trimInc;
|
||||
node["displayTrims"] >> rhs.trimsDisplay;
|
||||
node["disableThrottleWarning"] >> rhs.disableThrottleWarning;
|
||||
// node[] >> rhs.beepANACenter;
|
||||
node["extendedLimits"] >> rhs.extendedLimits;
|
||||
node["extendedTrims"] >> rhs.extendedTrims;
|
||||
node["throttleReversed"] >> rhs.throttleReversed;
|
||||
|
||||
// flightModeData[]
|
||||
// mixData[]
|
||||
// limitData[]
|
||||
// inputNames[]
|
||||
// expoData[]
|
||||
// curves[]
|
||||
// logicalSw[]
|
||||
// customFn[]
|
||||
|
||||
// swashRingData
|
||||
// thrTraceSrc
|
||||
// switchWarningStates
|
||||
// thrTrimSwitch
|
||||
// potsWarningMode
|
||||
// potsWarnEnabled[]
|
||||
// potsWarnPosition[]
|
||||
|
||||
node["displayChecklist"] >> rhs.displayChecklist;
|
||||
|
||||
// gvarData[]
|
||||
// mavlink ???
|
||||
// telemetryProtocol ???
|
||||
// frsky
|
||||
// rssiSource
|
||||
// rssiAlarms
|
||||
|
||||
node["trainerMode"] >> trainerModeLut >> rhs.trainerMode;
|
||||
|
||||
// moduleData[]
|
||||
// scriptData[]
|
||||
// sensorData[]
|
||||
|
||||
node["toplcdTimer"] >> rhs.toplcdTimer;
|
||||
|
||||
// customScreens
|
||||
// topBarData
|
||||
node["view"] >> rhs.view;
|
||||
node["modelRegistrationID"] >> rhs.registrationId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace YAML
|
||||
|
||||
@@ -25,118 +25,17 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
extern const YamlLookupTable timerModeLut;
|
||||
extern const YamlLookupTable trainerModeLut;
|
||||
|
||||
// extern const YamlLookupTable backlightModeLut;
|
||||
// extern const YamlLookupTable bluetoothModeLut;
|
||||
// extern const YamlLookupTable uartModeLut;
|
||||
// extern const YamlLookupTable antennaModeLut;
|
||||
|
||||
namespace YAML {
|
||||
|
||||
// ENUM_CONVERTER(GeneralSettings::BeeperMode, beeperModeLut);
|
||||
|
||||
template <>
|
||||
struct convert<TimerData> {
|
||||
// static YAML::Node encode(const GeneralSettings& rhs) {
|
||||
// Node node;
|
||||
// // TODO: convert struct into Node
|
||||
// return node;
|
||||
// }
|
||||
|
||||
static bool decode(const Node& node, TimerData& rhs)
|
||||
{
|
||||
node["swtch"] >> rhs.swtch;
|
||||
node["mode"] >> timerModeLut >> rhs.mode;
|
||||
node["name"] >> rhs.name;
|
||||
node["minuteBeep"] >> rhs.minuteBeep;
|
||||
node["countdownBeep"] >> rhs.countdownBeep;
|
||||
node["start"] >> rhs.val;
|
||||
node["persistent"] >> rhs.persistent;
|
||||
node["countdownStart"] >> rhs.countdownStart;
|
||||
node["value"] >> rhs.pvalue;
|
||||
return true;
|
||||
}
|
||||
static Node encode(const TimerData& rhs);
|
||||
static bool decode(const Node& node, TimerData& rhs);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert<ModelData> {
|
||||
// static YAML::Node encode(const GeneralSettings& rhs) {
|
||||
// Node node;
|
||||
// // TODO: convert struct into Node
|
||||
// return node;
|
||||
// }
|
||||
|
||||
static bool decode(const Node& node, ModelData& rhs)
|
||||
{
|
||||
if (!node.IsMap()) return false;
|
||||
|
||||
if (node["header"]) {
|
||||
const auto& header = node["header"];
|
||||
if (!header.IsMap()) return false;
|
||||
|
||||
header["name"] >> rhs.name;
|
||||
header["bitmap"] >> rhs.bitmap;
|
||||
// TODO: modelId
|
||||
}
|
||||
|
||||
if (node["timers"]) {
|
||||
const auto& timers = node["timers"];
|
||||
if (!timers.IsMap()) return false;
|
||||
timers >> rhs.timers;
|
||||
}
|
||||
|
||||
node["noGlobalFunctions"] >> rhs.noGlobalFunctions;
|
||||
node["thrTrim"] >> rhs.thrTrim;
|
||||
node["trimInc"] >> rhs.trimInc;
|
||||
node["displayTrims"] >> rhs.trimsDisplay;
|
||||
node["disableThrottleWarning"] >> rhs.disableThrottleWarning;
|
||||
//node[] >> rhs.beepANACenter;
|
||||
node["extendedLimits"] >> rhs.extendedLimits;
|
||||
node["extendedTrims"] >> rhs.extendedTrims;
|
||||
node["throttleReversed"] >> rhs.throttleReversed;
|
||||
|
||||
//flightModeData[]
|
||||
//mixData[]
|
||||
//limitData[]
|
||||
//inputNames[]
|
||||
//expoData[]
|
||||
//curves[]
|
||||
//logicalSw[]
|
||||
//customFn[]
|
||||
|
||||
//swashRingData
|
||||
//thrTraceSrc
|
||||
//switchWarningStates
|
||||
//thrTrimSwitch
|
||||
//potsWarningMode
|
||||
//potsWarnEnabled[]
|
||||
//potsWarnPosition[]
|
||||
|
||||
node["displayChecklist"] >> rhs.displayChecklist;
|
||||
|
||||
//gvarData[]
|
||||
//mavlink ???
|
||||
//telemetryProtocol ???
|
||||
//frsky
|
||||
//rssiSource
|
||||
//rssiAlarms
|
||||
|
||||
node["trainerMode"] >> trainerModeLut >> rhs.trainerMode;
|
||||
|
||||
//moduleData[]
|
||||
//scriptData[]
|
||||
//sensorData[]
|
||||
|
||||
node["toplcdTimer"] >> rhs.toplcdTimer;
|
||||
|
||||
//customScreens
|
||||
//topBarData
|
||||
node["view"] >> rhs.view;
|
||||
node["modelRegistrationID"] >> rhs.registrationId;
|
||||
|
||||
return true;
|
||||
}
|
||||
static Node encode(const ModelData& rhs);
|
||||
static bool decode(const Node& node, ModelData& rhs);
|
||||
};
|
||||
} // namespace YAML
|
||||
|
||||
@@ -56,7 +56,7 @@ void operator >> (const YAML::Node& node, bool& value)
|
||||
|
||||
namespace YAML {
|
||||
|
||||
Node operator << (const YamlLookupTable& lut, const int& value)
|
||||
std::string LookupValue(const YamlLookupTable& lut, const int& value)
|
||||
{
|
||||
const auto& it =
|
||||
find_if(lut.begin(), lut.end(), [=](const YamlLookupTableElmt& elmt) {
|
||||
@@ -65,7 +65,17 @@ Node operator << (const YamlLookupTable& lut, const int& value)
|
||||
});
|
||||
|
||||
if (it != lut.end()) {
|
||||
return Node(it->second);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
Node operator << (const YamlLookupTable& lut, const int& value)
|
||||
{
|
||||
std::string str = LookupValue(lut, value);
|
||||
if (!str.empty()) {
|
||||
return Node(str);
|
||||
}
|
||||
return Node();
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ void operator>>(const YAML::Node& node, T (&value)[N])
|
||||
|
||||
namespace YAML {
|
||||
|
||||
std::string LookupValue(const YamlLookupTable& lut, const int& value);
|
||||
Node operator << (const YamlLookupTable& lut, const int& value);
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -50,6 +50,55 @@ namespace YAML {
|
||||
|
||||
ENUM_CONVERTER(RawSwitchType, switchTypeLut);
|
||||
|
||||
Node convert<RawSwitch>::encode(const RawSwitch& rhs)
|
||||
{
|
||||
std::string sw_str;
|
||||
|
||||
int32_t sval = rhs.index;
|
||||
if (rhs.index < 0) {
|
||||
sval = -sval;
|
||||
sw_str += "!";
|
||||
}
|
||||
|
||||
switch (rhs.type) {
|
||||
case SWITCH_TYPE_SWITCH:
|
||||
sw_str += 'S';
|
||||
sw_str += 'A' + sval;
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_VIRTUAL:
|
||||
sw_str += "L";
|
||||
sw_str += std::to_string(sval + 1);
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_MULTIPOS_POT:
|
||||
sw_str += "6P";
|
||||
sw_str += std::to_string(sval / XPOTS_MULTIPOS_COUNT);
|
||||
sw_str += std::to_string(sval % XPOTS_MULTIPOS_COUNT);
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_TRIM:
|
||||
sw_str += LookupValue(trimSwitchLut, sval);
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_FLIGHT_MODE:
|
||||
sw_str += "FM";
|
||||
sw_str += std::to_string(sval);
|
||||
break;
|
||||
|
||||
case SWITCH_TYPE_SENSOR:
|
||||
sw_str += "T";
|
||||
sw_str += std::to_string(sval + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
sw_str += LookupValue(switchTypeLut, rhs.type);
|
||||
break;
|
||||
}
|
||||
|
||||
return Node(sw_str);
|
||||
}
|
||||
|
||||
bool convert<RawSwitch>::decode(const Node& node, RawSwitch& rhs)
|
||||
{
|
||||
const std::string& sw_str = node.Scalar();
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace YAML {
|
||||
|
||||
template <>
|
||||
struct convert<RawSwitch> {
|
||||
// static YAML::Node encode(const GeneralSettings& rhs);
|
||||
static Node encode(const RawSwitch& rhs);
|
||||
static bool decode(const Node& node, RawSwitch& rhs);
|
||||
};
|
||||
|
||||
|
||||
@@ -290,5 +290,30 @@ bool CategorizedStorageFormat::writeYaml(const RadioData & radioData)
|
||||
return false;
|
||||
}
|
||||
|
||||
return writeFile(radioSettingsBuffer, "RADIO/radio.yml");
|
||||
if (!writeFile(radioSettingsBuffer, "RADIO/radio.yml")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EtxModelfiles modelFiles;
|
||||
for (const auto& model : radioData.models) {
|
||||
|
||||
// TODO: verify '.yml' (in case we moved from '.bin')
|
||||
QString modelFilename = QString("MODELS/%1").arg(model.filename);
|
||||
QByteArray modelData;
|
||||
writeModelToYaml(model, modelData);
|
||||
if (!writeFile(modelData, modelFilename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
modelFiles.push_back({ std::string(model.filename), model.category });
|
||||
}
|
||||
|
||||
// TODO: sort 'modelFiles' by category index
|
||||
QByteArray modelslistBuffer;
|
||||
if (!writeModelsListToYaml(radioData.categories, modelFiles, modelslistBuffer)
|
||||
|| writeFile(modelslistBuffer, "MODELS/models.yml")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user