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 "moc_mainwindow.cpp"
#define TEST_ALL_OR_NOTHING 1 // 0
extern "C" {
//----------------------------------------------------- C and Fortran routines
@ -3247,39 +3246,9 @@ void MainWindow::readFromStdout() //readFromStdout
d.snr = decodedtext.snr();
m_bandActivity[offset].append(d);
#if TEST_ALL_OR_NOTHING
if(m_messageCache.contains(d.freq/10*10)){
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);
}
if(m_messageBuffer.contains(d.freq/10*10)){
m_messageBuffer[d.freq/10*10].msgs.append(d);
}
#endif
while(m_bandActivity[offset].count() > 10){
m_bandActivity[offset].removeFirst();
@ -3354,16 +3323,13 @@ void MainWindow::readFromStdout() //readFromStdout
d.freq = decodedtext.frequencyOffset();
d.snr = decodedtext.snr();
d.utcTimestamp = QDateTime::currentDateTimeUtc();
m_rxCommandQueue.append(d);
#if TEST_ALL_OR_NOTHING
// TODO: jsherer - process this elsewhere?
if(d.cmd == "|"){
// cache the message buffer commands
m_messageCache[d.freq/10*10].first = d;
m_messageCache[d.freq/10*10].second.clear();
if(Varicode::isCommandBuffered(d.cmd)){
m_messageBuffer[d.freq/10*10].cmd = d;
m_messageBuffer[d.freq/10*10].msgs.clear();
} else {
m_rxCommandQueue.append(d);
}
#endif
CallDetail cd;
cd.call = d.from;
@ -3416,7 +3382,7 @@ void MainWindow::readFromStdout() //readFromStdout
}
}
//Right (Rx Frequency) window
//Right (Rx Frequency) window
bool bDisplayRight=bAvgMsg;
int audioFreq=decodedtext.frequencyOffset();
@ -5667,7 +5633,8 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
QString stdFrame = parseFT8Message(line, &isFree);
int n = 0;
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &n);
QString dirCmd;
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &dirCmd, &n);
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)
@ -5724,15 +5691,10 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
lines.append(line.left(n) + " ");
line = line.mid(n);
#if TEST_ALL_OR_NOTHING
// 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...
if(!line.isEmpty()){
line = Varicode::checksum16(line) + line;
if(Varicode::isCommandBuffered(dirCmd) && !line.isEmpty()){
// TODO: jsherer - this is how we can add 16-bit checksum to the message, just encode it in the data...
line = Varicode::checksum16(line) + " " + line;
}
}
#endif
}
if(useDat){
@ -7254,7 +7216,17 @@ void MainWindow::buildQueryMenu(QMenu * menu){
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();
@ -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
if(m_txFrameQueue.isEmpty() && !m_rxCommandQueue.isEmpty()){
int f = currentFreq();
@ -8703,7 +8702,8 @@ void MainWindow::displayActivity(bool force){
}
// QUERIED STATIONS HEARD
else if(d.cmd == "$" && !isAllCall){
int i = 0;
int maxStations = 4;
auto calls = m_callActivity.keys();
qSort(calls.begin(), calls.end(), [this](QString const &a, QString const &b){
auto left = m_callActivity[a];
@ -8713,14 +8713,24 @@ void MainWindow::displayActivity(bool force){
QStringList lines;
foreach(auto call, calls){
if(i >= maxStations){
break;
}
if(Radio::base_callsign(call) == Radio::base_callsign(m_config.my_callsign())){
continue;
}
auto d = m_callActivity[call];
lines.append(QString("%1 SNR %2").arg(Radio::base_callsign(call)).arg(Varicode::formatSNR(d.snr)));
i++;
}
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()){
continue;

View File

@ -656,6 +656,7 @@ private:
int freq;
QDateTime utcTimestamp;
int snr;
QString text;
};
struct ActivityDetail
@ -670,6 +671,11 @@ private:
int snr;
};
struct MessageBuffer {
CommandDetail cmd;
QList<ActivityDetail> msgs;
};
bool m_rxDirty;
int m_txFrameCount;
QString m_lastTxMessage;
@ -686,7 +692,7 @@ private:
QCache<QString, int> m_rxCallCache; // call -> last freq seen
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
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)
QSet<QString> m_callSeenBeacon; // call
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> buffered_cmds = {6, 7};
QRegularExpression directed_re("^"
"(?<to>[A-Z0-9/]+)"
"(?<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]);
}
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 frame;
@ -751,7 +757,7 @@ QStringList Varicode::unpackCompoundMessage(const QString &text){
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;
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)
);
if(pCmd) *pCmd = cmd;
if(n) *n = match.captured(0).length();
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)));
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(Varicode::unpackCallsign(packed_to).trimmed());
unpacked.append(directed_cmds.key(packed_cmd % 32));
unpacked.append(to);
unpacked.append(cmd);
int num = (num_flag ? -1 : 1) * extra;
if(num != -31){

View File

@ -76,11 +76,12 @@ public:
static QString unpackGrid(quint16 value);
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 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 QString packDataMessage(QString const& text, int *n);