Commit 032eef30 authored by Gus Grubba's avatar Gus Grubba

Parse min, max, step and unit off camera definition file

Ignore Fact index if there are no enums (avoid adding an "Unknown" entry)
Add function to convert and clamp a (Fact) value.
parent 4dd68530
......@@ -28,6 +28,8 @@ static const char* kExclusion = "exclude";
static const char* kExclusions = "exclusions";
static const char* kLocale = "locale";
static const char* kLocalization = "localization";
static const char* kMax = "max";
static const char* kMin = "min";
static const char* kModel = "model";
static const char* kName = "name";
static const char* kOption = "option";
......@@ -39,9 +41,11 @@ static const char* kParameterranges = "parameterranges";
static const char* kParameters = "parameters";
static const char* kReadOnly = "readonly";
static const char* kRoption = "roption";
static const char* kStep = "step";
static const char* kStrings = "strings";
static const char* kTranslated = "translated";
static const char* kType = "type";
static const char* kUnit = "unit";
static const char* kUpdate = "update";
static const char* kUpdates = "updates";
static const char* kValue = "value";
......@@ -671,6 +675,61 @@ QGCCameraControl::_loadSettings(const QDomNodeList nodeList)
qWarning() << QStringLiteral("Duplicate fact name:") << factName;
delete metaData;
} else {
{
//-- Check for Min Value
QString attr;
if(read_attribute(parameterNode, kMin, attr)) {
QVariant typedValue;
QString errorString;
if (metaData->convertAndValidateRaw(attr, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawMin(typedValue);
} else {
qWarning() << "Invalid min value for" << factName
<< " type:" << metaData->type()
<< " value:" << attr
<< " error:" << errorString;
}
}
}
{
//-- Check for Max Value
QString attr;
if(read_attribute(parameterNode, kMax, attr)) {
QVariant typedValue;
QString errorString;
if (metaData->convertAndValidateRaw(attr, true /* convertOnly */, typedValue, errorString)) {
metaData->setRawMax(typedValue);
} else {
qWarning() << "Invalid max value for" << factName
<< " type:" << metaData->type()
<< " value:" << attr
<< " error:" << errorString;
}
}
}
{
//-- Check for Step Value
QString attr;
if(read_attribute(parameterNode, kStep, attr)) {
QVariant typedValue;
QString errorString;
if (metaData->convertAndValidateRaw(attr, true /* convertOnly */, typedValue, errorString)) {
metaData->setIncrement(typedValue.toDouble());
} else {
qWarning() << "Invalid step value for" << factName
<< " type:" << metaData->type()
<< " value:" << attr
<< " error:" << errorString;
}
}
}
{
//-- Check for Units
QString attr;
if(read_attribute(parameterNode, kUnit, attr)) {
metaData->setRawUnits(attr);
}
}
qCDebug(CameraControlLog) << "New parameter:" << factName;
_nameToFactMetaDataMap[factName] = metaData;
Fact* pFact = new Fact(_compID, factName, factType, this);
......
......@@ -191,28 +191,30 @@ int Fact::enumIndex(void)
{
static const double accuracy = 1.0 / 1000000.0;
if (_metaData) {
int index = 0;
foreach (QVariant enumValue, _metaData->enumValues()) {
if (enumValue == rawValue()) {
return index;
}
//-- Float comparissons don't always work
if(type() == FactMetaData::valueTypeFloat || type() == FactMetaData::valueTypeDouble) {
double diff = fabs(enumValue.toDouble() - rawValue().toDouble());
if(diff < accuracy) {
//-- Only enums have an index
if(_metaData->enumValues().count()) {
int index = 0;
foreach (QVariant enumValue, _metaData->enumValues()) {
if (enumValue == rawValue()) {
return index;
}
//-- Float comparissons don't always work
if(type() == FactMetaData::valueTypeFloat || type() == FactMetaData::valueTypeDouble) {
double diff = fabs(enumValue.toDouble() - rawValue().toDouble());
if(diff < accuracy) {
return index;
}
}
index ++;
}
index ++;
// Current value is not in list, add it manually
_metaData->addEnumInfo(QString("Unknown: %1").arg(rawValue().toString()), rawValue());
emit enumsChanged();
return index;
}
// Current value is not in list, add it manually
_metaData->addEnumInfo(QString("Unknown: %1").arg(rawValue().toString()), rawValue());
emit enumsChanged();
return index;
} else {
qWarning() << kMissingMetadata;
}
return -1;
}
......@@ -537,6 +539,22 @@ QString Fact::validate(const QString& cookedValue, bool convertOnly)
}
}
QVariant Fact::clamp(const QString& cookedValue)
{
if (_metaData) {
QVariant typedValue;
if(_metaData->clampValue(cookedValue, typedValue)) {
return typedValue;
} else {
//-- If conversion failed, return current value
return rawValue();
}
} else {
qWarning() << kMissingMetadata;
}
return QVariant();
}
bool Fact::rebootRequired(void) const
{
if (_metaData) {
......
......@@ -70,6 +70,8 @@ public:
/// Convert and validate value
/// @param convertOnly true: validate type conversion only, false: validate against meta data as well
Q_INVOKABLE QString validate(const QString& cookedValue, bool convertOnly);
/// Convert and clamp value
Q_INVOKABLE QVariant clamp(const QString& cookedValue);
QVariant cookedValue (void) const; /// Value after translation
QVariant rawValue (void) const { return _rawValue; } /// value prior to translation, careful
......
......@@ -398,6 +398,67 @@ bool FactMetaData::convertAndValidateCooked(const QVariant& cookedValue, bool co
return convertOk && errorString.isEmpty();
}
bool FactMetaData::clampValue(const QVariant& cookedValue, QVariant& typedValue)
{
bool convertOk = false;
switch (type()) {
case FactMetaData::valueTypeInt8:
case FactMetaData::valueTypeInt16:
case FactMetaData::valueTypeInt32:
typedValue = QVariant(cookedValue.toInt(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeUint8:
case FactMetaData::valueTypeUint16:
case FactMetaData::valueTypeUint32:
typedValue = QVariant(cookedValue.toUInt(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeFloat:
typedValue = QVariant(cookedValue.toFloat(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeElapsedTimeInSeconds:
case FactMetaData::valueTypeDouble:
typedValue = QVariant(cookedValue.toDouble(&convertOk));
if (convertOk) {
if (cookedMin() > typedValue) {
typedValue = cookedMin();
} else if(typedValue > cookedMax()) {
typedValue = cookedMax();
}
}
break;
case FactMetaData::valueTypeString:
convertOk = true;
typedValue = QVariant(cookedValue.toString());
break;
case FactMetaData::valueTypeBool:
convertOk = true;
typedValue = QVariant(cookedValue.toBool());
break;
}
return convertOk;
}
void FactMetaData::setBitmaskInfo(const QStringList& strings, const QVariantList& values)
{
if (strings.count() != values.count()) {
......
......@@ -145,6 +145,12 @@ public:
/// Same as convertAndValidateRaw except for cookedValue input
bool convertAndValidateCooked(const QVariant& cookedValue, bool convertOnly, QVariant& typedValue, QString& errorString);
/// Converts the specified cooked value and clamps it (max/min)
/// @param cookedValue Value to convert, can be string
/// @param typeValue Converted value, correctly typed and clamped
/// @returns false: Convertion failed
bool clampValue(const QVariant& cookedValue, QVariant& typedValue);
static const int defaultDecimalPlaces = 3; ///< Default value for decimal places if not specified/known
static const int unknownDecimalPlaces = -1; ///< Number of decimal places to specify is not known
......
......@@ -768,7 +768,10 @@ VideoReceiver::_updateTimer()
}
}
if(_videoRunning) {
uint32_t timeout = qgcApp()->toolbox()->settingsManager()->videoSettings()->rtspTimeout()->rawValue().toUInt();
uint32_t timeout = 1;
if(qgcApp()->toolbox() && qgcApp()->toolbox()->settingsManager()) {
timeout = qgcApp()->toolbox()->settingsManager()->videoSettings()->rtspTimeout()->rawValue().toUInt();
}
time_t elapsed = 0;
time_t lastFrame = _videoSurface->lastFrame();
if(lastFrame != 0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment