diff --git a/plugins/feature/map/mapgui.cpp b/plugins/feature/map/mapgui.cpp index 5c28b261c..e6b67525e 100644 --- a/plugins/feature/map/mapgui.cpp +++ b/plugins/feature/map/mapgui.cpp @@ -40,6 +40,7 @@ #include "gui/dialogpositioner.h" #include "device/deviceset.h" #include "device/deviceapi.h" +#include "channel/channelwebapiutils.h" #include "dsp/devicesamplesource.h" #include "device/deviceenumerator.h" #include "util/units.h" @@ -55,8 +56,6 @@ #include "ui_mapgui.h" #include "map.h" #include "mapgui.h" -#include "SWGMapItem.h" -#include "SWGDeviceSettings.h" #include "SWGKiwiSDRSettings.h" #include "SWGRemoteTCPInputSettings.h" @@ -310,7 +309,6 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur connect(profile, &QWebEngineProfile::downloadRequested, this, &MapGUI::downloadRequested); #endif -qDebug() << "Get station position"; // Get station position float stationLatitude = MainCore::instance()->getSettings().getLatitude(); float stationLongitude = MainCore::instance()->getSettings().getLongitude(); @@ -322,7 +320,6 @@ qDebug() << "Get station position"; m_polygonMapFilter.setPosition(stationPosition); m_polylineMapFilter.setPosition(stationPosition); -qDebug() << "Centre map"; // Centre map at My Position QQuickItem *item = ui->map->rootObject(); QObject *object = item->findChild("map"); @@ -334,7 +331,6 @@ qDebug() << "Centre map"; object->setProperty("center", QVariant::fromValue(coords)); } -qDebug() << "Creating antenna"; // Create antenna at My Position m_antennaMapItem.setName(new QString("Station")); m_antennaMapItem.setLatitude(stationLatitude); @@ -770,7 +766,7 @@ void MapGUI::sdrangelServerUpdated(const QList 0) { text.append(QString("\nTime limit: %1 mins").arg(sdr.m_timeLimit)); } - QString url = QString("sdrangel-server://%1").arg(address); + QString url; + if (sdr.m_protocol == "SDRangel wss") { + url = QString("sdrangel-wss-server://%1").arg(address); + } else { + url = QString("sdrangel-server://%1").arg(address); + } QString link = QString("%2").arg(url).arg(address); text.append(QString("\nURL: %1").arg(link)); sdrangelServerMapItem.setText(new QString(text)); @@ -803,7 +805,7 @@ void MapGUI::sdrangelServerUpdated(const QList 3000000000) { bands.append("SHF"); } - QString label = QString("SDRangel %1").arg(bands.join(" ")); + QString label = QString("%1 %2").arg(sdr.m_protocol).arg(bands.join(" ")); sdrangelServerMapItem.setLabel(new QString(label)); sdrangelServerMapItem.setLabelAltitudeOffset(4.5); sdrangelServerMapItem.setAltitudeReference(1); @@ -2720,120 +2722,29 @@ void MapGUI::linkClicked(const QString& url) QString spyServerURL = url.mid(21); openSpyServer(spyServerURL); } + else if (url.startsWith("sdrangel-wss-server://")) + { + QString sdrangelServerURL = url.mid(22); + openSDRangelServer(sdrangelServerURL, true); + } else if (url.startsWith("sdrangel-server://")) { QString sdrangelServerURL = url.mid(18); - openSDRangelServer(sdrangelServerURL); + openSDRangelServer(sdrangelServerURL, false); } } -bool MapGUI::openKiwiSDRInput() -{ - // Create DeviceSet - MainCore *mainCore = MainCore::instance(); - unsigned int deviceSetIndex = mainCore->getDeviceSets().size(); - MainCore::MsgAddDeviceSet *msg = MainCore::MsgAddDeviceSet::create(0); - mainCore->getMainMessageQueue()->push(msg); - - // Switch to KiwiSDR - int nbSamplingDevices = DeviceEnumerator::instance()->getNbRxSamplingDevices(); - bool found = false; - QString hwType = "KiwiSDR"; - for (int i = 0; i < nbSamplingDevices; i++) - { - const PluginInterface::SamplingDevice *samplingDevice; - - samplingDevice = DeviceEnumerator::instance()->getRxSamplingDevice(i); - - if (!hwType.isEmpty() && (hwType != samplingDevice->hardwareId)) { - continue; - } - - int direction = 0; - MainCore::MsgSetDevice *msg = MainCore::MsgSetDevice::create(deviceSetIndex, i, direction); - mainCore->getMainMessageQueue()->push(msg); - found = true; - break; - } - if (!found) - { - qCritical() << "MapGUI::openKiwiSDR: Failed to find KiwiSDR"; - return false; - } - - // Move to same workspace - //getWorkspaceIndex(); - - return true; -} - // Open a KiwiSDR RX device void MapGUI::openKiwiSDR(const QString& url) { m_remoteDeviceAddress = url; - connect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::kiwiSDRDeviceSetAdded); - if (!openKiwiSDRInput()) { - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::kiwiSDRDeviceSetAdded); - } -} + QStringList deviceSettingsKeys = {"serverAddress"}; + SWGSDRangel::SWGDeviceSettings *response = new SWGSDRangel::SWGDeviceSettings(); + response->init(); + SWGSDRangel::SWGKiwiSDRSettings *deviceSettings = response->getKiwiSdrSettings(); + deviceSettings->setServerAddress(new QString(m_remoteDeviceAddress)); -void MapGUI::kiwiSDRDeviceSetAdded(int index, DeviceAPI *device) -{ - (void) index; - - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::kiwiSDRDeviceSetAdded); - - // FIXME: Doesn't work if we do it immediately. Settings overwritten? - QTimer::singleShot(200, [=] { - // Set address setting - QStringList deviceSettingsKeys = {"serverAddress"}; - SWGSDRangel::SWGDeviceSettings response; - response.init(); - SWGSDRangel::SWGKiwiSDRSettings *deviceSettings = response.getKiwiSdrSettings(); - deviceSettings->setServerAddress(new QString(m_remoteDeviceAddress)); - QString errorMessage; - device->getSampleSource()->webapiSettingsPutPatch(false, deviceSettingsKeys, response, errorMessage); - }); -} - -bool MapGUI::openRemoteTCPInput() -{ - // Create DeviceSet - MainCore *mainCore = MainCore::instance(); - unsigned int deviceSetIndex = mainCore->getDeviceSets().size(); - MainCore::MsgAddDeviceSet *msg = MainCore::MsgAddDeviceSet::create(0); - mainCore->getMainMessageQueue()->push(msg); - - // Switch to RemoteTCPInput - int nbSamplingDevices = DeviceEnumerator::instance()->getNbRxSamplingDevices(); - bool found = false; - QString hwType = "RemoteTCPInput"; - for (int i = 0; i < nbSamplingDevices; i++) - { - const PluginInterface::SamplingDevice *samplingDevice; - - samplingDevice = DeviceEnumerator::instance()->getRxSamplingDevice(i); - - if (!hwType.isEmpty() && (hwType != samplingDevice->hardwareId)) { - continue; - } - - int direction = 0; - MainCore::MsgSetDevice *msg = MainCore::MsgSetDevice::create(deviceSetIndex, i, direction); - mainCore->getMainMessageQueue()->push(msg); - found = true; - break; - } - if (!found) - { - qCritical() << "MapGUI::openRemoteTCPInput: Failed to find RemoteTCPInput"; - return false; - } - - // Move to same workspace - //getWorkspaceIndex(); - - return true; + ChannelWebAPIUtils::addDevice("KiwiSDR", 0, deviceSettingsKeys, response); } // Open a RemoteTCPInput device to use for SpyServer @@ -2842,66 +2753,36 @@ void MapGUI::openSpyServer(const QString& url) QStringList address = url.split(":"); m_remoteDeviceAddress = address[0]; m_remoteDevicePort = address[1].toInt(); - connect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::spyServerDeviceSetAdded); - if (!openRemoteTCPInput()) { - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::spyServerDeviceSetAdded); - } -} -void MapGUI::spyServerDeviceSetAdded(int index, DeviceAPI *device) -{ - (void) index; + QStringList deviceSettingsKeys = {"dataAddress", "dataPort", "protocol", "overrideRemoteSettings"}; + SWGSDRangel::SWGDeviceSettings *response = new SWGSDRangel::SWGDeviceSettings(); + response->init(); + SWGSDRangel::SWGRemoteTCPInputSettings *deviceSettings = response->getRemoteTcpInputSettings(); + deviceSettings->setDataAddress(new QString(m_remoteDeviceAddress)); + deviceSettings->setDataPort(m_remoteDevicePort); + deviceSettings->setProtocol(new QString("Spy Server")); + deviceSettings->setOverrideRemoteSettings(false); - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::spyServerDeviceSetAdded); - - // FIXME: Doesn't work if we do it immediately. Settings overwritten? - QTimer::singleShot(200, [=] { - // Set address/port setting - QStringList deviceSettingsKeys = {"dataAddress", "dataPort", "protocol", "overrideRemoteSettings"}; - SWGSDRangel::SWGDeviceSettings response; - response.init(); - SWGSDRangel::SWGRemoteTCPInputSettings *deviceSettings = response.getRemoteTcpInputSettings(); - deviceSettings->setDataAddress(new QString(m_remoteDeviceAddress)); - deviceSettings->setDataPort(m_remoteDevicePort); - deviceSettings->setProtocol(new QString("Spy Server")); - deviceSettings->setOverrideRemoteSettings(false); - QString errorMessage; - device->getSampleSource()->webapiSettingsPutPatch(false, deviceSettingsKeys, response, errorMessage); - }); + ChannelWebAPIUtils::addDevice("RemoteTCPInput", 0, deviceSettingsKeys, response); } // Open a RemoteTCPInput device to use for SDRangel -void MapGUI::openSDRangelServer(const QString& url) +void MapGUI::openSDRangelServer(const QString& url, bool wss) { QStringList address = url.split(":"); m_remoteDeviceAddress = address[0]; m_remoteDevicePort = address[1].toInt(); - connect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::sdrangelServerDeviceSetAdded); - if (!openRemoteTCPInput()) { - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::sdrangelServerDeviceSetAdded); - } -} -void MapGUI::sdrangelServerDeviceSetAdded(int index, DeviceAPI *device) -{ - (void) index; + QStringList deviceSettingsKeys = {"dataAddress", "dataPort", "protocol", "overrideRemoteSettings"}; + SWGSDRangel::SWGDeviceSettings *response = new SWGSDRangel::SWGDeviceSettings(); + response->init(); + SWGSDRangel::SWGRemoteTCPInputSettings *deviceSettings = response->getRemoteTcpInputSettings(); + deviceSettings->setDataAddress(new QString(m_remoteDeviceAddress)); + deviceSettings->setDataPort(m_remoteDevicePort); + deviceSettings->setProtocol(new QString(wss ? "SDRangel wss" : "SDRangel")); + deviceSettings->setOverrideRemoteSettings(false); - disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &MapGUI::sdrangelServerDeviceSetAdded); - - // FIXME: Doesn't work if we do it immediately. Settings overwritten? - QTimer::singleShot(200, [=] { - // Set address/port setting - QStringList deviceSettingsKeys = {"dataAddress", "dataPort", "protocol", "overrideRemoteSettings"}; - SWGSDRangel::SWGDeviceSettings response; - response.init(); - SWGSDRangel::SWGRemoteTCPInputSettings *deviceSettings = response.getRemoteTcpInputSettings(); - deviceSettings->setDataAddress(new QString(m_remoteDeviceAddress)); - deviceSettings->setDataPort(m_remoteDevicePort); - deviceSettings->setProtocol(new QString("SDRangel")); - deviceSettings->setOverrideRemoteSettings(false); - QString errorMessage; - device->getSampleSource()->webapiSettingsPutPatch(false, deviceSettingsKeys, response, errorMessage); - }); + ChannelWebAPIUtils::addDevice("RemoteTCPInput", 0, deviceSettingsKeys, response); } #ifdef QT_WEBENGINE_FOUND diff --git a/plugins/feature/map/mapgui.h b/plugins/feature/map/mapgui.h index 4188698eb..dfe20cb6f 100644 --- a/plugins/feature/map/mapgui.h +++ b/plugins/feature/map/mapgui.h @@ -52,6 +52,7 @@ #include "availablechannelorfeaturehandler.h" #include "SWGMapItem.h" +#include "SWGDeviceSettings.h" #include "mapsettings.h" #include "mapbeacondialog.h" @@ -290,11 +291,9 @@ private: void applyNASAGlobalImagerySettings(); void createNASAGlobalImageryView(); void displayNASAMetaData(); - bool openKiwiSDRInput(); - bool openRemoteTCPInput(); void openKiwiSDR(const QString& url); void openSpyServer(const QString& url); - void openSDRangelServer(const QString& url); + void openSDRangelServer(const QString& url, bool wss); QString formatFrequency(qint64 frequency) const; void updateGIRO(const QDateTime& mapDateTime); @@ -371,11 +370,8 @@ private slots: void airportsUpdated(); void waypointsUpdated(); void kiwiSDRUpdated(const QList& sdrs); - void kiwiSDRDeviceSetAdded(int index, DeviceAPI *device); void spyServerUpdated(const QList& sdrs); - void spyServerDeviceSetAdded(int index, DeviceAPI *device); void sdrangelServerUpdated(const QList& sdrs); - void sdrangelServerDeviceSetAdded(int index, DeviceAPI *device); void linkClicked(const QString& url); }; diff --git a/sdrbase/channel/channelwebapiutils.cpp b/sdrbase/channel/channelwebapiutils.cpp index f78f06841..27e489c66 100644 --- a/sdrbase/channel/channelwebapiutils.cpp +++ b/sdrbase/channel/channelwebapiutils.cpp @@ -33,6 +33,7 @@ #include "maincore.h" #include "device/deviceset.h" #include "device/deviceapi.h" +#include "device/deviceenumerator.h" #include "channel/channelapi.h" #include "channel/channelutils.h" #include "dsp/devicesamplesource.h" @@ -1953,3 +1954,87 @@ bool ChannelWebAPIUtils::addChannel(unsigned int deviceSetIndex, const QString& return false; } } + +// response will be deleted after device is opened. +bool ChannelWebAPIUtils::addDevice(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) +{ + return DeviceOpener::open(hwType, direction, settingsKeys, response); +} + +DeviceOpener::DeviceOpener(int deviceIndex, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) : + m_deviceIndex(deviceIndex), + m_direction(direction), + m_settingsKeys(settingsKeys), + m_response(response), + m_device(nullptr) +{ + connect(MainCore::instance(), &MainCore::deviceSetAdded, this, &DeviceOpener::deviceSetAdded); + // Create DeviceSet + MainCore *mainCore = MainCore::instance(); + m_deviceSetIndex = mainCore->getDeviceSets().size(); + MainCore::MsgAddDeviceSet *msg = MainCore::MsgAddDeviceSet::create(m_direction); + mainCore->getMainMessageQueue()->push(msg); +} + +void DeviceOpener::deviceSetAdded(int index, DeviceAPI *device) +{ + if (index == m_deviceSetIndex) + { + disconnect(MainCore::instance(), &MainCore::deviceSetAdded, this, &DeviceOpener::deviceSetAdded); + + m_device = device; + // Set the correct device type + MainCore::MsgSetDevice *msg = MainCore::MsgSetDevice::create(m_deviceSetIndex, m_deviceIndex, m_direction); + MainCore::instance()->getMainMessageQueue()->push(msg); + // Wait until device has initialised - FIXME: Better way to do this other than polling? + m_timer.setInterval(250); + connect(&m_timer, &QTimer::timeout, this, &DeviceOpener::checkInitialised); + m_timer.start(); + } +} + +void DeviceOpener::checkInitialised() +{ + if (m_device && m_device->getSampleSource() && (m_device->state() >= DeviceAPI::EngineState::StIdle)) + { + m_timer.stop(); + + QString errorMessage; + if (200 != m_device->getSampleSource()->webapiSettingsPutPatch(false, m_settingsKeys, *m_response, errorMessage)) { + qDebug() << "DeviceOpener::checkInitialised: webapiSettingsPutPatch failed: " << errorMessage; + } + + delete m_response; + delete this; + } +} + +bool DeviceOpener::open(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response) +{ + if (direction) { + return false; // FIXME: Only RX support for now + } + + int nbSamplingDevices = DeviceEnumerator::instance()->getNbRxSamplingDevices(); + bool found = false; + + for (int i = 0; i < nbSamplingDevices; i++) + { + const PluginInterface::SamplingDevice *samplingDevice; + + samplingDevice = DeviceEnumerator::instance()->getRxSamplingDevice(i); + + if (!hwType.isEmpty() && (hwType != samplingDevice->hardwareId)) { + continue; + } + + new DeviceOpener(i, direction, settingsKeys, response); + + return true; + } + if (!found) + { + qCritical() << "DeviceOpener::open: Failed to find device with hwType " << hwType; + return false; + } +} diff --git a/sdrbase/channel/channelwebapiutils.h b/sdrbase/channel/channelwebapiutils.h index 1bfc7e808..be11eb02b 100644 --- a/sdrbase/channel/channelwebapiutils.h +++ b/sdrbase/channel/channelwebapiutils.h @@ -23,6 +23,7 @@ #include #include +#include #include "SWGDeviceSettings.h" #include "SWGDeviceReport.h" @@ -36,6 +37,28 @@ class DeviceSet; class Feature; class ChannelAPI; +class DeviceAPI; + +// Use ChannelWebAPIUtils::addDevice rather than this directly +class DeviceOpener : public QObject { + Q_OBJECT +protected: + DeviceOpener(int deviceIndex, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response); +private: + int m_deviceIndex; + int m_direction; + int m_deviceSetIndex; + QStringList m_settingsKeys; + SWGSDRangel::SWGDeviceSettings *m_response; + DeviceAPI *m_device; + QTimer m_timer; + +private slots: + void deviceSetAdded(int index, DeviceAPI *device); + void checkInitialised(); +public: + static bool open(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response); +}; class SDRBASE_API ChannelWebAPIUtils { @@ -103,6 +126,7 @@ public: static bool getChannelSettings(ChannelAPI *channel, SWGSDRangel::SWGChannelSettings &channelSettingsResponse); static bool getChannelReport(unsigned int deviceIndex, unsigned int channelIndex, SWGSDRangel::SWGChannelReport &channelReport); static bool addChannel(unsigned int deviceSetIndex, const QString& uri, int direction); + static bool addDevice(const QString hwType, int direction, const QStringList& settingsKeys, SWGSDRangel::SWGDeviceSettings *response); protected: static QString getDeviceHardwareId(unsigned int deviceIndex); }; diff --git a/sdrbase/util/kiwisdrlist.cpp b/sdrbase/util/kiwisdrlist.cpp index 0a01e562b..695349aca 100644 --- a/sdrbase/util/kiwisdrlist.cpp +++ b/sdrbase/util/kiwisdrlist.cpp @@ -97,6 +97,11 @@ void KiwiSDRList::handleHTML(const QString& url, const QByteArray& bytes) QList sdrs; QString html(bytes); + + // Strip nested divs, as the following div regexp can't handle them + QRegularExpression divName("
(.*?)<\\/div>", QRegularExpression::DotMatchesEverythingOption); + html.replace(divName, "\\1"); + QRegularExpression div("
(.*?)<\\/div>", QRegularExpression::DotMatchesEverythingOption); QRegularExpressionMatchIterator divItr = div.globalMatch(html);