Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8f8772f1bd | |||
| f09132f6b4 | |||
| bf57a67c43 | |||
| 091b3b3ee8 | |||
| 17033f1044 | |||
| 7c656fac71 | |||
| a6771b81c3 | |||
| eca184bac6 | |||
| 6ad2417804 | |||
| 21e87d8b6f | |||
| 52a5650a74 | |||
| 2158722ebc |
+1
-1
@@ -1,6 +1,6 @@
|
||||
# Version number components
|
||||
set (WSJTX_VERSION_MAJOR 0)
|
||||
set (WSJTX_VERSION_MINOR 3)
|
||||
set (WSJTX_VERSION_PATCH 0)
|
||||
set (WSJTX_VERSION_PATCH 2)
|
||||
set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions
|
||||
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ bool DecodedText::tryUnpackCompound(){
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList parts = Varicode::unpackCompoundMessage(m);
|
||||
QStringList parts = Varicode::unpackCompoundMessage(m, nullptr);
|
||||
|
||||
if(parts.isEmpty() || parts.length() < 2){
|
||||
return false;
|
||||
|
||||
+120
-22
@@ -248,6 +248,26 @@ namespace
|
||||
int roundDown = ( (int) (numToRound) / multiple) * multiple;
|
||||
return roundDown + multiple;
|
||||
}
|
||||
|
||||
QString rstrip(const QString& str) {
|
||||
int n = str.size() - 1;
|
||||
for (; n >= 0; --n) {
|
||||
if (!str.at(n).isSpace()) {
|
||||
return str.left(n + 1);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
QString lstrip(const QString& str) {
|
||||
int len = str.size() - 1;
|
||||
for (int n = 0; n < len; n++) {
|
||||
if (!str.at(n).isSpace()) {
|
||||
return str.mid(n);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------- MainWindow constructor
|
||||
@@ -446,6 +466,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_previousFreq {0}
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
createStatusBar();
|
||||
add_child_to_event_filter (this);
|
||||
ui->dxGridEntry->setValidator (new MaidenheadLocatorValidator {this});
|
||||
@@ -1056,8 +1077,23 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
auto clearAction2 = new QAction(QIcon::fromTheme("edit-clear"), QString("Clear"), ui->extFreeTextMsgEdit);
|
||||
connect(clearAction2, &QAction::triggered, this, [this](){ this->on_clearAction_triggered(ui->extFreeTextMsgEdit); });
|
||||
ui->extFreeTextMsgEdit->setContextMenuPolicy(Qt::ActionsContextMenu);
|
||||
ui->extFreeTextMsgEdit->addAction(clearAction2);
|
||||
ui->extFreeTextMsgEdit->addAction(clearActionAll);
|
||||
|
||||
auto restoreAction = new QAction(QString("Restore Previous Message"), ui->extFreeTextMsgEdit);
|
||||
connect(restoreAction, &QAction::triggered, this, [this](){ this->restoreMessage(); });
|
||||
|
||||
ui->extFreeTextMsgEdit->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->extFreeTextMsgEdit, &QTableWidget::customContextMenuRequested, this, [this, clearAction2, clearActionAll, restoreAction](QPoint const &point){
|
||||
QMenu * menu = new QMenu(ui->extFreeTextMsgEdit);
|
||||
|
||||
restoreAction->setDisabled(m_lastTxMessage.isEmpty());
|
||||
menu->addAction(restoreAction);
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addAction(clearAction2);
|
||||
menu->addAction(clearActionAll);
|
||||
|
||||
menu->popup(ui->extFreeTextMsgEdit->mapToGlobal(point));
|
||||
});
|
||||
|
||||
auto clearAction3 = new QAction(QIcon::fromTheme("edit-clear"), QString("Clear"), ui->tableWidgetRXAll);
|
||||
connect(clearAction3, &QAction::triggered, this, [this](){ this->on_clearAction_triggered(ui->tableWidgetRXAll); });
|
||||
@@ -1068,14 +1104,36 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
auto clearAction4 = new QAction(QIcon::fromTheme("edit-clear"), QString("Clear"), ui->tableWidgetCalls);
|
||||
connect(clearAction4, &QAction::triggered, this, [this](){ this->on_clearAction_triggered(ui->tableWidgetCalls); });
|
||||
|
||||
auto removeStation = new QAction(QString("Remove Station"), ui->tableWidgetCalls);
|
||||
connect(removeStation, &QAction::triggered, this, [this](){
|
||||
QString selectedCall = callsignSelected();
|
||||
if(!selectedCall.isEmpty() && m_callActivity.contains(selectedCall)){
|
||||
m_callActivity.remove(selectedCall);
|
||||
displayActivity(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
ui->tableWidgetCalls->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->tableWidgetCalls, &QTableWidget::customContextMenuRequested, this, [this, clearAction4, clearActionAll](QPoint const &point){
|
||||
connect(ui->tableWidgetCalls, &QTableWidget::customContextMenuRequested, this, [this, clearAction4, clearActionAll, removeStation](QPoint const &point){
|
||||
QMenu * menu = new QMenu(ui->tableWidgetCalls);
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
bool missingCallsign = selectedCall.isEmpty();
|
||||
if(!missingCallsign && m_callActivity.contains(selectedCall)){
|
||||
setFreqForRestore(m_callActivity[selectedCall].freq, true);
|
||||
}
|
||||
|
||||
auto directedMenu = menu->addMenu("Directed");
|
||||
directedMenu->setDisabled(callsignSelected().isEmpty());
|
||||
directedMenu->setDisabled(missingCallsign);
|
||||
buildQueryMenu(directedMenu);
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
removeStation->setDisabled(missingCallsign || callsignSelected() == "ALLCALL");
|
||||
menu->addAction(removeStation);
|
||||
|
||||
|
||||
menu->addSeparator();
|
||||
menu->addAction(clearAction4);
|
||||
menu->addAction(clearActionAll);
|
||||
@@ -1152,6 +1210,20 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
auto packed = Varicode::packCompoundMessage(basecall, fix, prefix, 99);
|
||||
qDebug() << packed << Varicode::unpackCompoundMessage(packed);
|
||||
|
||||
bool isCQ = false;
|
||||
|
||||
auto packed = Varicode::packBeaconMessage("KN4CRD/P", "EM73", true);
|
||||
qDebug() << packed << Varicode::unpackBeaconMessage(packed, &isCQ) << isCQ;
|
||||
|
||||
packed = Varicode::packBeaconMessage("VE3/KN4CRD", "EM73", false);
|
||||
qDebug() << packed << Varicode::unpackBeaconMessage(packed, &isCQ) << isCQ;
|
||||
|
||||
|
||||
bool isCQ = false;
|
||||
|
||||
auto packed = Varicode::packBeaconMessage("P/KN4CRD", "", true);
|
||||
qDebug() << packed << Varicode::unpackBeaconMessage(packed, &isCQ) << isCQ;
|
||||
|
||||
m_valid = false;
|
||||
#endif
|
||||
|
||||
@@ -1885,6 +1957,7 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
|
||||
}
|
||||
|
||||
displayDialFrequency ();
|
||||
displayActivity(true);
|
||||
|
||||
bool vhf {m_config.enable_VHF_features()};
|
||||
m_wideGraph->setVHF(vhf);
|
||||
@@ -2056,6 +2129,7 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
|
||||
QMainWindow::keyPressEvent (e);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int n;
|
||||
switch(e->key())
|
||||
{
|
||||
@@ -2171,6 +2245,7 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
QMainWindow::keyPressEvent (e);
|
||||
}
|
||||
@@ -3242,12 +3317,13 @@ void MainWindow::readFromStdout() //readFromStdout
|
||||
d.isCompound = decodedtext.isCompoundMessage();
|
||||
d.bits = decodedtext.bits();
|
||||
d.freq = offset;
|
||||
d.text = decodedtext.messageWords().isEmpty() ? "" : decodedtext.messageWords().first().trimmed();
|
||||
d.text = decodedtext.message(); //decodedtext.messageWords().isEmpty() ? "" : decodedtext.messageWords().first().trimmed();
|
||||
d.utcTimestamp = QDateTime::currentDateTimeUtc();
|
||||
d.snr = decodedtext.snr();
|
||||
m_bandActivity[offset].append(d);
|
||||
|
||||
if(m_messageBuffer.contains(d.freq/10*10)){
|
||||
qDebug() << "buffering" << (d.freq/10*10) << d.text;
|
||||
m_messageBuffer[d.freq/10*10].msgs.append(d);
|
||||
}
|
||||
|
||||
@@ -5396,6 +5472,7 @@ void MainWindow::clearActivity(){
|
||||
m_rxFrameBlockNumbers.clear();
|
||||
m_rxFrameQueue.clear();
|
||||
m_rxCommandQueue.clear();
|
||||
m_lastTxMessage.clear();
|
||||
|
||||
clearTableWidget(ui->tableWidgetCalls);
|
||||
|
||||
@@ -5527,6 +5604,13 @@ void MainWindow::createMessageTransmitQueue(QString const& text){
|
||||
m_lastTxMessage = text;
|
||||
}
|
||||
|
||||
void MainWindow::restoreMessage(){
|
||||
if(m_lastTxMessage.isEmpty()){
|
||||
return;
|
||||
}
|
||||
addMessageText(m_lastTxMessage, true);
|
||||
}
|
||||
|
||||
void MainWindow::resetMessageTransmitQueue(){
|
||||
m_txFrameCount = 0;
|
||||
m_txFrameQueue.clear();
|
||||
@@ -5700,8 +5784,12 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
||||
line = line.mid(n);
|
||||
|
||||
if(Varicode::isCommandBuffered(dirCmd) && !line.isEmpty()){
|
||||
// strip leading whitespace after a buffered directed command
|
||||
line = lstrip(line);
|
||||
// TODO: jsherer - this is how we can add 16-bit checksum to the message, just encode it in the data...
|
||||
line = Varicode::checksum16(line) + " " + line;
|
||||
qDebug() << "generating checksum for line" << line;
|
||||
line = line + " " + Varicode::checksum16(line);
|
||||
qDebug() << line;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5716,7 +5804,7 @@ QPair<QStringList, QStringList> MainWindow::buildFT8MessageFrames(QString const&
|
||||
#if 1
|
||||
qDebug() << "parsed frames:";
|
||||
foreach(auto frame, frames){
|
||||
qDebug() << "->" << frame << Varicode::unpackDataMessage(frame) << Varicode::unpackDirectedMessage(frame) << Varicode::unpackCompoundMessage(frame);
|
||||
qDebug() << "->" << frame << Varicode::unpackDataMessage(frame) << Varicode::unpackDirectedMessage(frame) << Varicode::unpackCompoundMessage(frame, nullptr);
|
||||
}
|
||||
|
||||
qDebug() << "lines:";
|
||||
@@ -5937,12 +6025,14 @@ void MainWindow::prepareBacon(){
|
||||
|
||||
QString call = m_config.my_callsign();
|
||||
QString grid = m_config.my_grid().left(4);
|
||||
if(call != Radio::base_callsign(call)){
|
||||
grid = "";
|
||||
QString beacon = QString("DE %1 %2").arg(call).arg(grid);
|
||||
QString parsed = parseFT8Message(beacon, nullptr);
|
||||
if(parsed != beacon){
|
||||
beacon = QString("DE %1").arg(call).arg(grid);
|
||||
}
|
||||
|
||||
lines.append(QString("DE %1 %2").arg(call).arg(grid));
|
||||
lines.append(QString("DE %1 %2").arg(call).arg(grid));
|
||||
lines.append(beacon);
|
||||
lines.append(beacon);
|
||||
|
||||
#if 0
|
||||
if(!m_callActivity.isEmpty()){
|
||||
@@ -7049,6 +7139,7 @@ void MainWindow::on_clearAction_triggered(QObject * sender){
|
||||
|
||||
if(sender == ui->extFreeTextMsgEdit){
|
||||
resetMessage();
|
||||
m_lastTxMessage.clear();
|
||||
}
|
||||
|
||||
if(sender == ui->textEditRX){
|
||||
@@ -7147,7 +7238,8 @@ void MainWindow::buildQueryMenu(QMenu * menu){
|
||||
|
||||
menu->addSeparator();
|
||||
|
||||
auto ackQueryAction = menu->addAction("? - Are you hearing me?");
|
||||
/*
|
||||
auto ackQueryAction = menu->addAction("^ - Are you hearing me?");
|
||||
connect(ackQueryAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
@@ -7158,9 +7250,9 @@ void MainWindow::buildQueryMenu(QMenu * menu){
|
||||
addMessageText(QString("%1?").arg(selectedCall), true);
|
||||
toggleTx(true);
|
||||
});
|
||||
*/
|
||||
|
||||
auto snrQueryAction = menu->addAction("^ - What is my signal report?");
|
||||
snrQueryAction->setDisabled(isAllCall);
|
||||
auto snrQueryAction = menu->addAction("? - What is my signal report?");
|
||||
connect(snrQueryAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
@@ -7168,7 +7260,7 @@ void MainWindow::buildQueryMenu(QMenu * menu){
|
||||
return;
|
||||
}
|
||||
|
||||
addMessageText(QString("%1^").arg(selectedCall), true);
|
||||
addMessageText(QString("%1?").arg(selectedCall), true);
|
||||
toggleTx(true);
|
||||
});
|
||||
|
||||
@@ -8642,15 +8734,18 @@ void MainWindow::displayActivity(bool force){
|
||||
foreach(auto part, buffer.msgs){
|
||||
message.append(part.text);
|
||||
}
|
||||
message = rstrip(message);
|
||||
|
||||
QString checksum = message.left(3);
|
||||
message = message.mid(4);
|
||||
QString checksum = message.right(3);
|
||||
message = message.left(message.length()-4);
|
||||
|
||||
if(Varicode::checksum16Valid(checksum, message)){
|
||||
buffer.cmd.text = message;
|
||||
m_rxCommandQueue.append(buffer.cmd);
|
||||
} else {
|
||||
qDebug() << "Buffered message failed checksum...discarding";
|
||||
qDebug() << "Checksum:" << checksum;
|
||||
qDebug() << "Message:" << message;
|
||||
}
|
||||
|
||||
// regardless of valid or not, remove the "complete" buffered message from the buffer cache
|
||||
@@ -8693,14 +8788,15 @@ void MainWindow::displayActivity(bool force){
|
||||
// construct reply
|
||||
QString reply;
|
||||
|
||||
// QUERIED ACK
|
||||
if(d.cmd == "?"){
|
||||
reply = QString("%1 ACK").arg(Radio::base_callsign(d.from));
|
||||
}
|
||||
|
||||
// QUERIED SNR
|
||||
else if(d.cmd == "^" && !isAllCall){
|
||||
if(d.cmd == "?"){
|
||||
reply = QString("%1 SNR %2").arg(Radio::base_callsign(d.from)).arg(Varicode::formatSNR(d.snr));
|
||||
}
|
||||
// QUERIED ACK
|
||||
//else if(d.cmd == "#"){
|
||||
// reply = QString("%1 ACK").arg(Radio::base_callsign(d.from));
|
||||
//}
|
||||
// QUERIED PWR
|
||||
else if(d.cmd == "%" && !isAllCall && m_config.my_dBm() >= 0){
|
||||
reply = QString("%1 PWR %2").arg(Radio::base_callsign(d.from)).arg(Varicode::formatPWR(m_config.my_dBm()));
|
||||
@@ -8781,6 +8877,8 @@ void MainWindow::displayActivity(bool force){
|
||||
msgBox->show();
|
||||
|
||||
continue;
|
||||
} else if(d.cmd == " AGN?" && !isAllCall && !m_lastTxMessage.isEmpty()){
|
||||
reply = m_lastTxMessage;
|
||||
}
|
||||
|
||||
if(reply.isEmpty()){
|
||||
|
||||
@@ -127,6 +127,7 @@ public slots:
|
||||
void addMessageText(QString text, bool clear=false);
|
||||
void resetMessage();
|
||||
void resetMessageUI();
|
||||
void restoreMessage();
|
||||
void createMessage(QString const& text);
|
||||
void createMessageTransmitQueue(QString const& text);
|
||||
void resetMessageTransmitQueue();
|
||||
|
||||
+70
-12
@@ -31,7 +31,7 @@ const int nalphabet = 41;
|
||||
QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"};
|
||||
QString grid_pattern = {R"((?<grid>[A-R]{2}[0-9]{2})+)"};
|
||||
QString orig_compound_callsign_pattern = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){2,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"};
|
||||
QString compound_callsign_pattern = {R"((?<callsign>\b([A-Z0-9]{1,4}\/)?([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?(\/[A-Z0-9]{1,4})?)\b)"};
|
||||
QString compound_callsign_pattern = {R"((?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"};
|
||||
QString pack_callsign_pattern = {R"(([0-9A-Z ])([0-9A-Z])([0-9])([A-Z ])([A-Z ])([A-Z ]))"};
|
||||
QString callsign_alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ "};
|
||||
|
||||
@@ -39,11 +39,11 @@ QMap<QString, int> directed_cmds = {
|
||||
// any changes here need to be made also in the directed regular xpression for parsing
|
||||
|
||||
// directed queries
|
||||
{"?", 0 }, // query ack
|
||||
{"?", 0 }, // query snr
|
||||
{"@", 1 }, // query qth
|
||||
{"&", 2 }, // query station message
|
||||
{"$", 3 }, // query station(s) heard
|
||||
{"^", 4 }, // query snr
|
||||
// {"^", 4 }, // query ack
|
||||
{"%", 5 }, // query pwr
|
||||
{"|", 6 }, // relay message?
|
||||
{"!", 7 }, // alert message?
|
||||
@@ -63,7 +63,7 @@ QMap<QString, int> directed_cmds = {
|
||||
{" ", 31 }, // send freetext
|
||||
};
|
||||
|
||||
QSet<int> allowed_cmds = {0, 1, 2, 3, 4, 5, 6, 7, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
QSet<int> allowed_cmds = {0, 1, 2, 3, 4, 5, 6, 7, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
|
||||
QSet<int> buffered_cmds = {6, 7};
|
||||
|
||||
@@ -772,6 +772,9 @@ QPair<float, float> grid2deg(QString const &grid){
|
||||
// pack a 4-digit maidenhead grid locator into a 15-bit value
|
||||
quint16 Varicode::packGrid(QString const& grid){
|
||||
// TODO: validate grid...
|
||||
if(grid.length() < 4){
|
||||
return (1<<15)-1;
|
||||
}
|
||||
|
||||
// TODO: encode non-grid data...
|
||||
|
||||
@@ -784,7 +787,7 @@ quint16 Varicode::packGrid(QString const& grid){
|
||||
|
||||
QString Varicode::unpackGrid(quint16 value){
|
||||
if(value > 180*180){
|
||||
// TODO: decode non-grid data...
|
||||
// TODO: decode non-grid data... for now just return an empty string...
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -802,6 +805,50 @@ bool Varicode::isCommandBuffered(const QString &cmd){
|
||||
return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]);
|
||||
}
|
||||
|
||||
QString Varicode::packBeaconMessage(QString const &callsign, QString const &extra, bool isCQ){
|
||||
QString frame;
|
||||
|
||||
auto parsedCall = QRegularExpression(compound_callsign_pattern).match(callsign);
|
||||
if(!parsedCall.hasMatch()){
|
||||
return frame;
|
||||
}
|
||||
|
||||
QString base = parsedCall.captured("base");
|
||||
|
||||
bool isPrefix = false;
|
||||
QString fix = parsedCall.captured("prefix");
|
||||
if(!fix.isEmpty()){
|
||||
isPrefix = true;
|
||||
}
|
||||
|
||||
if(!isPrefix){
|
||||
fix = parsedCall.captured("suffix");
|
||||
}
|
||||
|
||||
quint16 packed_extra = 180*180 + 1; // maximum grid + 1 (which will display an empty string)
|
||||
if(extra.length() == 4 && QRegularExpression(grid_pattern).match(extra).hasMatch()){
|
||||
packed_extra = Varicode::packGrid(extra);
|
||||
}
|
||||
|
||||
if(isCQ){
|
||||
packed_extra |= (1<<15);
|
||||
}
|
||||
|
||||
return packCompoundMessage(base, fix, isPrefix, packed_extra);
|
||||
}
|
||||
|
||||
QStringList Varicode::unpackBeaconMessage(const QString &text, bool * isCQ){
|
||||
quint16 num = 0;
|
||||
|
||||
QStringList unpacked = unpackCompoundMessage(text, &num);
|
||||
|
||||
if(isCQ) *isCQ = (num & (1<<15));
|
||||
|
||||
unpacked.append(Varicode::unpackGrid(num & ((1<<15)-1)));
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num){
|
||||
QString frame;
|
||||
|
||||
@@ -834,10 +881,10 @@ QString Varicode::packCompoundMessage(const QString &baseCallsign, const QString
|
||||
return Varicode::pack64bits(Varicode::bitsToInt(bits)) + Varicode::pack5bits(packed_5 % 32);
|
||||
}
|
||||
|
||||
QStringList Varicode::unpackCompoundMessage(const QString &text){
|
||||
QStringList Varicode::unpackCompoundMessage(const QString &text, quint16 *pNum){
|
||||
QStringList unpacked;
|
||||
|
||||
if(text.length() < 13){
|
||||
if(text.length() < 13 || text.contains(" ")){
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
@@ -856,20 +903,23 @@ QStringList Varicode::unpackCompoundMessage(const QString &text){
|
||||
quint8 is_prefix = Varicode::bitsToInt(Varicode::strToBits(bits.mid(2,1)));
|
||||
quint32 packed_base = Varicode::bitsToInt(Varicode::strToBits(bits.mid(3, 28)));
|
||||
quint32 packed_fix = Varicode::bitsToInt(Varicode::strToBits(bits.mid(31, 22)));
|
||||
quint8 packed_11 = Varicode::bitsToInt(Varicode::strToBits(bits.mid(53, 11)));
|
||||
quint16 packed_11 = Varicode::bitsToInt(Varicode::strToBits(bits.mid(53, 11)));
|
||||
|
||||
QString base = Varicode::unpackCallsign(packed_base).trimmed();
|
||||
QString fix = Varicode::unpackCallsignPrefixSuffix(packed_fix);
|
||||
quint16 num = (packed_11 << 5) | packed_5;
|
||||
|
||||
if(pNum) *pNum = num;
|
||||
|
||||
if(is_prefix){
|
||||
unpacked.append(fix);
|
||||
}
|
||||
|
||||
unpacked.append(base);
|
||||
|
||||
if(!is_prefix){
|
||||
unpacked.append(fix);
|
||||
}
|
||||
unpacked.append(QString("%1").arg(num));
|
||||
|
||||
return unpacked;
|
||||
}
|
||||
@@ -890,12 +940,20 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &baseCa
|
||||
QString pwr = match.captured("pwr").trimmed().toUpper();
|
||||
|
||||
// validate callsign
|
||||
bool validToCallsign = (to != baseCallsign) && (basecalls.contains(to) || QRegularExpression(compound_callsign_pattern).match(to).hasMatch());
|
||||
auto parsedTo = QRegularExpression(compound_callsign_pattern).match(to);
|
||||
bool validToCallsign = (to != baseCallsign) && (basecalls.contains(to) || parsedTo.hasMatch());
|
||||
if(!validToCallsign){
|
||||
if(n) *n = 0;
|
||||
return frame;
|
||||
}
|
||||
|
||||
if(parsedTo.hasMatch()){
|
||||
auto parsedBase = parsedTo.captured("base");
|
||||
if(parsedBase.length() != to.length()){
|
||||
to = parsedBase;
|
||||
}
|
||||
}
|
||||
|
||||
// validate command
|
||||
if(!Varicode::isCommandAllowed(cmd)){
|
||||
if(n) *n = 0;
|
||||
@@ -955,7 +1013,7 @@ QString Varicode::packDirectedMessage(const QString &text, const QString &baseCa
|
||||
QStringList Varicode::unpackDirectedMessage(const QString &text){
|
||||
QStringList unpacked;
|
||||
|
||||
if(text.length() < 13){
|
||||
if(text.length() < 13 || text.contains(" ")){
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
@@ -1034,7 +1092,7 @@ QString Varicode::packDataMessage(const QString &input, QString * out, int *n){
|
||||
QString Varicode::unpackDataMessage(const QString &text){
|
||||
QString unpacked;
|
||||
|
||||
if(text.length() < 13){
|
||||
if(text.length() < 13 || text.contains(" ")){
|
||||
return unpacked;
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -83,8 +83,11 @@ public:
|
||||
static bool isCommandAllowed(const QString &cmd);
|
||||
static bool isCommandBuffered(const QString &cmd);
|
||||
|
||||
static QString packBeaconMessage(QString const &callsign, QString const &extra, bool isCQ);
|
||||
static QStringList unpackBeaconMessage(const QString &text, bool *isCQ);
|
||||
|
||||
static QString packCompoundMessage(const QString &baseCallsign, const QString &fix, bool isPrefix, quint16 num);
|
||||
static QStringList unpackCompoundMessage(const QString &text);
|
||||
static QStringList unpackCompoundMessage(const QString &text, quint16 *pNum);
|
||||
|
||||
static QString packDirectedMessage(QString const& text, QString const& callsign, QString * pCmd, int *n);
|
||||
static QStringList unpackDirectedMessage(QString const& text);
|
||||
|
||||
Reference in New Issue
Block a user