Refactor message buffering for relay

This commit is contained in:
Jordan Sherer 2018-07-25 22:49:19 -04:00
parent f67ea3803d
commit 9e9c996813
4 changed files with 85 additions and 59 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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){

View File

@ -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);