Added message storage and retreival

This commit is contained in:
Jordan Sherer 2019-01-23 20:31:26 -05:00
parent a1f0a15d41
commit faf653d8ba
4 changed files with 117 additions and 23 deletions

View File

@ -805,17 +805,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->labDialFreqOffset->setCursor(QCursor(Qt::PointingHandCursor)); ui->labDialFreqOffset->setCursor(QCursor(Qt::PointingHandCursor));
auto ldmp = new MousePressEater(); auto ldmp = new MousePressEater();
connect(ldmp, &MousePressEater::mousePressed, this, [this](QObject *, QMouseEvent *, bool *pProcessed){ connect(ldmp, &MousePressEater::mousePressed, this, [this](QObject *, QMouseEvent *, bool *pProcessed){
bool ok = false; on_actionSetOffset_triggered();
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);
if(pProcessed) *pProcessed = true; 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()); 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){ void MainWindow::on_actionShow_Fullscreen_triggered(bool checked){
auto state = windowState(); auto state = windowState();
if(checked){ if(checked){
@ -9875,7 +9879,7 @@ void MainWindow::processCommandActivity() {
} }
// if we make it here, this is a message // if we make it here, this is a message
addCommandToInbox(d); addCommandToMyInbox(d);
QTimer::singleShot(500, this, [this, 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)); 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 // PROCESS AGN
else if (d.cmd == " AGN?" && !isAllCall && !isGroupCall && !m_lastTxMessage.isEmpty()) { else if (d.cmd == " AGN?" && !isAllCall && !isGroupCall && !m_lastTxMessage.isEmpty()) {
reply = m_lastTxMessage; reply = m_lastTxMessage;
@ -9910,6 +9947,44 @@ void MainWindow::processCommandActivity() {
continue; 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 // PROCESS BUFFERED QUERY CALL
else if (d.cmd == " QUERY CALL" && ui->autoReplyButton->isChecked()){ else if (d.cmd == " QUERY CALL" && ui->autoReplyButton->isChecked()){
auto who = d.text; auto who = d.text;
@ -10091,10 +10166,15 @@ void MainWindow::refreshInboxCounts(){
} }
} }
void MainWindow::addCommandToInbox(CommandDetail d){ void MainWindow::addCommandToMyInbox(CommandDetail d){
// legacy // local cache for inbox count
m_rxInboxCountCache[d.from] = m_rxInboxCountCache.value(d.from, 0) + 1; 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: // inbox:
auto inbox = Inbox(inboxPath()); auto inbox = Inbox(inboxPath());
if(inbox.open()){ if(inbox.open()){
@ -10124,7 +10204,7 @@ void MainWindow::addCommandToInbox(CommandDetail d){
v["TEXT"] = QVariant(d.text); v["TEXT"] = QVariant(d.text);
} }
auto m = Message("UNREAD", "", v); auto m = Message(type, "", v);
inbox.append(m); inbox.append(m);
} }
} }

View File

@ -178,6 +178,7 @@ private slots:
void on_actionEnable_Spotting_toggled(bool checked); void on_actionEnable_Spotting_toggled(bool checked);
void on_actionEnable_Auto_Reply_toggled(bool checked); void on_actionEnable_Auto_Reply_toggled(bool checked);
void on_menuWindow_aboutToShow(); void on_menuWindow_aboutToShow();
void on_actionSetOffset_triggered();
void on_actionShow_Fullscreen_triggered(bool checked); void on_actionShow_Fullscreen_triggered(bool checked);
void on_actionShow_Statusbar_triggered(bool checked); void on_actionShow_Statusbar_triggered(bool checked);
void on_actionShow_Frequency_Clock_triggered(bool checked); void on_actionShow_Frequency_Clock_triggered(bool checked);
@ -951,7 +952,8 @@ private:
void processCommandActivity(); void processCommandActivity();
QString inboxPath(); QString inboxPath();
void refreshInboxCounts(); 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 processAlertReplyForCommand(CommandDetail d, QString from, QString cmd);
void processSpots(); void processSpots();
void processTxQueue(); void processTxQueue();

View File

@ -4746,12 +4746,14 @@ list. The list can be maintained in Settings (F2).</string>
<string>C&amp;ontrol</string> <string>C&amp;ontrol</string>
</property> </property>
<addaction name="actionSetFrequency"/> <addaction name="actionSetFrequency"/>
<addaction name="actionSetOffset"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionEnable_Spotting"/> <addaction name="actionEnable_Spotting"/>
<addaction name="actionEnable_Auto_Reply"/> <addaction name="actionEnable_Auto_Reply"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionHeartbeat"/> <addaction name="actionHeartbeat"/>
<addaction name="actionCQ"/> <addaction name="actionCQ"/>
<addaction name="separator"/>
</widget> </widget>
<addaction name="menuFile"/> <addaction name="menuFile"/>
<addaction name="menuConfig"/> <addaction name="menuConfig"/>
@ -5636,6 +5638,11 @@ list. The list can be maintained in Settings (F2).</string>
<string>Set Frequency...</string> <string>Set Frequency...</string>
</property> </property>
</action> </action>
<action name="actionSetOffset">
<property name="text">
<string>Set Offset...</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

View File

@ -69,10 +69,12 @@ QMap<QString, int> directed_cmds = {
{" HB", -1 }, // this is my heartbeat (unused except for faux processing of HBs as directed commands) {" HB", -1 }, // this is my heartbeat (unused except for faux processing of HBs as directed commands)
// {" ", 10 }, // unused {" MSG TO:", 10 }, // store message at a station
// {" ", 11 }, // unused
{" 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? {" QUERY CALL", 13 }, // can you transmit a ping to callsign?
{" APRS:", 14 }, // send an aprs packet {" APRS:", 14 }, // send an aprs packet
@ -99,13 +101,13 @@ QMap<QString, int> directed_cmds = {
}; };
// commands allowed to be processed // commands allowed to be processed
QSet<int> 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<int> 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 // commands that result in an autoreply
QSet<int> autoreply_cmds = {0, 1, 2, 3, 4, 6, 12, 13, 30}; QSet<int> autoreply_cmds = {0, 1, 2, 3, 4, 6, 10, 12, 13, 30};
// commands that should be buffered // commands that should be buffered
QSet<int> buffered_cmds = {3, 5, /*6,*/ /*7,*/ 12, 13, 14, 15}; QSet<int> buffered_cmds = {3, 5, /*6,*/ /*7,*/ 10, 11, 12, 13, 14, 15};
// commands that may include an SNR value // commands that may include an SNR value
QSet<int> snr_cmds = {25, 29}; QSet<int> snr_cmds = {25, 29};
@ -113,6 +115,8 @@ QSet<int> snr_cmds = {25, 29};
// commands that are checksummed and their crc size // commands that are checksummed and their crc size
QMap<int, int> checksum_cmds = { QMap<int, int> checksum_cmds = {
{ 5, 16 }, { 5, 16 },
{ 10, 16 },
{ 11, 16 },
{ 12, 16 }, { 12, 16 },
{ 13, 16 }, { 13, 16 },
{ 14, 16 }, { 14, 16 },
@ -120,7 +124,7 @@ QMap<int, int> checksum_cmds = {
}; };
QString callsign_pattern = QString("(?<callsign>[@]?[A-Z0-9/]+)"); QString callsign_pattern = QString("(?<callsign>[@]?[A-Z0-9/]+)");
QString optional_cmd_pattern = QString("(?<cmd>\\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("(?<cmd>\\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("(?<grid>\\s?[A-R]{2}[0-9]{2})?"); QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?");
QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?"); QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?");
QString optional_num_pattern = QString("(?<num>(?<=SNR|ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?"); QString optional_num_pattern = QString("(?<num>(?<=SNR|ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
@ -199,6 +203,7 @@ quint16 nmaxgrid = (1<<15)-1;
QMap<QString, quint32> basecalls = { QMap<QString, quint32> basecalls = {
{ "<....>", nbasecall + 1 }, // incomplete callsign { "<....>", nbasecall + 1 }, // incomplete callsign
{ "@ALLCALL", nbasecall + 2 }, // ALLCALL group { "@ALLCALL", nbasecall + 2 }, // ALLCALL group
{ "@JS8NET", nbasecall + 3 }, // JS8NET group
}; };
QMap<quint32, QString> cqs = { QMap<quint32, QString> cqs = {