Skip to content

Commit

Permalink
Fixed bugs with array datarefs, added support for modifiers.
Browse files Browse the repository at this point in the history
  • Loading branch information
vranki committed Mar 30, 2018
1 parent 81adc00 commit 1ae0ec1
Show file tree
Hide file tree
Showing 18 changed files with 199 additions and 121 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,18 @@ Commands and replies are sent as text strings as defined below.

### Datarefs ###

* **sub {dataref} [accuracy]** Subscribe to dataref, with optional accuracy.
* **unsub {dataref}** Unsubscribe dataref.
* **set {dataref} {value}** Set dataref to value. Dataref must be subscribed first.
* **sub {dataref}:[modifiers] [accuracy]** Subscribe to dataref, with optional accuracy.
* **unsub {dataref}** Unsubscribe dataref.
* **set {dataref} {value}** Set dataref to value. Dataref must be subscribed first.

With accuracy you can decide how much the dataref's value can
change before a update is sent. Set it to as large value as possible
to maximize frame rate and minimize network traffic. For data datarefs,
the accuracy represents the update interval in milliseconds.

Modifiers is a comma-separated list of strings that can modify behavior of
dataref. See example on data dataref.

List of datarefs can be found at:
http://www.xsquawkbox.net/xpsdk/docs/DataRefs.txt

Expand All @@ -217,6 +220,12 @@ holds. For example this sets full throttle for engines 1 & 2:
```
set sim/flightmodel/engine/ENGN_thro [1,1]
```
Note: subscribe to array datarefs with full ref name without indices:
```
sub sim/flightmodel/engine/ENGN_thro
WRONG: sub sim/flightmodel/engine/ENGN_thro[1]
```


### Keys and Buttons ###

Expand Down Expand Up @@ -276,6 +285,13 @@ Data datarefs output data in base64:
```
ub sim/aircraft/view/acf_descrip RXh0UGxhbmUgU2ltdWxhdGVkIENvbm5lY3Rpb24=
```
Use modifier "string" to output data as text (make sure it's really printable):
```
sub sim/aircraft/view/acf_descrip:string
->
ub sim/aircraft/view/acf_descrip:string "Boeing 737-800"
```


### Console Output ###

Expand Down
18 changes: 16 additions & 2 deletions clients/extplane-client-qt/simulateddatarefs/simulateddataref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,22 @@

#include <qmath.h>

SimulatedDataRef::SimulatedDataRef(QObject *parent, double minV, double maxV, double changeDivisor, bool round, int arrayCount, QString refName) :
QObject(parent), minValue(minV), maxValue(maxV), currentValue(minV), actualCurrentValue(minV), change((maxValue - minValue)/changeDivisor), round(round), arrayCount(arrayCount), myClientRef(0, refName, 0)
SimulatedDataRef::SimulatedDataRef(QObject *parent,
double minV,
double maxV,
double changeDivisor,
bool round,
int arrayCount,
QString refName) :
QObject(parent)
, minValue(minV)
, maxValue(maxV)
, currentValue(minV)
, actualCurrentValue(minV)
, change((maxValue - minValue)/changeDivisor)
, round(round)
, arrayCount(arrayCount)
, myClientRef(nullptr, refName, 0)
{
connect(&changeTimer, SIGNAL(timeout()), this, SLOT(changeTimeout()));
changeTimer.setSingleShot(false);
Expand Down
53 changes: 33 additions & 20 deletions extplane-plugin/xplaneplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ XPlanePlugin::XPlanePlugin(QObject *parent) : QObject(parent)
, argv(nullptr)
, app(nullptr)
, server(nullptr)
, flightLoopInterval(1.0f / 30.f) { // Default to 30hz
}
, flightLoopInterval(1.0f / 30.f) // Default to 30hz
{ }

XPlanePlugin::~XPlanePlugin() {
DEBUG << Q_FUNC_INFO;
}

float XPlanePlugin::flightLoop(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop,
int inCounter, void *inRefcon) {
float XPlanePlugin::flightLoop(float inElapsedSinceLastCall,
float inElapsedTimeSinceLastFlightLoop,
int inCounter,
void *inRefcon) {
Q_UNUSED(inElapsedSinceLastCall);
Q_UNUSED(inElapsedTimeSinceLastFlightLoop);
Q_UNUSED(inCounter);
Expand Down Expand Up @@ -110,10 +112,11 @@ DataRef* XPlanePlugin::subscribeRef(QString &name) {
}

// Not yet subscribed - create a new dataref
XPLMDataRef ref = XPLMFindDataRef(name.toLatin1());
QString realName = refNameWithoutModifiers(name);
XPLMDataRef ref = XPLMFindDataRef(realName.toLatin1());
if(ref) {
XPLMDataTypeID refType = XPLMGetDataRefTypes(ref);
DataRef *dr = 0;
DataRef *dr = nullptr;
if(refType & xplmType_Double) {
dr = new DoubleDataRef(this, name, ref);
} else if(refType & xplmType_Float) {
Expand All @@ -129,10 +132,11 @@ DataRef* XPlanePlugin::subscribeRef(QString &name) {
}
if(dr) {
dr->setSubscriberCount(1);
dr->setWritable(XPLMCanWriteDataRef(ref) != 0);
DEBUG << "Subscribed to ref " << dr->name() << ", type: " << dr->typeString() << ", writable:" << dr->isWritable();
dr->setWritable(XPLMCanWriteDataRef(ref));
DEBUG << "Subscribed to ref " << dr->name()
<< ", type: " << dr->typeString()
<< ", writable:" << dr->isWritable();
refs.append(dr);
emit dr->changed(dr); // Force update to all clients
return dr;
} else {
INFO << "Dataref type " << refType << "not supported";
Expand All @@ -146,6 +150,7 @@ DataRef* XPlanePlugin::subscribeRef(QString &name) {
void XPlanePlugin::unsubscribeRef(DataRef *ref) {
Q_ASSERT(refs.contains(ref));
DEBUG << ref->name() << ref->subscriberCount();

ref->setSubscriberCount(ref->subscriberCount() - 1);
if(ref->subscriberCount() == 0) {
refs.removeOne(ref);
Expand All @@ -154,6 +159,7 @@ void XPlanePlugin::unsubscribeRef(DataRef *ref) {
}
}

// Called for each ref on every flight loop
void XPlanePlugin::updateDataRef(DataRef *ref)
{
Q_ASSERT(ref);
Expand All @@ -180,29 +186,27 @@ void XPlanePlugin::updateDataRef(DataRef *ref)
};
case extplaneRefTypeIntArray:
{
IntArrayDataRef *faRef = qobject_cast<IntArrayDataRef*>(ref);
int arrayLength = faRef->value().length();
if(arrayLength == 0) {
arrayLength = XPLMGetDatavi(faRef->ref(), NULL, 0, 0);
faRef->setLength(arrayLength);
IntArrayDataRef *iaRef = qobject_cast<IntArrayDataRef*>(ref);
int arrayLength = iaRef->value().length();
if(arrayLength <= 0) {
arrayLength = XPLMGetDatavi(iaRef->ref(), NULL, 0, 0);
iaRef->setLength(arrayLength);
}
int valuesCopied = XPLMGetDatavi(faRef->ref(), faRef->valueArray(), 0, arrayLength);
int valuesCopied = XPLMGetDatavi(iaRef->ref(), iaRef->valueArray(), 0, arrayLength);
Q_ASSERT(valuesCopied == arrayLength);
faRef->updateValue();
iaRef->updateValue();
break;
};
case extplaneRefTypeInt:
{
IntDataRef *iRef = qobject_cast<IntDataRef*>(ref);
int newValue = XPLMGetDatai(ref->ref());
iRef->updateValue(newValue);
qobject_cast<IntDataRef*>(ref)->updateValue(newValue);
break;
};
case extplaneRefTypeDouble:
{
DoubleDataRef *dRef = qobject_cast<DoubleDataRef*>(ref);
double newValue = XPLMGetDatad(ref->ref());
dRef->updateValue(newValue);
qobject_cast<DoubleDataRef*>(ref)->updateValue(newValue);
break;
};
case extplaneRefTypeData:
Expand Down Expand Up @@ -308,6 +312,15 @@ void XPlanePlugin::setFlightLoopInterval(float newInterval) {
}
}

QString XPlanePlugin::refNameWithoutModifiers(QString &original)
{
if(original.contains(":")) {
return original.left(original.indexOf(":"));
}
return original;
}


void XPlanePlugin::pluginStop() {
DEBUG;
app->processEvents();
Expand Down
3 changes: 3 additions & 0 deletions extplane-plugin/xplaneplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public slots:
void setFlightLoopInterval(float newInterval);

private:
// Returns the ref name without modifier part (after :)
QString refNameWithoutModifiers(QString &original);

QList<DataRef*> refs;
int argc; // Fake argc and argv for QCoreApplication
char *argv;
Expand Down
8 changes: 6 additions & 2 deletions extplane-server/datarefs/datadataref.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "datadataref.h"
#include "../util/console.h"

DataDataRef::DataDataRef(QObject *parent, QString name, void *ref) : DataRef(parent, name, ref)
DataDataRef::DataDataRef(QObject *parent, QString &name, void *ref) : DataRef(parent, name, ref)
{
_typeString = "b";
_type = extplaneRefTypeData;
Expand Down Expand Up @@ -51,7 +51,11 @@ void DataDataRef::setValue(QByteArray &newValue) {
}

QString DataDataRef::valueString() {
return QString(_value).toUtf8().toBase64();
if(modifiers().contains("string")) {
return QString("\"%1\"").arg(QString(_value));
} else {
return QString(_value).toUtf8().toBase64();
}
}

void DataDataRef::setValue(QString &newValue) {
Expand Down
5 changes: 4 additions & 1 deletion extplane-server/datarefs/datadataref.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@
* The accuracy for binary datarefs represents how often ExtPlane
* should check for updates in milliseconds. When the accuracy
* is set to 0, ExtPlane will check for updates as soon as possible.
*
* Defaults to base64 encoding.
* Use modifier "string" to return text as string.
*/
class DataDataRef : public DataRef {
Q_OBJECT

public:
DataDataRef(QObject *parent, QString name, void* ref);
DataDataRef(QObject *parent, QString &name, void* ref);
QByteArray &value();
QByteArray &newValue(); // Write to this and call updatevalue to change value
void setValue(QByteArray &newValue); // @todo implement
Expand Down
18 changes: 14 additions & 4 deletions extplane-server/datarefs/dataref.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "dataref.h"
#include "../util/console.h"

DataRef::DataRef(QObject *parent, QString name, void *ref) : QObject(parent)
DataRef::DataRef(QObject *parent, const QString &name, void *ref) : QObject(parent)
, _typeString("?")
, _type(extplaneRefTypeUnknown)
, _ref(ref)
Expand All @@ -10,13 +11,22 @@ DataRef::DataRef(QObject *parent, QString name, void *ref) : QObject(parent)
, _subscriberCount(0)
, _writable(false)
, _unsubscribeAfterChange(false)
{ }
{
if(name.contains(":")) {
QString modifiersPart = name.right(name.length() - name.indexOf(":") - 1);
_modifiers = modifiersPart.split(",");
}
}

const QString &DataRef::name() const {
return _name;
}

void *DataRef::ref() {
QStringList DataRef::modifiers() const {
return _modifiers;
}

void *DataRef::ref() const {
return _ref;
}

Expand All @@ -33,7 +43,7 @@ void DataRef::setWritable(const bool cw) {
_writable = cw;
}

bool DataRef::isWritable() {
bool DataRef::isWritable() const {
return _writable;
}

Expand Down
12 changes: 7 additions & 5 deletions extplane-server/datarefs/dataref.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,23 @@ enum {
class DataRef : public QObject {
Q_OBJECT
public:
DataRef(QObject *parent, QString name, void* ref);
DataRef(QObject *parent, const QString &name, void* ref);
const QString &name() const;
void* ref();
QStringList modifiers() const;
void* ref() const;
int subscriberCount() const;
void setSubscriberCount(const int subs);
void setWritable(const bool cw);
bool isWritable();
bool isWritable() const;
virtual QString valueString() = 0;
virtual void setValue(QString &newValue) = 0;
extplaneRefID type() const; // NOTE: always only one type, although XPLMDataTypeID can have many.
virtual void setType(extplaneRefID newType); // Only set after constructor
QString typeString() const;
virtual void setAccuracy(double val);
virtual void updateAccuracy(double val);
double accuracy() { return _accuracy; }
void setUnsubscribeAfterChange();
double accuracy() const { return _accuracy; }
void setUnsubscribeAfterChange(); // Call to mark this ref to be unsubscribed after one change
bool shouldUnsubscribeAfterChange() const;
bool isValid() const; // True if the value has been set initially. False if not.

Expand All @@ -58,6 +59,7 @@ class DataRef : public QObject {

private:
QString _name;
QStringList _modifiers;
int _subscriberCount;
bool _writable;
bool _unsubscribeAfterChange;
Expand Down
24 changes: 14 additions & 10 deletions extplane-server/datarefs/floatarraydataref.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ FloatArrayDataRef::FloatArrayDataRef(QObject *parent, QString name, void *ref) :
_typeString = "fa";
_type = extplaneRefTypeFloatArray;
_length = 0;
_valueArray = 0;
_valueArray = nullptr;
}

FloatArrayDataRef::~FloatArrayDataRef() {
Expand All @@ -27,14 +27,15 @@ QVector<float> & FloatArrayDataRef::value() {

// Copies values from valuearray to value list and emits changed as needed
void FloatArrayDataRef::updateValue() {
bool notequal = false;
Q_ASSERT(_length > 0);
bool valuesChanged = false;
for(int i=0;i<_length;i++){
if(_values[i] != _valueArray[i]) {
_values[i] = _valueArray[i];
notequal = true;
if(_values.at(i) != _valueArray[i]) {
_values.replace(i, _valueArray[i]);
valuesChanged = true;
}
}
if (notequal) {
if (valuesChanged) {
if(!_valueValid) setValueValid();
emit changed(this);
}
Expand All @@ -53,7 +54,7 @@ QString FloatArrayDataRef::valueString() {
void FloatArrayDataRef::setValue(QString &newValue) {
// Check that value starts with [ and ends with ]
if(!newValue.startsWith('[') || !newValue.endsWith(']')) {
INFO << "Invalid array value";
INFO << "Invalid array value" << newValue;
return;
}

Expand All @@ -69,7 +70,7 @@ void FloatArrayDataRef::setValue(QString &newValue) {
bool ok = true;
float value = values[i].toFloat(&ok);
if(!ok) {
INFO << "Invalid value " << values[i] << "in array";
INFO << "Invalid value " << values.at(i) << "in array";
return;
}
_valueArray[i]=value;
Expand All @@ -79,12 +80,15 @@ void FloatArrayDataRef::setValue(QString &newValue) {

void FloatArrayDataRef::setLength(int newLength)
{
_values.fill(-9999, _length); // Resize and initialize vector
Q_ASSERT(newLength > 0);
_values.fill(-9999, newLength); // Resize and initialize vector
if(_valueArray) delete[] _valueArray;
_valueArray = new float[_length];
_valueArray = new float[newLength];
_length = newLength;
}

float *FloatArrayDataRef::valueArray()
{
Q_ASSERT(_valueArray);
return _valueArray;
}
2 changes: 1 addition & 1 deletion extplane-server/datarefs/floatarraydataref.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class FloatArrayDataRef : public DataRef {
private:
QVector<float> _values; // Actual values in a vector
int _length; // Length of dataref, as given by X-Plane. 0 if not set.
float * _valueArray; // Array for reading & writing values. Allocated dynamically.
float *_valueArray; // Array for reading & writing values. Allocated dynamically.
};

#endif // FloatArrayDataRef_H
Loading

0 comments on commit 1ae0ec1

Please sign in to comment.