Updated text decoding to support more commands as well as numerical options for those commands
This commit is contained in:
parent
5c84e79e5b
commit
553f2400e5
@ -52,6 +52,12 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString
|
||||
, contest_mode_
|
||||
, grid_c_string.constData ()
|
||||
, 22, 6);
|
||||
|
||||
// We're only going to unpack standard messages for CQs && beacons...
|
||||
// TODO: jsherer - this is a hack for now...
|
||||
if(is_standard_){
|
||||
is_standard_ = QRegularExpression("^(CQ|DE|QRZ)\\s").match(message_).hasMatch();
|
||||
}
|
||||
}
|
||||
|
||||
if(!is_standard_){
|
||||
@ -63,7 +69,6 @@ DecodedText::DecodedText (QString const& the_string, bool contest_mode, QString
|
||||
if(!unpacked){
|
||||
unpacked = tryUnpackData();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,8 +87,11 @@ bool DecodedText::tryUnpackDirected(){
|
||||
}
|
||||
|
||||
if(parts.length() == 3){
|
||||
// replace it with the correct unpacked (query)
|
||||
// replace it with the correct unpacked (directed)
|
||||
message_ = QString("%1: %2%3").arg(parts.at(0), parts.at(1), parts.at(2));
|
||||
} else if(parts.length() == 4){
|
||||
// replace it with the correct unpacked (directed numeric)
|
||||
message_ = QString("%1: %2%3 %4").arg(parts.at(0), parts.at(1), parts.at(2), parts.at(3));
|
||||
} else {
|
||||
// replace it with the correct unpacked (freetext)
|
||||
message_ = QString(parts.join(QChar()));
|
||||
|
@ -5473,6 +5473,9 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
||||
int m = 0;
|
||||
QString datFrame = Varicode::packDataMessage(line.left(21) + "\x04", &m); // 63 / 3 = 21 (maximum number of 3bit chars we could possibly stuff in here)
|
||||
|
||||
qDebug() << "parsing message line" << line;
|
||||
qDebug() << "-> isFree?" << isFree << n << m;
|
||||
|
||||
// if this parses to a standard FT8 free text message
|
||||
// but it can be parsed as a directed message, then we
|
||||
// should send the directed version
|
||||
@ -5522,7 +5525,7 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
qDebug() << "parsed frames:";
|
||||
foreach(auto frame, frames){
|
||||
qDebug() << "->" << frame << Varicode::unpackDataMessage(frame);
|
||||
@ -5573,11 +5576,17 @@ QString MainWindow::parseFT8Message(QString input, bool *isFree){
|
||||
int c = msgbytes[11];
|
||||
int d = ((a & 15) << 12) + (b << 6) + c;
|
||||
|
||||
QString output = QString::fromLatin1(msgsent);
|
||||
|
||||
if(isFree){
|
||||
*isFree = (d >= 32768);
|
||||
// TODO: jsherer - lets figure out a better way to detect this for the case:
|
||||
// KN4CRD 16
|
||||
// this gets encoded as a standard message, but doesn't seem to make sense as to why...
|
||||
// see decodedtext.cpp for the alternate decoding side of this...
|
||||
*isFree = (d >= 32768) || !QRegularExpression("^(CQ|DE|QRZ)\\s").match(output).hasMatch();
|
||||
}
|
||||
|
||||
return QString::fromLatin1(msgsent).trimmed();
|
||||
return output.trimmed();
|
||||
}
|
||||
|
||||
bool MainWindow::prepareNextMessageFrame()
|
||||
@ -6861,13 +6870,7 @@ void MainWindow::on_snrMacroButton_clicked(){
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_queryButton_pressed(){
|
||||
QMenu *menu = ui->queryButton->menu();
|
||||
if(!menu){
|
||||
menu = new QMenu(ui->queryButton);
|
||||
}
|
||||
menu->clear();
|
||||
|
||||
void MainWindow::buildQueryMenu(QMenu * menu){
|
||||
QString call = callsignSelected();
|
||||
if(call.isEmpty()){
|
||||
return;
|
||||
@ -6877,7 +6880,6 @@ void MainWindow::on_queryButton_pressed(){
|
||||
|
||||
auto snrAction = menu->addAction("? - What is my signal report?");
|
||||
|
||||
// TODO: jsherer - this should be extracted
|
||||
connect(snrAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
@ -6939,7 +6941,30 @@ void MainWindow::on_queryButton_pressed(){
|
||||
addMessageText(QString("%1 RR").arg(selectedCall), true);
|
||||
});
|
||||
|
||||
auto sevenThreeAction = menu->addAction("73 - Best regards / end of contact");
|
||||
|
||||
auto yesAction = menu->addAction("YES - I confirm your last inquiry");
|
||||
connect(yesAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
if(selectedCall.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
addMessageText(QString("%1 YES").arg(selectedCall), true);
|
||||
});
|
||||
|
||||
auto noAction = menu->addAction("NO - I do not confirm your last inquiry");
|
||||
connect(noAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
if(selectedCall.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
addMessageText(QString("%1 NO").arg(selectedCall), true);
|
||||
});
|
||||
|
||||
auto sevenThreeAction = menu->addAction("73 - I send my best regards / end of contact");
|
||||
connect(sevenThreeAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
@ -6949,6 +6974,16 @@ void MainWindow::on_queryButton_pressed(){
|
||||
|
||||
addMessageText(QString("%1 73").arg(selectedCall), true);
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::on_queryButton_pressed(){
|
||||
QMenu *menu = ui->queryButton->menu();
|
||||
if(!menu){
|
||||
menu = new QMenu(ui->queryButton);
|
||||
}
|
||||
menu->clear();
|
||||
|
||||
buildQueryMenu(menu);
|
||||
|
||||
ui->queryButton->setMenu(menu);
|
||||
ui->queryButton->showMenu();
|
||||
@ -8194,7 +8229,9 @@ void MainWindow::displayActivity(bool force){
|
||||
|
||||
bool isAllCall = d.to == "ALLCALL";
|
||||
|
||||
#if 0
|
||||
qDebug() << "processing command" << d.from << d.to << d.cmd << d.freq;
|
||||
#endif
|
||||
|
||||
// we're only processing a subset of queries at this point
|
||||
if(!Varicode::isCommandAllowed(d.cmd)){
|
||||
@ -8217,7 +8254,8 @@ void MainWindow::displayActivity(bool force){
|
||||
// SNR
|
||||
if(d.cmd == "?"){
|
||||
// standard FT8 reply
|
||||
reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign()).arg(d.snr);
|
||||
// reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign()).arg(d.snr);
|
||||
reply = QString("%1 %2").arg(d.from).arg(d.snr);
|
||||
}
|
||||
// QTH
|
||||
else if(d.cmd == "@" && !isAllCall){
|
||||
@ -8228,10 +8266,11 @@ void MainWindow::displayActivity(bool force){
|
||||
continue;
|
||||
}
|
||||
// standard FT8 reply
|
||||
reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign()).arg(grid);
|
||||
} else {
|
||||
reply = QString("%1 %2").arg(d.from).arg(qth);
|
||||
// reply = QString("%1 %2 %3").arg(d.from).arg(m_config.my_callsign()).arg(grid);
|
||||
qth = grid;
|
||||
}
|
||||
|
||||
reply = QString("%1 %2").arg(d.from).arg(qth);
|
||||
}
|
||||
// STATION MESSAGE
|
||||
else if(d.cmd == "&" && !isAllCall){
|
||||
|
@ -240,6 +240,7 @@ private slots:
|
||||
void on_replyMacroButton_clicked();
|
||||
void on_qthMacroButton_clicked();
|
||||
void on_snrMacroButton_clicked();
|
||||
void buildQueryMenu(QMenu *);
|
||||
void on_queryButton_pressed();
|
||||
void on_macrosMacroButton_pressed();
|
||||
void on_tableWidgetRXAll_cellClicked(int row, int col);
|
||||
|
@ -1123,6 +1123,9 @@ background:yellow;
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QPushButton" name="deMacroButton">
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
|
61
varicode.cpp
61
varicode.cpp
@ -43,24 +43,26 @@ QMap<QString, int> directed_cmds = {
|
||||
{"&", 3 }, // query station message
|
||||
//{"|", 4 }, // relay message
|
||||
|
||||
//{"+", 5 }, // report +snr
|
||||
//{"-", 6 }, // report -snr
|
||||
|
||||
// ...
|
||||
{" NO", 26 }, // negative confirm
|
||||
{" YES", 27 }, // confirm
|
||||
{" 73", 28 }, // best regards, end of contact
|
||||
{" RR", 29 }, // confirm message
|
||||
{" AGN?", 30 }, // repeat message
|
||||
{" ", 31 }, // send freetext
|
||||
};
|
||||
|
||||
QSet<int> allowed_cmds = {0, 2, 3, 28, 29, 30, 31};
|
||||
QSet<int> allowed_cmds = {0, 2, 3, 26, 27, 28, 29, 30, 31};
|
||||
|
||||
QRegularExpression directed_re(R"(^(?:(?<from>[A-Z0-9/]+):\s?)?(?<to>[A-Z0-9/]+)(?<cmd>(\s?(?:RR|AGN[?]|73)|[?$@&| ])))");
|
||||
QRegularExpression directed_re("^"
|
||||
"(?<to>[A-Z0-9/]+)"
|
||||
"(?<cmd>\\s?(?:AGN[?]|RR|73|YES|NO|[?$@&| ]))"
|
||||
"(?<num>\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
|
||||
|
||||
QMap<QChar, QString> huff = {
|
||||
// char code weight
|
||||
{' ' , "001" }, // 1300
|
||||
{'E' , "000" }, // 1270.2
|
||||
{' ' , "000" }, // 1300
|
||||
{'E' , "001" }, // 1270.2
|
||||
{'T' , "1100" }, // 905.6
|
||||
{'A' , "1010" }, // 816.7
|
||||
{'O' , "0111" }, // 750.7
|
||||
@ -517,12 +519,20 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &callsi
|
||||
|
||||
auto match = directed_re.match(text);
|
||||
if(match.hasMatch()){
|
||||
QString from = match.captured("from");
|
||||
if(from.isEmpty()){
|
||||
from = callsign;
|
||||
}
|
||||
QString from = callsign;
|
||||
QString to = match.captured("to");
|
||||
QString cmd = match.captured("cmd");
|
||||
QString num = match.captured("num").trimmed();
|
||||
|
||||
int inum = -31;
|
||||
bool hasnum = false;
|
||||
if(!num.isEmpty()){
|
||||
inum = qMax(-30, qMin(num.toInt(&hasnum, 10), 30));
|
||||
}
|
||||
|
||||
qDebug() << "match" << match.captured(0);
|
||||
qDebug() << "groups" << from << to << cmd << num;
|
||||
qDebug() << "packed num" << num << inum << hasnum;
|
||||
|
||||
if(to == callsign){
|
||||
*n = 0;
|
||||
@ -535,11 +545,12 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &callsi
|
||||
return frame;
|
||||
}
|
||||
|
||||
auto fromBytes = from.toLocal8Bit();
|
||||
auto fromCRC = CRC::Calculate(fromBytes.data(), fromBytes.length(), CRC::CRC_5_ITU());
|
||||
// TODO: jsherer - we don't need this CRC... the FT8 msg already has a 12 bit CRC...
|
||||
//auto fromBytes = from.toLocal8Bit();
|
||||
//auto fromCRC = CRC::Calculate(fromBytes.data(), fromBytes.length(), CRC::CRC_5_ITU());
|
||||
|
||||
quint8 packed_is_data = 0;
|
||||
quint8 packed_flag = 0;
|
||||
quint8 packed_flag = inum < 0 ? 1 : 0;
|
||||
quint32 packed_from = Varicode::packCallsign(from);
|
||||
quint32 packed_to = Varicode::packCallsign(to);
|
||||
|
||||
@ -549,7 +560,7 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &callsi
|
||||
}
|
||||
|
||||
quint8 packed_cmd = directed_cmds[cmd];
|
||||
quint8 packed_extra = fromCRC;
|
||||
quint8 packed_extra = qAbs(inum);
|
||||
|
||||
// [1][2][28][28][5],[5] = 69
|
||||
auto bits = (
|
||||
@ -563,6 +574,8 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &callsi
|
||||
*n = match.captured(0).length();
|
||||
return frame;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
QStringList Varicode::unpackDirectedMessage(const QString &text){
|
||||
@ -587,23 +600,29 @@ QStringList Varicode::unpackDirectedMessage(const QString &text){
|
||||
|
||||
QString from = Varicode::unpackCallsign(packed_from).trimmed();
|
||||
|
||||
auto fromBytes = from.toLocal8Bit();
|
||||
auto fromCRC = CRC::Calculate(fromBytes.data(), fromBytes.length(), CRC::CRC_5_ITU());
|
||||
if(fromCRC != extra){
|
||||
return unpacked;
|
||||
}
|
||||
// TODO: jsherer - we don't need this CRC... the FT8 msg already has a 12 bit CRC...
|
||||
//auto fromBytes = from.toLocal8Bit();
|
||||
//auto fromCRC = CRC::Calculate(fromBytes.data(), fromBytes.length(), CRC::CRC_5_ITU());
|
||||
//if(fromCRC != extra){
|
||||
// return unpacked;
|
||||
//}
|
||||
|
||||
unpacked.append(from);
|
||||
unpacked.append(Varicode::unpackCallsign(packed_to).trimmed());
|
||||
unpacked.append(directed_cmds.key(packed_cmd & 31));
|
||||
|
||||
int num = (flag ? -1 : 1) * extra;
|
||||
if(num != -31){
|
||||
unpacked.append(QString(num > 0 ? "+%1" : "%1").arg(num));
|
||||
}
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
QString Varicode::packDataMessage(const QString &text, int *n){
|
||||
QString frame;
|
||||
|
||||
// [1][63],[5]
|
||||
// [1][63],[5] = 69
|
||||
quint8 is_data = 1;
|
||||
auto frameBits = (
|
||||
Varicode::intToBits(is_data, 1)
|
||||
|
Loading…
Reference in New Issue
Block a user