From 4f823d45b83fc0934b722f0487cf44605b3dc3c2 Mon Sep 17 00:00:00 2001 From: Ville Ranki Date: Wed, 3 Mar 2021 20:32:34 +0200 Subject: [PATCH] Fixes and enhancements to UDP protocol support --- UDP.md | 1 - clients/extplane-client-qt/clientdataref.cpp | 34 ++-- clients/extplane-client-qt/clientdataref.h | 4 +- .../extplane-client-qt/extplaneconnection.cpp | 22 +-- .../extplane-client-qt/extplaneconnection.h | 2 +- .../extplane-client-qt/extplaneudpclient.cpp | 18 +-- .../extplane-client-qt/extplaneudpclient.h | 2 +- extplane-plugin/main.cpp | 6 +- extplane-plugin/xplaneplugin.cpp | 147 +++++++++--------- extplane-plugin/xplaneplugin.h | 16 +- extplane-server/datarefs/dataref.cpp | 7 - extplane-server/datarefs/dataref.h | 16 +- extplane-server/datarefs/floatdataref.cpp | 1 - extplane-server/datarefs/floatdataref.h | 2 +- extplane-server/tcpclient.cpp | 41 ++--- extplane-server/udpsender.cpp | 76 +++++---- extplane-server/udpsender.h | 16 +- .../datasources/condordatasource.cpp | 4 +- .../datasources/flightgeardatasource.cpp | 4 +- 19 files changed, 208 insertions(+), 211 deletions(-) diff --git a/UDP.md b/UDP.md index 4983b11..fbc9518 100644 --- a/UDP.md +++ b/UDP.md @@ -77,4 +77,3 @@ Repeated double_count times: * ref_id (2, uint16) - ref id * value (8, double) - value of the double dataref - diff --git a/clients/extplane-client-qt/clientdataref.cpp b/clients/extplane-client-qt/clientdataref.cpp index 0e3cbf1..5f395f3 100644 --- a/clients/extplane-client-qt/clientdataref.cpp +++ b/clients/extplane-client-qt/clientdataref.cpp @@ -29,8 +29,11 @@ void ClientDataRef::setName(QString &name) { emit nameChanged(m_name); } -QString ClientDataRef::value() const { - return m_values.isEmpty() ? "" : m_values.first(); +QString ClientDataRef::value() { + if(m_values.isEmpty()) { + m_values.append(valueString()); + } + return m_values.first(); } int ClientDataRef::valueInt() @@ -74,12 +77,22 @@ void ClientDataRef::clientDestroyed() { setClient(nullptr); } +QString ClientDataRef::valueString() +{ + if(m_valueIntValid) return QString::number(m_valueInt); + if(!qIsNaN(m_valueFloat)) return QString::number(m_valueFloat); + if(!qIsNaN(m_valueDouble)) return QString::number(m_valueDouble); + // qDebug() << Q_FUNC_INFO << "No value set for" << name(); + return ""; +} + void ClientDataRef::invalidateValue() { // Invalidate value types m_valueIntValid = false; m_valueFloat = std::nanf(""); m_valueDouble = std::nan(""); + m_values.clear(); } void ClientDataRef::setDataFormat(QString dataFormat) { @@ -95,25 +108,19 @@ QStringList& ClientDataRef::values() { } void ClientDataRef::updateValue(QString newValue) { - if(m_changedOnce && !m_values.isEmpty() && newValue == m_values.first()) return; + invalidateValue(); if(m_values.isEmpty()) { m_values.push_back(newValue); } else { m_values.replace(0, newValue); } - m_changedOnce = true; - - invalidateValue(); - emit changed(this); } void ClientDataRef::updateValue(QStringList &newValues) { - if(m_changedOnce && newValues == m_values) return; - m_values = newValues; - m_changedOnce = true; invalidateValue(); + m_values = newValues; emit changed(this); } @@ -122,25 +129,30 @@ void ClientDataRef::updateValue(int newValue) invalidateValue(); m_valueInt = newValue; m_valueIntValid = true; + emit changed(this); } void ClientDataRef::updateValue(float newValue) { invalidateValue(); m_valueFloat = newValue; + emit changed(this); } void ClientDataRef::updateValue(double newValue) { invalidateValue(); m_valueDouble = newValue; + emit changed(this); } void ClientDataRef::setValue(QString _newValue, int index) { + if(m_values.size() <= 1) + invalidateValue(); + while(m_values.size() < index + 1) // Resize list if needed m_values.append(QString("")); m_values[index] = _newValue; - invalidateValue(); emit valueSet(this); } diff --git a/clients/extplane-client-qt/clientdataref.h b/clients/extplane-client-qt/clientdataref.h index e79b31b..294ab45 100644 --- a/clients/extplane-client-qt/clientdataref.h +++ b/clients/extplane-client-qt/clientdataref.h @@ -40,7 +40,7 @@ class ClientDataRef : public QObject { QString& name(); QStringList& values(); // Returns all values double accuracy(); - QString value() const; // Returns first value + QString value(); // Returns first value int valueInt(); float valueFloat(); double valueDouble(); @@ -80,6 +80,7 @@ private slots: void clientDestroyed(); private: + QString valueString(); // Generate string from raw values, if possible void invalidateValue(); QString m_name; QStringList m_values; // Length 1 if not array @@ -91,7 +92,6 @@ private slots: int m_subscribers = 0; ExtPlaneClient* m_client = nullptr; QString m_dataFormat; - bool m_changedOnce = false; // False until first update sent. QStringList m_modifiers; quint16 m_udpId = 0; }; diff --git a/clients/extplane-client-qt/extplaneconnection.cpp b/clients/extplane-client-qt/extplaneconnection.cpp index b195543..0e892dd 100644 --- a/clients/extplane-client-qt/extplaneconnection.cpp +++ b/clients/extplane-client-qt/extplaneconnection.cpp @@ -70,14 +70,14 @@ bool ExtPlaneConnection::isConnected() const ClientDataRef *ExtPlaneConnection::subscribeDataRef(QString name, double accuracy) { ClientDataRef *ref = dataRefs[name]; if(ref) { - DEBUG << QString("Ref %1 already subscribed %2 times").arg(name).arg(ref->subscribers()); + // DEBUG << QString("Ref %1 already subscribed %2 times").arg(name).arg(ref->subscribers()); ref->setSubscribers(ref->subscribers()+1); if(accuracy < ref->accuracy()) { if(server_ok) subRef(ref); // Re-subscribe with higher accuracy } } else { - DEBUG << QString("Subscribing to new ref %1").arg(name); + // DEBUG << "Subscribing to new ref" << name << "accuracy" << accuracy; ref = createDataRef(name, accuracy); dataRefs[ref->name()] = ref; @@ -97,7 +97,6 @@ ClientDataRef *ExtPlaneConnection::createDataRef(QString name, double accuracy) } void ExtPlaneConnection::unsubscribeDataRef(ClientDataRef *ref) { - qDebug() << Q_FUNC_INFO << ref->name(); if(m_udpClient) m_udpClient->unsubscribedRef(ref); @@ -117,11 +116,11 @@ void ExtPlaneConnection::receivedLineSlot(QString & line) { if(line=="EXTPLANE 1") { server_ok = true; emit connectionMessage(QString("Connected to ExtPlane at %1:%2").arg(hostName()).arg(port())); - DEBUG << "Setting update interval to " << m_updateInterval; + // DEBUG << "Setting update interval to " << m_updateInterval; setUpdateInterval(m_updateInterval); // Sub all refs for(auto &refPair : dataRefs) { - DEBUG << "Subscribing to ref" << refPair.second->name(); + // DEBUG << "Subscribing to ref" << refPair.second->name(); subRef(refPair.second); } emit connectedChanged(true); @@ -154,7 +153,7 @@ void ExtPlaneConnection::receivedLineSlot(QString & line) { m_udpClient = new ExtPlaneUdpClient(m_clientId, this); } m_udpClient->subscribedRef(ref); - INFO << "Tracking ref via UDP" << cmd.value(3) << id; + // INFO << "Tracking ref via UDP" << cmd.value(3) << id; } else { INFO << "Can't find dataref" << cmd.value(3); } @@ -212,14 +211,14 @@ void ExtPlaneConnection::subRef(ClientDataRef *ref) { writeLine(subLine); } -void ExtPlaneConnection::writeLine(QString line) { +void ExtPlaneConnection::writeLine(const QString &line) { if(!server_ok) { emit connectionMessage(QString("Connection not ok! Tried to write %1").arg(line)); DEBUG << "Connection not ok! Tried to write" << line; return; } - line +="\n"; write(line.toUtf8()); + write("\n"); } void ExtPlaneConnection::keyPress(int id) { @@ -253,7 +252,12 @@ void ExtPlaneConnection::commandEnd(QString name) { } void ExtPlaneConnection::setValue(QString name, QString value) { - QString line = "set " + name + " " + value; + if(value.isEmpty()) { + DEBUG << "Trying to set empty value for ref" << name; + return; + } + + QString line = QString("set %1 %2").arg(name, value); writeLine(line); } diff --git a/clients/extplane-client-qt/extplaneconnection.h b/clients/extplane-client-qt/extplaneconnection.h index c537369..2fd0cb3 100644 --- a/clients/extplane-client-qt/extplaneconnection.h +++ b/clients/extplane-client-qt/extplaneconnection.h @@ -53,7 +53,7 @@ private slots: protected: void subRef(ClientDataRef *ref); - virtual void writeLine(QString line); + virtual void writeLine(const QString &line); virtual ClientDataRef *createDataRef(QString newName, double accuracy = 0); std::set clients; std::map dataRefs; diff --git a/clients/extplane-client-qt/extplaneudpclient.cpp b/clients/extplane-client-qt/extplaneudpclient.cpp index 2d2e586..d387152 100644 --- a/clients/extplane-client-qt/extplaneudpclient.cpp +++ b/clients/extplane-client-qt/extplaneudpclient.cpp @@ -5,8 +5,8 @@ ExtPlaneUdpClient::ExtPlaneUdpClient(quint8 clientId, QObject *parent) : QObject(parent) , m_clientId(clientId) -{ - m_udpPort = UDP_OUT_PORT_BASE + m_clientId; + , m_udpPort(UDP_OUT_PORT_BASE + m_clientId) +{ if(m_socket.bind(m_udpPort)) { connect(&m_socket, &QUdpSocket::readyRead, this, &ExtPlaneUdpClient::readPendingDatagrams); INFO << "UDP listener bound to port" << m_udpPort; @@ -25,26 +25,26 @@ void ExtPlaneUdpClient::unsubscribedRef(ClientDataRef *ref) { m_idRefMap.erase(ref->udpId()); } -void ExtPlaneUdpClient::readPendingDatagrams() -{ +void ExtPlaneUdpClient::readPendingDatagrams() { while(m_socket.hasPendingDatagrams()) { QNetworkDatagram dg = m_socket.receiveDatagram(); processDatagram(dg); } } -void ExtPlaneUdpClient::processDatagram(QNetworkDatagram &dg) -{ +void ExtPlaneUdpClient::processDatagram(QNetworkDatagram &dg) { QByteArray data = dg.data(); QDataStream s(&data, QIODevice::ReadOnly); if(!data.startsWith("EXTP_")) { - qWarning() << Q_FUNC_INFO << "Wrong header, not extplane packet??"; + qWarning() << Q_FUNC_INFO << "Wrong header, non extplane packet sen to port" << m_udpPort; return; } s.skipRawData(5); + quint8 clientid; quint16 id; quint16 dataCount; + s >> clientid; if(m_clientId && (clientid != m_clientId)) { // Packet meant for another client, ignore @@ -64,10 +64,10 @@ void ExtPlaneUdpClient::processDatagram(QNetworkDatagram &dg) } } s.skipRawData(2); - dataCount = 0; s >> dataCount; for(unsigned int i=0;i> id >> data; auto ref = m_idRefMap[id]; if(id) { @@ -79,10 +79,10 @@ void ExtPlaneUdpClient::processDatagram(QNetworkDatagram &dg) } } s.skipRawData(2); - dataCount = 0; s >> dataCount; for(unsigned int i=0;i> id >> data; auto ref = m_idRefMap[id]; if(id) { diff --git a/clients/extplane-client-qt/extplaneudpclient.h b/clients/extplane-client-qt/extplaneudpclient.h index c1c3222..af3aa87 100644 --- a/clients/extplane-client-qt/extplaneudpclient.h +++ b/clients/extplane-client-qt/extplaneudpclient.h @@ -21,7 +21,7 @@ private slots: void dataReceived(quint16 id, QString value); QUdpSocket m_socket; std::map m_idRefMap; - quint8 m_clientId=0; + quint8 m_clientId = 0; quint16 m_udpPort = 0; }; diff --git a/extplane-plugin/main.cpp b/extplane-plugin/main.cpp index df8fc0a..b0c8094 100644 --- a/extplane-plugin/main.cpp +++ b/extplane-plugin/main.cpp @@ -38,11 +38,15 @@ PLUGIN_API void XPluginStop() { PLUGIN_API void XPluginDisable() { DEBUG; + if(globalPlugin) + globalPlugin->pluginDisable(); } PLUGIN_API int XPluginEnable() { DEBUG; - return 1; + if(globalPlugin) + return globalPlugin->pluginEnable(); + return 0; } PLUGIN_API void XPluginReceiveMessage( diff --git a/extplane-plugin/xplaneplugin.cpp b/extplane-plugin/xplaneplugin.cpp index 17a711d..c2e8048 100644 --- a/extplane-plugin/xplaneplugin.cpp +++ b/extplane-plugin/xplaneplugin.cpp @@ -13,14 +13,7 @@ #include #include -XPlanePlugin::XPlanePlugin(QObject *parent) : QObject(parent) - , argc(0) - , argv(nullptr) - , m_app(nullptr) - , m_server(nullptr) - , m_flightLoopInterval(-1) // Default to every flight loop - , m_menu_container_idx(0) -{ } +XPlanePlugin::XPlanePlugin(QObject *parent) : QObject(parent) { } XPlanePlugin::~XPlanePlugin() { } @@ -47,63 +40,11 @@ int XPlanePlugin::pluginStart(char * outName, char * outSig, char *outDesc) { std::strcpy(outSig, "org.vranki.extplaneplugin"); std::strcpy(outDesc, "Read and write X-Plane datarefs from external programs on TCP port " EXTPLANE_PORT_STR " with protocol " EXTPLANE_PROTOCOL_STR " version " EXTPLANE_VERSION_STR); - m_menu_container_idx = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "ExtPlane", nullptr, 0); - m_menu_id = XPLMCreateMenu("ExtPlane", XPLMFindPluginsMenu(), m_menu_container_idx, nullptr, nullptr); - XPLMAppendMenuItem(m_menu_id, "Listening on TCP port " EXTPLANE_PORT_STR " with protocol " EXTPLANE_PROTOCOL_STR " version " EXTPLANE_VERSION_STR ". No GUI yet.", nullptr, 1); - + Q_ASSERT(!m_app); // Init application and server m_app = new QCoreApplication(argc, &argv); setlocale(LC_NUMERIC, "C"); // See http://stackoverflow.com/questions/25661295/why-does-qcoreapplication-call-setlocalelc-all-by-default-on-unix-linux - m_server = new TcpServer(this, this); - connect(m_server, &TcpServer::setFlightLoopInterval, this, &XPlanePlugin::setFlightLoopInterval); - - // Log that we have started - XPLMDebugString ("ExtPlane listening on TCP port " EXTPLANE_PORT_STR " with protocol " EXTPLANE_PROTOCOL_STR " version " EXTPLANE_VERSION_STR "\n"); - - // Register the nav custom data accessors - XPLMRegisterDataAccessor("extplane/navdata/5km", - xplmType_Data, // The types we support - 0, // Writable - nullptr, nullptr, // Integer accessors - nullptr, nullptr, // Float accessors - nullptr, nullptr, // Doubles accessors - nullptr, nullptr, // Int array accessors - nullptr, nullptr, // Float array accessors - NavCustomData::DataCallback_5km, nullptr, // Raw data accessors - nullptr, nullptr); // Refcons not used - XPLMRegisterDataAccessor("extplane/navdata/20km", - xplmType_Data, // The types we support - 0, // Writable - nullptr, nullptr, // Integer accessors - nullptr, nullptr, // Float accessors - nullptr, nullptr, // Doubles accessors - nullptr, nullptr, // Int array accessors - nullptr, nullptr, // Float array accessors - NavCustomData::DataCallback_20km, nullptr, // Raw data accessors - nullptr, nullptr); // Refcons not used - XPLMRegisterDataAccessor("extplane/navdata/100km", - xplmType_Data, // The types we support - 0, // Writable - nullptr, nullptr, // Integer accessors - nullptr, nullptr, // Float accessors - nullptr, nullptr, // Doubles accessors - nullptr, nullptr, // Int array accessors - nullptr, nullptr, // Float array accessors - NavCustomData::DataCallback_100km, nullptr, // Raw data accessors - nullptr, nullptr); // Refcons not used - XPLMRegisterDataAccessor("extplane/atc/124thatc/latest", - xplmType_Data, // The types we support - 0, // Writable - nullptr, nullptr, // Integer accessors - nullptr, nullptr, // Float accessors - nullptr, nullptr, // Doubles accessors - nullptr, nullptr, // Int array accessors - nullptr, nullptr, // Float array accessors - ATCCustomData::DataCallback, nullptr, // Raw data accessors - nullptr, nullptr); - - m_app->processEvents(); return 1; } @@ -324,12 +265,8 @@ void XPlanePlugin::command(QString &name, extplaneCommandType type) } void XPlanePlugin::setFlightLoopInterval(float newInterval) { - if(newInterval > 0) { - m_flightLoopInterval = newInterval; - DEBUG << "New interval" << m_flightLoopInterval; - } else { - m_server->extplaneWarning(QString("Invalid interval %1").arg(newInterval)); - } + m_flightLoopInterval = newInterval; + DEBUG << "New interval" << m_flightLoopInterval; } QString XPlanePlugin::refNameWithoutModifiers(QString &original) { @@ -394,15 +331,75 @@ void XPlanePlugin::setDestinationFmsEntry(int index) { void XPlanePlugin::pluginStop() { DEBUG; + Q_ASSERT(m_app); + delete m_app; + m_app = nullptr; +} + +int XPlanePlugin::pluginEnable() { + m_menu_container_idx = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "ExtPlane", nullptr, 0); + m_menu_id = XPLMCreateMenu("ExtPlane", XPLMFindPluginsMenu(), m_menu_container_idx, nullptr, nullptr); + XPLMAppendMenuItem(m_menu_id, "Listening on TCP port " EXTPLANE_PORT_STR " with protocol " EXTPLANE_PROTOCOL_STR " version " EXTPLANE_VERSION_STR ". No GUI yet.", nullptr, 1); + + Q_ASSERT(!m_server); + m_server = new TcpServer(this, this); + connect(m_server, &TcpServer::setFlightLoopInterval, this, &XPlanePlugin::setFlightLoopInterval); + + // Log that we have started + XPLMDebugString ("ExtPlane listening on TCP port " EXTPLANE_PORT_STR " with protocol " EXTPLANE_PROTOCOL_STR " version " EXTPLANE_VERSION_STR "\n"); + + // Register the nav custom data accessors + XPLMRegisterDataAccessor("extplane/navdata/5km", + xplmType_Data, // The types we support + 0, // Writable + nullptr, nullptr, // Integer accessors + nullptr, nullptr, // Float accessors + nullptr, nullptr, // Doubles accessors + nullptr, nullptr, // Int array accessors + nullptr, nullptr, // Float array accessors + NavCustomData::DataCallback_5km, nullptr, // Raw data accessors + nullptr, nullptr); // Refcons not used + XPLMRegisterDataAccessor("extplane/navdata/20km", + xplmType_Data, // The types we support + 0, // Writable + nullptr, nullptr, // Integer accessors + nullptr, nullptr, // Float accessors + nullptr, nullptr, // Doubles accessors + nullptr, nullptr, // Int array accessors + nullptr, nullptr, // Float array accessors + NavCustomData::DataCallback_20km, nullptr, // Raw data accessors + nullptr, nullptr); // Refcons not used + XPLMRegisterDataAccessor("extplane/navdata/100km", + xplmType_Data, // The types we support + 0, // Writable + nullptr, nullptr, // Integer accessors + nullptr, nullptr, // Float accessors + nullptr, nullptr, // Doubles accessors + nullptr, nullptr, // Int array accessors + nullptr, nullptr, // Float array accessors + NavCustomData::DataCallback_100km, nullptr, // Raw data accessors + nullptr, nullptr); // Refcons not used + XPLMRegisterDataAccessor("extplane/atc/124thatc/latest", + xplmType_Data, // The types we support + 0, // Writable + nullptr, nullptr, // Integer accessors + nullptr, nullptr, // Float accessors + nullptr, nullptr, // Doubles accessors + nullptr, nullptr, // Int array accessors + nullptr, nullptr, // Float array accessors + ATCCustomData::DataCallback, nullptr, // Raw data accessors + nullptr, nullptr); + return 1; +} + +void XPlanePlugin::pluginDisable() { + XPLMRemoveMenuItem(XPLMFindPluginsMenu(), m_menu_container_idx); + m_menu_container_idx = -1; XPLMDestroyMenu(m_menu_id); - m_app->processEvents(); - m_server->disconnectClients(); + m_menu_id = nullptr; + if(m_server) + m_server->disconnectClients(); delete m_server; + Q_ASSERT(m_refs.empty()); m_server = nullptr; - m_app->quit(); - m_app->processEvents(); - delete m_app; - m_app = nullptr; - qDeleteAll(m_refs); - m_refs.clear(); } diff --git a/extplane-plugin/xplaneplugin.h b/extplane-plugin/xplaneplugin.h index 1b4ec5e..032ca4a 100644 --- a/extplane-plugin/xplaneplugin.h +++ b/extplane-plugin/xplaneplugin.h @@ -27,6 +27,8 @@ class XPlanePlugin : public QObject, public DataRefProvider { float flightLoop(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop, int inCounter, void *inRefcon); int pluginStart(char * outName, char * outSig, char *outDesc); void pluginStop(); + int pluginEnable(); + void pluginDisable(); public: // DataRefProvider implementation virtual DataRef *subscribeRef(QString &name); @@ -53,13 +55,13 @@ public slots: QString refNameWithoutModifiers(QString &original); std::set m_refs; - int argc; // Fake argc and argv for QCoreApplication - char *argv; - QCoreApplication *m_app; // For Qt main loop - TcpServer *m_server; - float m_flightLoopInterval; // Delay between loop calls (in seconds) - int m_menu_container_idx; - XPLMMenuID m_menu_id; // ExtPlane menus + int argc = 0; // Fake argc and argv for QCoreApplication + char *argv = nullptr; + QCoreApplication *m_app = nullptr; // For Qt main loop + TcpServer *m_server = nullptr; + float m_flightLoopInterval = -1; // Delay between loop calls (in seconds) + int m_menu_container_idx = -1; + XPLMMenuID m_menu_id = nullptr; // ExtPlane menus }; #endif // XPLANEPLUGIN_H diff --git a/extplane-server/datarefs/dataref.cpp b/extplane-server/datarefs/dataref.cpp index 1df3584..7c99a5a 100644 --- a/extplane-server/datarefs/dataref.cpp +++ b/extplane-server/datarefs/dataref.cpp @@ -2,15 +2,8 @@ #include "../util/console.h" DataRef::DataRef(QObject *parent, const QString &name, void *ref) : QObject(parent) - , _typeString("?") - , _type(extplaneRefTypeUnknown) , _ref(ref) - , _accuracy(0) - , _valueValid(false) , _name(name) - , _subscriberCount(0) - , _writable(false) - , _unsubscribeAfterChange(false) { if(name.contains(":")) { QString modifiersPart = name.right(name.length() - name.indexOf(":") - 1); diff --git a/extplane-server/datarefs/dataref.h b/extplane-server/datarefs/dataref.h index 670c0ab..7a18760 100644 --- a/extplane-server/datarefs/dataref.h +++ b/extplane-server/datarefs/dataref.h @@ -52,18 +52,18 @@ class DataRef : public QObject { protected: void setValueValid(); // Call this to mark the value valid. - QString _typeString; - extplaneRefID _type; - void* _ref; - double _accuracy; - bool _valueValid; + QString _typeString = "?"; + extplaneRefID _type = extplaneRefTypeUnknown; + void* _ref = nullptr; + double _accuracy = 0; + bool _valueValid = false; private: QString _name; QStringList _modifiers; - int _subscriberCount; - bool _writable; - bool _unsubscribeAfterChange; + int _subscriberCount = 0; + bool _writable = false; + bool _unsubscribeAfterChange = false; quint16 _udpId = 0; // UDP id, global for all clients }; diff --git a/extplane-server/datarefs/floatdataref.cpp b/extplane-server/datarefs/floatdataref.cpp index b1036a2..c9660a5 100644 --- a/extplane-server/datarefs/floatdataref.cpp +++ b/extplane-server/datarefs/floatdataref.cpp @@ -2,7 +2,6 @@ #include "../util/console.h" FloatDataRef::FloatDataRef(QObject *parent, QString &name, void *ref) : DataRef(parent, name, ref) - , _value(-999999.0f) { _type = extplaneRefTypeFloat; _typeString = "f"; diff --git a/extplane-server/datarefs/floatdataref.h b/extplane-server/datarefs/floatdataref.h index 732b080..cd1dcbb 100644 --- a/extplane-server/datarefs/floatdataref.h +++ b/extplane-server/datarefs/floatdataref.h @@ -12,7 +12,7 @@ class FloatDataRef : public DataRef { virtual QString valueString(); void setValue(QString & newValue); private: - float _value; + float _value = -999999.0f; }; #endif // FLOATDATAREF_H diff --git a/extplane-server/tcpclient.cpp b/extplane-server/tcpclient.cpp index acee727..515b87d 100644 --- a/extplane-server/tcpclient.cpp +++ b/extplane-server/tcpclient.cpp @@ -46,7 +46,7 @@ void TcpClient::socketError(QAbstractSocket::SocketError err) { } void TcpClient::disconnectClient() { - INFO << Q_FUNC_INFO << this << m_subscribedRefs.size(); + // INFO << Q_FUNC_INFO << this << m_clientId << m_subscribedRefs.size(); while(!m_subscribedRefs.empty()) { DataRef *ref = *m_subscribedRefs.begin(); m_subscribedRefs.erase(ref); @@ -139,18 +139,17 @@ void TcpClient::readClient() { // ref can be null now! if(ref && ref->isValid()) { sendRef(ref); // Force update - - // Send UDP info - if(ref->modifiers().contains("udp")) { - if(!m_udpSender) { - m_udpSender = new UdpSender(m_refProvider, m_socket->peerAddress(), m_clientId, this); - } - if(!ref->udpId()) { - ref->setUdpId(m_tcpserver->reserveUdpId()); - } - m_udpSender->subscribedRef(ref); - sendUdpInfo(ref); + } + // Send UDP info + if(ref && ref->modifiers().contains("udp")) { + if(!m_udpSender) { + m_udpSender = new UdpSender(m_refProvider, m_socket->peerAddress(), m_clientId, this); + } + if(!ref->udpId()) { + ref->setUdpId(m_tcpserver->reserveUdpId()); } + m_udpSender->subscribedRef(ref); + sendUdpInfo(ref); } if(command == "get" && ref) ref->setUnsubscribeAfterChange(); } else { @@ -280,12 +279,15 @@ void TcpClient::refChanged(DataRef *ref) { Q_ASSERT(m_subscribedRefs.find(ref) != m_subscribedRefs.end()); Q_ASSERT(ref->isValid()); // Never send invalid values. + if(ref->udpId()) return; // Handled by UDP + // Check if the ref has changed enough to be worth sending if(ref->type()== extplaneRefTypeFloat) { FloatDataRef *refF = qobject_cast(ref); - if(qAbs(refF->value() - m_refValueF[ref]) < ref->accuracy()) + auto val = refF->value(); + if(qAbs(val - m_refValueF[ref]) < ref->accuracy()) return; // Hasn't changed enough - m_refValueF.insert({ref, refF->value()}); + m_refValueF[ref] = val; } else if(ref->type()== extplaneRefTypeFloatArray) { FloatArrayDataRef *refF = qobject_cast(ref); bool bigenough = false; @@ -327,7 +329,7 @@ void TcpClient::refChanged(DataRef *ref) { } } if (bigenough){ // Values have changed enough - m_refValueIA.insert({ref, values}); + m_refValueIA[ref] = values; } else { return; } @@ -336,25 +338,24 @@ void TcpClient::refChanged(DataRef *ref) { IntDataRef *refI = qobject_cast(ref); if(qAbs(refI->value() - m_refValueI.at(ref)) < ref->accuracy()) return; // Hasn't changed enough - m_refValueI.insert({ref, refI->value()}); + m_refValueI[ref] = refI->value(); } else if(ref->type() == extplaneRefTypeDouble) { DoubleDataRef *refD = qobject_cast(ref); if(qAbs(refD->value() - m_refValueD.at(ref)) < ref->accuracy()) return; // Hasn't changed enough - m_refValueD.insert({ref, refD->value()}); + m_refValueD[ref] = refD->value(); } else if(ref->type() == extplaneRefTypeData) { // The accuracy is handled internally for the data dataref, when it emits the update signal // it's time to send the update... DataDataRef *refB = qobject_cast(ref); - m_refValueB.insert({ref, refB->value()}); + m_refValueB[ref] = refB->value(); } else { extplaneWarning(QString("Ref type %1 not supported (this should not happen!)").arg(ref->type())); return; } // Send the ref value if we got this far.. - if(!ref->udpId()) - sendRef(ref); + sendRef(ref); if(ref->shouldUnsubscribeAfterChange()) unsubscribeRef(ref->name()); diff --git a/extplane-server/udpsender.cpp b/extplane-server/udpsender.cpp index 0d9047f..bfcbe9e 100644 --- a/extplane-server/udpsender.cpp +++ b/extplane-server/udpsender.cpp @@ -7,6 +7,7 @@ #include "console.h" #include "../protocoldefs.h" #include +#include UdpSender::UdpSender(DataRefProvider *refProvider, QHostAddress host, quint8 clientId, QObject *parent) : QObject(parent) , m_refProvider(refProvider) @@ -14,8 +15,9 @@ UdpSender::UdpSender(DataRefProvider *refProvider, QHostAddress host, quint8 cli , m_clientId(clientId) { Q_ASSERT(m_refProvider); + Q_ASSERT(m_clientId); m_udpPort = UDP_OUT_PORT_BASE + m_clientId; - INFO << "Created ExtPlane UdpSender for peer" << m_host << "client id" << QString::number(m_clientId) << "sending to port" << m_udpPort; + INFO << "Created ExtPlane UdpSender for peer" << m_host << "client id" << QString::number(m_clientId) << "sending to port" << QString::number(m_udpPort); } bool UdpSender::subscribedRef(DataRef *ref) @@ -27,70 +29,62 @@ bool UdpSender::subscribedRef(DataRef *ref) void UdpSender::unsubscribedRef(DataRef *ref) { + m_changedRefs.erase(ref); disconnect(ref, 0, this, 0); } void UdpSender::flightLoop() { - if(!m_countInt && !m_countFloat && !m_countDouble) return; + Q_ASSERT(m_clientId); QByteArray buf; QDataStream s(&buf, QIODevice::WriteOnly); s.writeRawData("EXTP_", 5); - s << (quint8 ) m_clientId; - s << (quint16) m_countInt; - s.writeRawData(m_bufInt.data(), m_bufInt.size()); + s << m_clientId; + s << countRefs(extplaneRefTypeInt); + for(auto ref : m_changedRefs) { + if(ref->type() == extplaneRefTypeInt) { + s << ref->udpId() << qobject_cast(ref)->value(); + } + } s.writeRawData("Ef", 2); - s << (quint16) m_countFloat; - s.writeRawData(m_bufFloat.data(), m_bufFloat.size()); + s << countRefs(extplaneRefTypeFloat); + s.setFloatingPointPrecision(QDataStream::SinglePrecision); + for(auto ref : m_changedRefs) { + if(ref->type() == extplaneRefTypeFloat) { + s << ref->udpId() << qobject_cast(ref)->value(); + } + } s.writeRawData("Ed", 2); - s << (quint16) m_countDouble; - s.writeRawData(m_bufDouble.data(), m_bufDouble.size()); - + s << countRefs(extplaneRefTypeDouble); + s.setFloatingPointPrecision(QDataStream::DoublePrecision); + for(auto ref : m_changedRefs) { + if(ref->type() == extplaneRefTypeDouble) { + s << ref->udpId() << qobject_cast(ref)->value(); + } + } auto outSize = m_socket.writeDatagram(buf, m_host, m_udpPort); if(outSize != buf.size()) { INFO << "Failed sending UDP datagram! Sent only" << outSize << "bytes of" << buf.size(); } else { // INFO << "Sent" << outSize << "bytes to" << m_host << m_udpPort << "client id" << m_clientId << "counts" << m_countInt << m_countFloat << m_countDouble; } - - m_bufInt.clear(); - // m_bufInt.reserve(BUFFER_RESERVE); - m_countInt = 0; - - m_bufFloat.clear(); - // m_bufFloat.reserve(BUFFER_RESERVE); - m_countFloat = 0; - - m_bufDouble.clear(); - // m_bufDouble.reserve(BUFFER_RESERVE); - m_countDouble = 0; - - Q_ASSERT(m_bufInt.isEmpty()); - Q_ASSERT(m_bufFloat.isEmpty()); - Q_ASSERT(m_bufDouble.isEmpty()); + m_changedRefs.clear(); } void UdpSender::refChanged(DataRef *ref) { Q_ASSERT(ref); Q_ASSERT(ref->udpId()); - if(ref->type() == extplaneRefTypeInt) { - auto intRef = qobject_cast(ref); - QDataStream s(&m_bufInt, QIODevice::WriteOnly); - s << (quint16) intRef->udpId() << (qint32) intRef->value(); - m_countInt++; - } else if(ref->type() == extplaneRefTypeFloat) { - auto floatRef = qobject_cast(ref); - QDataStream s(&m_bufFloat, QIODevice::WriteOnly); - s << (quint16) floatRef->udpId() << (float) floatRef->value(); // Float is 4 bytes always - m_countFloat++; - } else if(ref->type() == extplaneRefTypeDouble) { - auto doubleRef = qobject_cast(ref); - QDataStream s(&m_bufDouble, QIODevice::WriteOnly); - s << (quint16) doubleRef->udpId() << (double) doubleRef->value(); // Double is 8 bytes always - m_countDouble++; + m_changedRefs.insert(ref); +} + +quint16 UdpSender::countRefs(int type) { + quint16 res = 0; + for(auto ref : m_changedRefs) { + if(ref->type() == type) res++; } + return res; } diff --git a/extplane-server/udpsender.h b/extplane-server/udpsender.h index bd1005e..12bd772 100644 --- a/extplane-server/udpsender.h +++ b/extplane-server/udpsender.h @@ -3,17 +3,10 @@ #include #include -#include #include class DataRef; class DataRefProvider; -class FloatDataRef; -class DoubleDataRef; -class IntDataRef; - -#define UDP_PACKET_SIZE 508 -#define BUFFER_RESERVE 4096 // Size to resize empty buffers class UdpSender : public QObject { @@ -28,19 +21,14 @@ private slots: void refChanged(DataRef *ref); private: + quint16 countRefs(int type); DataRefProvider *m_refProvider = nullptr; QUdpSocket m_socket; QHostAddress m_host; quint8 m_clientId = 0; - - QByteArray m_bufInt; - quint16 m_countInt = 0; - QByteArray m_bufFloat; - quint16 m_countFloat = 0; - QByteArray m_bufDouble; - quint16 m_countDouble = 0; quint16 m_udpPort = 0; + std::set m_changedRefs; // List of refs changed since last send }; #endif // UDPSENDER_H diff --git a/extplane-transformer/datasources/condordatasource.cpp b/extplane-transformer/datasources/condordatasource.cpp index c392799..d69b785 100755 --- a/extplane-transformer/datasources/condordatasource.cpp +++ b/extplane-transformer/datasources/condordatasource.cpp @@ -105,7 +105,9 @@ void CondorDatasource::buttonRelease(int buttonid) {} void CondorDatasource::command(QString &name, extplaneCommandType type) {} -bool CondorDatasource::loadSituation(QString sitFileLocation) {} +bool CondorDatasource::loadSituation(QString sitFileLocation) { + return false; +} void CondorDatasource::addFMSEntryLatLon(QString fmsEntryLine) {} diff --git a/extplane-transformer/datasources/flightgeardatasource.cpp b/extplane-transformer/datasources/flightgeardatasource.cpp index a7f4eed..a19ccdb 100644 --- a/extplane-transformer/datasources/flightgeardatasource.cpp +++ b/extplane-transformer/datasources/flightgeardatasource.cpp @@ -79,7 +79,9 @@ void FlightGearDataSource::command(QString &name, extplaneCommandType type) {} bool FlightGearDataSource::loadSituation(QString sitFileLocation) -{} +{ + return false; +} void FlightGearDataSource::addFMSEntryLatLon(QString fmsEntryLine) {}