Added command processing, code cleanup, new parsing of messages to be sent, etc.
This commit is contained in:
parent
983790a3ff
commit
6a265efe48
145
mainwindow.cpp
145
mainwindow.cpp
@ -164,7 +164,7 @@ namespace
|
|||||||
{
|
{
|
||||||
Radio::Frequency constexpr default_frequency {14074000};
|
Radio::Frequency constexpr default_frequency {14074000};
|
||||||
QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
|
QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
|
||||||
QRegExp message_input_alphabet {"[- A-Za-z0-9+./?\\n*]*"};
|
QRegExp message_input_alphabet {"[- A-Za-z0-9+./?\\n:]*"};
|
||||||
// grid exact match excluding RR73
|
// grid exact match excluding RR73
|
||||||
QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"};
|
QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"};
|
||||||
|
|
||||||
@ -214,6 +214,13 @@ namespace
|
|||||||
return QString {};
|
return QString {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString formatSNR(int snr){
|
||||||
|
if(snr < -60 || snr > 60){
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return QString("%1%2").arg(snr >= 0 ? "+" : "").arg(snr);
|
||||||
|
}
|
||||||
|
|
||||||
void clearTableWidget(QTableWidget *widget){
|
void clearTableWidget(QTableWidget *widget){
|
||||||
if(!widget){
|
if(!widget){
|
||||||
return;
|
return;
|
||||||
@ -1003,13 +1010,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
ui->mdiArea->addSubWindow(m_wideGraph.data(), Qt::Dialog | Qt::FramelessWindowHint | Qt::CustomizeWindowHint | Qt::Tool)->showMaximized();
|
ui->mdiArea->addSubWindow(m_wideGraph.data(), Qt::Dialog | Qt::FramelessWindowHint | Qt::CustomizeWindowHint | Qt::Tool)->showMaximized();
|
||||||
ui->menuDecode->setEnabled(false);
|
ui->menuDecode->setEnabled(false);
|
||||||
ui->menuMode->setEnabled(false);
|
ui->menuMode->setEnabled(false);
|
||||||
ui->menuSave->setEnabled(false);
|
ui->menuSave->setEnabled(true);
|
||||||
ui->menuTools->setEnabled(false);
|
ui->menuTools->setEnabled(false);
|
||||||
ui->menuView->setEnabled(false);
|
ui->menuView->setEnabled(false);
|
||||||
ui->dxCallEntry->clear();
|
ui->dxCallEntry->clear();
|
||||||
ui->dxGridEntry->clear();
|
ui->dxGridEntry->clear();
|
||||||
ui->TxFreqSpinBox->setValue(1500);
|
auto f = findFreeFreqOffset(500, 2000, 50);
|
||||||
ui->RxFreqSpinBox->setValue(1500);
|
setFreq4(f, f);
|
||||||
ui->cbVHFcontest->setChecked(false); // this needs to always be false
|
ui->cbVHFcontest->setChecked(false); // this needs to always be false
|
||||||
|
|
||||||
ui->spotButton->setChecked(m_config.spot_to_psk_reporter());
|
ui->spotButton->setChecked(m_config.spot_to_psk_reporter());
|
||||||
@ -1060,6 +1067,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
auto decoded = Varicode::huffDecode(Varicode::huffFlatten(encoded));
|
auto decoded = Varicode::huffDecode(Varicode::huffFlatten(encoded));
|
||||||
qDebug() << input << Varicode::bitsToStr(Varicode::huffFlatten(encoded)) << decoded;
|
qDebug() << input << Varicode::bitsToStr(Varicode::huffFlatten(encoded)) << decoded;
|
||||||
qDebug() << Varicode::packCallsign("JY1") << Varicode::unpackCallsign(Varicode::packCallsign("JY1"));
|
qDebug() << Varicode::packCallsign("JY1") << Varicode::unpackCallsign(Varicode::packCallsign("JY1"));
|
||||||
|
|
||||||
|
auto frames = buildFT8MessageFrames("OH8STN:KN4CRD?");
|
||||||
|
qDebug() << frames.first() << Varicode::unpackDirectedMessage(frames.first());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// this must be the last statement of constructor
|
// this must be the last statement of constructor
|
||||||
@ -3221,9 +3231,40 @@ void MainWindow::readFromStdout() //readFromStdout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOD0: jsherer - parse for commands?
|
// TOD0: jsherer - parse for commands?
|
||||||
// KN4CRD K1JT ?
|
// KN4CRD K1JT ?
|
||||||
|
bool shouldParseDirected = false;
|
||||||
|
if(shouldParseDirected){
|
||||||
|
// can this be decoded as a directed message?
|
||||||
|
if(!decodedtext.isStandardMessage()){
|
||||||
|
QStringList parts = Varicode::unpackDirectedMessage(decodedtext.message());
|
||||||
|
|
||||||
|
if(!parts.isEmpty()){
|
||||||
|
if(parts.at(1) == m_config.my_callsign()){
|
||||||
|
CommandDetail d;
|
||||||
|
d.call = parts.at(0);
|
||||||
|
d.command = parts.at(2);
|
||||||
|
d.freq = decodedtext.frequencyOffset();
|
||||||
|
d.snr = decodedtext.snr();
|
||||||
|
d.utcTimestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
m_rxCommandQueue.append(d);
|
||||||
|
|
||||||
|
// TODO: jsherer - don't hardcode this here...
|
||||||
|
if(m_txFrameQueue.isEmpty() && QDateTime::currentDateTimeUtc().secsTo(m_nextBeacon) > 0){
|
||||||
|
QString text = QString("%1 %2 %3").arg(d.call.trimmed()).arg(m_config.my_callsign().trimmed()).arg(d.snr);
|
||||||
|
|
||||||
|
setFreq4(d.freq, d.freq);
|
||||||
|
m_bandActivity[decodedtext.frequencyOffset()].last().text = QString("%1:%2%3").arg(d.call.trimmed()).arg(m_config.my_callsign()).arg(d.command);
|
||||||
|
m_rxDirectedCache.insert(decodedtext.frequencyOffset()/10*10, new QDateTime(QDateTime::currentDateTimeUtc()), 25);
|
||||||
|
|
||||||
|
ui->extFreeTextMsgEdit->setPlainText(text);
|
||||||
|
ui->startTxButton->setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5367,18 +5408,28 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
|
|||||||
QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
||||||
QStringList frames;
|
QStringList frames;
|
||||||
|
|
||||||
foreach(QString input, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
|
foreach(QString line, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
|
||||||
while(input.size() > 0){
|
while(line.size() > 0){
|
||||||
QString frame = parseFT8Message(input);
|
int n = 0;
|
||||||
if(frame.isEmpty()){
|
QString frame = Varicode::packDirectedMessage(line, &n);
|
||||||
break;
|
if(n > 0){
|
||||||
}
|
frames.append(frame);
|
||||||
frames.append(frame);
|
line = line.mid(n).trimmed();
|
||||||
|
} else {
|
||||||
|
frame = parseFT8Message(line);
|
||||||
|
if(frame.isEmpty()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frames.append(frame);
|
||||||
|
|
||||||
int sz = input.size();
|
if(!line.startsWith(frame)){
|
||||||
input = input.remove(QRegExp("^" + QRegExp::escape(frame))).trimmed();
|
line = (
|
||||||
if(input.size() == sz){
|
line.left(frame.length()).replace(':', ' ') +
|
||||||
break;
|
line.mid(frame.length())
|
||||||
|
).trimmed();
|
||||||
|
}
|
||||||
|
|
||||||
|
line = line.mid(frame.length()).trimmed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5386,6 +5437,7 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
|
|||||||
return frames;
|
return frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QString MainWindow::parseFT8Message(QString input){
|
QString MainWindow::parseFT8Message(QString input){
|
||||||
char message[29];
|
char message[29];
|
||||||
char msgsent[29];
|
char msgsent[29];
|
||||||
@ -6693,7 +6745,7 @@ void MainWindow::on_snrMacroButton_clicked(){
|
|||||||
if(!items.isEmpty()){
|
if(!items.isEmpty()){
|
||||||
QString selectedCall = items.first()->text();
|
QString selectedCall = items.first()->text();
|
||||||
int snr = m_callActivity[selectedCall].snr;
|
int snr = m_callActivity[selectedCall].snr;
|
||||||
QString text = QString("%1").arg(snr);
|
QString text = QString("%1").arg(formatSNR(snr));
|
||||||
addMessageText(text);
|
addMessageText(text);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -6707,6 +6759,36 @@ void MainWindow::on_snrMacroButton_clicked(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_queryButton_pressed(){
|
||||||
|
QMenu *menu = ui->queryButton->menu();
|
||||||
|
if(!menu){
|
||||||
|
menu = new QMenu(ui->queryButton);
|
||||||
|
}
|
||||||
|
menu->clear();
|
||||||
|
|
||||||
|
auto snrAction = menu->addAction("? - What is my signal report?");
|
||||||
|
|
||||||
|
// TODO: jsherer - this should be extracted
|
||||||
|
connect(snrAction, &QAction::triggered, this, [this](){
|
||||||
|
|
||||||
|
QString selectedCall;
|
||||||
|
auto items = ui->tableWidgetCalls->selectedItems();
|
||||||
|
if(!items.isEmpty()){
|
||||||
|
selectedCall = items.first()->text();
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessageText(QString("%1:%2?").arg(m_config.my_callsign(), selectedCall));
|
||||||
|
});
|
||||||
|
|
||||||
|
menu->addAction("$ - What stations are you hearing?")->setEnabled(false);
|
||||||
|
menu->addAction("@ - What is your QTH?")->setEnabled(false);
|
||||||
|
menu->addAction("&& - What is your message?")->setEnabled(false);
|
||||||
|
menu->addAction("| - Relay the following message")->setEnabled(false);
|
||||||
|
|
||||||
|
ui->queryButton->setMenu(menu);
|
||||||
|
ui->queryButton->showMenu();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_macrosMacroButton_pressed(){
|
void MainWindow::on_macrosMacroButton_pressed(){
|
||||||
if(m_config.macros()->stringList().isEmpty()){
|
if(m_config.macros()->stringList().isEmpty()){
|
||||||
on_actionSettings_triggered();
|
on_actionSettings_triggered();
|
||||||
@ -6759,13 +6841,7 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_tableWidgetRXAll_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected){
|
void MainWindow::on_tableWidgetRXAll_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected){
|
||||||
if(ui->tableWidgetRXAll->selectedItems().isEmpty() && ui->tableWidgetCalls->selectedItems().isEmpty()){
|
updateButtonDisplay();
|
||||||
ui->replyMacroButton->setDisabled(true);
|
|
||||||
ui->snrMacroButton->setDisabled(true);
|
|
||||||
} else {
|
|
||||||
ui->replyMacroButton->setDisabled(false);
|
|
||||||
ui->snrMacroButton->setDisabled(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_tableWidgetCalls_cellClicked(int row, int col){
|
void MainWindow::on_tableWidgetCalls_cellClicked(int row, int col){
|
||||||
@ -7691,12 +7767,18 @@ void MainWindow::displayTransmit(){
|
|||||||
// Transmit Activity
|
// Transmit Activity
|
||||||
update_dynamic_property (ui->startTxButton, "transmitting", m_transmitting);
|
update_dynamic_property (ui->startTxButton, "transmitting", m_transmitting);
|
||||||
|
|
||||||
if(ui->tableWidgetCalls->selectedItems().isEmpty() && ui->tableWidgetRXAll->selectedItems().isEmpty()){
|
updateButtonDisplay();
|
||||||
ui->replyMacroButton->setDisabled(true);
|
}
|
||||||
ui->snrMacroButton->setDisabled(true);
|
|
||||||
|
void MainWindow::updateButtonDisplay(){
|
||||||
|
if(ui->tableWidgetRXAll->selectedItems().isEmpty() && ui->tableWidgetCalls->selectedItems().isEmpty()){
|
||||||
|
ui->replyMacroButton->setDisabled(true);
|
||||||
|
ui->snrMacroButton->setDisabled(true);
|
||||||
|
ui->queryButton->setDisabled(true);
|
||||||
} else {
|
} else {
|
||||||
ui->replyMacroButton->setDisabled(false);
|
ui->replyMacroButton->setDisabled(false);
|
||||||
ui->snrMacroButton->setDisabled(false);
|
ui->snrMacroButton->setDisabled(false);
|
||||||
|
ui->queryButton->setDisabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7717,13 +7799,6 @@ bool MainWindow::isMyCallIncluded(const QString &text){
|
|||||||
return text.contains(myCall);
|
return text.contains(myCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString formatSNR(int snr){
|
|
||||||
if(snr < -60 || snr > 60){
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
return QString("%1%2").arg(snr >= 0 ? "+" : "").arg(snr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::displayActivity(){
|
void MainWindow::displayActivity(){
|
||||||
if(!m_rxDirty){
|
if(!m_rxDirty){
|
||||||
return;
|
return;
|
||||||
|
12
mainwindow.h
12
mainwindow.h
@ -240,6 +240,7 @@ private slots:
|
|||||||
void on_replyMacroButton_clicked();
|
void on_replyMacroButton_clicked();
|
||||||
void on_qthMacroButton_clicked();
|
void on_qthMacroButton_clicked();
|
||||||
void on_snrMacroButton_clicked();
|
void on_snrMacroButton_clicked();
|
||||||
|
void on_queryButton_pressed();
|
||||||
void on_macrosMacroButton_pressed();
|
void on_macrosMacroButton_pressed();
|
||||||
void on_tableWidgetRXAll_cellClicked(int row, int col);
|
void on_tableWidgetRXAll_cellClicked(int row, int col);
|
||||||
void on_tableWidgetRXAll_cellDoubleClicked(int row, int col);
|
void on_tableWidgetRXAll_cellDoubleClicked(int row, int col);
|
||||||
@ -640,6 +641,15 @@ private:
|
|||||||
int snr;
|
int snr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CommandDetail
|
||||||
|
{
|
||||||
|
QString call;
|
||||||
|
QString command;
|
||||||
|
int freq;
|
||||||
|
QDateTime utcTimestamp;
|
||||||
|
int snr;
|
||||||
|
};
|
||||||
|
|
||||||
struct ActivityDetail
|
struct ActivityDetail
|
||||||
{
|
{
|
||||||
bool isFree;
|
bool isFree;
|
||||||
@ -664,6 +674,7 @@ private:
|
|||||||
int m_txFrameCount;
|
int m_txFrameCount;
|
||||||
QQueue<QString> m_txFrameQueue;
|
QQueue<QString> m_txFrameQueue;
|
||||||
QQueue<RXDetail> m_rxFrameQueue;
|
QQueue<RXDetail> m_rxFrameQueue;
|
||||||
|
QQueue<CommandDetail> m_rxCommandQueue;
|
||||||
QCache<int, QDateTime> m_rxDirectedCache; // freq -> last directed rx
|
QCache<int, QDateTime> m_rxDirectedCache; // freq -> last directed rx
|
||||||
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
|
||||||
@ -741,6 +752,7 @@ private:
|
|||||||
void replayDecodes ();
|
void replayDecodes ();
|
||||||
void postDecode (bool is_new, QString const& message);
|
void postDecode (bool is_new, QString const& message);
|
||||||
void displayTransmit();
|
void displayTransmit();
|
||||||
|
void updateButtonDisplay();
|
||||||
bool isMyCallIncluded(QString const &text);
|
bool isMyCallIncluded(QString const &text);
|
||||||
bool isRecentlyDirected(int offset);
|
bool isRecentlyDirected(int offset);
|
||||||
void displayActivity();
|
void displayActivity();
|
||||||
|
Loading…
Reference in New Issue
Block a user