Added command processing, code cleanup, new parsing of messages to be sent, etc.

This commit is contained in:
Jordan Sherer 2018-07-13 04:44:41 -04:00
parent 983790a3ff
commit 6a265efe48
2 changed files with 122 additions and 35 deletions

View File

@ -164,7 +164,7 @@ namespace
{
Radio::Frequency constexpr default_frequency {14074000};
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
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 {};
}
QString formatSNR(int snr){
if(snr < -60 || snr > 60){
return QString();
}
return QString("%1%2").arg(snr >= 0 ? "+" : "").arg(snr);
}
void clearTableWidget(QTableWidget *widget){
if(!widget){
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->menuDecode->setEnabled(false);
ui->menuMode->setEnabled(false);
ui->menuSave->setEnabled(false);
ui->menuSave->setEnabled(true);
ui->menuTools->setEnabled(false);
ui->menuView->setEnabled(false);
ui->dxCallEntry->clear();
ui->dxGridEntry->clear();
ui->TxFreqSpinBox->setValue(1500);
ui->RxFreqSpinBox->setValue(1500);
auto f = findFreeFreqOffset(500, 2000, 50);
setFreq4(f, f);
ui->cbVHFcontest->setChecked(false); // this needs to always be false
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));
qDebug() << input << Varicode::bitsToStr(Varicode::huffFlatten(encoded)) << decoded;
qDebug() << Varicode::packCallsign("JY1") << Varicode::unpackCallsign(Varicode::packCallsign("JY1"));
auto frames = buildFT8MessageFrames("OH8STN:KN4CRD?");
qDebug() << frames.first() << Varicode::unpackDirectedMessage(frames.first());
#endif
// this must be the last statement of constructor
@ -3221,9 +3231,40 @@ void MainWindow::readFromStdout() //readFromStdout
}
}
}
// TOD0: jsherer - parse for commands?
// 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 frames;
foreach(QString input, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
while(input.size() > 0){
QString frame = parseFT8Message(input);
if(frame.isEmpty()){
break;
}
frames.append(frame);
foreach(QString line, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
while(line.size() > 0){
int n = 0;
QString frame = Varicode::packDirectedMessage(line, &n);
if(n > 0){
frames.append(frame);
line = line.mid(n).trimmed();
} else {
frame = parseFT8Message(line);
if(frame.isEmpty()){
break;
}
frames.append(frame);
int sz = input.size();
input = input.remove(QRegExp("^" + QRegExp::escape(frame))).trimmed();
if(input.size() == sz){
break;
if(!line.startsWith(frame)){
line = (
line.left(frame.length()).replace(':', ' ') +
line.mid(frame.length())
).trimmed();
}
line = line.mid(frame.length()).trimmed();
}
}
}
@ -5386,6 +5437,7 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
return frames;
}
QString MainWindow::parseFT8Message(QString input){
char message[29];
char msgsent[29];
@ -6693,7 +6745,7 @@ void MainWindow::on_snrMacroButton_clicked(){
if(!items.isEmpty()){
QString selectedCall = items.first()->text();
int snr = m_callActivity[selectedCall].snr;
QString text = QString("%1").arg(snr);
QString text = QString("%1").arg(formatSNR(snr));
addMessageText(text);
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(){
if(m_config.macros()->stringList().isEmpty()){
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){
if(ui->tableWidgetRXAll->selectedItems().isEmpty() && ui->tableWidgetCalls->selectedItems().isEmpty()){
ui->replyMacroButton->setDisabled(true);
ui->snrMacroButton->setDisabled(true);
} else {
ui->replyMacroButton->setDisabled(false);
ui->snrMacroButton->setDisabled(false);
}
updateButtonDisplay();
}
void MainWindow::on_tableWidgetCalls_cellClicked(int row, int col){
@ -7691,12 +7767,18 @@ void MainWindow::displayTransmit(){
// Transmit Activity
update_dynamic_property (ui->startTxButton, "transmitting", m_transmitting);
if(ui->tableWidgetCalls->selectedItems().isEmpty() && ui->tableWidgetRXAll->selectedItems().isEmpty()){
ui->replyMacroButton->setDisabled(true);
ui->snrMacroButton->setDisabled(true);
updateButtonDisplay();
}
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 {
ui->replyMacroButton->setDisabled(false);
ui->snrMacroButton->setDisabled(false);
ui->replyMacroButton->setDisabled(false);
ui->snrMacroButton->setDisabled(false);
ui->queryButton->setDisabled(false);
}
}
@ -7717,13 +7799,6 @@ bool MainWindow::isMyCallIncluded(const QString &text){
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(){
if(!m_rxDirty){
return;

View File

@ -240,6 +240,7 @@ private slots:
void on_replyMacroButton_clicked();
void on_qthMacroButton_clicked();
void on_snrMacroButton_clicked();
void on_queryButton_pressed();
void on_macrosMacroButton_pressed();
void on_tableWidgetRXAll_cellClicked(int row, int col);
void on_tableWidgetRXAll_cellDoubleClicked(int row, int col);
@ -640,6 +641,15 @@ private:
int snr;
};
struct CommandDetail
{
QString call;
QString command;
int freq;
QDateTime utcTimestamp;
int snr;
};
struct ActivityDetail
{
bool isFree;
@ -664,6 +674,7 @@ private:
int m_txFrameCount;
QQueue<QString> m_txFrameQueue;
QQueue<RXDetail> m_rxFrameQueue;
QQueue<CommandDetail> m_rxCommandQueue;
QCache<int, QDateTime> m_rxDirectedCache; // freq -> last directed rx
QCache<QString, int> m_rxCallCache; // call -> last freq seen
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
@ -741,6 +752,7 @@ private:
void replayDecodes ();
void postDecode (bool is_new, QString const& message);
void displayTransmit();
void updateButtonDisplay();
bool isMyCallIncluded(QString const &text);
bool isRecentlyDirected(int offset);
void displayActivity();