diff --git a/mainwindow.cpp b/mainwindow.cpp
index 85ee06a..1e16c4e 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -805,17 +805,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->labDialFreqOffset->setCursor(QCursor(Qt::PointingHandCursor));
auto ldmp = new MousePressEater();
connect(ldmp, &MousePressEater::mousePressed, this, [this](QObject *, QMouseEvent *, bool *pProcessed){
- bool ok = false;
- auto currentFreq = currentFreqOffset();
- QString newFreq = QInputDialog::getText(this, tr("Set Frequency Offset..."),
- tr("Offset in Hz:"), QLineEdit::Normal,
- QString("%1").arg(currentFreq), &ok).toUpper().trimmed();
- int offset = newFreq.toInt(&ok);
- if(!ok){
- return;
- }
-
- setFreqOffsetForRestore(offset, false);
+ on_actionSetOffset_triggered();
if(pProcessed) *pProcessed = true;
});
@@ -2526,6 +2516,20 @@ void MainWindow::on_menuWindow_aboutToShow(){
ui->actionShow_Band_Heartbeats_and_ACKs->setEnabled(ui->actionShow_Band_Activity->isChecked());
}
+void MainWindow::on_actionSetOffset_triggered(){
+ bool ok = false;
+ auto currentFreq = currentFreqOffset();
+ QString newFreq = QInputDialog::getText(this, tr("Set Frequency Offset..."),
+ tr("Offset in Hz:"), QLineEdit::Normal,
+ QString("%1").arg(currentFreq), &ok).toUpper().trimmed();
+ int offset = newFreq.toInt(&ok);
+ if(!ok){
+ return;
+ }
+
+ setFreqOffsetForRestore(offset, false);
+}
+
void MainWindow::on_actionShow_Fullscreen_triggered(bool checked){
auto state = windowState();
if(checked){
@@ -9875,7 +9879,7 @@ void MainWindow::processCommandActivity() {
}
// if we make it here, this is a message
- addCommandToInbox(d);
+ addCommandToMyInbox(d);
QTimer::singleShot(500, this, [this, d](){
MessageBox::information_message(this, QString("A new message was received at %1 UTC from %2").arg(d.utcTimestamp.time().toString()).arg(d.from));
@@ -9883,6 +9887,39 @@ void MainWindow::processCommandActivity() {
}
}
+ // PROCESS MESSAGE STORAGE
+ else if (d.cmd == " MSG TO:" && !isAllCall && !isGroupCall && !m_config.relay_off()){
+
+ // store message
+ QStringList segs = d.text.split(" ");
+ if(segs.isEmpty()){
+ continue;
+ }
+
+ auto to = segs.first();
+ auto text = d.text.mid(to.length()).trimmed();
+
+ CommandDetail cd = {};
+ cd.bits = d.bits;
+ cd.cmd = d.cmd;
+ cd.extra = d.extra;
+ cd.freq = d.freq;
+ cd.from = d.from;
+ cd.grid = d.grid;
+ cd.relayPath = d.relayPath;
+ cd.snr = d.snr;
+ cd.tdrift = d.tdrift;
+ cd.text = text;
+ cd.to = to;
+ cd.utcTimestamp = d.utcTimestamp;
+
+ qDebug() << "storing message to" << to << ":" << text;
+
+ addCommandToInboxStorage("STORE", cd);
+
+ reply = QString("%1 ACK").arg(d.from);
+ }
+
// PROCESS AGN
else if (d.cmd == " AGN?" && !isAllCall && !isGroupCall && !m_lastTxMessage.isEmpty()) {
reply = m_lastTxMessage;
@@ -9910,6 +9947,44 @@ void MainWindow::processCommandActivity() {
continue;
}
+ // PROCESS BUFFERED QUERY MSGS
+ else if (d.cmd == " QUERY MSGS" && ui->autoReplyButton->isChecked()){
+ auto who = d.from;
+#if 0
+ QString key;
+ if(d.text.isEmpty()){
+ key = who;
+ } else {
+ QStringList segs = d.text.trimmed().split(" ");
+ if(segs.isEmpty()){
+ continue;
+ }
+ key = segs.first();
+ }
+#endif
+
+ auto inbox = Inbox(inboxPath());
+ if(!inbox.open()){
+ continue;
+ }
+
+ auto v = inbox.values("STORE", "$.params.TO", who, 0, 10);
+ foreach(auto pair, v){
+ auto params = pair.second.params();
+ auto text = params.value("TEXT").toString().trimmed();
+ auto from = params.value("FROM").toString();
+ if(!text.isEmpty()){
+ // mark as delivered
+ pair.second.setType("DELIVERED");
+ inbox.set(pair.first, pair.second);
+
+ // and then reply with the text
+ reply = QString("%1>%2 DE %3").arg(who).arg(text).arg(from);
+ break;
+ }
+ }
+ }
+
// PROCESS BUFFERED QUERY CALL
else if (d.cmd == " QUERY CALL" && ui->autoReplyButton->isChecked()){
auto who = d.text;
@@ -10091,10 +10166,15 @@ void MainWindow::refreshInboxCounts(){
}
}
-void MainWindow::addCommandToInbox(CommandDetail d){
- // legacy
+void MainWindow::addCommandToMyInbox(CommandDetail d){
+ // local cache for inbox count
m_rxInboxCountCache[d.from] = m_rxInboxCountCache.value(d.from, 0) + 1;
+ // add it to my unread inbox
+ addCommandToInboxStorage("UNREAD", d);
+}
+
+void MainWindow::addCommandToInboxStorage(QString type, CommandDetail d){
// inbox:
auto inbox = Inbox(inboxPath());
if(inbox.open()){
@@ -10124,7 +10204,7 @@ void MainWindow::addCommandToInbox(CommandDetail d){
v["TEXT"] = QVariant(d.text);
}
- auto m = Message("UNREAD", "", v);
+ auto m = Message(type, "", v);
inbox.append(m);
}
}
diff --git a/mainwindow.h b/mainwindow.h
index 2a6a251..b381943 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -178,6 +178,7 @@ private slots:
void on_actionEnable_Spotting_toggled(bool checked);
void on_actionEnable_Auto_Reply_toggled(bool checked);
void on_menuWindow_aboutToShow();
+ void on_actionSetOffset_triggered();
void on_actionShow_Fullscreen_triggered(bool checked);
void on_actionShow_Statusbar_triggered(bool checked);
void on_actionShow_Frequency_Clock_triggered(bool checked);
@@ -951,7 +952,8 @@ private:
void processCommandActivity();
QString inboxPath();
void refreshInboxCounts();
- void addCommandToInbox(CommandDetail d);
+ void addCommandToMyInbox(CommandDetail d);
+ void addCommandToInboxStorage(QString type, CommandDetail d);
void processAlertReplyForCommand(CommandDetail d, QString from, QString cmd);
void processSpots();
void processTxQueue();
diff --git a/mainwindow.ui b/mainwindow.ui
index ee4525c..136ad88 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -4746,12 +4746,14 @@ list. The list can be maintained in Settings (F2).
C&ontrol
+
+
@@ -5636,6 +5638,11 @@ list. The list can be maintained in Settings (F2).
Set Frequency...
+
+
+ Set Offset...
+
+
diff --git a/varicode.cpp b/varicode.cpp
index 2a04176..07edb9f 100644
--- a/varicode.cpp
+++ b/varicode.cpp
@@ -69,10 +69,12 @@ QMap directed_cmds = {
{" HB", -1 }, // this is my heartbeat (unused except for faux processing of HBs as directed commands)
- // {" ", 10 }, // unused
- // {" ", 11 }, // unused
+ {" MSG TO:", 10 }, // store message at a station
+
+ {" QUERY", 11 }, // generic query
+
+ {" QUERY MSGS", 12 }, // do you have any stored messages?
- {" QUERY", 12 }, // issue a generic query
{" QUERY CALL", 13 }, // can you transmit a ping to callsign?
{" APRS:", 14 }, // send an aprs packet
@@ -99,13 +101,13 @@ QMap directed_cmds = {
};
// commands allowed to be processed
-QSet allowed_cmds = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /*10,*/ /*11,*/ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, /*24,*/ 25, 26, 27, 28, 29, 30, 31};
+QSet allowed_cmds = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, /*24,*/ 25, 26, 27, 28, 29, 30, 31};
// commands that result in an autoreply
-QSet autoreply_cmds = {0, 1, 2, 3, 4, 6, 12, 13, 30};
+QSet autoreply_cmds = {0, 1, 2, 3, 4, 6, 10, 12, 13, 30};
// commands that should be buffered
-QSet buffered_cmds = {3, 5, /*6,*/ /*7,*/ 12, 13, 14, 15};
+QSet buffered_cmds = {3, 5, /*6,*/ /*7,*/ 10, 11, 12, 13, 14, 15};
// commands that may include an SNR value
QSet snr_cmds = {25, 29};
@@ -113,6 +115,8 @@ QSet snr_cmds = {25, 29};
// commands that are checksummed and their crc size
QMap checksum_cmds = {
{ 5, 16 },
+ { 10, 16 },
+ { 11, 16 },
{ 12, 16 },
{ 13, 16 },
{ 14, 16 },
@@ -120,7 +124,7 @@ QMap checksum_cmds = {
};
QString callsign_pattern = QString("(?[@]?[A-Z0-9/]+)");
-QString optional_cmd_pattern = QString("(?\\s?(?:AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|SNR[?]|QTC[?]|QTH[?]|GRID[?]|STATUS[?]|HEARING[?]|(?:(?:STATUS|HEARING|QUERY CALL|QUERY|ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|QTC|GRID|TU)(?=[ ]|$))|[?> ]))?");
+QString optional_cmd_pattern = QString("(?\\s?(?:AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|MSG TO[:]|SNR[?]|QTC[?]|QTH[?]|GRID[?]|STATUS[?]|HEARING[?]|(?:(?:STATUS|HEARING|QUERY CALL|QUERY MSGS|QUERY|ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|QTC|GRID|TU)(?=[ ]|$))|[?> ]))?");
QString optional_grid_pattern = QString("(?\\s?[A-R]{2}[0-9]{2})?");
QString optional_extended_grid_pattern = QString("^(?\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?");
QString optional_num_pattern = QString("(?(?<=SNR|ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
@@ -199,6 +203,7 @@ quint16 nmaxgrid = (1<<15)-1;
QMap basecalls = {
{ "<....>", nbasecall + 1 }, // incomplete callsign
{ "@ALLCALL", nbasecall + 2 }, // ALLCALL group
+ { "@JS8NET", nbasecall + 3 }, // JS8NET group
};
QMap cqs = {