wfview/cluster.cpp

315 wiersze
11 KiB
C++
Czysty Zwykły widok Historia

2022-09-29 16:17:51 +00:00
#include "cluster.h"
#include "logcategories.h"
dxClusterClient::dxClusterClient(QObject* parent):
QObject(parent)
{
qInfo(logCluster()) << "starting dxClusterClient()";
}
dxClusterClient::~dxClusterClient()
{
qInfo(logCluster()) << "closing dxClusterClient()";
enableUdp(false);
enableTcp(false);
2022-10-05 11:43:39 +00:00
#ifdef USESQL
database db;
db.close();
2022-10-05 11:43:39 +00:00
#else
QMap<QString, spotData*>::iterator spot = allSpots.begin();
while (spot != allSpots.end())
{
delete spot.value(); // Stop memory leak?
spot = allSpots.erase(spot);
}
#endif
2022-09-29 16:17:51 +00:00
}
void dxClusterClient::enableUdp(bool enable)
{
udpEnable = enable;
if (enable)
{
if (udpSocket == Q_NULLPTR)
{
udpSocket = new QUdpSocket(this);
bool result = udpSocket->bind(QHostAddress::AnyIPv4, udpPort);
qInfo(logCluster()) << "Starting udpSocket() on:" << udpPort << "Result:" << result;
connect(udpSocket, SIGNAL(readyRead()), this, SLOT(udpDataReceived()), Qt::QueuedConnection);
}
}
else {
if (udpSocket != Q_NULLPTR)
{
2022-09-30 16:05:42 +00:00
qInfo(logCluster()) << "Stopping udpSocket() on:" << udpPort;
2022-09-29 16:17:51 +00:00
udpSocket->disconnect();
delete udpSocket;
2022-09-30 16:05:42 +00:00
udpSocket = Q_NULLPTR;
2022-09-29 16:17:51 +00:00
}
}
}
void dxClusterClient::enableTcp(bool enable)
{
tcpEnable = enable;
2022-09-30 16:05:42 +00:00
if (enable)
{
tcpRegex = QRegularExpression("^DX de ([a-z-|A-Z|0-9|#|/]+):\\s+([0-9|.]+)\\s+([a-z|A-Z|0-9|/]+)+\\s+(.*)\\s+(\\d{4}Z)");
2022-09-30 16:05:42 +00:00
if (tcpSocket == Q_NULLPTR)
{
tcpSocket = new QTcpSocket(this);
tcpSocket->connectToHost(tcpServerName, tcpPort);
qInfo(logCluster()) << "Starting tcpSocket() on:" << tcpPort;
connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(tcpDataReceived()), Qt::QueuedConnection);
connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(tcpDisconnected()));
2022-09-30 16:05:42 +00:00
tcpCleanupTimer = new QTimer(this);
tcpCleanupTimer->setInterval(1000 * 10); // Run once a minute
connect(tcpCleanupTimer, SIGNAL(timeout()), this, SLOT(tcpCleanup()));
tcpCleanupTimer->start();
2022-10-31 12:15:42 +00:00
authenticated = false;
2022-09-30 16:05:42 +00:00
}
}
else {
if (tcpSocket != Q_NULLPTR)
{
sendTcpData(QString("bye\n"));
2022-09-30 16:05:42 +00:00
qInfo(logCluster()) << "Disconnecting tcpSocket() on:" << tcpPort;
if (tcpCleanupTimer != Q_NULLPTR)
{
tcpCleanupTimer->stop();
delete tcpCleanupTimer;
tcpCleanupTimer = Q_NULLPTR;
}
tcpSocket->disconnect();
delete tcpSocket;
tcpSocket = Q_NULLPTR;
}
}
2022-09-29 16:17:51 +00:00
}
void dxClusterClient::udpDataReceived()
{
QHostAddress sender;
quint16 port;
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &port);
if (udpSpotReader.setContent(datagram))
{
QDomElement spot = udpSpotReader.firstChildElement("spot");
if (spot.nodeName() == "spot")
{
// This is a spot?
QString action = spot.firstChildElement("action").text();
if (action == "add") {
2022-09-30 16:05:42 +00:00
spotData* data = new spotData();
data->dxcall = spot.firstChildElement("dxcall").text();
data->frequency = spot.firstChildElement("frequency").text().toDouble() / 1000.0;
data->spottercall = spot.firstChildElement("spottercall").text();
data->timestamp = QDateTime::fromString(spot.firstChildElement("timestamp").text(),"yyyy-MM-dd hh:mm:ss");
data->mode = spot.firstChildElement("mode").text();
data->comment = spot.firstChildElement("comment").text();
2022-10-05 11:43:39 +00:00
#ifdef USESQL
database db = database();
db.query(QString("DELETE from spots where dxcall='%1'").arg(data->dxcall));
QString query = QString("INSERT INTO spots(type,spottercall,frequency,dxcall,mode,comment,timestamp) VALUES('%1','%2',%3,'%4','%5','%6','%7')\n")
.arg("UDP").arg(data->spottercall).arg(data->frequency).arg(data->dxcall).arg(data->mode).arg(data->comment).arg(data->timestamp.toString("yyyy-MM-dd hh:mm:ss"));
db.query(query);
2022-10-05 11:43:39 +00:00
#else
bool found = false;
QMap<QString, spotData*>::iterator spot = allSpots.find(data->dxcall);
while (spot != allSpots.end() && spot.key() == data->dxcall && spot.value()->frequency == data->frequency) {
found = true;
++spot;
}
if (found == false) {
allSpots.insert(data->dxcall, data);
}
#endif
2022-10-09 13:23:07 +00:00
emit sendOutput(QString("<spot><action>add</action><dxcall>%1</dxcall><spottercall>%2</spottercall><frequency>%3</frequency><comment>%4</comment></spot>\n")
.arg(data->dxcall).arg(data->spottercall).arg(data->frequency).arg(data->comment));
2022-10-05 11:43:39 +00:00
2022-09-29 16:17:51 +00:00
}
else if (action == "delete")
{
QString dxcall = spot.firstChildElement("dxcall").text();
double frequency = spot.firstChildElement("frequency").text().toDouble() / 1000.0;
2022-10-05 11:43:39 +00:00
#ifdef USESQL
database db = database();
QString query=QString("DELETE from spots where dxcall='%1' AND frequency=%2").arg(dxcall).arg(frequency);
db.query(query);
qInfo(logCluster()) << query;
2022-10-05 11:43:39 +00:00
#else
QMap<QString, spotData*>::iterator spot = allSpots.find(dxcall);
while (spot != allSpots.end() && spot.key() == dxcall && spot.value()->frequency == frequency)
{
delete spot.value(); // Stop memory leak?
spot = allSpots.erase(spot);
}
#endif
2022-10-09 13:23:07 +00:00
emit sendOutput(QString("<spot><action>delete</action><dxcall>%1</dxcall<frequency>%3</frequency></spot>\n")
.arg(dxcall).arg(frequency));
2022-09-29 16:17:51 +00:00
}
updateSpots();
2022-09-29 16:17:51 +00:00
}
}
}
2022-09-30 16:05:42 +00:00
void dxClusterClient::tcpDataReceived()
{
QString data = QString(tcpSocket->readAll());
2022-10-09 13:35:24 +00:00
emit sendOutput(data);
2022-10-31 12:15:42 +00:00
if (!authenticated) {
if (data.contains("login:") || data.contains("call:") || data.contains("callsign:")) {
sendTcpData(QString("%1\n").arg(tcpUserName));
return;
}
if (data.contains("password:")) {
sendTcpData(QString("%1\n").arg(tcpPassword));
return;
}
if (data.contains("Hello")) {
authenticated = true;
enableSkimmerSpots(skimmerSpots);
2022-10-31 12:15:42 +00:00
}
2022-09-30 16:05:42 +00:00
}
2022-10-31 12:15:42 +00:00
else {
QRegularExpressionMatchIterator i = tcpRegex.globalMatch(data);
while (i.hasNext()) {
QRegularExpressionMatch match = i.next();
if (match.hasMatch()) {
spotData* data = new spotData();
data->spottercall = match.captured(1);
data->frequency = match.captured(2).toDouble() / 1000.0;
data->dxcall = match.captured(3);
data->comment = match.captured(4).trimmed();
data->timestamp = QDateTime::currentDateTimeUtc();
2022-10-05 11:43:39 +00:00
#ifdef USESQL
2022-10-31 12:15:42 +00:00
database db = database();
db.query(QString("DELETE from spots where dxcall='%1'").arg(data->dxcall));
QString query = QString("INSERT INTO spots(type,spottercall,frequency,dxcall,comment,timestamp) VALUES('%1','%2',%3,'%4','%5','%6')\n")
.arg("TCP").arg(data->spottercall).arg(data->frequency).arg(data->dxcall).arg(data->comment).arg(data->timestamp.toString("yyyy-MM-dd hh:mm:ss"));
db.query(query);
2022-10-05 11:43:39 +00:00
#else
2022-10-31 12:15:42 +00:00
bool found = false;
QMap<QString, spotData*>::iterator spot = allSpots.find(data->dxcall);
while (spot != allSpots.end() && spot.key() == data->dxcall && spot.value()->frequency == data->frequency) {
found = true;
++spot;
}
if (found == false) {
allSpots.insert(data->dxcall, data);
}
2022-10-05 11:43:39 +00:00
#endif
2022-10-31 12:15:42 +00:00
}
2022-09-30 16:05:42 +00:00
}
2022-10-31 12:15:42 +00:00
updateSpots();
2022-09-30 16:05:42 +00:00
}
}
void dxClusterClient::sendTcpData(QString data)
{
qInfo(logCluster()) << "Sending:" << data;
if (tcpSocket != Q_NULLPTR && tcpSocket->isValid() && tcpSocket->isOpen())
{
tcpSocket->write(data.toLatin1());
}
else
{
qInfo(logCluster()) << "socket not open!";
}
}
void dxClusterClient::tcpCleanup()
{
2022-10-05 11:43:39 +00:00
#ifdef USESQL
database db = database();
db.query(QString("DELETE FROM spots where timestamp < datetime('now', '-%1 minutes')").arg(tcpTimeout));
2022-10-05 11:43:39 +00:00
#else
QMap<QString, spotData*>::iterator spot = allSpots.begin();;
while (spot != allSpots.end()) {
if (spot.value()->timestamp.addSecs(tcpTimeout * 60) < QDateTime::currentDateTimeUtc())
{
delete spot.value(); // Stop memory leak?
spot = allSpots.erase(spot);
}
else
{
++spot;
}
}
#endif
}
void dxClusterClient::tcpDisconnected() {
qWarning(logCluster()) << "TCP Cluster server disconnected...";
// Need to start a timer and attempt reconnect.
}
void dxClusterClient::freqRange(double low, double high)
{
lowFreq = low;
highFreq = high;
//qInfo(logCluster) << "New range" << low << "-" << high;
updateSpots();
}
void dxClusterClient::updateSpots()
{
2022-10-05 11:43:39 +00:00
QList<spotData> spots;
#ifdef USESQL
// Set the required frequency range.
2022-10-05 10:05:29 +00:00
QString queryText = QString("SELECT * FROM spots WHERE frequency > %1 AND frequency < %2").arg(lowFreq).arg(highFreq);
//QString queryText = QString("SELECT * FROM spots");
database db;
auto query = db.query(queryText);
while (query.next()) {
// Step through all current spots within range
spotData s = spotData();
s.dxcall = query.value(query.record().indexOf("dxcall")).toString();
s.frequency = query.value(query.record().indexOf("frequency")).toDouble();
spots.append(s);
}
2022-10-05 11:43:39 +00:00
#else
QMap<QString, spotData*>::iterator spot = allSpots.begin();;
while (spot != allSpots.end()) {
if (spot.value()->frequency > lowFreq && spot.value()->frequency < highFreq)
{
spots.append(**spot);
}
2022-10-05 13:26:42 +00:00
++spot;
2022-10-05 11:43:39 +00:00
}
#endif
emit sendSpots(spots);
}
void dxClusterClient::enableSkimmerSpots(bool enable)
{
skimmerSpots = enable;
if (authenticated) {
if (skimmerSpots) {
sendTcpData(QString("Set Dx Filter Skimmer\n"));
}
else
{
sendTcpData(QString("Set Dx Filter Not Skimmer\n"));
}
}
}