Add IBP beacons and GRAVES to Map feature

This commit is contained in:
Jon Beniston 2021-12-03 18:23:14 +00:00
parent 3d0a5d70fe
commit 629d174c31
15 changed files with 535 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -6,6 +6,7 @@ set(map_SOURCES
mapplugin.cpp
mapwebapiadapter.cpp
osmtemplateserver.cpp
ibpbeacon.cpp
)
set(map_HEADERS
@ -16,6 +17,7 @@ set(map_HEADERS
mapwebapiadapter.h
osmtemplateserver.h
beacon.h
ibpbeacon.h
)
include_directories(
@ -35,6 +37,8 @@ if(NOT SERVER_MODE)
mapsettingsdialog.ui
mapbeacondialog.cpp
mapbeacondialog.ui
mapibpbeacondialog.cpp
mapibpbeacondialog.ui
mapradiotimedialog.cpp
mapradiotimedialog.ui
map.qrc
@ -47,6 +51,7 @@ if(NOT SERVER_MODE)
mapmaidenheaddialog.h
mapsettingsdialog.h
mapbeacondialog.h
mapibpbeacon.h
mapradiotimedialog.h
)

View File

@ -0,0 +1,45 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "ibpbeacon.h"
QList<IBPBeacon> IBPBeacon::m_beacons = {
IBPBeacon("4U1UN", "United Nations NY", "FN30AS", 0),
IBPBeacon("VE8AT", "North Canada", "EQ79AX", 10),
IBPBeacon("W6WX", "USA (CA)", "CM97BD", 20),
IBPBeacon("KH6WO", "Hawaii", "BL10TS", 30),
IBPBeacon("ZL6B", "New Zealand", "RE78TW", 40),
IBPBeacon("VK6RBP", "West Australia", "OF87AV", 50),
IBPBeacon("JA2IGY", "Japan", "PM84JK", 60),
IBPBeacon("RR9O", "Siberia", "NO14KX", 70),
IBPBeacon("VR2HK", "China", "OL72CQ", 80),
IBPBeacon("4S7B", "Sri Lanka", "NJ06CR", 90),
IBPBeacon("ZS6DN", "South Africa", "KG44DC", 100),
IBPBeacon("5Z4B", "Kenya", "KI88MX", 110),
IBPBeacon("4X6TU", "Israel", "KM72JB", 120),
IBPBeacon("OH2B", "Finland", "KP20BM", 130),
IBPBeacon("CS3B", "Madeira", "IM12OR", 140),
IBPBeacon("LU4AA", "Argentina", "GF05TJ", 150),
IBPBeacon("OA4B", "Peru", "FH17MW", 160),
IBPBeacon("YV5B", "Venezuela", "FJ69CC", 170)
};
// The frequencies in MHz through which the IBP beacons rotate
QList<double> IBPBeacon::m_frequencies = {
14.1, 18.11, 21.150, 24.93, 28.2
};

View File

@ -0,0 +1,64 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_IBP_BEACON_H
#define INCLUDE_IBP_BEACON_H
#include <QString>
#include <QList>
#include "util/maidenhead.h"
// International Beacon Project beacons
// https://www.ncdxf.org/beacon/
struct IBPBeacon {
QString m_callsign;
QString m_location;
int m_offset; // Time offset in seconds
float m_latitude;
float m_longitude;
IBPBeacon(QString callsign, QString location, QString locator, int offset) :
m_callsign(callsign),
m_location(location),
m_offset(offset)
{
Maidenhead::fromMaidenhead(locator, m_latitude, m_longitude);
}
QString getText() const
{
QStringList list;
list.append("IBP Beacon");
list.append(QString("Callsign: %1").arg(m_callsign));
list.append(QString("Frequency: 14.1, 18.11, 21.15, 24.92, 28.2MHz"));
list.append(QString("Power: 100 Watts ERP"));
list.append(QString("Polarization: V"));
list.append(QString("Pattern: Omni"));
list.append(QString("Key: A1"));
list.append(QString("Locator: %1").arg(m_location));
return list.join("\n");
}
static QList<IBPBeacon> m_beacons;
static QList<double> m_frequencies;
static const int m_period = 10; // Beacons rotate every 10 seconds
};
#endif // INCLUDE_IBP_BEACON_H

View File

@ -2,5 +2,6 @@
<qresource prefix="/map/">
<file>icons/groundtracks.png</file>
<file>icons/clock.png</file>
<file>icons/ibp.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -38,6 +38,7 @@
#include "maplocationdialog.h"
#include "mapmaidenheaddialog.h"
#include "mapsettingsdialog.h"
#include "ibpbeacon.h"
#include "ui_mapgui.h"
#include "map.h"
@ -683,6 +684,7 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
m_mapModel(this),
m_beacons(nullptr),
m_beaconDialog(this),
m_ibpBeaconDialog(this),
m_radioTimeDialog(this)
{
ui->setupUi(this);
@ -748,8 +750,10 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
QList<Beacon *> *beacons = Beacon::readIARUCSV(MapGUI::getBeaconFilename());
if (beacons != nullptr)
setBeacons(beacons);
addIBPBeacons();
addRadioTimeTransmitters();
addRadar();
}
MapGUI::~MapGUI()
@ -787,6 +791,24 @@ void MapGUI::setBeacons(QList<Beacon *> *beacons)
}
}
void MapGUI::addIBPBeacons()
{
// Add to Map
for (const auto beacon : IBPBeacon::m_beacons)
{
SWGSDRangel::SWGMapItem beaconMapItem;
beaconMapItem.setName(new QString(beacon.m_callsign));
beaconMapItem.setLatitude(beacon.m_latitude);
beaconMapItem.setLongitude(beacon.m_longitude);
beaconMapItem.setAltitude(0);
beaconMapItem.setImage(new QString("antenna.png"));
beaconMapItem.setImageRotation(0);
beaconMapItem.setImageMinZoom(8);
beaconMapItem.setText(new QString(beacon.getText()));
m_mapModel.update(m_map, &beaconMapItem, MapSettings::SOURCE_BEACONS);
}
}
const QList<RadioTimeTransmitter> MapGUI::m_radioTimeTransmitters = {
{"MSF", 60000, 54.9075f, -3.27333f, 17},
{"DCF77", 77500, 50.01611111f, 9.00805556f, 50},
@ -818,6 +840,23 @@ void MapGUI::addRadioTimeTransmitters()
}
}
void MapGUI::addRadar()
{
SWGSDRangel::SWGMapItem radarMapItem;
radarMapItem.setName(new QString("GRAVES"));
radarMapItem.setLatitude(47.3480);
radarMapItem.setLongitude(5.5151);
radarMapItem.setAltitude(0.0);
radarMapItem.setImage(new QString("antenna.png"));
radarMapItem.setImageRotation(0);
radarMapItem.setImageMinZoom(8);
QString text = QString("Radar\nCallsign: %1\nFrequency: %2 MHz")
.arg("GRAVES")
.arg("143.050");
radarMapItem.setText(new QString(text));
m_mapModel.update(m_map, &radarMapItem, MapSettings::SOURCE_RADAR);
}
static QString arrayToString(QJsonArray array)
{
QString s;
@ -1300,6 +1339,11 @@ void MapGUI::on_beacons_clicked()
m_beaconDialog.show();
}
void MapGUI::on_ibpBeacons_clicked()
{
m_ibpBeaconDialog.show();
}
void MapGUI::on_radiotime_clicked()
{
m_radioTimeDialog.updateTable();

View File

@ -31,6 +31,7 @@
#include "mapsettings.h"
#include "SWGMapItem.h"
#include "mapbeacondialog.h"
#include "mapibpbeacondialog.h"
#include "mapradiotimedialog.h"
#include "osmtemplateserver.h"
@ -481,8 +482,10 @@ public:
static QString getBeaconFilename();
QList<Beacon *> *getBeacons() { return m_beacons; }
void setBeacons(QList<Beacon *> *beacons);
void addIBPBeacons();
QList<RadioTimeTransmitter> getRadioTimeTransmitters() { return m_radioTimeTransmitters; }
void addRadioTimeTransmitters();
void addRadar();
void addDAB();
void find(const QString& target);
Q_INVOKABLE void supportedMapsChanged();
@ -501,6 +504,7 @@ private:
AzEl m_azEl; // Position of station
QList<Beacon *> *m_beacons;
MapBeaconDialog m_beaconDialog;
MapIBPBeaconDialog m_ibpBeaconDialog;
MapRadioTimeDialog m_radioTimeDialog;
quint16 m_osmPort;
OSMTemplateServer *m_templateServer;
@ -536,6 +540,7 @@ private slots:
void on_displaySettings_clicked();
void on_mapTypes_currentIndexChanged(int index);
void on_beacons_clicked();
void on_ibpBeacons_clicked();
void on_radiotime_clicked();
};

View File

@ -140,6 +140,20 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="ibpBeacons">
<property name="toolTip">
<string>Display IBP Beacon dialog</string>
</property>
<property name="text">
<string>IBP</string>
</property>
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/map/icons/ibp.png</normaloff>:/map/icons/ibp.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="radiotime">
<property name="toolTip">

View File

@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "mapibpbeacondialog.h"
#include <QDebug>
#include "channel/channelwebapiutils.h"
#include "mapgui.h"
MapIBPBeaconDialog::MapIBPBeaconDialog(MapGUI *gui, QWidget* parent) :
QDialog(parent),
m_gui(gui),
m_timer(this),
ui(new Ui::MapIBPBeaconDialog)
{
ui->setupUi(this);
connect(&m_timer, &QTimer::timeout, this, &MapIBPBeaconDialog::updateTime);
m_timer.setInterval(1000);
m_timer.start();
ui->beacons->setRowCount(IBPBeacon::m_frequencies.size());
for (int row = 0; row < IBPBeacon::m_frequencies.size(); row++)
{
ui->beacons->setItem(row, IBP_BEACON_COL_FREQUENCY, new QTableWidgetItem(QString::number(IBPBeacon::m_frequencies[row], 'f', 3)));
ui->beacons->setItem(row, IBP_BEACON_COL_CALLSIGN, new QTableWidgetItem(""));
ui->beacons->setItem(row, IBP_BEACON_COL_LOCATION, new QTableWidgetItem(""));
ui->beacons->setItem(row, IBP_BEACON_COL_AZIMUTH, new QTableWidgetItem(""));
ui->beacons->setItem(row, IBP_BEACON_COL_DISTANCE, new QTableWidgetItem(""));
}
updateTable(QTime::currentTime());
}
MapIBPBeaconDialog::~MapIBPBeaconDialog()
{
delete ui;
}
void MapIBPBeaconDialog::updateTable(QTime time)
{
AzEl azEl = *m_gui->getAzEl();
// Repeat from begining every 3 minutes
int index = ((time.minute() * 60 + time.second()) % 180) / IBPBeacon::m_period;
for (int row = 0; row < IBPBeacon::m_frequencies.size(); row++)
{
ui->beacons->item(row, IBP_BEACON_COL_CALLSIGN)->setText(IBPBeacon::m_beacons[index].m_callsign);
ui->beacons->item(row, IBP_BEACON_COL_LOCATION)->setText(IBPBeacon::m_beacons[index].m_location);
// Calculate azimuth and distance to beacon
azEl.setTarget(IBPBeacon::m_beacons[index].m_latitude, IBPBeacon::m_beacons[index].m_longitude, 0.0);
azEl.calculate();
ui->beacons->item(row, IBP_BEACON_COL_AZIMUTH)->setData(Qt::DisplayRole, round(azEl.getAzimuth()));
int km = round(azEl.getDistance()/1000);
ui->beacons->item(row, IBP_BEACON_COL_DISTANCE)->setData(Qt::DisplayRole, km);
index--;
if (index < 0) {
index = IBPBeacon::m_beacons.size() - 1;
}
}
}
void MapIBPBeaconDialog::accept()
{
QDialog::accept();
}
void MapIBPBeaconDialog::on_beacons_cellDoubleClicked(int row, int column)
{
if (column == IBP_BEACON_COL_CALLSIGN)
{
// Find beacon on map
QString location = ui->beacons->item(row, column)->text();
m_gui->find(location);
}
else if (column == IBP_BEACON_COL_FREQUENCY)
{
// Tune to beacon freq
ChannelWebAPIUtils::setCenterFrequency(0, ui->beacons->item(row, column)->text().toDouble() * 1e6);
}
}
void MapIBPBeaconDialog::updateTime()
{
QTime t = QTime::currentTime();
ui->time->setTime(t);
// Beacons rotate every 10 seconds
if ((t.second() % IBPBeacon::m_period) == 0) {
updateTable(t);
}
}

View File

@ -0,0 +1,57 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_FEATURE_MAPIBPBEACONDIALOG_H
#define INCLUDE_FEATURE_MAPIBPBEACONDIALOG_H
#include "ui_mapibpbeacondialog.h"
#include <QTimer>
#include <QTime>
#include "ibpbeacon.h"
class MapGUI;
class MapIBPBeaconDialog : public QDialog {
Q_OBJECT
public:
explicit MapIBPBeaconDialog(MapGUI *gui, QWidget* parent = 0);
~MapIBPBeaconDialog();
void updateTable(QTime time);
private slots:
void accept();
void on_beacons_cellDoubleClicked(int row, int column);
void updateTime();
private:
MapGUI *m_gui;
QTimer m_timer;
Ui::MapIBPBeaconDialog* ui;
enum BeaconCol {
IBP_BEACON_COL_FREQUENCY,
IBP_BEACON_COL_CALLSIGN,
IBP_BEACON_COL_LOCATION,
IBP_BEACON_COL_AZIMUTH,
IBP_BEACON_COL_DISTANCE
};
};
#endif // INCLUDE_FEATURE_MAPIBPBEACONDIALOG_H

View File

@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MapIBPBeaconDialog</class>
<widget class="QDialog" name="MapIBPBeaconDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>584</width>
<height>311</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>IBP Beacons</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="topMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="timeLabel">
<property name="text">
<string>Time</string>
</property>
</widget>
</item>
<item>
<widget class="QTimeEdit" name="time">
<property name="toolTip">
<string>Current time</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="currentSection">
<enum>QDateTimeEdit::HourSection</enum>
</property>
<property name="displayFormat">
<string>HH:mm:ss</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<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="QTableWidget" name="beacons">
<property name="toolTip">
<string>Displays which IBP beacon is transmitting on which frequency</string>
</property>
<column>
<property name="text">
<string>Frequency (MHz)</string>
</property>
</column>
<column>
<property name="text">
<string>Callsign</string>
</property>
</column>
<column>
<property name="text">
<string>Location</string>
</property>
</column>
<column>
<property name="text">
<string>Azimuth (°)</string>
</property>
</column>
<column>
<property name="text">
<string>Distance (km)</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>beacons</tabstop>
<tabstop>time</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>MapIBPBeaconDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>MapIBPBeaconDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -68,9 +68,10 @@ struct MapSettings
static const quint32 SOURCE_SATELLITE_TRACKER = 0x10;
static const quint32 SOURCE_BEACONS = 0x20;
static const quint32 SOURCE_RADIO_TIME = 0x40;
static const quint32 SOURCE_AM = 0x80;
static const quint32 SOURCE_FM = 0x100;
static const quint32 SOURCE_DAB = 0x200;
static const quint32 SOURCE_RADAR = 0x80;
static const quint32 SOURCE_AM = 0x100;
static const quint32 SOURCE_FM = 0x200;
static const quint32 SOURCE_DAB = 0x400;
static const quint32 SOURCE_STATION = 0x400; // Antenna at "My Position"
};

View File

@ -97,6 +97,14 @@
<enum>Checked</enum>
</property>
</item>
<item>
<property name="text">
<string>Radar</string>
</property>
<property name="checkState">
<enum>Checked</enum>
</property>
</item>
</widget>
</item>
<item>

View File

@ -10,8 +10,9 @@ On top of this, it can plot data from other plugins, such as:
* Ships from the AIS Demodulator,
* Satellites from the Satellite Tracker,
* The Sun, Moon and Stars from the Star Tracker,
* Beacons based on the IARU Region 1 beacon database.
* Radio time transmitters.
* Beacons based on the IARU Region 1 beacon database and International Beacon Project,
* Radio time transmitters,
* GRAVES radar.
It can also create tracks showing the path aircraft, ships and APRS objects have taken, as well as predicted paths for satellites.
@ -49,7 +50,20 @@ The beacons will then be displayed in the table and on the map.
![Beacon dialog](../../../doc/img/Map_plugin_beacon_dialog.png)
<h3>5: Display Radio Time Transmitters dialog</h3>
<h3>5: Display IBP Beacon Project Dialog</h3>
When clicked, opens the International Beacon Project dialog. The IBP consists of 18 HF beacons around the world,
that each transmit once on each of the frequencies 14.100, 18.110, 21.150, 24.930 and 28.200MHz every 3 minutes, for 10 seconds.
The IBP dialog shows which of the beacons should currently be transmitting.
![IBP beacon dialog](../../../doc/img/Map_plugin_ibp_beacon_dialog.png)
* Double clicking in a cell in the Callsign column will centre the map on that beacon.
* Double clicking in a cell in the Frequency column will set the Device center frequency.
More details of the IBP can be found at: https://www.ncdxf.org/beacon/beaconfaq.html
<h3>6: Display Radio Time Transmitters dialog</h3>
When clicked, opens the Radio Time Transmitters dialog.
@ -58,23 +72,23 @@ When clicked, opens the Radio Time Transmitters dialog.
![Radio Time transmitters dialog](../../../doc/img/Map_plugin_radiotime_dialog.png)
<h3>6: Display Names</h3>
<h3>7: Display Names</h3>
When checked, names of objects are displayed in a bubble next to each object.
<h3>7: Display tracks for selected object</h3>
<h3>8: Display tracks for selected object</h3>
When checked, displays the track (taken or predicted) for the selected object.
<h3>8: Display tracks for all objects</h3>
<h3>9: Display tracks for all objects</h3>
When checked, displays the track (taken or predicted) for the all objects.
<h3>9: Delete</h3>
<h3>10: Delete</h3>
When clicked, all items will be deleted from the map.
<h3>10: Display settings</h3>
<h3>11: Display settings</h3>
When clicked, opens the Map Display Settings dialog, which allows setting: