From 2aab4cc2cba3f97dddfe0b642ef2ef5a8eee46ab Mon Sep 17 00:00:00 2001 From: Jon Beniston Date: Wed, 7 Apr 2021 21:13:10 +0100 Subject: [PATCH] Add UDP port for packet forwarding in ChirpChat mod. --- .../channeltx/modchirpchat/chirpchatmod.cpp | 95 +++++++++++++++- plugins/channeltx/modchirpchat/chirpchatmod.h | 5 + .../modchirpchat/chirpchatmodgui.cpp | 21 ++++ .../channeltx/modchirpchat/chirpchatmodgui.h | 3 + .../channeltx/modchirpchat/chirpchatmodgui.ui | 107 +++++++++++++++++- .../modchirpchat/chirpchatmodsettings.cpp | 15 +++ .../modchirpchat/chirpchatmodsettings.h | 3 + .../api/swagger/include/ChirpChatMod.yaml | 9 ++ .../qt5/client/SWGChirpChatModSettings.cpp | 71 ++++++++++++ .../code/qt5/client/SWGChirpChatModSettings.h | 18 +++ 10 files changed, 341 insertions(+), 6 deletions(-) diff --git a/plugins/channeltx/modchirpchat/chirpchatmod.cpp b/plugins/channeltx/modchirpchat/chirpchatmod.cpp index c5d19a572..0adbbfe15 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmod.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmod.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -52,7 +54,8 @@ ChirpChatMod::ChirpChatMod(DeviceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_currentPayloadTime(0.0), m_settingsMutex(QMutex::Recursive), - m_sampleRate(48000) + m_sampleRate(48000), + m_udpSocket(nullptr) { setObjectName(m_channelId); @@ -327,6 +330,27 @@ void ChirpChatMod::applySettings(const ChirpChatModSettings& settings, bool forc } } + if ((settings.m_udpEnabled != m_settings.m_udpEnabled) || force) { + reverseAPIKeys.append("udpEnabled"); + } + if ((settings.m_udpAddress != m_settings.m_udpAddress) || force) { + reverseAPIKeys.append("udpAddress"); + } + if ((settings.m_udpPort != m_settings.m_udpPort) || force) { + reverseAPIKeys.append("udpPort"); + } + + if ( (settings.m_udpEnabled != m_settings.m_udpEnabled) + || (settings.m_udpAddress != m_settings.m_udpAddress) + || (settings.m_udpPort != m_settings.m_udpPort) + || force) + { + if (settings.m_udpEnabled) + openUDP(settings); + else + closeUDP(); + } + if (m_settings.m_streamIndex != settings.m_streamIndex) { if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only @@ -524,6 +548,15 @@ void ChirpChatMod::webapiUpdateChannelSettings( if (channelSettingsKeys.contains("messageRepeat")) { settings.m_messageRepeat = response.getChirpChatModSettings()->getMessageRepeat(); } + if (channelSettingsKeys.contains("udpEnabled")) { + settings.m_udpEnabled = response.getPacketDemodSettings()->getUdpEnabled(); + } + if (channelSettingsKeys.contains("udpAddress")) { + settings.m_udpAddress = *response.getPacketDemodSettings()->getUdpAddress(); + } + if (channelSettingsKeys.contains("udpPort")) { + settings.m_udpPort = response.getPacketDemodSettings()->getUdpPort(); + } if (channelSettingsKeys.contains("rgbColor")) { settings.m_rgbColor = response.getChirpChatModSettings()->getRgbColor(); } @@ -665,6 +698,10 @@ void ChirpChatMod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& bytesStr->push_back(new QString(tr("%1").arg(b, 2, 16, QChar('0')))); } + response.getChirpChatModSettings()->setUdpEnabled(settings.m_udpEnabled); + response.getChirpChatModSettings()->setUdpAddress(new QString(settings.m_udpAddress)); + response.getChirpChatModSettings()->setUdpPort(settings.m_udpPort); + response.getChirpChatModSettings()->setRgbColor(settings.m_rgbColor); if (response.getChirpChatModSettings()->getTitle()) { @@ -855,6 +892,16 @@ void ChirpChatMod::webapiFormatChannelSettings( swgChirpChatModSettings->setMessageRepeat(settings.m_messageRepeat); } + if (channelSettingsKeys.contains("udpEnabled") || force) { + swgChirpChatModSettings->setUdpEnabled(settings.m_udpEnabled); + } + if (channelSettingsKeys.contains("udpAddress") || force) { + swgChirpChatModSettings->setUdpAddress(new QString(settings.m_udpAddress)); + } + if (channelSettingsKeys.contains("udpPort") || force) { + swgChirpChatModSettings->setUdpPort(settings.m_udpPort); + } + if (channelSettingsKeys.contains("rgbColor") || force) { swgChirpChatModSettings->setRgbColor(settings.m_rgbColor); } @@ -903,3 +950,49 @@ bool ChirpChatMod::getModulatorActive() const { return m_basebandSource->getActive(); } + +void ChirpChatMod::openUDP(const ChirpChatModSettings& settings) +{ + closeUDP(); + m_udpSocket = new QUdpSocket(); + if (!m_udpSocket->bind(QHostAddress(settings.m_udpAddress), settings.m_udpPort)) + qCritical() << "ChirpChatMod::openUDP: Failed to bind to port " << settings.m_udpAddress << ":" << settings.m_udpPort << ". Error: " << m_udpSocket->error(); + else + qDebug() << "ChirpChatMod::openUDP: Listening for packets on " << settings.m_udpAddress << ":" << settings.m_udpPort; + connect(m_udpSocket, &QUdpSocket::readyRead, this, &ChirpChatMod::udpRx); +} + +void ChirpChatMod::closeUDP() +{ + if (m_udpSocket != nullptr) + { + disconnect(m_udpSocket, &QUdpSocket::readyRead, this, &ChirpChatMod::udpRx); + delete m_udpSocket; + m_udpSocket = nullptr; + } +} + +void ChirpChatMod::udpRx() +{ + while (m_udpSocket->hasPendingDatagrams()) + { + QNetworkDatagram datagram = m_udpSocket->receiveDatagram(); + ChirpChatModBaseband::MsgConfigureChirpChatModPayload *payloadMsg = nullptr; + std::vector symbols; + + m_encoder.encodeBytes(datagram.data(), symbols); + payloadMsg = ChirpChatModBaseband::MsgConfigureChirpChatModPayload::create(symbols); + + if (payloadMsg) + { + m_basebandSource->getInputMessageQueue()->push(payloadMsg); + m_currentPayloadTime = (symbols.size()*(1<push(rpt); + } + } + } +} diff --git a/plugins/channeltx/modchirpchat/chirpchatmod.h b/plugins/channeltx/modchirpchat/chirpchatmod.h index 5731d313a..008cca810 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmod.h +++ b/plugins/channeltx/modchirpchat/chirpchatmod.h @@ -35,6 +35,7 @@ class QNetworkAccessManager; class QNetworkReply; class QThread; +class QUdpSocket; class DeviceAPI; class CWKeyer; class ChirpChatModBaseband; @@ -159,6 +160,7 @@ private: QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; + QUdpSocket *m_udpSocket; void applySettings(const ChirpChatModSettings& settings, bool force = false); void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response); @@ -175,9 +177,12 @@ private: const ChirpChatModSettings& settings, bool force ); + void openUDP(const ChirpChatModSettings& settings); + void closeUDP(); private slots: void networkManagerFinished(QNetworkReply *reply); + void udpRx(); }; diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp b/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp index c73eab1f1..65c97f11c 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.cpp @@ -333,6 +333,24 @@ void ChirpChatModGUI::on_hexText_editingFinished() applySettings(); } +void ChirpChatModGUI::on_udpEnabled_clicked(bool checked) +{ + m_settings.m_udpEnabled = checked; + applySettings(); +} + +void ChirpChatModGUI::on_udpAddress_editingFinished() +{ + m_settings.m_udpAddress = ui->udpAddress->text(); + applySettings(); +} + +void ChirpChatModGUI::on_udpPort_editingFinished() +{ + m_settings.m_udpPort = ui->udpPort->text().toInt(); + applySettings(); +} + void ChirpChatModGUI::onWidgetRolled(QWidget* widget, bool rollDown) { (void) widget; @@ -498,6 +516,9 @@ void ChirpChatModGUI::displaySettings() ui->repeatMessage->setValue(m_settings.m_messageRepeat); ui->repeatText->setText(tr("%1").arg(m_settings.m_messageRepeat)); ui->msgType->setCurrentIndex((int) m_settings.m_messageType); + ui->udpEnabled->setChecked(m_settings.m_udpEnabled); + ui->udpAddress->setText(m_settings.m_udpAddress); + ui->udpPort->setText(QString::number(m_settings.m_udpPort)); blockApplySettings(false); } diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.h b/plugins/channeltx/modchirpchat/chirpchatmodgui.h index 5c40ccc63..8e53d680b 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.h @@ -104,6 +104,9 @@ private slots: void on_generateMessages_clicked(bool checked); void on_messageText_editingFinished(); void on_hexText_editingFinished(); + void on_udpEnabled_clicked(bool checked); + void on_udpAddress_editingFinished(); + void on_udpPort_editingFinished(); void onWidgetRolled(QWidget* widget, bool rollDown); void onMenuDialogCalled(const QPoint& p); void tick(); diff --git a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui index f001176ed..5f75c16fd 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodgui.ui +++ b/plugins/channeltx/modchirpchat/chirpchatmodgui.ui @@ -7,7 +7,7 @@ 0 0 402 - 373 + 461 @@ -497,16 +497,16 @@ - 1 - 150 + 0 + 160 400 - 221 + 250 0 - 220 + 250 @@ -1168,6 +1168,103 @@ Sync + + + + 2 + 230 + 50 + 16 + + + + Forward messages received via UDP + + + Qt::RightToLeft + + + UDP + + + + + + 199 + 230 + 50 + 16 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + Qt::ClickFocus + + + UDP port to listen for messages to forward on + + + 00000 + + + 9997 + + + + + + 184 + 230 + 10 + 16 + + + + : + + + Qt::AlignCenter + + + + + + 60 + 230 + 120 + 16 + + + + + 120 + 0 + + + + Qt::ClickFocus + + + UDP address to listen for messages to forward on + + + 000.000.000.000 + + + 127.0.0.1 + + diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp b/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp index a371d87a9..f6e942fca 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp +++ b/plugins/channeltx/modchirpchat/chirpchatmodsettings.cpp @@ -81,6 +81,9 @@ void ChirpChatModSettings::resetToDefaults() m_syncWord = 0x34; m_channelMute = false; m_messageRepeat = 1; + m_udpEnabled = false; + m_udpAddress = "127.0.0.1"; + m_udpPort = 9998; m_rgbColor = QColor(255, 0, 255).rgb(); m_title = "ChirpChat Modulator"; m_streamIndex = 0; @@ -189,6 +192,9 @@ QByteArray ChirpChatModSettings::serialize() const s.writeU32(53, m_reverseAPIDeviceIndex); s.writeU32(54, m_reverseAPIChannelIndex); s.writeS32(55, m_streamIndex); + s.writeBool(56, m_udpEnabled); + s.writeString(57, m_udpAddress); + s.writeU32(58, m_udpPort); return s.final(); } @@ -279,6 +285,15 @@ bool ChirpChatModSettings::deserialize(const QByteArray& data) m_reverseAPIChannelIndex = utmp > 99 ? 99 : utmp; d.readS32(55, &m_streamIndex, 0); + d.readBool(56, &m_udpEnabled); + d.readString(57, &m_udpAddress, "127.0.0.1"); + d.readU32(58, &utmp); + if ((utmp > 1023) && (utmp < 65535)) { + m_udpPort = utmp; + } else { + m_udpPort = 9998; + } + return true; } else diff --git a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h index 451b9c102..97cbf7b08 100644 --- a/plugins/channeltx/modchirpchat/chirpchatmodsettings.h +++ b/plugins/channeltx/modchirpchat/chirpchatmodsettings.h @@ -77,6 +77,9 @@ struct ChirpChatModSettings QString m_textMessage; QByteArray m_bytesMessage; int m_messageRepeat; + bool m_udpEnabled; + QString m_udpAddress; + uint16_t m_udpPort; uint32_t m_rgbColor; QString m_title; int m_streamIndex; diff --git a/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml b/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml index 933cd11af..f33edaf6e 100644 --- a/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml +++ b/swagger/sdrangel/api/swagger/include/ChirpChatMod.yaml @@ -130,6 +130,15 @@ ChirpChatModSettings: messageRepeat: description: number of repetitions of the same message (0 for infinite) type: integer + udpEnabled: + description: boolean 1 to enable forwarding messages via UDP else 0 + type: integer + udpAddress: + description: UDP address to listen for messages to transmit on + type: string + udpPort: + description: UDP port to listen for messages to transmit on + type: integer rgbColor: type: integer title: diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp index 9756cdaa6..39f893043 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.cpp @@ -84,6 +84,12 @@ SWGChirpChatModSettings::SWGChirpChatModSettings() { m_bytes_message_isSet = false; message_repeat = 0; m_message_repeat_isSet = false; + udp_enabled = 0; + m_udp_enabled_isSet = false; + udp_address = nullptr; + m_udp_address_isSet = false; + udp_port = 0; + m_udp_port_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = nullptr; @@ -164,6 +170,12 @@ SWGChirpChatModSettings::init() { m_bytes_message_isSet = false; message_repeat = 0; m_message_repeat_isSet = false; + udp_enabled = 0; + m_udp_enabled_isSet = false; + udp_address = new QString(""); + m_udp_address_isSet = false; + udp_port = 0; + m_udp_port_isSet = false; rgb_color = 0; m_rgb_color_isSet = false; title = new QString(""); @@ -245,6 +257,11 @@ SWGChirpChatModSettings::cleanup() { } + if(udp_address != nullptr) { + delete udp_address; + } + + if(title != nullptr) { delete title; } @@ -325,6 +342,12 @@ SWGChirpChatModSettings::fromJsonObject(QJsonObject &pJson) { ::SWGSDRangel::setValue(&bytes_message, pJson["bytesMessage"], "QList", "QString"); ::SWGSDRangel::setValue(&message_repeat, pJson["messageRepeat"], "qint32", ""); + ::SWGSDRangel::setValue(&udp_enabled, pJson["udpEnabled"], "qint32", ""); + + ::SWGSDRangel::setValue(&udp_address, pJson["udpAddress"], "QString", "QString"); + + ::SWGSDRangel::setValue(&udp_port, pJson["udpPort"], "qint32", ""); + ::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", ""); ::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString"); @@ -441,6 +464,15 @@ SWGChirpChatModSettings::asJsonObject() { if(m_message_repeat_isSet){ obj->insert("messageRepeat", QJsonValue(message_repeat)); } + if(m_udp_enabled_isSet){ + obj->insert("udpEnabled", QJsonValue(udp_enabled)); + } + if(udp_address != nullptr && *udp_address != QString("")){ + toJsonValue(QString("udpAddress"), udp_address, obj, QString("QString")); + } + if(m_udp_port_isSet){ + obj->insert("udpPort", QJsonValue(udp_port)); + } if(m_rgb_color_isSet){ obj->insert("rgbColor", QJsonValue(rgb_color)); } @@ -749,6 +781,36 @@ SWGChirpChatModSettings::setMessageRepeat(qint32 message_repeat) { this->m_message_repeat_isSet = true; } +qint32 +SWGChirpChatModSettings::getUdpEnabled() { + return udp_enabled; +} +void +SWGChirpChatModSettings::setUdpEnabled(qint32 udp_enabled) { + this->udp_enabled = udp_enabled; + this->m_udp_enabled_isSet = true; +} + +QString* +SWGChirpChatModSettings::getUdpAddress() { + return udp_address; +} +void +SWGChirpChatModSettings::setUdpAddress(QString* udp_address) { + this->udp_address = udp_address; + this->m_udp_address_isSet = true; +} + +qint32 +SWGChirpChatModSettings::getUdpPort() { + return udp_port; +} +void +SWGChirpChatModSettings::setUdpPort(qint32 udp_port) { + this->udp_port = udp_port; + this->m_udp_port_isSet = true; +} + qint32 SWGChirpChatModSettings::getRgbColor() { return rgb_color; @@ -918,6 +980,15 @@ SWGChirpChatModSettings::isSet(){ if(m_message_repeat_isSet){ isObjectUpdated = true; break; } + if(m_udp_enabled_isSet){ + isObjectUpdated = true; break; + } + if(udp_address && *udp_address != QString("")){ + isObjectUpdated = true; break; + } + if(m_udp_port_isSet){ + isObjectUpdated = true; break; + } if(m_rgb_color_isSet){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h index 0ac1e7838..aa24fbc7b 100644 --- a/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGChirpChatModSettings.h @@ -127,6 +127,15 @@ public: qint32 getMessageRepeat(); void setMessageRepeat(qint32 message_repeat); + qint32 getUdpEnabled(); + void setUdpEnabled(qint32 udp_enabled); + + QString* getUdpAddress(); + void setUdpAddress(QString* udp_address); + + qint32 getUdpPort(); + void setUdpPort(qint32 udp_port); + qint32 getRgbColor(); void setRgbColor(qint32 rgb_color); @@ -239,6 +248,15 @@ private: qint32 message_repeat; bool m_message_repeat_isSet; + qint32 udp_enabled; + bool m_udp_enabled_isSet; + + QString* udp_address; + bool m_udp_address_isSet; + + qint32 udp_port; + bool m_udp_port_isSet; + qint32 rgb_color; bool m_rgb_color_isSet;