Added active/inactive flag and restructuring heartbeat
This commit is contained in:
parent
09cea086c7
commit
d9d3e6fba3
@ -140,7 +140,7 @@ bool DecodedText::tryUnpackHeartbeat(){
|
|||||||
cmp.append(parts.at(1));
|
cmp.append(parts.at(1));
|
||||||
}
|
}
|
||||||
compound_ = cmp.join("/");
|
compound_ = cmp.join("/");
|
||||||
message_ = QString("%1: %2 %3 ").arg(compound_).arg(isAlt ? Varicode::cqString(bits3) : "HEARTBEAT").arg(extra_);
|
message_ = QString("%1: %2 %3 ").arg(compound_).arg(isAlt ? Varicode::cqString(bits3) : Varicode::hbString(bits3)).arg(extra_);
|
||||||
frameType_ = type;
|
frameType_ = type;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
145
mainwindow.cpp
145
mainwindow.cpp
@ -1405,21 +1405,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
// Don't block heartbeat's first run...
|
// Don't block heartbeat's first run...
|
||||||
m_lastTxTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300);
|
m_lastTxTime = DriftingDateTime::currentDateTimeUtc().addSecs(-300);
|
||||||
|
|
||||||
|
|
||||||
auto heartbeatNow = new QAction(QString("Send Heartbeat Now"), ui->heartbeatButton);
|
|
||||||
connect(heartbeatNow, &QAction::triggered, this, [this](){
|
|
||||||
if(m_transmitting){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!ui->heartbeatButton->isChecked()){
|
|
||||||
ui->heartbeatButton->setChecked(true);
|
|
||||||
}
|
|
||||||
scheduleHeartbeat(true);
|
|
||||||
});
|
|
||||||
ui->heartbeatButton->setContextMenuPolicy(Qt::ActionsContextMenu);
|
|
||||||
ui->heartbeatButton->addAction(heartbeatNow);
|
|
||||||
|
|
||||||
|
|
||||||
int width = 75;
|
int width = 75;
|
||||||
/*
|
/*
|
||||||
QList<QPushButton*> btns;
|
QList<QPushButton*> btns;
|
||||||
@ -1564,12 +1549,6 @@ void MainWindow::initializeDummyData(){
|
|||||||
displayTextForFreq("HELLO BRAVE NEW WORLD \u2301 ", 42, DriftingDateTime::currentDateTimeUtc().addSecs(-300), false, true, true);
|
displayTextForFreq("HELLO BRAVE NEW WORLD \u2301 ", 42, DriftingDateTime::currentDateTimeUtc().addSecs(-300), false, true, true);
|
||||||
|
|
||||||
displayActivity(true);
|
displayActivity(true);
|
||||||
|
|
||||||
ui->heartbeatButton->click();
|
|
||||||
QTimer::singleShot(10000, this, [this](){
|
|
||||||
m_idleMinutes = 61;
|
|
||||||
scheduleHeartbeat(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::initialize_fonts ()
|
void MainWindow::initialize_fonts ()
|
||||||
@ -2361,8 +2340,8 @@ void rebuildMacQAction(QMenu *menu, QAction *existingAction){
|
|||||||
|
|
||||||
void MainWindow::on_menuControl_aboutToShow(){
|
void MainWindow::on_menuControl_aboutToShow(){
|
||||||
ui->actionEnable_Spotting->setChecked(ui->spotButton->isChecked());
|
ui->actionEnable_Spotting->setChecked(ui->spotButton->isChecked());
|
||||||
|
ui->actionEnable_Active->setChecked(ui->activeButton->isChecked());
|
||||||
ui->actionEnable_Auto_Reply->setChecked(ui->autoReplyButton->isChecked());
|
ui->actionEnable_Auto_Reply->setChecked(ui->autoReplyButton->isChecked());
|
||||||
ui->actionEnable_Heartbeat->setChecked(ui->heartbeatButton->isChecked());
|
|
||||||
ui->actionEnable_Selcall->setChecked(ui->selcalButton->isChecked());
|
ui->actionEnable_Selcall->setChecked(ui->selcalButton->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2374,8 +2353,8 @@ void MainWindow::on_actionEnable_Auto_Reply_toggled(bool checked){
|
|||||||
ui->autoReplyButton->setChecked(checked);
|
ui->autoReplyButton->setChecked(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionEnable_Heartbeat_toggled(bool checked){
|
void MainWindow::on_actionEnable_Active_toggled(bool checked){
|
||||||
ui->heartbeatButton->setChecked(checked);
|
ui->activeButton->setChecked(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionEnable_Selcall_toggled(bool checked){
|
void MainWindow::on_actionEnable_Selcall_toggled(bool checked){
|
||||||
@ -2715,6 +2694,27 @@ void MainWindow::on_spotButton_toggled(bool checked){
|
|||||||
resetPushButtonToggleText(ui->spotButton);
|
resetPushButtonToggleText(ui->spotButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_activeButton_toggled(bool checked){
|
||||||
|
#if 0
|
||||||
|
// clear the ping queue when you toggle the button
|
||||||
|
m_txHeartbeatQueue.clear();
|
||||||
|
displayBandActivity();
|
||||||
|
|
||||||
|
// then process the action
|
||||||
|
if(checked){
|
||||||
|
scheduleHeartbeat(false);
|
||||||
|
} else {
|
||||||
|
pauseHeartbeat();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// we call this so hb button disabled state is updated
|
||||||
|
updateButtonDisplay();
|
||||||
|
|
||||||
|
resetPushButtonToggleText(ui->activeButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void MainWindow::on_heartbeatButton_toggled(bool checked){
|
void MainWindow::on_heartbeatButton_toggled(bool checked){
|
||||||
// clear the ping queue when you toggle the button
|
// clear the ping queue when you toggle the button
|
||||||
m_txHeartbeatQueue.clear();
|
m_txHeartbeatQueue.clear();
|
||||||
@ -2729,6 +2729,7 @@ void MainWindow::on_heartbeatButton_toggled(bool checked){
|
|||||||
|
|
||||||
resetPushButtonToggleText(ui->heartbeatButton);
|
resetPushButtonToggleText(ui->heartbeatButton);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MainWindow::auto_tx_mode (bool state)
|
void MainWindow::auto_tx_mode (bool state)
|
||||||
{
|
{
|
||||||
@ -3852,7 +3853,7 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
// convert HEARTBEAT to a directed command and process...
|
// convert HEARTBEAT to a directed command and process...
|
||||||
cmd.from = cd.call;
|
cmd.from = cd.call;
|
||||||
cmd.to = "@ALLCALL";
|
cmd.to = "@ALLCALL";
|
||||||
cmd.cmd = " HEARTBEAT";
|
cmd.cmd = " ACTIVE";
|
||||||
cmd.snr = cd.snr;
|
cmd.snr = cd.snr;
|
||||||
cmd.bits = cd.bits;
|
cmd.bits = cd.bits;
|
||||||
cmd.grid = cd.grid;
|
cmd.grid = cd.grid;
|
||||||
@ -4569,7 +4570,7 @@ void MainWindow::guiUpdate()
|
|||||||
} else if(m_monitoring) {
|
} else if(m_monitoring) {
|
||||||
if (m_tx_watchdog) {
|
if (m_tx_watchdog) {
|
||||||
tx_status_label.setStyleSheet ("QLabel{background-color: #ff0000}");
|
tx_status_label.setStyleSheet ("QLabel{background-color: #ff0000}");
|
||||||
tx_status_label.setText ("Idle watchdog");
|
tx_status_label.setText ("Inactive watchdog");
|
||||||
} else {
|
} else {
|
||||||
tx_status_label.setStyleSheet("QLabel{background-color: #00ff00}");
|
tx_status_label.setStyleSheet("QLabel{background-color: #00ff00}");
|
||||||
QString t;
|
QString t;
|
||||||
@ -4594,24 +4595,22 @@ void MainWindow::guiUpdate()
|
|||||||
parts << t.date().toString("yyyy MMM dd");
|
parts << t.date().toString("yyyy MMM dd");
|
||||||
ui->labUTC->setText(parts.join("\n"));
|
ui->labUTC->setText(parts.join("\n"));
|
||||||
|
|
||||||
|
#if 0
|
||||||
auto delta = t.secsTo(m_nextHeartbeat);
|
auto delta = t.secsTo(m_nextHeartbeat);
|
||||||
QString ping;
|
QString ping;
|
||||||
if(ui->heartbeatButton->isChecked()){
|
|
||||||
if(heartbeatTimer.isActive()){
|
if(heartbeatTimer.isActive()){
|
||||||
if(delta > 0){
|
if(delta > 0){
|
||||||
ping = QString("%1 s").arg(delta);
|
ping = QString("%1 s").arg(delta);
|
||||||
} else {
|
} else {
|
||||||
ping = "queued!";
|
ping = "queued!";
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
ping = "on demand";
|
|
||||||
}
|
|
||||||
} else if (m_nextHeartPaused) {
|
} else if (m_nextHeartPaused) {
|
||||||
ping = "paused";
|
ping = "paused";
|
||||||
} else {
|
} else {
|
||||||
ping = "disabled";
|
ping = "on demand";
|
||||||
}
|
}
|
||||||
ui->labHeartbeat->setText(QString("Next Heartbeat: %1").arg(ping));
|
ui->labHeartbeat->setText(QString("Next Heartbeat: %1").arg(ping));
|
||||||
|
#endif
|
||||||
|
|
||||||
auto callLabel = m_config.my_callsign();
|
auto callLabel = m_config.my_callsign();
|
||||||
if(m_config.use_dynamic_grid() && !m_config.my_grid().isEmpty()){
|
if(m_config.use_dynamic_grid() && !m_config.my_grid().isEmpty()){
|
||||||
@ -5446,7 +5445,6 @@ void MainWindow::enqueueMessage(int priority, QString message, int freq, Callbac
|
|||||||
|
|
||||||
void MainWindow::enqueueHeartbeat(QString message){
|
void MainWindow::enqueueHeartbeat(QString message){
|
||||||
m_txHeartbeatQueue.enqueue(message);
|
m_txHeartbeatQueue.enqueue(message);
|
||||||
scheduleHeartbeat(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::resetMessage(){
|
void MainWindow::resetMessage(){
|
||||||
@ -5664,10 +5662,7 @@ bool MainWindow::prepareNextMessageFrame()
|
|||||||
|
|
||||||
updateTxButtonDisplay();
|
updateTxButtonDisplay();
|
||||||
|
|
||||||
if(ui->heartbeatButton->isChecked()){
|
// TODO: bump heartbeat
|
||||||
// bump ping
|
|
||||||
scheduleHeartbeat(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -5726,10 +5721,10 @@ int MainWindow::findFreeFreqOffset(int fmin, int fmax, int bw){
|
|||||||
return fmin;
|
return fmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
// schedulePing
|
// schedulePing
|
||||||
void MainWindow::scheduleHeartbeat(bool first){
|
void MainWindow::scheduleHeartbeat(bool first){
|
||||||
auto timestamp = DriftingDateTime::currentDateTimeUtc();
|
auto timestamp = DriftingDateTime::currentDateTimeUtc();
|
||||||
auto orig = timestamp;
|
|
||||||
|
|
||||||
// if we have the heartbeat interval disabled, return early, unless this is a "heartbeat now"
|
// if we have the heartbeat interval disabled, return early, unless this is a "heartbeat now"
|
||||||
if(!m_config.heartbeat() && !first){
|
if(!m_config.heartbeat() && !first){
|
||||||
@ -5765,7 +5760,6 @@ void MainWindow::scheduleHeartbeat(bool first){
|
|||||||
|
|
||||||
// pausePing
|
// pausePing
|
||||||
void MainWindow::pauseHeartbeat(){
|
void MainWindow::pauseHeartbeat(){
|
||||||
ui->heartbeatButton->setChecked(false);
|
|
||||||
m_nextHeartPaused = true;
|
m_nextHeartPaused = true;
|
||||||
|
|
||||||
if(heartbeatTimer.isActive()){
|
if(heartbeatTimer.isActive()){
|
||||||
@ -5775,13 +5769,12 @@ void MainWindow::pauseHeartbeat(){
|
|||||||
|
|
||||||
// unpausePing
|
// unpausePing
|
||||||
void MainWindow::unpauseHeartbeat(){
|
void MainWindow::unpauseHeartbeat(){
|
||||||
ui->heartbeatButton->setChecked(true);
|
|
||||||
scheduleHeartbeat(false);
|
scheduleHeartbeat(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkPing
|
// checkPing
|
||||||
void MainWindow::checkHeartbeat(){
|
void MainWindow::checkHeartbeat(){
|
||||||
if(!ui->heartbeatButton->isChecked()){
|
if(m_config.heartbeat() <= 0){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto secondsUntilHeartbeat = DriftingDateTime::currentDateTimeUtc().secsTo(m_nextHeartbeat);
|
auto secondsUntilHeartbeat = DriftingDateTime::currentDateTimeUtc().secsTo(m_nextHeartbeat);
|
||||||
@ -5835,8 +5828,11 @@ void MainWindow::prepareHeartbeat(){
|
|||||||
|
|
||||||
m_nextHeartbeatQueued = true;
|
m_nextHeartbeatQueued = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void MainWindow::checkHeartbeat(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
QString MainWindow::calculateDistance(QString const& value, int *pDistance, int *pAzimuth)
|
QString MainWindow::calculateDistance(QString const& value, int *pDistance, int *pAzimuth)
|
||||||
{
|
{
|
||||||
@ -6496,6 +6492,16 @@ void MainWindow::on_clearAction_triggered(QObject * sender){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_hbMacroButton_clicked(){
|
||||||
|
QString mycall = m_config.my_callsign();
|
||||||
|
QString mygrid = m_config.my_grid().left(4);
|
||||||
|
QString message = QString("%1: ACTIVE %2").arg(mycall).arg(mygrid).trimmed();
|
||||||
|
|
||||||
|
addMessageText(message);
|
||||||
|
|
||||||
|
if(m_config.transmit_directed()) toggleTx(true);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_cqMacroButton_clicked(){
|
void MainWindow::on_cqMacroButton_clicked(){
|
||||||
auto message = m_config.cq_message();
|
auto message = m_config.cq_message();
|
||||||
if(message.isEmpty()){
|
if(message.isEmpty()){
|
||||||
@ -6911,7 +6917,7 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){
|
|||||||
addMessageText(QString("%1>[MESSAGE]").arg(selectedCall), true, true);
|
addMessageText(QString("%1>[MESSAGE]").arg(selectedCall), true, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto qsoQueryAction = menu->addAction(QString("%1 HEARTBEAT REQ [CALLSIGN]? - Please acknowledge you can communicate directly with [CALLSIGN]").arg(call).trimmed());
|
auto qsoQueryAction = menu->addAction(QString("%1 QUERY [CALLSIGN]? - Please acknowledge you can communicate directly with [CALLSIGN]").arg(call).trimmed());
|
||||||
connect(qsoQueryAction, &QAction::triggered, this, [this](){
|
connect(qsoQueryAction, &QAction::triggered, this, [this](){
|
||||||
|
|
||||||
QString selectedCall = callsignSelected();
|
QString selectedCall = callsignSelected();
|
||||||
@ -6919,7 +6925,7 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
addMessageText(QString("%1 HEARTBEAT REQ [CALLSIGN]?").arg(selectedCall), true, true);
|
addMessageText(QString("%1 QUERY [CALLSIGN]?").arg(selectedCall), true, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
@ -7135,6 +7141,7 @@ QMap<QString, QString> MainWindow::buildMacroValues(){
|
|||||||
{"<MYQTH>", m_config.my_qth()},
|
{"<MYQTH>", m_config.my_qth()},
|
||||||
{"<MYCQ>", m_config.cq_message()},
|
{"<MYCQ>", m_config.cq_message()},
|
||||||
{"<MYREPLY>", m_config.reply_message()},
|
{"<MYREPLY>", m_config.reply_message()},
|
||||||
|
{"<MYSTATUS>", (ui->activeButton->isChecked() ? "ACTIVE" : "INACTIVE")},
|
||||||
};
|
};
|
||||||
|
|
||||||
auto selectedCall = callsignSelected();
|
auto selectedCall = callsignSelected();
|
||||||
@ -8260,7 +8267,9 @@ void MainWindow::updateButtonDisplay(){
|
|||||||
|
|
||||||
auto selectedCallsign = callsignSelected(true);
|
auto selectedCallsign = callsignSelected(true);
|
||||||
bool emptyCallsign = selectedCallsign.isEmpty();
|
bool emptyCallsign = selectedCallsign.isEmpty();
|
||||||
|
bool isActive = ui->activeButton->isChecked();
|
||||||
|
|
||||||
|
ui->hbMacroButton->setDisabled(isTransmitting || !isActive);
|
||||||
ui->cqMacroButton->setDisabled(isTransmitting);
|
ui->cqMacroButton->setDisabled(isTransmitting);
|
||||||
ui->replyMacroButton->setDisabled(isTransmitting || emptyCallsign);
|
ui->replyMacroButton->setDisabled(isTransmitting || emptyCallsign);
|
||||||
ui->snrMacroButton->setDisabled(isTransmitting || emptyCallsign);
|
ui->snrMacroButton->setDisabled(isTransmitting || emptyCallsign);
|
||||||
@ -8603,7 +8612,7 @@ void MainWindow::processRxActivity() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d.isDirected && d.text.contains(": HEARTBEAT")){
|
if(d.isDirected && d.text.contains(": ACTIVE")){ // TODO: HEARTBEAT
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8885,7 +8894,7 @@ void MainWindow::processCommandActivity() {
|
|||||||
cd.snr = d.snr;
|
cd.snr = d.snr;
|
||||||
cd.freq = d.freq;
|
cd.freq = d.freq;
|
||||||
cd.bits = d.bits;
|
cd.bits = d.bits;
|
||||||
cd.ackTimestamp = d.text.contains("HEARTBEAT ACK") || toMe ? d.utcTimestamp : QDateTime{};
|
cd.ackTimestamp = d.text.contains(": ACK") || toMe ? d.utcTimestamp : QDateTime{};
|
||||||
cd.utcTimestamp = d.utcTimestamp;
|
cd.utcTimestamp = d.utcTimestamp;
|
||||||
cd.tdrift = d.tdrift;
|
cd.tdrift = d.tdrift;
|
||||||
logCallActivity(cd, true);
|
logCallActivity(cd, true);
|
||||||
@ -8927,7 +8936,7 @@ void MainWindow::processCommandActivity() {
|
|||||||
bool shouldDisplay = true;
|
bool shouldDisplay = true;
|
||||||
|
|
||||||
// don't display ping allcalls
|
// don't display ping allcalls
|
||||||
if(isAllCall && (d.cmd != " " || ad.text.contains(": HEARTBEAT"))){ // || d.cmd == " HEARTBEAT")){
|
if(isAllCall && (d.cmd != " " || ad.text.contains(": ACTIVE"))){ // || d.cmd == " HEARTBEAT")){
|
||||||
shouldDisplay = false;
|
shouldDisplay = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8938,7 +8947,7 @@ void MainWindow::processCommandActivity() {
|
|||||||
|
|
||||||
// ACKs are the most likely source of items to be overwritten (multiple responses at once)...
|
// ACKs are the most likely source of items to be overwritten (multiple responses at once)...
|
||||||
// so don't overwrite those (i.e., print each on a new line)
|
// so don't overwrite those (i.e., print each on a new line)
|
||||||
bool shouldOverwrite = (!d.cmd.contains("HEARTBEAT ACK")); /* && isRecentOffset(d.freq);*/
|
bool shouldOverwrite = (!d.cmd.contains(" ACK")); /* && isRecentOffset(d.freq);*/
|
||||||
|
|
||||||
if(shouldOverwrite && ui->textEditRX->find(d.utcTimestamp.time().toString(), QTextDocument::FindBackward)){
|
if(shouldOverwrite && ui->textEditRX->find(d.utcTimestamp.time().toString(), QTextDocument::FindBackward)){
|
||||||
// ... maybe we could delete the last line that had this message on this frequency...
|
// ... maybe we could delete the last line that had this message on this frequency...
|
||||||
@ -9006,10 +9015,10 @@ void MainWindow::processCommandActivity() {
|
|||||||
|
|
||||||
// QUERIED ACTIVE
|
// QUERIED ACTIVE
|
||||||
else if (d.cmd == " STATUS?" && !isAllCall) {
|
else if (d.cmd == " STATUS?" && !isAllCall) {
|
||||||
if(m_idleMinutes < 10){
|
if(ui->activeButton->isChecked()){
|
||||||
reply = QString("%1 ACTIVE").arg(d.from);
|
reply = QString("%1 ACTIVE").arg(d.from);
|
||||||
} else {
|
} else {
|
||||||
reply = QString("%1 IDLE").arg(d.from);
|
reply = QString("%1 INACTIVE").arg(d.from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9142,22 +9151,18 @@ void MainWindow::processCommandActivity() {
|
|||||||
reply = m_lastTxMessage;
|
reply = m_lastTxMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PROCESS HEARTBEAT
|
// PROCESS ACTIVE HEARTBEAT
|
||||||
else if (d.cmd == " HEARTBEAT" && ui->heartbeatButton->isChecked() && ui->autoReplyButton->isChecked() && !ui->selcalButton->isChecked()){
|
else if (d.cmd == " ACTIVE" && ui->autoReplyButton->isChecked() && !ui->selcalButton->isChecked()){
|
||||||
reply = QString("%1 HEARTBEAT ACK %2").arg(d.from).arg(Varicode::formatSNR(d.snr));
|
reply = QString("%1 ACK %2").arg(d.from).arg(Varicode::formatSNR(d.snr));
|
||||||
|
|
||||||
enqueueHeartbeat(reply);
|
|
||||||
|
|
||||||
if(isAllCall){
|
if(isAllCall){
|
||||||
// since all pings are technically @ALLCALL, let's bump the allcall cache here...
|
// since all pings are technically @ALLCALL, let's bump the allcall cache here...
|
||||||
m_txAllcallCommandCache.insert(d.from, new QDateTime(now), 5);
|
m_txAllcallCommandCache.insert(d.from, new QDateTime(now), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PROCESS BUFFERED HEARTBEAT REQ QUERY
|
// PROCESS BUFFERED QUERY
|
||||||
else if (d.cmd == " HEARTBEAT REQ" && ui->heartbeatButton->isChecked()){
|
else if (d.cmd == " QUERY" && ui->autoReplyButton->isChecked() && !ui->selcalButton->isChecked()){
|
||||||
auto who = d.text;
|
auto who = d.text;
|
||||||
if(who.isEmpty()){
|
if(who.isEmpty()){
|
||||||
continue;
|
continue;
|
||||||
@ -9184,15 +9189,11 @@ void MainWindow::processCommandActivity() {
|
|||||||
reply = replies.join("\n");
|
reply = replies.join("\n");
|
||||||
|
|
||||||
if(!reply.isEmpty()){
|
if(!reply.isEmpty()){
|
||||||
enqueueHeartbeat(reply);
|
|
||||||
|
|
||||||
if(isAllCall){
|
if(isAllCall){
|
||||||
// since all pings are technically @ALLCALL, let's bump the allcall cache here...
|
// since all pings are technically @ALLCALL, let's bump the allcall cache here...
|
||||||
m_txAllcallCommandCache.insert(d.from, new QDateTime(now), 25);
|
m_txAllcallCommandCache.insert(d.from, new QDateTime(now), 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PROCESS BUFFERED APRS:
|
// PROCESS BUFFERED APRS:
|
||||||
@ -9246,7 +9247,7 @@ void MainWindow::processCommandActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do not queue @ALLCALL replies if auto-reply is not checked or it's a ping reply
|
// do not queue @ALLCALL replies if auto-reply is not checked or it's a ping reply
|
||||||
if(!ui->autoReplyButton->isChecked() && isAllCall && !d.cmd.contains("HEARTBEAT")){
|
if(!ui->autoReplyButton->isChecked() && isAllCall && !d.cmd.contains("ACTIVE")){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9428,8 +9429,7 @@ void MainWindow::processTxQueue(){
|
|||||||
|
|
||||||
// check to see if this is a high priority message, or if we have autoreply enabled, or if this is a ping and the ping button is enabled
|
// check to see if this is a high priority message, or if we have autoreply enabled, or if this is a ping and the ping button is enabled
|
||||||
if(message.priority >= PriorityHigh ||
|
if(message.priority >= PriorityHigh ||
|
||||||
(ui->autoReplyButton->isChecked()) ||
|
(ui->autoReplyButton->isChecked())
|
||||||
(ui->heartbeatButton->isChecked() && message.message.contains("HEARTBEAT"))
|
|
||||||
){
|
){
|
||||||
// then try to set the frequency...
|
// then try to set the frequency...
|
||||||
setFreqOffsetForRestore(f, true);
|
setFreqOffsetForRestore(f, true);
|
||||||
@ -9470,7 +9470,9 @@ void MainWindow::displayBandActivity() {
|
|||||||
selectedOffset = selectedItems.first()->text().toInt();
|
selectedOffset = selectedItems.first()->text().toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pingEnabled = ui->heartbeatButton->isChecked();
|
#if 0
|
||||||
|
bool pingEnabled = m_config.heartbeat() > 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
ui->tableWidgetRXAll->setUpdatesEnabled(false);
|
ui->tableWidgetRXAll->setUpdatesEnabled(false);
|
||||||
{
|
{
|
||||||
@ -9562,10 +9564,12 @@ void MainWindow::displayBandActivity() {
|
|||||||
if (!isOffsetSelected && activityAging && item.utcTimestamp.secsTo(now) / 60 >= activityAging) {
|
if (!isOffsetSelected && activityAging && item.utcTimestamp.secsTo(now) / 60 >= activityAging) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
if (!pingEnabled && (item.text.contains(": HEARTBEAT") || item.text.contains("HEARTBEAT ACK"))){
|
if (!pingEnabled && (item.text.contains(": HEARTBEAT") || item.text.contains("HEARTBEAT ACK"))){
|
||||||
// hide pings if we're not pinging.
|
// hide pings if we're not pinging.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (item.text.isEmpty()) {
|
if (item.text.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -9933,7 +9937,7 @@ void MainWindow::networkMessage(Message const &message)
|
|||||||
|
|
||||||
auto type = message.type();
|
auto type = message.type();
|
||||||
|
|
||||||
if(type == "HEARTBEAT"){
|
if(type == "PING"){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10611,11 +10615,12 @@ void MainWindow::tx_watchdog (bool triggered)
|
|||||||
if (m_auto) auto_tx_mode (false);
|
if (m_auto) auto_tx_mode (false);
|
||||||
stopTx();
|
stopTx();
|
||||||
tx_status_label.setStyleSheet ("QLabel{background-color: #ff0000}");
|
tx_status_label.setStyleSheet ("QLabel{background-color: #ff0000}");
|
||||||
tx_status_label.setText ("Idle watchdog");
|
tx_status_label.setText ("Inactive watchdog");
|
||||||
|
|
||||||
pauseHeartbeat();
|
// if the watchdog is triggered...we're no longer active
|
||||||
MessageBox::warning_message(this, QString("Attempting to transmit heartbeat, but you have been idle for more than %1 minutes.").arg(m_config.watchdog()));
|
ui->activeButton->setChecked(false);
|
||||||
unpauseHeartbeat();
|
|
||||||
|
MessageBox::warning_message(this, QString("Attempting to transmit, but you have been inactive for more than %1 minutes.").arg(m_config.watchdog()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -173,8 +173,8 @@ private slots:
|
|||||||
void on_tx6_editingFinished();
|
void on_tx6_editingFinished();
|
||||||
void on_menuControl_aboutToShow();
|
void on_menuControl_aboutToShow();
|
||||||
void on_actionEnable_Spotting_toggled(bool checked);
|
void on_actionEnable_Spotting_toggled(bool checked);
|
||||||
|
void on_actionEnable_Active_toggled(bool checked);
|
||||||
void on_actionEnable_Auto_Reply_toggled(bool checked);
|
void on_actionEnable_Auto_Reply_toggled(bool checked);
|
||||||
void on_actionEnable_Heartbeat_toggled(bool checked);
|
|
||||||
void on_actionEnable_Selcall_toggled(bool checked);
|
void on_actionEnable_Selcall_toggled(bool checked);
|
||||||
void on_menuWindow_aboutToShow();
|
void on_menuWindow_aboutToShow();
|
||||||
void on_actionShow_Fullscreen_triggered(bool checked);
|
void on_actionShow_Fullscreen_triggered(bool checked);
|
||||||
@ -274,6 +274,7 @@ private slots:
|
|||||||
void on_rbGenMsg_clicked(bool checked);
|
void on_rbGenMsg_clicked(bool checked);
|
||||||
void on_rbFreeText_clicked(bool checked);
|
void on_rbFreeText_clicked(bool checked);
|
||||||
void on_clearAction_triggered(QObject * sender);
|
void on_clearAction_triggered(QObject * sender);
|
||||||
|
void on_hbMacroButton_clicked();
|
||||||
void on_cqMacroButton_clicked();
|
void on_cqMacroButton_clicked();
|
||||||
void on_replyMacroButton_clicked();
|
void on_replyMacroButton_clicked();
|
||||||
void on_snrMacroButton_clicked();
|
void on_snrMacroButton_clicked();
|
||||||
@ -311,11 +312,7 @@ private slots:
|
|||||||
bool prepareNextMessageFrame();
|
bool prepareNextMessageFrame();
|
||||||
bool isFreqOffsetFree(int f, int bw);
|
bool isFreqOffsetFree(int f, int bw);
|
||||||
int findFreeFreqOffset(int fmin, int fmax, int bw);
|
int findFreeFreqOffset(int fmin, int fmax, int bw);
|
||||||
void scheduleHeartbeat(bool first=false);
|
|
||||||
void pauseHeartbeat();
|
|
||||||
void unpauseHeartbeat();
|
|
||||||
void checkHeartbeat();
|
void checkHeartbeat();
|
||||||
void prepareHeartbeat();
|
|
||||||
QString calculateDistance(QString const& grid, int *pDistance=nullptr, int *pAzimuth=nullptr);
|
QString calculateDistance(QString const& grid, int *pDistance=nullptr, int *pAzimuth=nullptr);
|
||||||
void on_driftSpinBox_valueChanged(int n);
|
void on_driftSpinBox_valueChanged(int n);
|
||||||
void on_driftSyncButton_clicked();
|
void on_driftSyncButton_clicked();
|
||||||
@ -355,7 +352,7 @@ private slots:
|
|||||||
void on_selcalButton_toggled(bool checked);
|
void on_selcalButton_toggled(bool checked);
|
||||||
void on_tuneButton_toggled(bool checked);
|
void on_tuneButton_toggled(bool checked);
|
||||||
void on_spotButton_toggled(bool checked);
|
void on_spotButton_toggled(bool checked);
|
||||||
void on_heartbeatButton_toggled(bool checked);
|
void on_activeButton_toggled(bool checked);
|
||||||
|
|
||||||
void on_actionMessage_averaging_triggered();
|
void on_actionMessage_averaging_triggered();
|
||||||
void on_actionFox_Log_triggered();
|
void on_actionFox_Log_triggered();
|
||||||
|
462
mainwindow.ui
462
mainwindow.ui
@ -359,7 +359,7 @@ QPushButton[oob="true"] {
|
|||||||
</string>
|
</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string/>
|
<string>Callsign</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
@ -411,29 +411,6 @@ color : white;
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="labHeartbeat">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">QLabel {
|
|
||||||
font-family: MS Shell Dlg 2;
|
|
||||||
font-size: 11pt;
|
|
||||||
color : white;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Next Heartbeat: disabled</string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::RichText</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignCenter</set>
|
|
||||||
</property>
|
|
||||||
<property name="margin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@ -499,7 +476,7 @@ QPushButton:checked {
|
|||||||
<property name="frameShadow">
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Plain</enum>
|
<enum>QFrame::Plain</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout_8" columnstretch="1,1,1,1,0" columnminimumwidth="75,75,75,75,0">
|
<layout class="QGridLayout" name="gridLayout_8" columnstretch="1,1,1,1" columnminimumwidth="75,75,75,75">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -573,43 +550,6 @@ QPushButton:checked {
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QPushButton" name="activeButton">
|
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="visible">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Enable or disable automatic station replies to directed queries</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>ACTIVE</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QPushButton" name="monitorButton">
|
<widget class="QPushButton" name="monitorButton">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
@ -776,7 +716,7 @@ QPushButton:checked {
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QPushButton" name="heartbeatButton">
|
<widget class="QPushButton" name="activeButton">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
@ -804,7 +744,7 @@ QPushButton:checked {
|
|||||||
</font>
|
</font>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Enable or disable the automatic heartbeat transmission</p></body></html></string>
|
<string><html><head/><body><p>Register your station as active or idle</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
<string notr="true">QPushButton {
|
<string notr="true">QPushButton {
|
||||||
@ -820,7 +760,7 @@ QPushButton:checked {
|
|||||||
}</string>
|
}</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>HB</string>
|
<string>ACTIVE</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@ -1361,192 +1301,7 @@ QTextEdit[transmitting="true"] {
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="11">
|
|
||||||
<widget class="QPushButton" name="queryButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send a directed message to another station</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Directed</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="16">
|
<item row="1" column="16">
|
||||||
<widget class="QPushButton" name="stopTxButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>75</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Stop transmitting</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Halt</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="14">
|
|
||||||
<spacer name="horizontalSpacer_5">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Preferred</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>10</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="5">
|
|
||||||
<widget class="QPushButton" name="qtcMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send your station message</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>QTC</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
|
||||||
<widget class="QPushButton" name="snrMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send an SNR message</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>SNR</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="7">
|
|
||||||
<spacer name="horizontalSpacer_8">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Preferred</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>10</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<widget class="QPushButton" name="replyMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Reply to a CQ</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Reply</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="6">
|
|
||||||
<widget class="QPushButton" name="macrosMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send a saved message</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Saved</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="12">
|
|
||||||
<widget class="QPushButton" name="deselectButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Deselect the current callsign for directed messaging</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Deselect</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="4">
|
|
||||||
<widget class="QPushButton" name="qthMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send your station location message</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>QTH</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QPushButton" name="cqMacroButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p>Send a CQ message</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>CQ</string>
|
|
||||||
</property>
|
|
||||||
<property name="flat">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="15">
|
|
||||||
<widget class="QPushButton" name="startTxButton">
|
<widget class="QPushButton" name="startTxButton">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@ -1578,6 +1333,207 @@ color:#555;
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="17">
|
||||||
|
<widget class="QPushButton" name="stopTxButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>75</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Stop transmitting</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Halt</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="15">
|
||||||
|
<spacer name="horizontalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="5">
|
||||||
|
<widget class="QPushButton" name="qthMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send your station location message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>QTH</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="13">
|
||||||
|
<widget class="QPushButton" name="deselectButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Deselect the current callsign for directed messaging</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Deselect</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QPushButton" name="snrMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send an SNR message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>SNR</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="8">
|
||||||
|
<spacer name="horizontalSpacer_8">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QPushButton" name="replyMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Reply to a CQ</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Reply</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QPushButton" name="cqMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send a CQ message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>CQ</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="6">
|
||||||
|
<widget class="QPushButton" name="qtcMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send your station message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>QTC</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="7">
|
||||||
|
<widget class="QPushButton" name="macrosMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send a saved message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Saved</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="12">
|
||||||
|
<widget class="QPushButton" name="queryButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Send a directed message to another station</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Directed</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QPushButton" name="hbMacroButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p align="justify">Send a Heartbeat message</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>HB</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QFrame" name="frame_5">
|
<widget class="QFrame" name="frame_5">
|
||||||
@ -4757,7 +4713,7 @@ list. The list can be maintained in Settings (F2).</string>
|
|||||||
<string>C&ontrol</string>
|
<string>C&ontrol</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionEnable_Spotting"/>
|
<addaction name="actionEnable_Spotting"/>
|
||||||
<addaction name="actionEnable_Heartbeat"/>
|
<addaction name="actionEnable_Active"/>
|
||||||
<addaction name="actionEnable_Auto_Reply"/>
|
<addaction name="actionEnable_Auto_Reply"/>
|
||||||
<addaction name="actionEnable_Selcall"/>
|
<addaction name="actionEnable_Selcall"/>
|
||||||
</widget>
|
</widget>
|
||||||
@ -5578,12 +5534,12 @@ list. The list can be maintained in Settings (F2).</string>
|
|||||||
<string>Enable Spotting</string>
|
<string>Enable Spotting</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionEnable_Heartbeat">
|
<action name="actionEnable_Active">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable Heartbeat</string>
|
<string>Enable Active</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionEnable_Auto_Reply">
|
<action name="actionEnable_Auto_Reply">
|
||||||
|
56
varicode.cpp
56
varicode.cpp
@ -71,11 +71,12 @@ QMap<QString, int> directed_cmds = {
|
|||||||
{" TU", 9 }, // thank you
|
{" TU", 9 }, // thank you
|
||||||
|
|
||||||
{" ACTIVE", 10 }, // i have been active in the past 10 minutes
|
{" ACTIVE", 10 }, // i have been active in the past 10 minutes
|
||||||
{" IDLE", 11 }, // i have not been active in the past 10 minutes
|
{" INACTIVE", 11 }, // i have not been active in the past 10 minutes
|
||||||
|
|
||||||
{" HEARTBEAT", -1 }, // this is my ping (unused except for faux processing of pings as directed commands)
|
//{" HEARTBEAT", -1 }, // this is my ping (unused except for faux processing of pings as directed commands)
|
||||||
{" HEARTBEAT ACK", 12 }, // i acknowledge your ping at this SNR
|
//{" HEARTBEAT ACK", 12 }, // i acknowledge your ping at this SNR
|
||||||
{" HEARTBEAT REQ", 13 }, // can you transmit a ping to callsign?
|
|
||||||
|
{" QUERY", 13 }, // can you transmit a ping to callsign?
|
||||||
|
|
||||||
{" APRS:", 14 }, // send an aprs packet
|
{" APRS:", 14 }, // send an aprs packet
|
||||||
|
|
||||||
@ -103,7 +104,7 @@ QSet<int> allowed_cmds = {-1, 0, 1, 2, 3, 4, 5, 6, /*7,*/ 8, 9, 10, 11, 12, 13,
|
|||||||
|
|
||||||
QSet<int> buffered_cmds = {3, 5, /*6,*/ /*7,*/ 8, 13, 14, 15};
|
QSet<int> buffered_cmds = {3, 5, /*6,*/ /*7,*/ 8, 13, 14, 15};
|
||||||
|
|
||||||
QSet<int> snr_cmds = {12, 25};
|
QSet<int> snr_cmds = {25, 29};
|
||||||
|
|
||||||
QMap<int, int> checksum_cmds = {
|
QMap<int, int> checksum_cmds = {
|
||||||
{ 5, 16 },
|
{ 5, 16 },
|
||||||
@ -114,17 +115,17 @@ 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?(?:HEARTBEAT (ACK|REQ)|AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|QRZ[?]|SNR[?]|QTC[?]|QTH[?]|GRID[?]|STATUS[?]|(?:(?:ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|QTC|GRID|ACTIVE|IDLE|TU)(?=[ ]|$))|[?*^&@#> ]))?");
|
QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|QRZ[?]|SNR[?]|QTC[?]|QTH[?]|GRID[?]|STATUS[?]|(?:(?:QUERY|ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|QTC|GRID|INACTIVE|ACTIVE|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|HEARTBEAT ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
|
QString optional_num_pattern = QString("(?<num>(?<=SNR|ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
|
||||||
|
|
||||||
QRegularExpression directed_re("^" +
|
QRegularExpression directed_re("^" +
|
||||||
callsign_pattern +
|
callsign_pattern +
|
||||||
optional_cmd_pattern +
|
optional_cmd_pattern +
|
||||||
optional_num_pattern);
|
optional_num_pattern);
|
||||||
|
|
||||||
QRegularExpression heartbeat_re(R"(^\s*(?<type>CQCQCQ|CQ QRPP?|CQ DX|CQ TEST|CQ( CQ){0,2}|HEARTBEAT)(?:\s(?<grid>[A-R]{2}[0-9]{2}))?\b)");
|
QRegularExpression heartbeat_re(R"(^\s*(?<type>CQCQCQ|CQ QRPP?|CQ DX|CQ TEST|CQ( CQ){0,2}|ACTIVE)(?:\s(?<grid>[A-R]{2}[0-9]{2}))?\b)");
|
||||||
|
|
||||||
QRegularExpression compound_re("^\\s*[`]" +
|
QRegularExpression compound_re("^\\s*[`]" +
|
||||||
callsign_pattern +
|
callsign_pattern +
|
||||||
@ -206,6 +207,12 @@ QMap<quint32, QString> cqs = {
|
|||||||
{ 7, "CQ CQ CQ"},
|
{ 7, "CQ CQ CQ"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QMap<quint32, QString> hbs = {
|
||||||
|
{ 0, "ACTIVE" },
|
||||||
|
{ 1, "INACTIVE" },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
QMap<int, int> dbm2mw = {
|
QMap<int, int> dbm2mw = {
|
||||||
{0 , 1}, // 1mW
|
{0 , 1}, // 1mW
|
||||||
{3 , 2}, // 2mW
|
{3 , 2}, // 2mW
|
||||||
@ -292,6 +299,13 @@ QString Varicode::cqString(int number){
|
|||||||
return cqs[number];
|
return cqs[number];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Varicode::hbString(int number){
|
||||||
|
if(!hbs.contains(number)){
|
||||||
|
return QString{};
|
||||||
|
}
|
||||||
|
return hbs[number];
|
||||||
|
}
|
||||||
|
|
||||||
bool Varicode::startsWithCQ(QString text){
|
bool Varicode::startsWithCQ(QString text){
|
||||||
foreach(auto cq, cqs.values()){
|
foreach(auto cq, cqs.values()){
|
||||||
if(text.startsWith(cq)){
|
if(text.startsWith(cq)){
|
||||||
@ -301,6 +315,15 @@ bool Varicode::startsWithCQ(QString text){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Varicode::startsWithHB(QString text){
|
||||||
|
foreach(auto cq, hbs.values()){
|
||||||
|
if(text.startsWith(cq)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString Varicode::formatSNR(int snr){
|
QString Varicode::formatSNR(int snr){
|
||||||
if(snr < -60 || snr > 60){
|
if(snr < -60 || snr > 60){
|
||||||
return QString();
|
return QString();
|
||||||
@ -994,7 +1017,7 @@ quint8 Varicode::packCmd(quint8 cmd, quint8 num, bool *pPackedNum){
|
|||||||
// [1][X][6]
|
// [1][X][6]
|
||||||
// X = 0 == SNR
|
// X = 0 == SNR
|
||||||
// X = 1 == ACK
|
// X = 1 == ACK
|
||||||
value = ((1 << 1) | (int)(cmdStr == " HEARTBEAT ACK")) << 6;
|
value = ((1 << 1) | (int)(cmdStr == " ACK")) << 6;
|
||||||
value = value + (num & ((1<<6)-1));
|
value = value + (num & ((1<<6)-1));
|
||||||
if(pPackedNum) *pPackedNum = true;
|
if(pPackedNum) *pPackedNum = true;
|
||||||
} else {
|
} else {
|
||||||
@ -1012,7 +1035,7 @@ quint8 Varicode::unpackCmd(quint8 value, quint8 *pNum){
|
|||||||
|
|
||||||
auto cmd = directed_cmds[" SNR"];
|
auto cmd = directed_cmds[" SNR"];
|
||||||
if(value & (1<<6)){
|
if(value & (1<<6)){
|
||||||
cmd = directed_cmds[" HEARTBEAT ACK"];
|
cmd = directed_cmds[" ACK"];
|
||||||
}
|
}
|
||||||
return cmd;
|
return cmd;
|
||||||
} else {
|
} else {
|
||||||
@ -1121,7 +1144,7 @@ bool Varicode::isCompoundCallsign(const QString &callsign){
|
|||||||
// CQCQCQ EM73
|
// CQCQCQ EM73
|
||||||
// CQ DX EM73
|
// CQ DX EM73
|
||||||
// CQ QRP EM73
|
// CQ QRP EM73
|
||||||
// HEARTBEAT EM73
|
// ACTIVE EM73
|
||||||
QString Varicode::packHeartbeatMessage(QString const &text, const QString &callsign, int *n){
|
QString Varicode::packHeartbeatMessage(QString const &text, const QString &callsign, int *n){
|
||||||
QString frame;
|
QString frame;
|
||||||
|
|
||||||
@ -1135,7 +1158,7 @@ QString Varicode::packHeartbeatMessage(QString const &text, const QString &calls
|
|||||||
|
|
||||||
// Heartbeat Alt Type
|
// Heartbeat Alt Type
|
||||||
// ---------------
|
// ---------------
|
||||||
// 1 0 HEARTBEAT
|
// 1 0 ACTIVE
|
||||||
// 1 1 CQCQCQ
|
// 1 1 CQCQCQ
|
||||||
|
|
||||||
auto type = parsedText.captured("type");
|
auto type = parsedText.captured("type");
|
||||||
@ -1151,12 +1174,13 @@ QString Varicode::packHeartbeatMessage(QString const &text, const QString &calls
|
|||||||
packed_extra = Varicode::packGrid(extra);
|
packed_extra = Varicode::packGrid(extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint8 cqNumber = cqs.key(type, 0);
|
||||||
|
|
||||||
if(isAlt){
|
if(isAlt){
|
||||||
packed_extra |= (1<<15);
|
packed_extra |= (1<<15);
|
||||||
|
cqNumber = hbs.key(type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
quint8 cqNumber = cqs.key(type, 0);
|
|
||||||
|
|
||||||
frame = packCompoundFrame(callsign, FrameHeartbeat, packed_extra, cqNumber);
|
frame = packCompoundFrame(callsign, FrameHeartbeat, packed_extra, cqNumber);
|
||||||
if(frame.isEmpty()){
|
if(frame.isEmpty()){
|
||||||
if(n) *n = 0;
|
if(n) *n = 0;
|
||||||
@ -1658,8 +1682,8 @@ QList<QPair<QString, int>> Varicode::buildMessageFrames(
|
|||||||
if(!selectedCall.isEmpty() && !line.startsWith(selectedCall) && !line.startsWith("`")){
|
if(!selectedCall.isEmpty() && !line.startsWith(selectedCall) && !line.startsWith("`")){
|
||||||
bool lineStartsWithBaseCall = (
|
bool lineStartsWithBaseCall = (
|
||||||
line.startsWith("@ALLCALL") ||
|
line.startsWith("@ALLCALL") ||
|
||||||
line.contains("HEARTBEAT") ||
|
Varicode::startsWithCQ(line) ||
|
||||||
Varicode::startsWithCQ(line)
|
Varicode::startsWithHB(line)
|
||||||
);
|
);
|
||||||
|
|
||||||
#if AUTO_PREPEND_DIRECTED_ALLOW_TEXT_CALLSIGNS
|
#if AUTO_PREPEND_DIRECTED_ALLOW_TEXT_CALLSIGNS
|
||||||
|
@ -63,7 +63,9 @@ public:
|
|||||||
|
|
||||||
static QMap<QString, QString> defaultHuffTable();
|
static QMap<QString, QString> defaultHuffTable();
|
||||||
static QString cqString(int number);
|
static QString cqString(int number);
|
||||||
|
static QString hbString(int number);
|
||||||
static bool startsWithCQ(QString text);
|
static bool startsWithCQ(QString text);
|
||||||
|
static bool startsWithHB(QString text);
|
||||||
static QString formatSNR(int snr);
|
static QString formatSNR(int snr);
|
||||||
static QString formatPWR(int dbm);
|
static QString formatPWR(int dbm);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user