Add UDP ports for packet forwarding in 802.15.4 mod.

This commit is contained in:
Jon Beniston 2021-04-07 21:09:03 +01:00
parent e15470494a
commit 960af9157e
11 changed files with 349 additions and 26 deletions

View File

@ -21,6 +21,8 @@
#include <QMutexLocker>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUdpSocket>
#include <QNetworkDatagram>
#include <QBuffer>
#include <QThread>
@ -56,7 +58,8 @@ IEEE_802_15_4_Mod::IEEE_802_15_4_Mod(DeviceAPI *deviceAPI) :
ChannelAPI(m_channelIdURI, ChannelAPI::StreamSingleSource),
m_deviceAPI(deviceAPI),
m_spectrumVis(SDR_TX_SCALEF),
m_settingsMutex(QMutex::Recursive)
m_settingsMutex(QMutex::Recursive),
m_udpSocket(nullptr)
{
setObjectName(m_channelId);
@ -76,6 +79,7 @@ IEEE_802_15_4_Mod::IEEE_802_15_4_Mod(DeviceAPI *deviceAPI) :
IEEE_802_15_4_Mod::~IEEE_802_15_4_Mod()
{
closeUDP();
disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*)));
delete m_networkManager;
m_deviceAPI->removeChannelSourceAPI(this);
@ -193,6 +197,29 @@ void IEEE_802_15_4_Mod::applySettings(const IEEE_802_15_4_ModSettings& settings,
reverseAPIKeys.append("repeatCount");
}
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
@ -314,6 +341,15 @@ void IEEE_802_15_4_Mod::webapiUpdateChannelSettings(
if (channelSettingsKeys.contains("repeatCount")) {
settings.m_repeatCount = response.getIeee802154ModSettings()->getRepeatCount();
}
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.getIeee802154ModSettings()->getRgbColor();
}
@ -401,6 +437,9 @@ void IEEE_802_15_4_Mod::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSetti
response.getIeee802154ModSettings()->setRepeat(settings.m_repeat ? 1 : 0);
response.getIeee802154ModSettings()->setRepeatDelay(settings.m_repeatDelay);
response.getIeee802154ModSettings()->setRepeatCount(settings.m_repeatCount);
response.getIeee802154ModSettings()->setUdpEnabled(settings.m_udpEnabled);
response.getIeee802154ModSettings()->setUdpAddress(new QString(settings.m_udpAddress));
response.getIeee802154ModSettings()->setUdpPort(settings.m_udpPort);
response.getIeee802154ModSettings()->setRgbColor(settings.m_rgbColor);
if (response.getIeee802154ModSettings()->getTitle()) {
@ -512,6 +551,15 @@ void IEEE_802_15_4_Mod::webapiFormatChannelSettings(
if (channelSettingsKeys.contains("repeatCount") || force) {
swgIEEE_802_15_4_ModSettings->setRepeatCount(settings.m_repeatCount);
}
if (channelSettingsKeys.contains("udpEnabled") || force) {
swgIEEE_802_15_4_ModSettings->setUdpEnabled(settings.m_udpEnabled);
}
if (channelSettingsKeys.contains("udpAddress") || force) {
swgIEEE_802_15_4_ModSettings->setUdpAddress(new QString(settings.m_udpAddress));
}
if (channelSettingsKeys.contains("udpPort") || force) {
swgIEEE_802_15_4_ModSettings->setUdpPort(settings.m_udpPort);
}
if (channelSettingsKeys.contains("rgbColor") || force) {
swgIEEE_802_15_4_ModSettings->setRgbColor(settings.m_rgbColor);
}
@ -563,3 +611,36 @@ void IEEE_802_15_4_Mod::setScopeSink(BasebandSampleSink* scopeSink)
{
m_basebandSource->setScopeSink(scopeSink);
}
void IEEE_802_15_4_Mod::openUDP(const IEEE_802_15_4_ModSettings& settings)
{
closeUDP();
m_udpSocket = new QUdpSocket();
if (!m_udpSocket->bind(QHostAddress(settings.m_udpAddress), settings.m_udpPort))
qCritical() << "IEEE_802_15_4_Mod::openUDP: Failed to bind to port " << settings.m_udpAddress << ":" << settings.m_udpPort << ". Error: " << m_udpSocket->error();
else
qDebug() << "IEEE_802_15_4_Mod::openUDP: Listening for packets on " << settings.m_udpAddress << ":" << settings.m_udpPort;
connect(m_udpSocket, &QUdpSocket::readyRead, this, &IEEE_802_15_4_Mod::udpRx);
}
void IEEE_802_15_4_Mod::closeUDP()
{
if (m_udpSocket != nullptr)
{
disconnect(m_udpSocket, &QUdpSocket::readyRead, this, &IEEE_802_15_4_Mod::udpRx);
delete m_udpSocket;
m_udpSocket = nullptr;
}
}
void IEEE_802_15_4_Mod::udpRx()
{
while (m_udpSocket->hasPendingDatagrams())
{
QNetworkDatagram datagram = m_udpSocket->receiveDatagram();
// Convert from binary to hex string
QString string = datagram.data().toHex(' ');
IEEE_802_15_4_Mod::MsgTXIEEE_802_15_4_Mod *msg = IEEE_802_15_4_Mod::MsgTXIEEE_802_15_4_Mod::create(string);
m_basebandSource->getInputMessageQueue()->push(msg);
}
}

View File

@ -36,6 +36,7 @@
class QNetworkAccessManager;
class QNetworkReply;
class QThread;
class QUdpSocket;
class DeviceAPI;
class IEEE_802_15_4_ModBaseband;
@ -163,6 +164,7 @@ private:
QNetworkAccessManager *m_networkManager;
QNetworkRequest m_networkRequest;
QUdpSocket *m_udpSocket;
void applySettings(const IEEE_802_15_4_ModSettings& settings, bool force = false);
void webapiFormatChannelReport(SWGSDRangel::SWGChannelReport& response);
@ -179,9 +181,12 @@ private:
const IEEE_802_15_4_ModSettings& settings,
bool force
);
void openUDP(const IEEE_802_15_4_ModSettings& settings);
void closeUDP();
private slots:
void networkManagerFinished(QNetworkReply *reply);
void udpRx();
};

View File

@ -269,6 +269,24 @@ void IEEE_802_15_4_ModGUI::txSettingsSelect()
}
}
void IEEE_802_15_4_ModGUI::on_udpEnabled_clicked(bool checked)
{
m_settings.m_udpEnabled = checked;
applySettings();
}
void IEEE_802_15_4_ModGUI::on_udpAddress_editingFinished()
{
m_settings.m_udpAddress = ui->udpAddress->text();
applySettings();
}
void IEEE_802_15_4_ModGUI::on_udpPort_editingFinished()
{
m_settings.m_udpPort = ui->udpPort->text().toInt();
applySettings();
}
void IEEE_802_15_4_ModGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
@ -514,6 +532,10 @@ void IEEE_802_15_4_ModGUI::displaySettings()
ui->frame->setText(m_settings.m_data);
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);
}

View File

@ -102,6 +102,9 @@ private slots:
void on_repeat_toggled(bool checked);
void repeatSelect();
void txSettingsSelect();
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);

View File

@ -43,7 +43,7 @@
<x>2</x>
<y>2</y>
<width>341</width>
<height>121</height>
<height>151</height>
</rect>
</property>
<property name="minimumSize">
@ -410,6 +410,103 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="udpLayout">
<item>
<widget class="QCheckBox" name="udpEnabled">
<property name="toolTip">
<string>Forward frames received via UDP</string>
</property>
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>UDP</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="udpAddress">
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Destination UDP address</string>
</property>
<property name="inputMask">
<string>000.000.000.000</string>
</property>
<property name="text">
<string>127.0.0.1</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="udpSeparator">
<property name="text">
<string>:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="udpPort">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string>Destination UDP port</string>
</property>
<property name="inputMask">
<string>00000</string>
</property>
<property name="text">
<string>9997</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="frameDataLayout">
<item>
@ -600,35 +697,12 @@
</widget>
</widget>
<customwidgets>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>RollupWidget</class>
<extends>QWidget</extends>
<header>gui/rollupwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ValueDialZ</class>
<extends>QWidget</extends>
<header>gui/valuedialz.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLScope</class>
<extends>QWidget</extends>
<header>gui/glscope.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLScopeGUI</class>
<extends>QWidget</extends>
<header>gui/glscopegui.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLSpectrum</class>
<extends>QWidget</extends>
@ -641,12 +715,35 @@
<header>gui/glspectrumgui.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ValueDialZ</class>
<extends>QWidget</extends>
<header>gui/valuedialz.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ButtonSwitch</class>
<extends>QToolButton</extends>
<header>gui/buttonswitch.h</header>
</customwidget>
<customwidget>
<class>LevelMeterVU</class>
<extends>QWidget</extends>
<header>gui/levelmeter.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLScope</class>
<extends>QWidget</extends>
<header>gui/glscope.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GLScopeGUI</class>
<extends>QWidget</extends>
<header>gui/glscopegui.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>deltaFrequency</tabstop>

View File

@ -69,6 +69,9 @@ void IEEE_802_15_4_ModSettings::resetToDefaults()
m_pulseShaping = RC;
m_beta = 1.0f;
m_symbolSpan = 6;
m_udpEnabled = false;
m_udpAddress = "127.0.0.1";
m_udpPort = 9998;
}
bool IEEE_802_15_4_ModSettings::setPHY(QString phy)
@ -176,6 +179,9 @@ QByteArray IEEE_802_15_4_ModSettings::serialize() const
s.writeS32(31, m_symbolSpan);
s.writeS32(32, m_spectrumRate);
s.writeS32(33, m_modulation);
s.writeBool(34, m_udpEnabled);
s.writeString(35, m_udpAddress);
s.writeU32(36, m_udpPort);
return s.final();
}
@ -245,6 +251,14 @@ bool IEEE_802_15_4_ModSettings::deserialize(const QByteArray& data)
d.readS32(31, &m_symbolSpan, 6);
d.readS32(32, &m_spectrumRate, m_rfBandwidth);
d.readS32(33, (qint32 *)&m_modulation, m_bitRate < 100000 ? IEEE_802_15_4_ModSettings::BPSK : IEEE_802_15_4_ModSettings::OQPSK);
d.readBool(34, &m_udpEnabled);
d.readString(35, &m_udpAddress, "127.0.0.1");
d.readU32(36, &utmp);
if ((utmp > 1023) && (utmp < 65535)) {
m_udpPort = utmp;
} else {
m_udpPort = 9998;
}
return true;
}

View File

@ -62,6 +62,9 @@ struct IEEE_802_15_4_ModSettings
enum PulseShaping {RC, SINE} m_pulseShaping;
float m_beta;
int m_symbolSpan;
bool m_udpEnabled;
QString m_udpAddress;
uint16_t m_udpPort;
IEEE_802_15_4_ModSettings();
void resetToDefaults();

View File

@ -577,7 +577,7 @@ void IEEE_802_15_4_ModSource::addTXFrame(QString data)
// PHY payload
crcStart = p;
// Data
p = hexToBin(p, data);
p = hexToBin(p, data.trimmed());
// MAC FCS
crc.calculate(crcStart, p-crcStart);
crcValue = crc.get();

View File

@ -25,6 +25,15 @@ IEEE_802_15_4_ModSettings:
repeatCount:
description: Number of times to repeat the frame (-1 for infinite).
type: integer
udpEnabled:
description: Enable forwarding of frames via UDP
type: integer
udpAddress:
description: UDP address to listen for frames to transmit on
type: string
udpPort:
description: UDP port to listen for frames to transmit on
type: integer
rgbColor:
type: integer
title:

View File

@ -44,6 +44,12 @@ SWGIEEE_802_15_4_ModSettings::SWGIEEE_802_15_4_ModSettings() {
m_repeat_delay_isSet = false;
repeat_count = 0;
m_repeat_count_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;
@ -84,6 +90,12 @@ SWGIEEE_802_15_4_ModSettings::init() {
m_repeat_delay_isSet = false;
repeat_count = 0;
m_repeat_count_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("");
@ -115,6 +127,11 @@ SWGIEEE_802_15_4_ModSettings::cleanup() {
if(udp_address != nullptr) {
delete udp_address;
}
if(title != nullptr) {
delete title;
}
@ -155,6 +172,12 @@ SWGIEEE_802_15_4_ModSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&repeat_count, pJson["repeatCount"], "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");
@ -211,6 +234,15 @@ SWGIEEE_802_15_4_ModSettings::asJsonObject() {
if(m_repeat_count_isSet){
obj->insert("repeatCount", QJsonValue(repeat_count));
}
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));
}
@ -319,6 +351,36 @@ SWGIEEE_802_15_4_ModSettings::setRepeatCount(qint32 repeat_count) {
this->m_repeat_count_isSet = true;
}
qint32
SWGIEEE_802_15_4_ModSettings::getUdpEnabled() {
return udp_enabled;
}
void
SWGIEEE_802_15_4_ModSettings::setUdpEnabled(qint32 udp_enabled) {
this->udp_enabled = udp_enabled;
this->m_udp_enabled_isSet = true;
}
QString*
SWGIEEE_802_15_4_ModSettings::getUdpAddress() {
return udp_address;
}
void
SWGIEEE_802_15_4_ModSettings::setUdpAddress(QString* udp_address) {
this->udp_address = udp_address;
this->m_udp_address_isSet = true;
}
qint32
SWGIEEE_802_15_4_ModSettings::getUdpPort() {
return udp_port;
}
void
SWGIEEE_802_15_4_ModSettings::setUdpPort(qint32 udp_port) {
this->udp_port = udp_port;
this->m_udp_port_isSet = true;
}
qint32
SWGIEEE_802_15_4_ModSettings::getRgbColor() {
return rgb_color;
@ -428,6 +490,15 @@ SWGIEEE_802_15_4_ModSettings::isSet(){
if(m_repeat_count_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;
}

View File

@ -66,6 +66,15 @@ public:
qint32 getRepeatCount();
void setRepeatCount(qint32 repeat_count);
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);
@ -118,6 +127,15 @@ private:
qint32 repeat_count;
bool m_repeat_count_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;