mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-10-31 15:47:10 -04:00
Post FST4W spots to WSPRNet.org
Includes a re-factoring of the WSPRNet class, particularly to handle direct spot posts as well as via a file from wsprd. Switched from GET http request method to POST method. FST4W spots post the same information a WSPR spots except the drift field is always zero (FST4W has no drift compensation, so no drift figure is calculated by the decoder), and the mode field reflects the T/R period in minutes. This means FST4W-120A will be similar to WSPR-2, an FST4W-900 will be similar to WSPR-15. I don't see any way to view the mode field on either the new or old database format queries on WSPRnet, so it is hard to tell if that field is actually stored.
This commit is contained in:
parent
63b1b0729a
commit
7566f3548d
@ -8,6 +8,8 @@
|
||||
|
||||
#include <QTimer>
|
||||
#include <QFile>
|
||||
#include <QRegExp>
|
||||
#include <QRegularExpression>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
@ -18,83 +20,184 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
char const * const wsprNetUrl = "http://wsprnet.org/post?";
|
||||
// char const * const wsprNetUrl = "http://127.0.0.1/post?";
|
||||
char const * const wsprNetUrl = "http://wsprnet.org/post/";
|
||||
//char const * const wsprNetUrl = "http://127.0.0.1:5000/post/";
|
||||
|
||||
//
|
||||
// tested with this python REST mock of WSPRNet.org
|
||||
//
|
||||
/*
|
||||
# Mock WSPRNet.org RESTful API
|
||||
from flask import Flask, request, url_for
|
||||
from flask_restful import Resource, Api
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route ('/post/', methods=['GET', 'POST'])
|
||||
def spot ():
|
||||
if request.method == 'POST':
|
||||
print (request.form)
|
||||
return "1 spot(s) added"
|
||||
|
||||
with app.test_request_context ():
|
||||
print (url_for ('spot'))
|
||||
*/
|
||||
|
||||
// regexp to parse FST4W decodes
|
||||
QRegularExpression fst4_re {R"(
|
||||
(?<time>\d{4})
|
||||
\s+(?<db>[-+]?\d+)
|
||||
\s+(?<dt>[-+]?\d+\.\d+)
|
||||
\s+(?<freq>\d+)
|
||||
\s+`
|
||||
\s+<?(?<call>[A-Z0-9/]+)>?(?:\s(?<grid>[A-R]{2}[0-9]{2}(?:[A-X]{2})?))?(?:\s+(?<dBm>\d+))?
|
||||
)", QRegularExpression::ExtendedPatternSyntaxOption};
|
||||
|
||||
// regexp to parse wspr_spots.txt from wsprd
|
||||
//
|
||||
// 130223 2256 7 -21 -0.3 14.097090 DU1MGA PK04 37 0 40 0
|
||||
// Date Time Sync dBm DT Freq Msg
|
||||
// 1 2 3 4 5 6 -------7------ 8 9 10
|
||||
QRegularExpression wspr_re(R"(^(\d+)\s+(\d+)\s+(\d+)\s+([+-]?\d+)\s+([+-]?\d+\.\d+)\s+(\d+\.\d+)\s+([^ ].*[^ ])\s+([+-]?\d+)\s+([+-]?\d+)\s+([+-]?\d+))");
|
||||
};
|
||||
|
||||
WSPRNet::WSPRNet(QNetworkAccessManager * manager, QObject *parent)
|
||||
: QObject{parent}
|
||||
, networkManager {manager}
|
||||
, uploadTimer {new QTimer {this}}
|
||||
, m_urlQueueSize {0}
|
||||
WSPRNet::WSPRNet (QNetworkAccessManager * manager, QObject *parent)
|
||||
: QObject {parent}
|
||||
, network_manager_ {manager}
|
||||
, spots_to_send_ {0}
|
||||
{
|
||||
connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkReply(QNetworkReply*)));
|
||||
connect( uploadTimer, SIGNAL(timeout()), this, SLOT(work()));
|
||||
connect (network_manager_, &QNetworkAccessManager::finished, this, &WSPRNet::networkReply);
|
||||
connect (&upload_timer_, &QTimer::timeout, this, &WSPRNet::work);
|
||||
}
|
||||
|
||||
void WSPRNet::upload(QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, QString const& tpct, QString const& dbm, QString const& version,
|
||||
QString const& fileName)
|
||||
void WSPRNet::upload (QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, float TR_period, QString const& tpct, QString const& dbm,
|
||||
QString const& version, QString const& fileName)
|
||||
{
|
||||
m_call = call;
|
||||
m_grid = grid;
|
||||
m_rfreq = rfreq;
|
||||
m_tfreq = tfreq;
|
||||
m_mode = mode;
|
||||
TR_period_ = TR_period;
|
||||
m_tpct = tpct;
|
||||
m_dbm = dbm;
|
||||
m_vers = version;
|
||||
m_file = fileName;
|
||||
|
||||
// Open the wsprd.out file
|
||||
QFile wsprdOutFile(fileName);
|
||||
if (!wsprdOutFile.open(QIODevice::ReadOnly | QIODevice::Text) ||
|
||||
wsprdOutFile.size() == 0) {
|
||||
urlQueue.enqueue( wsprNetUrl + urlEncodeNoSpot());
|
||||
QFile wsprdOutFile (fileName);
|
||||
if (!wsprdOutFile.open (QIODevice::ReadOnly | QIODevice::Text) || !wsprdOutFile.size ())
|
||||
{
|
||||
spot_queue_.enqueue (urlEncodeNoSpot ());
|
||||
m_uploadType = 1;
|
||||
uploadTimer->start(200);
|
||||
return;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Read the contents
|
||||
while (!wsprdOutFile.atEnd()) {
|
||||
QHash<QString,QString> query;
|
||||
if ( decodeLine(wsprdOutFile.readLine(), query) ) {
|
||||
while (!wsprdOutFile.atEnd())
|
||||
{
|
||||
SpotQueue::value_type query;
|
||||
if (decodeLine (wsprdOutFile.readLine(), query))
|
||||
{
|
||||
// Prevent reporting data ouside of the current frequency band
|
||||
float f = fabs(m_rfreq.toFloat() - query["tqrg"].toFloat());
|
||||
if (f < 0.0002) {
|
||||
urlQueue.enqueue( wsprNetUrl + urlEncodeSpot(query));
|
||||
float f = fabs (m_rfreq.toFloat() - query.queryItemValue ("tqrg", QUrl::FullyDecoded).toFloat());
|
||||
if (f < 0.0002)
|
||||
{
|
||||
spot_queue_.enqueue(urlEncodeSpot (query));
|
||||
m_uploadType = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_urlQueueSize = urlQueue.size();
|
||||
uploadTimer->start(200);
|
||||
}
|
||||
spots_to_send_ = spot_queue_.size ();
|
||||
upload_timer_.start (200);
|
||||
}
|
||||
|
||||
void WSPRNet::networkReply(QNetworkReply *reply)
|
||||
void WSPRNet::post (QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, float TR_period, QString const& tpct, QString const& dbm,
|
||||
QString const& version, QString const& decode_text)
|
||||
{
|
||||
m_call = call;
|
||||
m_grid = grid;
|
||||
m_rfreq = rfreq;
|
||||
m_tfreq = tfreq;
|
||||
m_mode = mode;
|
||||
TR_period_ = TR_period;
|
||||
m_tpct = tpct;
|
||||
m_dbm = dbm;
|
||||
m_vers = version;
|
||||
|
||||
if (!decode_text.size ())
|
||||
{
|
||||
if (!spot_queue_.size ())
|
||||
{
|
||||
spot_queue_.enqueue (urlEncodeNoSpot ());
|
||||
m_uploadType = 1;
|
||||
}
|
||||
spots_to_send_ = spot_queue_.size ();
|
||||
upload_timer_.start (200);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& match = fst4_re.match (decode_text);
|
||||
if (match.hasMatch ())
|
||||
{
|
||||
SpotQueue::value_type query;
|
||||
// Prevent reporting data ouside of the current frequency band
|
||||
auto tqrg = match.captured ("freq").toInt ();
|
||||
if (tqrg >= 1400 && tqrg <= 1600)
|
||||
{
|
||||
query.addQueryItem ("function", "wspr");
|
||||
// use time as at 3/4 of T/R period before current to
|
||||
// ensure date is in Rx period
|
||||
auto const& date = QDateTime::currentDateTimeUtc ().addSecs (-TR_period * 3. / 4.).date ();
|
||||
query.addQueryItem ("date", date.toString ("yyMMdd"));
|
||||
query.addQueryItem ("time", match.captured ("time"));
|
||||
query.addQueryItem ("sig", match.captured ("db"));
|
||||
query.addQueryItem ("dt", match.captured ("dt"));
|
||||
query.addQueryItem ("tqrg", QString::number (rfreq.toDouble () + (tqrg - 1500) / 1e6, 'f', 6));
|
||||
query.addQueryItem ("tcall", match.captured ("call"));
|
||||
query.addQueryItem ("drift", "0");
|
||||
query.addQueryItem ("tgrid", match.captured ("grid"));
|
||||
query.addQueryItem ("dbm", match.captured ("dBm"));
|
||||
spot_queue_.enqueue (urlEncodeSpot (query));
|
||||
m_uploadType = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WSPRNet::networkReply (QNetworkReply * reply)
|
||||
{
|
||||
// check if request was ours
|
||||
if (m_outstandingRequests.removeOne (reply)) {
|
||||
if (QNetworkReply::NoError != reply->error ()) {
|
||||
if (m_outstandingRequests.removeOne (reply))
|
||||
{
|
||||
if (QNetworkReply::NoError != reply->error ())
|
||||
{
|
||||
Q_EMIT uploadStatus (QString {"Error: %1"}.arg (reply->error ()));
|
||||
// not clearing queue or halting queuing as it may be a transient
|
||||
// one off request error
|
||||
// not clearing queue or halting queuing as it may be a
|
||||
// transient one off request error
|
||||
}
|
||||
else {
|
||||
QString serverResponse = reply->readAll();
|
||||
if( m_uploadType == 2) {
|
||||
if (!serverResponse.contains(QRegExp("spot\\(s\\) added"))) {
|
||||
emit uploadStatus(QString {"Upload Failed: %1"}.arg (serverResponse));
|
||||
urlQueue.clear();
|
||||
uploadTimer->stop();
|
||||
else
|
||||
{
|
||||
QString serverResponse = reply->readAll ();
|
||||
if (m_uploadType == 2)
|
||||
{
|
||||
if (!serverResponse.contains(QRegExp("spot\\(s\\) added")))
|
||||
{
|
||||
Q_EMIT uploadStatus (QString {"Upload Failed: %1"}.arg (serverResponse));
|
||||
spot_queue_.clear ();
|
||||
upload_timer_.stop ();
|
||||
}
|
||||
}
|
||||
|
||||
if (urlQueue.isEmpty()) {
|
||||
emit uploadStatus("done");
|
||||
QFile::remove(m_file);
|
||||
uploadTimer->stop();
|
||||
if (!spot_queue_.size ())
|
||||
{
|
||||
Q_EMIT uploadStatus("done");
|
||||
QFile f {m_file};
|
||||
if (f.exists ()) f.remove ();
|
||||
upload_timer_.stop ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,45 +208,43 @@ void WSPRNet::networkReply(QNetworkReply *reply)
|
||||
}
|
||||
}
|
||||
|
||||
bool WSPRNet::decodeLine(QString const& line, QHash<QString,QString> &query)
|
||||
bool WSPRNet::decodeLine (QString const& line, SpotQueue::value_type& query)
|
||||
{
|
||||
// 130223 2256 7 -21 -0.3 14.097090 DU1MGA PK04 37 0 40 0
|
||||
// Date Time Sync dBm DT Freq Msg
|
||||
// 1 2 3 4 5 6 -------7------ 8 9 10
|
||||
QRegExp rx("^(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+([+-]?\\d+)\\s+([+-]?\\d+\\.\\d+)\\s+(\\d+\\.\\d+)\\s+(.*)\\s+([+-]?\\d+)\\s+([+-]?\\d+)\\s+([+-]?\\d+)");
|
||||
if (rx.indexIn(line) != -1) {
|
||||
auto const& rx_match = wspr_re.match (line);
|
||||
if (rx_match.hasMatch ()) {
|
||||
int msgType = 0;
|
||||
QString msg = rx.cap(7);
|
||||
msg.remove(QRegExp("\\s+$"));
|
||||
msg.remove(QRegExp("^\\s+"));
|
||||
QString msg = rx_match.captured (7);
|
||||
QString call, grid, dbm;
|
||||
QRegExp msgRx;
|
||||
QRegularExpression msgRx;
|
||||
|
||||
// Check for Message Type 1
|
||||
msgRx.setPattern("^([A-Z0-9]{3,6})\\s+([A-Z]{2}\\d{2})\\s+(\\d+)");
|
||||
if (msgRx.indexIn(msg) != -1) {
|
||||
msgRx.setPattern(R"(^([A-Z0-9]{3,6})\s+([A-R]{2}\d{2})\s+(\d+))");
|
||||
auto match = msgRx.match (msg);
|
||||
if (match.hasMatch ()) {
|
||||
msgType = 1;
|
||||
call = msgRx.cap(1);
|
||||
grid = msgRx.cap(2);
|
||||
dbm = msgRx.cap(3);
|
||||
call = match.captured (1);
|
||||
grid = match.captured (2);
|
||||
dbm = match.captured (3);
|
||||
}
|
||||
|
||||
// Check for Message Type 2
|
||||
msgRx.setPattern("^([A-Z0-9/]+)\\s+(\\d+)");
|
||||
if (msgRx.indexIn(msg) != -1) {
|
||||
msgRx.setPattern(R"(^([A-Z0-9/]+)\s+(\d+))");
|
||||
match = msgRx.match (msg);
|
||||
if (match.hasMatch ()) {
|
||||
msgType = 2;
|
||||
call = msgRx.cap(1);
|
||||
call = match.captured (1);
|
||||
grid = "";
|
||||
dbm = msgRx.cap(2);
|
||||
dbm = match.captured (2);
|
||||
}
|
||||
|
||||
// Check for Message Type 3
|
||||
msgRx.setPattern("^<([A-Z0-9/]+)>\\s+([A-Z]{2}\\d{2}[A-Z]{2})\\s+(\\d+)");
|
||||
if (msgRx.indexIn(msg) != -1) {
|
||||
msgRx.setPattern(R"(^<([A-Z0-9/]+)>\s+([A-R]{2}\d{2}[A-X]{2})\s+(\d+))");
|
||||
match = msgRx.match (msg);
|
||||
if (match.hasMatch ()) {
|
||||
msgType = 3;
|
||||
call = msgRx.cap(1);
|
||||
grid = msgRx.cap(2);
|
||||
dbm = msgRx.cap(3);
|
||||
call = match.captured (1);
|
||||
grid = match.captured (2);
|
||||
dbm = match.captured (3);
|
||||
}
|
||||
|
||||
// Unknown message format
|
||||
@ -151,82 +252,82 @@ bool WSPRNet::decodeLine(QString const& line, QHash<QString,QString> &query)
|
||||
return false;
|
||||
}
|
||||
|
||||
query["function"] = "wspr";
|
||||
query["date"] = rx.cap(1);
|
||||
query["time"] = rx.cap(2);
|
||||
query["sig"] = rx.cap(4);
|
||||
query["dt"] = rx.cap(5);
|
||||
query["drift"] = rx.cap(8);
|
||||
query["tqrg"] = rx.cap(6);
|
||||
query["tcall"] = call;
|
||||
query["tgrid"] = grid;
|
||||
query["dbm"] = dbm;
|
||||
query.addQueryItem ("function", "wspr");
|
||||
query.addQueryItem ("date", rx_match.captured (1));
|
||||
query.addQueryItem ("time", rx_match.captured (2));
|
||||
query.addQueryItem ("sig", rx_match.captured (4));
|
||||
query.addQueryItem ("dt", rx_match.captured(5));
|
||||
query.addQueryItem ("drift", rx_match.captured(8));
|
||||
query.addQueryItem ("tqrg", rx_match.captured(6));
|
||||
query.addQueryItem ("tcall", call);
|
||||
query.addQueryItem ("tgrid", grid);
|
||||
query.addQueryItem ("dbm", dbm);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString WSPRNet::urlEncodeNoSpot()
|
||||
auto WSPRNet::urlEncodeNoSpot () -> SpotQueue::value_type
|
||||
{
|
||||
QString queryString;
|
||||
queryString += "function=wsprstat&";
|
||||
queryString += "rcall=" + m_call + "&";
|
||||
queryString += "rgrid=" + m_grid + "&";
|
||||
queryString += "rqrg=" + m_rfreq + "&";
|
||||
queryString += "tpct=" + m_tpct + "&";
|
||||
queryString += "tqrg=" + m_tfreq + "&";
|
||||
queryString += "dbm=" + m_dbm + "&";
|
||||
queryString += "version=" + m_vers;
|
||||
if(m_mode=="WSPR") queryString += "&mode=2";
|
||||
if(m_mode=="WSPR-15") queryString += "&mode=15";
|
||||
return queryString;;
|
||||
SpotQueue::value_type query;
|
||||
query.addQueryItem ("function", "wsprstat");
|
||||
query.addQueryItem ("rcall", m_call);
|
||||
query.addQueryItem ("rgrid", m_grid);
|
||||
query.addQueryItem ("rqrg", m_rfreq);
|
||||
query.addQueryItem ("tpct", m_tpct);
|
||||
query.addQueryItem ("tqrg", m_tfreq);
|
||||
query.addQueryItem ("dbm", m_dbm);
|
||||
query.addQueryItem ("version", m_vers);
|
||||
if (m_mode == "WSPR") query.addQueryItem ("mode", "2");
|
||||
if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15");
|
||||
if (m_mode == "FST4W")
|
||||
{
|
||||
query.addQueryItem ("mode", QString::number (static_cast<int> ((TR_period_ / 60.)+.5)));
|
||||
}
|
||||
return query;;
|
||||
}
|
||||
|
||||
QString WSPRNet::urlEncodeSpot(QHash<QString,QString> const& query)
|
||||
auto WSPRNet::urlEncodeSpot (SpotQueue::value_type& query) -> SpotQueue::value_type
|
||||
{
|
||||
QString queryString;
|
||||
queryString += "function=" + query["function"] + "&";
|
||||
queryString += "rcall=" + m_call + "&";
|
||||
queryString += "rgrid=" + m_grid + "&";
|
||||
queryString += "rqrg=" + m_rfreq + "&";
|
||||
queryString += "date=" + query["date"] + "&";
|
||||
queryString += "time=" + query["time"] + "&";
|
||||
queryString += "sig=" + query["sig"] + "&";
|
||||
queryString += "dt=" + query["dt"] + "&";
|
||||
queryString += "drift=" + query["drift"] + "&";
|
||||
queryString += "tqrg=" + query["tqrg"] + "&";
|
||||
queryString += "tcall=" + query["tcall"] + "&";
|
||||
queryString += "tgrid=" + query["tgrid"] + "&";
|
||||
queryString += "dbm=" + query["dbm"] + "&";
|
||||
queryString += "version=" + m_vers;
|
||||
if(m_mode=="WSPR") queryString += "&mode=2";
|
||||
if(m_mode=="WSPR-15") queryString += "&mode=15";
|
||||
return queryString;
|
||||
query.addQueryItem ("version", m_vers);
|
||||
query.addQueryItem ("rcall", m_call);
|
||||
query.addQueryItem ("rgrid", m_grid);
|
||||
query.addQueryItem ("rqrg", m_rfreq);
|
||||
if (m_mode == "WSPR") query.addQueryItem ("mode", "2");
|
||||
if (m_mode == "WSPR-15") query.addQueryItem ("mode", "15");
|
||||
if (m_mode == "FST4W")
|
||||
{
|
||||
query.addQueryItem ("mode", QString::number (static_cast<int> ((TR_period_ / 60.)+.5)));
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
void WSPRNet::work()
|
||||
{
|
||||
if (!urlQueue.isEmpty()) {
|
||||
if (spots_to_send_ && spot_queue_.size ())
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK (5, 15, 0)
|
||||
if (QNetworkAccessManager::Accessible != networkManager->networkAccessible ()) {
|
||||
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) {
|
||||
// try and recover network access for QNAM
|
||||
networkManager->setNetworkAccessible (QNetworkAccessManager::Accessible);
|
||||
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
|
||||
}
|
||||
#endif
|
||||
QUrl url(urlQueue.dequeue());
|
||||
QNetworkRequest request(url);
|
||||
m_outstandingRequests << networkManager->get(request);
|
||||
emit uploadStatus(QString {"Uploading Spot %1/%2"}.arg (m_urlQueueSize - urlQueue.size()).arg (m_urlQueueSize));
|
||||
} else {
|
||||
uploadTimer->stop();
|
||||
QNetworkRequest request (QUrl {wsprNetUrl});
|
||||
request.setHeader (QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
auto const& spot = spot_queue_.dequeue ();
|
||||
m_outstandingRequests << network_manager_->post (request, spot.query (QUrl::FullyEncoded).toUtf8 ());
|
||||
Q_EMIT uploadStatus(QString {"Uploading Spot %1/%2"}.arg (spots_to_send_ - spot_queue_.size()).arg (spots_to_send_));
|
||||
}
|
||||
else
|
||||
{
|
||||
upload_timer_.stop ();
|
||||
}
|
||||
}
|
||||
|
||||
void WSPRNet::abortOutstandingRequests () {
|
||||
urlQueue.clear ();
|
||||
spot_queue_.clear ();
|
||||
for (auto& request : m_outstandingRequests) {
|
||||
request->abort ();
|
||||
}
|
||||
m_urlQueueSize = 0;
|
||||
}
|
||||
|
@ -2,45 +2,58 @@
|
||||
#define WSPRNET_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include <QUrlQuery>
|
||||
#include <QQueue>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
class QTimer;
|
||||
class QNetworkReply;
|
||||
|
||||
class WSPRNet : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
Q_OBJECT
|
||||
|
||||
using SpotQueue = QQueue<QUrlQuery>;
|
||||
|
||||
public:
|
||||
explicit WSPRNet(QNetworkAccessManager *, QObject *parent = nullptr);
|
||||
void upload(QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, QString const& tpct, QString const& dbm, QString const& version,
|
||||
QString const& fileName);
|
||||
static bool decodeLine(QString const& line, QHash<QString,QString> &query);
|
||||
|
||||
explicit WSPRNet (QNetworkAccessManager *, QObject *parent = nullptr);
|
||||
void upload (QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, float TR_peirod, QString const& tpct, QString const& dbm,
|
||||
QString const& version, QString const& fileName);
|
||||
void post (QString const& call, QString const& grid, QString const& rfreq, QString const& tfreq,
|
||||
QString const& mode, float TR_period, QString const& tpct, QString const& dbm,
|
||||
QString const& version, QString const& decode_text = QString {});
|
||||
signals:
|
||||
void uploadStatus(QString);
|
||||
void uploadStatus (QString);
|
||||
|
||||
public slots:
|
||||
void networkReply(QNetworkReply *);
|
||||
void work();
|
||||
void networkReply (QNetworkReply *);
|
||||
void work ();
|
||||
void abortOutstandingRequests ();
|
||||
|
||||
private:
|
||||
QNetworkAccessManager *networkManager;
|
||||
QList<QNetworkReply *> m_outstandingRequests;
|
||||
QString m_call, m_grid, m_rfreq, m_tfreq, m_mode, m_tpct, m_dbm, m_vers, m_file;
|
||||
QQueue<QString> urlQueue;
|
||||
QTimer *uploadTimer;
|
||||
int m_urlQueueSize;
|
||||
int m_uploadType;
|
||||
bool decodeLine (QString const& line, SpotQueue::value_type& query);
|
||||
SpotQueue::value_type urlEncodeNoSpot ();
|
||||
SpotQueue::value_type urlEncodeSpot (SpotQueue::value_type& spot);
|
||||
|
||||
QString urlEncodeNoSpot();
|
||||
QString urlEncodeSpot(QHash<QString,QString> const& spot);
|
||||
QNetworkAccessManager * network_manager_;
|
||||
QList<QNetworkReply *> m_outstandingRequests;
|
||||
QString m_call;
|
||||
QString m_grid;;
|
||||
QString m_rfreq;
|
||||
QString m_tfreq;
|
||||
QString m_mode;
|
||||
QString m_tpct;
|
||||
QString m_dbm;
|
||||
QString m_vers;
|
||||
QString m_file;
|
||||
float TR_period_;
|
||||
int spots_to_send_;
|
||||
SpotQueue spot_queue_;
|
||||
QTimer upload_timer_;
|
||||
int m_uploadType;
|
||||
};
|
||||
|
||||
#endif // WSPRNET_H
|
||||
|
@ -803,7 +803,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
connect(&killFileTimer, &QTimer::timeout, this, &MainWindow::killFile);
|
||||
|
||||
uploadTimer.setSingleShot(true);
|
||||
connect(&uploadTimer, SIGNAL(timeout()), this, SLOT(uploadSpots()));
|
||||
connect(&uploadTimer, &QTimer::timeout, [this] () {uploadWSPRSpots ();});
|
||||
|
||||
TxAgainTimer.setSingleShot(true);
|
||||
connect(&TxAgainTimer, SIGNAL(timeout()), this, SLOT(TxAgain()));
|
||||
@ -944,7 +944,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_saveAll=ui->actionSave_all->isChecked();
|
||||
ui->sbTxPercent->setValue(m_pctx);
|
||||
ui->TxPowerComboBox->setCurrentIndex(int(.3 * m_dBm + .2));
|
||||
ui->cbUploadWSPR_Spots->setChecked(m_uploadSpots);
|
||||
ui->cbUploadWSPR_Spots->setChecked(m_uploadWSPRSpots);
|
||||
if((m_ndepth&7)==1) ui->actionQuickDecode->setChecked(true);
|
||||
if((m_ndepth&7)==2) ui->actionMediumDecode->setChecked(true);
|
||||
if((m_ndepth&7)==3) ui->actionDeepestDecode->setChecked(true);
|
||||
@ -1118,7 +1118,7 @@ void MainWindow::writeSettings()
|
||||
m_settings->setValue("dBm",m_dBm);
|
||||
m_settings->setValue("RR73",m_send_RR73);
|
||||
m_settings->setValue ("WSPRPreferType1", ui->WSPR_prefer_type_1_check_box->isChecked ());
|
||||
m_settings->setValue("UploadSpots",m_uploadSpots);
|
||||
m_settings->setValue("UploadSpots",m_uploadWSPRSpots);
|
||||
m_settings->setValue("NoOwnCall",ui->cbNoOwnCall->isChecked());
|
||||
m_settings->setValue ("BandHopping", ui->band_hopping_group_box->isChecked ());
|
||||
m_settings->setValue ("TRPeriod", ui->sbTR->value ());
|
||||
@ -1213,8 +1213,8 @@ void MainWindow::readSettings()
|
||||
on_txrb4_doubleClicked();
|
||||
}
|
||||
ui->WSPR_prefer_type_1_check_box->setChecked (m_settings->value ("WSPRPreferType1", true).toBool ());
|
||||
m_uploadSpots=m_settings->value("UploadSpots",false).toBool();
|
||||
if(!m_uploadSpots) ui->cbUploadWSPR_Spots->setStyleSheet("QCheckBox{background-color: yellow}");
|
||||
m_uploadWSPRSpots=m_settings->value("UploadSpots",false).toBool();
|
||||
if(!m_uploadWSPRSpots) ui->cbUploadWSPR_Spots->setStyleSheet("QCheckBox{background-color: yellow}");
|
||||
ui->cbNoOwnCall->setChecked(m_settings->value("NoOwnCall",false).toBool());
|
||||
ui->band_hopping_group_box->setChecked (m_settings->value ("BandHopping", false).toBool());
|
||||
// setup initial value of tx attenuator
|
||||
@ -1540,7 +1540,7 @@ void MainWindow::dataSink(qint64 frames)
|
||||
if(m_mode=="WSPR") {
|
||||
QStringList t2;
|
||||
QStringList depth_args;
|
||||
t2 << "-f" << QString {"%1"}.arg (m_dialFreqRxWSPR / 1000000.0, 0, 'f', 6);
|
||||
t2 << "-f" << QString {"%1"}.arg (m_dialFreqRxWSPR / 1e6, 0, 'f', 6);
|
||||
if((m_ndepth&7)==1) depth_args << "-qB"; //2 pass w subtract, no Block detection, no shift jittering
|
||||
if((m_ndepth&7)==2) depth_args << "-C" << "500" << "-o" << "4"; //3 pass, subtract, Block detection, OSD
|
||||
if((m_ndepth&7)==3) depth_args << "-C" << "500" << "-o" << "4" << "-d"; //3 pass, subtract, Block detect, OSD, more candidates
|
||||
@ -3112,6 +3112,10 @@ void MainWindow::decodeDone ()
|
||||
{
|
||||
if(m_mode!="FT8" or dec_data.params.nzhsym==50) m_nDecodes=0;
|
||||
if(m_mode=="QRA64") m_wideGraph->drawRed(0,0);
|
||||
if ("FST4W" == m_mode)
|
||||
{
|
||||
uploadWSPRSpots (true); // DE station info and trigger posts
|
||||
}
|
||||
auto tnow = QDateTime::currentDateTimeUtc ();
|
||||
double tdone = fmod(double(tnow.time().second()),m_TRperiod);
|
||||
int mswait;
|
||||
@ -3210,6 +3214,10 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
}
|
||||
m_tBlankLine = line_read.left(ntime);
|
||||
}
|
||||
if ("FST4W" == m_mode)
|
||||
{
|
||||
uploadWSPRSpots (true, line_read);
|
||||
}
|
||||
DecodedText decodedtext0 {QString::fromUtf8(line_read.constData())};
|
||||
DecodedText decodedtext {QString::fromUtf8(line_read.constData()).remove("TU; ")};
|
||||
|
||||
@ -7786,7 +7794,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
}
|
||||
m_nWSPRdecodes=0;
|
||||
ui->DecodeButton->setChecked (false);
|
||||
if(m_uploadSpots
|
||||
if (m_uploadWSPRSpots
|
||||
&& m_config.is_transceiver_online ()) { // need working rig control
|
||||
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
|
||||
uploadTimer.start(QRandomGenerator::global ()->bounded (0, 20000)); // Upload delay
|
||||
@ -7794,8 +7802,8 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
uploadTimer.start(20000 * qrand()/((double)RAND_MAX + 1.0)); // Upload delay
|
||||
#endif
|
||||
} else {
|
||||
QFile f(QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "/wspr_spots.txt");
|
||||
if(f.exists()) f.remove();
|
||||
QFile f {QDir::toNativeSeparators (m_config.writeable_data_dir ().absoluteFilePath ("wspr_spots.txt"))};
|
||||
if (f.exists ()) f.remove ();
|
||||
}
|
||||
m_RxLog=0;
|
||||
m_startAnother=m_loopall;
|
||||
@ -7910,23 +7918,35 @@ void MainWindow::WSPR_history(Frequency dialFreq, int ndecodes)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::uploadSpots()
|
||||
void MainWindow::uploadWSPRSpots (bool direct_post, QString const& decode_text)
|
||||
{
|
||||
// do not spot replays or if rig control not working
|
||||
if(m_diskData || !m_config.is_transceiver_online ()) return;
|
||||
// do not spot if disabled, replays, or if rig control not working
|
||||
if(!m_uploadWSPRSpots || m_diskData || !m_config.is_transceiver_online ()) return;
|
||||
if(m_uploading) {
|
||||
qDebug() << "Previous upload has not completed, spots were lost";
|
||||
wsprNet->abortOutstandingRequests ();
|
||||
m_uploading = false;
|
||||
}
|
||||
QString rfreq = QString("%1").arg(0.000001*(m_dialFreqRxWSPR + 1500), 0, 'f', 6);
|
||||
QString tfreq = QString("%1").arg(0.000001*(m_dialFreqRxWSPR +
|
||||
ui->TxFreqSpinBox->value()), 0, 'f', 6);
|
||||
wsprNet->upload(m_config.my_callsign(), m_config.my_grid(), rfreq, tfreq,
|
||||
m_mode, QString::number(ui->autoButton->isChecked() ? m_pctx : 0),
|
||||
QString::number(m_dBm), version(),
|
||||
QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "/wspr_spots.txt");
|
||||
QString rfreq = QString("%1").arg((m_dialFreqRxWSPR + 1500) / 1e6, 0, 'f', 6);
|
||||
QString tfreq = QString("%1").arg((m_dialFreqRxWSPR +
|
||||
ui->TxFreqSpinBox->value()) / 1e6, 0, 'f', 6);
|
||||
if (!direct_post)
|
||||
{
|
||||
wsprNet->upload (m_config.my_callsign (), m_config.my_grid (), rfreq, tfreq,
|
||||
m_mode, m_TRperiod, QString::number (ui->autoButton->isChecked () ? m_pctx : 0),
|
||||
QString::number (m_dBm), version (),
|
||||
m_config.writeable_data_dir ().absoluteFilePath ("wspr_spots.txt"));
|
||||
}
|
||||
else
|
||||
{
|
||||
wsprNet->post (m_config.my_callsign (), m_config.my_grid (), rfreq, tfreq,
|
||||
m_mode, m_TRperiod, QString::number (ui->autoButton->isChecked () ? m_pctx : 0),
|
||||
QString::number (m_dBm), version (), decode_text);
|
||||
}
|
||||
if (!decode_text.size ())
|
||||
{
|
||||
m_uploading = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::uploadResponse(QString response)
|
||||
@ -7960,9 +7980,9 @@ void MainWindow::on_sbTxPercent_valueChanged(int n)
|
||||
|
||||
void MainWindow::on_cbUploadWSPR_Spots_toggled(bool b)
|
||||
{
|
||||
m_uploadSpots=b;
|
||||
if(m_uploadSpots) ui->cbUploadWSPR_Spots->setStyleSheet("");
|
||||
if(!m_uploadSpots) ui->cbUploadWSPR_Spots->setStyleSheet(
|
||||
m_uploadWSPRSpots=b;
|
||||
if(m_uploadWSPRSpots) ui->cbUploadWSPR_Spots->setStyleSheet("");
|
||||
if(!m_uploadWSPRSpots) ui->cbUploadWSPR_Spots->setStyleSheet(
|
||||
"QCheckBox{background-color: yellow}");
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ private slots:
|
||||
void on_sbTxPercent_valueChanged(int n);
|
||||
void on_cbUploadWSPR_Spots_toggled(bool b);
|
||||
void WSPR_config(bool b);
|
||||
void uploadSpots();
|
||||
void uploadWSPRSpots (bool direct_post = false, QString const& decode_text = QString {});
|
||||
void TxAgain();
|
||||
void uploadResponse(QString response);
|
||||
void on_WSPRfreqSpinBox_valueChanged(int n);
|
||||
@ -500,7 +500,7 @@ private:
|
||||
QString m_tBlankLine;
|
||||
bool m_bShMsgs;
|
||||
bool m_bSWL;
|
||||
bool m_uploadSpots;
|
||||
bool m_uploadWSPRSpots;
|
||||
bool m_uploading;
|
||||
bool m_txNext;
|
||||
bool m_grid6;
|
||||
|
Loading…
Reference in New Issue
Block a user