Refactor message buffering for relay
This commit is contained in:
parent
f67ea3803d
commit
9e9c996813
114
mainwindow.cpp
114
mainwindow.cpp
@ -62,7 +62,6 @@
|
|||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "moc_mainwindow.cpp"
|
#include "moc_mainwindow.cpp"
|
||||||
|
|
||||||
#define TEST_ALL_OR_NOTHING 1 // 0
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
//----------------------------------------------------- C and Fortran routines
|
//----------------------------------------------------- C and Fortran routines
|
||||||
@ -3247,39 +3246,9 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
d.snr = decodedtext.snr();
|
d.snr = decodedtext.snr();
|
||||||
m_bandActivity[offset].append(d);
|
m_bandActivity[offset].append(d);
|
||||||
|
|
||||||
#if TEST_ALL_OR_NOTHING
|
if(m_messageBuffer.contains(d.freq/10*10)){
|
||||||
if(m_messageCache.contains(d.freq/10*10)){
|
m_messageBuffer[d.freq/10*10].msgs.append(d);
|
||||||
m_messageCache[d.freq/10*10].second.append(d);
|
|
||||||
|
|
||||||
if(d.bits == Varicode::FT8CallLast){
|
|
||||||
auto c = m_messageCache[d.freq/10*10].first;
|
|
||||||
auto fs = m_messageCache[d.freq/10*10].second;
|
|
||||||
if(!fs.isEmpty()){
|
|
||||||
qDebug() << "MESSAGE COMPLETE:" << c.from << c.to;
|
|
||||||
QString message;
|
|
||||||
foreach(auto f, fs){
|
|
||||||
message.append(f.text);
|
|
||||||
}
|
}
|
||||||
QString checksum = message.left(3);
|
|
||||||
message = message.mid(3);
|
|
||||||
bool valid = Varicode::checksum16Valid(checksum, message);
|
|
||||||
qDebug() << "> CHECKSUM:" << checksum;
|
|
||||||
qDebug() << "> MESSAGE:" << message;
|
|
||||||
qDebug() << "> VALID:" << valid;
|
|
||||||
|
|
||||||
// TODO: jsherer - we should process this where all the other commands are processes...
|
|
||||||
if(valid){
|
|
||||||
addMessageText(QString("%1 ACK\n").arg(c.from), true);
|
|
||||||
addMessageText(message, false);
|
|
||||||
if(ui->autoReplyButton->isChecked()){
|
|
||||||
toggleTx(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_messageCache.remove(d.freq/10*10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while(m_bandActivity[offset].count() > 10){
|
while(m_bandActivity[offset].count() > 10){
|
||||||
m_bandActivity[offset].removeFirst();
|
m_bandActivity[offset].removeFirst();
|
||||||
@ -3354,16 +3323,13 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
d.freq = decodedtext.frequencyOffset();
|
d.freq = decodedtext.frequencyOffset();
|
||||||
d.snr = decodedtext.snr();
|
d.snr = decodedtext.snr();
|
||||||
d.utcTimestamp = QDateTime::currentDateTimeUtc();
|
d.utcTimestamp = QDateTime::currentDateTimeUtc();
|
||||||
m_rxCommandQueue.append(d);
|
|
||||||
|
|
||||||
#if TEST_ALL_OR_NOTHING
|
if(Varicode::isCommandBuffered(d.cmd)){
|
||||||
// TODO: jsherer - process this elsewhere?
|
m_messageBuffer[d.freq/10*10].cmd = d;
|
||||||
if(d.cmd == "|"){
|
m_messageBuffer[d.freq/10*10].msgs.clear();
|
||||||
// cache the message buffer commands
|
} else {
|
||||||
m_messageCache[d.freq/10*10].first = d;
|
m_rxCommandQueue.append(d);
|
||||||
m_messageCache[d.freq/10*10].second.clear();
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
CallDetail cd;
|
CallDetail cd;
|
||||||
cd.call = d.from;
|
cd.call = d.from;
|
||||||
@ -5667,7 +5633,8 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
|||||||
QString stdFrame = parseFT8Message(line, &isFree);
|
QString stdFrame = parseFT8Message(line, &isFree);
|
||||||
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &n);
|
QString dirCmd;
|
||||||
|
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &dirCmd, &n);
|
||||||
|
|
||||||
int m = 0;
|
int m = 0;
|
||||||
QString datFrame = Varicode::packDataMessage(line.left(21) + "\x04", &m); // 63 / 3 = 21 (maximum number of 3bit chars we could possibly stuff in here)
|
QString datFrame = Varicode::packDataMessage(line.left(21) + "\x04", &m); // 63 / 3 = 21 (maximum number of 3bit chars we could possibly stuff in here)
|
||||||
@ -5724,16 +5691,11 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
|||||||
lines.append(line.left(n) + " ");
|
lines.append(line.left(n) + " ");
|
||||||
line = line.mid(n);
|
line = line.mid(n);
|
||||||
|
|
||||||
#if TEST_ALL_OR_NOTHING
|
if(Varicode::isCommandBuffered(dirCmd) && !line.isEmpty()){
|
||||||
// TODO: jsherer - don't do this... refactor pack to return the packed frame _and_ its components instead
|
|
||||||
if(Varicode::unpackDirectedMessage(dirFrame).at(2) == "|"){
|
|
||||||
// TODO: jsherer - this is how we can add 16-bit checksum to the message, just encode it in the data...
|
// TODO: jsherer - this is how we can add 16-bit checksum to the message, just encode it in the data...
|
||||||
if(!line.isEmpty()){
|
line = Varicode::checksum16(line) + " " + line;
|
||||||
line = Varicode::checksum16(line) + line;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if(useDat){
|
if(useDat){
|
||||||
frames.append(frame);
|
frames.append(frame);
|
||||||
@ -7254,7 +7216,17 @@ void MainWindow::buildQueryMenu(QMenu * menu){
|
|||||||
toggleTx(true);
|
toggleTx(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
//menu->addAction("| - Please relay the following message")->setEnabled(false);
|
auto retransmitAction = menu->addAction("|message - Please ACK and retransmit the following message");
|
||||||
|
retransmitAction->setDisabled(isAllCall);
|
||||||
|
connect(retransmitAction, &QAction::triggered, this, [this](){
|
||||||
|
|
||||||
|
QString selectedCall = callsignSelected();
|
||||||
|
if(selectedCall.isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageText(QString("%1|").arg(selectedCall), true);
|
||||||
|
});
|
||||||
|
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
@ -8634,9 +8606,36 @@ void MainWindow::displayActivity(bool force){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Buffered Activity
|
||||||
|
foreach(auto freq, m_messageBuffer.keys()){
|
||||||
|
auto buffer = m_messageBuffer[freq];
|
||||||
|
|
||||||
|
if(buffer.msgs.isEmpty()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buffer.msgs.last().bits == Varicode::FT8Call){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString message;
|
||||||
|
foreach(auto part, buffer.msgs){
|
||||||
|
message.append(part.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString checksum = message.left(3);
|
||||||
|
message = message.mid(4);
|
||||||
|
|
||||||
|
if(Varicode::checksum16Valid(checksum, message)){
|
||||||
|
buffer.cmd.text = message;
|
||||||
|
m_rxCommandQueue.append(buffer.cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// regardless of valid or not, remove the "complete" buffered message from the buffer cache
|
||||||
|
m_messageBuffer.remove(freq);
|
||||||
|
}
|
||||||
|
|
||||||
// Command Activity
|
// Command Activity
|
||||||
|
|
||||||
if(m_txFrameQueue.isEmpty() && !m_rxCommandQueue.isEmpty()){
|
if(m_txFrameQueue.isEmpty() && !m_rxCommandQueue.isEmpty()){
|
||||||
int f = currentFreq();
|
int f = currentFreq();
|
||||||
|
|
||||||
@ -8703,7 +8702,8 @@ void MainWindow::displayActivity(bool force){
|
|||||||
}
|
}
|
||||||
// QUERIED STATIONS HEARD
|
// QUERIED STATIONS HEARD
|
||||||
else if(d.cmd == "$" && !isAllCall){
|
else if(d.cmd == "$" && !isAllCall){
|
||||||
|
int i = 0;
|
||||||
|
int maxStations = 4;
|
||||||
auto calls = m_callActivity.keys();
|
auto calls = m_callActivity.keys();
|
||||||
qSort(calls.begin(), calls.end(), [this](QString const &a, QString const &b){
|
qSort(calls.begin(), calls.end(), [this](QString const &a, QString const &b){
|
||||||
auto left = m_callActivity[a];
|
auto left = m_callActivity[a];
|
||||||
@ -8713,14 +8713,24 @@ void MainWindow::displayActivity(bool force){
|
|||||||
|
|
||||||
QStringList lines;
|
QStringList lines;
|
||||||
foreach(auto call, calls){
|
foreach(auto call, calls){
|
||||||
|
if(i >= maxStations){
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(Radio::base_callsign(call) == Radio::base_callsign(m_config.my_callsign())){
|
if(Radio::base_callsign(call) == Radio::base_callsign(m_config.my_callsign())){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto d = m_callActivity[call];
|
auto d = m_callActivity[call];
|
||||||
lines.append(QString("%1 SNR %2").arg(Radio::base_callsign(call)).arg(Varicode::formatSNR(d.snr)));
|
lines.append(QString("%1 SNR %2").arg(Radio::base_callsign(call)).arg(Varicode::formatSNR(d.snr)));
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
reply = lines.join('\n');
|
reply = lines.join('\n');
|
||||||
}
|
}
|
||||||
|
// PROCESS RETRANSMIT
|
||||||
|
else if(d.cmd == "|" && !isAllCall){
|
||||||
|
// TODO: jsherer - perhaps parse d.text and ensure it is a valid message?
|
||||||
|
reply = QString("%1 ACK\n%2").arg(d.from).arg(d.text);
|
||||||
|
}
|
||||||
|
|
||||||
if(reply.isEmpty()){
|
if(reply.isEmpty()){
|
||||||
continue;
|
continue;
|
||||||
|
@ -656,6 +656,7 @@ private:
|
|||||||
int freq;
|
int freq;
|
||||||
QDateTime utcTimestamp;
|
QDateTime utcTimestamp;
|
||||||
int snr;
|
int snr;
|
||||||
|
QString text;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActivityDetail
|
struct ActivityDetail
|
||||||
@ -670,6 +671,11 @@ private:
|
|||||||
int snr;
|
int snr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MessageBuffer {
|
||||||
|
CommandDetail cmd;
|
||||||
|
QList<ActivityDetail> msgs;
|
||||||
|
};
|
||||||
|
|
||||||
bool m_rxDirty;
|
bool m_rxDirty;
|
||||||
int m_txFrameCount;
|
int m_txFrameCount;
|
||||||
QString m_lastTxMessage;
|
QString m_lastTxMessage;
|
||||||
@ -686,7 +692,7 @@ private:
|
|||||||
QCache<QString, int> m_rxCallCache; // call -> last freq seen
|
QCache<QString, int> m_rxCallCache; // call -> last freq seen
|
||||||
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
|
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
|
||||||
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
|
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
|
||||||
QMap<int, QPair<CommandDetail, QList<ActivityDetail>>> m_messageCache; // freq -> (cmd, [frames, ...])
|
QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
|
||||||
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
|
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
|
||||||
QSet<QString> m_callSeenBeacon; // call
|
QSet<QString> m_callSeenBeacon; // call
|
||||||
int m_previousFreq;
|
int m_previousFreq;
|
||||||
|
15
varicode.cpp
15
varicode.cpp
@ -65,6 +65,8 @@ QMap<QString, int> directed_cmds = {
|
|||||||
|
|
||||||
QSet<int> allowed_cmds = {0, 1, 2, 3, 4, 5, 6, /*7,*/ 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
QSet<int> allowed_cmds = {0, 1, 2, 3, 4, 5, 6, /*7,*/ 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||||
|
|
||||||
|
QSet<int> buffered_cmds = {6, 7};
|
||||||
|
|
||||||
QRegularExpression directed_re("^"
|
QRegularExpression directed_re("^"
|
||||||
"(?<to>[A-Z0-9/]+)"
|
"(?<to>[A-Z0-9/]+)"
|
||||||
"(?<cmd>\\s?(?:AGN[?]|RR|73|YES|NO|SNR|PWR|ACK|[?@&$^%|! ]))"
|
"(?<cmd>\\s?(?:AGN[?]|RR|73|YES|NO|SNR|PWR|ACK|[?@&$^%|! ]))"
|
||||||
@ -679,6 +681,10 @@ bool Varicode::isCommandAllowed(const QString &cmd){
|
|||||||
return directed_cmds.contains(cmd) && allowed_cmds.contains(directed_cmds[cmd]);
|
return directed_cmds.contains(cmd) && allowed_cmds.contains(directed_cmds[cmd]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Varicode::isCommandBuffered(const QString &cmd){
|
||||||
|
return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]);
|
||||||
|
}
|
||||||
|
|
||||||
QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num){
|
QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num){
|
||||||
QString frame;
|
QString frame;
|
||||||
|
|
||||||
@ -751,7 +757,7 @@ QStringList Varicode::unpackCompoundMessage(const QString &text){
|
|||||||
return unpacked;
|
return unpacked;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Varicode::packDirectedMessage(const QString &text, const QString &baseCallsign, int *n){
|
QString Varicode::packDirectedMessage(const QString &text, const QString &baseCallsign, QString * pCmd, int *n){
|
||||||
QString frame;
|
QString frame;
|
||||||
|
|
||||||
auto match = directed_re.match(text);
|
auto match = directed_re.match(text);
|
||||||
@ -824,6 +830,7 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &baseCa
|
|||||||
Varicode::intToBits(packed_cmd % 32, 5)
|
Varicode::intToBits(packed_cmd % 32, 5)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if(pCmd) *pCmd = cmd;
|
||||||
if(n) *n = match.captured(0).length();
|
if(n) *n = match.captured(0).length();
|
||||||
return Varicode::pack64bits(Varicode::bitsToInt(bits)) + Varicode::pack5bits(packed_extra % 32);
|
return Varicode::pack64bits(Varicode::bitsToInt(bits)) + Varicode::pack5bits(packed_extra % 32);
|
||||||
}
|
}
|
||||||
@ -853,10 +860,12 @@ QStringList Varicode::unpackDirectedMessage(const QString &text){
|
|||||||
quint8 packed_cmd = Varicode::bitsToInt(Varicode::strToBits(bits.mid(59, 5)));
|
quint8 packed_cmd = Varicode::bitsToInt(Varicode::strToBits(bits.mid(59, 5)));
|
||||||
|
|
||||||
QString from = Varicode::unpackCallsign(packed_from).trimmed();
|
QString from = Varicode::unpackCallsign(packed_from).trimmed();
|
||||||
|
QString to = Varicode::unpackCallsign(packed_to).trimmed();
|
||||||
|
QString cmd = directed_cmds.key(packed_cmd % 32);
|
||||||
|
|
||||||
unpacked.append(from);
|
unpacked.append(from);
|
||||||
unpacked.append(Varicode::unpackCallsign(packed_to).trimmed());
|
unpacked.append(to);
|
||||||
unpacked.append(directed_cmds.key(packed_cmd % 32));
|
unpacked.append(cmd);
|
||||||
|
|
||||||
int num = (num_flag ? -1 : 1) * extra;
|
int num = (num_flag ? -1 : 1) * extra;
|
||||||
if(num != -31){
|
if(num != -31){
|
||||||
|
@ -76,11 +76,12 @@ public:
|
|||||||
static QString unpackGrid(quint16 value);
|
static QString unpackGrid(quint16 value);
|
||||||
|
|
||||||
static bool isCommandAllowed(const QString &cmd);
|
static bool isCommandAllowed(const QString &cmd);
|
||||||
|
static bool isCommandBuffered(const QString &cmd);
|
||||||
|
|
||||||
static QString packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num);
|
static QString packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num);
|
||||||
static QStringList unpackCompoundMessage(const QString &text);
|
static QStringList unpackCompoundMessage(const QString &text);
|
||||||
|
|
||||||
static QString packDirectedMessage(QString const& text, QString const& callsign, int *n);
|
static QString packDirectedMessage(QString const& text, QString const& callsign, QString * pCmd, int *n);
|
||||||
static QStringList unpackDirectedMessage(QString const& text);
|
static QStringList unpackDirectedMessage(QString const& text);
|
||||||
|
|
||||||
static QString packDataMessage(QString const& text, int *n);
|
static QString packDataMessage(QString const& text, int *n);
|
||||||
|
Loading…
Reference in New Issue
Block a user