1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-03-30 19:55:52 -04:00

Meshtastic: some Sonar fixes

This commit is contained in:
f4exb 2026-03-27 21:17:46 +01:00
parent 66dfc3a0c8
commit efa232db88
12 changed files with 292 additions and 398 deletions

View File

@ -120,13 +120,13 @@ struct RegionBand
bool wideLora;
};
static const uint8_t kDefaultChannelKey[16] = {
const std::array<uint8_t, 16> kDefaultChannelKey = {
0xD4, 0xF1, 0xBB, 0x3A, 0x20, 0x29, 0x07, 0x59,
0xF0, 0xBC, 0xFF, 0xAB, 0xCF, 0x4E, 0x69, 0x01
};
// Port numbers from meshtastic/portnums.proto (high value subset is accepted as numeric fallback).
static QMap<QString, uint32_t> makePortMap()
QMap<QString, uint32_t> makePortMap()
{
QMap<QString, uint32_t> m;
m.insert("UNKNOWN_APP", 0);
@ -160,9 +160,9 @@ static QMap<QString, uint32_t> makePortMap()
return m;
}
static const QMap<QString, uint32_t> kPortMap = makePortMap();
const QMap<QString, uint32_t> kPortMap = makePortMap();
static const RegionBand kRegionBands[] = {
const std::array<RegionBand, 26> kRegionBands = {{
{"US", 902.0, 928.0, 0.0, false},
{"EU_433", 433.0, 434.0, 0.0, false},
{"EU_868", 869.4, 869.65, 0.0, false},
@ -189,11 +189,11 @@ static const RegionBand kRegionBands[] = {
{"NP_865", 865.0, 868.0, 0.0, false},
{"BR_902", 902.0, 907.5, 0.0, false},
{"LORA_24", 2400.0, 2483.5, 0.0, true}
};
}};
static const int kRegionBandsCount = static_cast<int>(sizeof(kRegionBands) / sizeof(kRegionBands[0]));
const int kRegionBandsCount = static_cast<int>(kRegionBands.size());
static QString trimQuotes(const QString& s)
QString trimQuotes(const QString& s)
{
QString out = s.trimmed();
if ((out.startsWith('"') && out.endsWith('"')) || (out.startsWith('\'') && out.endsWith('\''))) {
@ -202,7 +202,7 @@ static QString trimQuotes(const QString& s)
return out;
}
static bool parseBool(const QString& s, bool& out)
bool parseBool(const QString& s, bool& out)
{
const QString v = s.trimmed().toLower();
@ -219,7 +219,7 @@ static bool parseBool(const QString& s, bool& out)
return false;
}
static bool parseUInt(const QString& s, uint64_t& out)
bool parseUInt(const QString& s, uint64_t& out)
{
QString v = s.trimmed();
v.remove('_');
@ -236,7 +236,7 @@ static bool parseUInt(const QString& s, uint64_t& out)
return ok;
}
static bool parseDouble(const QString& s, double& out)
bool parseDouble(const QString& s, double& out)
{
QString v = s.trimmed();
v.remove('_');
@ -245,7 +245,7 @@ static bool parseDouble(const QString& s, double& out)
return ok;
}
static QString normalizeToken(const QString& value)
QString normalizeToken(const QString& value)
{
QString v = value.trimmed().toUpper();
v.replace('-', '_');
@ -253,7 +253,7 @@ static QString normalizeToken(const QString& value)
return v;
}
static QByteArray normalizeHex(const QString& s)
QByteArray normalizeHex(const QString& s)
{
QByteArray out;
const QByteArray in = s.toLatin1();
@ -269,7 +269,7 @@ static QByteArray normalizeHex(const QString& s)
return out;
}
static bool parseHexBytes(const QString& s, QByteArray& out)
bool parseHexBytes(const QString& s, QByteArray& out)
{
QByteArray hex = normalizeHex(s);
@ -281,7 +281,7 @@ static bool parseHexBytes(const QString& s, QByteArray& out)
return !out.isEmpty();
}
static QByteArray expandSimpleKey(unsigned int simple)
QByteArray expandSimpleKey(unsigned int simple)
{
if (simple == 0) {
return QByteArray();
@ -291,17 +291,17 @@ static QByteArray expandSimpleKey(unsigned int simple)
return QByteArray();
}
QByteArray key(reinterpret_cast<const char*>(kDefaultChannelKey), sizeof(kDefaultChannelKey));
QByteArray key(reinterpret_cast<const char*>(kDefaultChannelKey.data()), static_cast<int>(kDefaultChannelKey.size()));
if (simple > 1) {
const int offset = static_cast<int>(simple - 1);
const auto offset = static_cast<int>(simple - 1);
key[15] = static_cast<char>(static_cast<uint8_t>(kDefaultChannelKey[15] + offset));
}
return key;
}
static bool parseKeySpec(const QString& rawSpec, QByteArray& key, QString& label)
bool parseKeySpec(const QString& rawSpec, QByteArray& key, QString& label)
{
QString spec = rawSpec.trimmed();
const QString lower = spec.toLower();
@ -385,7 +385,7 @@ static bool parseKeySpec(const QString& rawSpec, QByteArray& key, QString& label
return false;
}
static uint32_t readU32LE(const char* p)
uint32_t readU32LE(const char* p)
{
return static_cast<uint32_t>(static_cast<uint8_t>(p[0]))
| (static_cast<uint32_t>(static_cast<uint8_t>(p[1])) << 8)
@ -393,7 +393,7 @@ static uint32_t readU32LE(const char* p)
| (static_cast<uint32_t>(static_cast<uint8_t>(p[3])) << 24);
}
static void writeU32LE(char* p, uint32_t v)
void writeU32LE(char* p, uint32_t v)
{
p[0] = static_cast<char>(v & 0xFF);
p[1] = static_cast<char>((v >> 8) & 0xFF);
@ -401,7 +401,7 @@ static void writeU32LE(char* p, uint32_t v)
p[3] = static_cast<char>((v >> 24) & 0xFF);
}
static bool parseHeader(const QByteArray& frame, Header& h)
bool parseHeader(const QByteArray& frame, Header& h)
{
if (frame.size() < kHeaderLength) {
return false;
@ -418,7 +418,7 @@ static bool parseHeader(const QByteArray& frame, Header& h)
return true;
}
static QByteArray encodeHeader(const Header& h)
QByteArray encodeHeader(const Header& h)
{
QByteArray out(kHeaderLength, 0);
char* p = out.data();
@ -432,14 +432,14 @@ static QByteArray encodeHeader(const Header& h)
return out;
}
static bool readVarint(const QByteArray& bytes, int& pos, uint64_t& value)
bool readVarint(const QByteArray& bytes, int& pos, uint64_t& value)
{
value = 0;
int shift = 0;
while (pos < bytes.size() && shift <= 63)
{
const uint8_t b = static_cast<uint8_t>(bytes[pos++]);
const auto b = static_cast<uint8_t>(bytes[pos++]);
value |= static_cast<uint64_t>(b & 0x7F) << shift;
if ((b & 0x80) == 0) {
@ -452,7 +452,7 @@ static bool readVarint(const QByteArray& bytes, int& pos, uint64_t& value)
return false;
}
static bool readFixed32(const QByteArray& bytes, int& pos, uint32_t& value)
bool readFixed32(const QByteArray& bytes, int& pos, uint32_t& value)
{
if ((pos + 4) > bytes.size()) {
return false;
@ -463,7 +463,7 @@ static bool readFixed32(const QByteArray& bytes, int& pos, uint32_t& value)
return true;
}
static bool readFixed64(const QByteArray& bytes, int& pos, uint64_t& value)
bool readFixed64(const QByteArray& bytes, int& pos, uint64_t& value)
{
if ((pos + 8) > bytes.size()) {
return false;
@ -482,7 +482,7 @@ static bool readFixed64(const QByteArray& bytes, int& pos, uint64_t& value)
return true;
}
static bool skipField(const QByteArray& bytes, int& pos, uint32_t wireType)
bool skipField(const QByteArray& bytes, int& pos, uint32_t wireType)
{
switch (wireType)
{
@ -518,7 +518,7 @@ static bool skipField(const QByteArray& bytes, int& pos, uint32_t wireType)
}
}
static bool parseData(const QByteArray& bytes, DataFields& d)
bool parseData(const QByteArray& bytes, DataFields& d)
{
int pos = 0;
@ -530,8 +530,8 @@ static bool parseData(const QByteArray& bytes, DataFields& d)
return false;
}
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -683,11 +683,11 @@ static bool parseData(const QByteArray& bytes, DataFields& d)
return d.hasPortnum;
}
static void writeVarint(QByteArray& out, uint64_t value)
void writeVarint(QByteArray& out, uint64_t value)
{
while (true)
{
uint8_t b = static_cast<uint8_t>(value & 0x7F);
auto b = static_cast<uint8_t>(value & 0x7F);
value >>= 7;
if (value != 0) {
@ -700,20 +700,20 @@ static void writeVarint(QByteArray& out, uint64_t value)
}
}
static void writeTag(QByteArray& out, uint32_t field, uint32_t wire)
void writeTag(QByteArray& out, uint32_t field, uint32_t wire)
{
const uint64_t tag = (static_cast<uint64_t>(field) << 3) | static_cast<uint64_t>(wire);
writeVarint(out, tag);
}
static void writeFixed32(QByteArray& out, uint32_t v)
void writeFixed32(QByteArray& out, uint32_t v)
{
char b[4];
writeU32LE(b, v);
out.append(b, 4);
}
static QByteArray encodeData(const DataFields& d)
QByteArray encodeData(const DataFields& d)
{
QByteArray out;
@ -764,7 +764,7 @@ static QByteArray encodeData(const DataFields& d)
return out;
}
static uint8_t xorHash(const QByteArray& bytes)
uint8_t xorHash(const QByteArray& bytes)
{
uint8_t h = 0;
@ -775,7 +775,7 @@ static uint8_t xorHash(const QByteArray& bytes)
return h;
}
static uint8_t generateChannelHash(const QString& channelName, const QByteArray& key)
uint8_t generateChannelHash(const QString& channelName, const QByteArray& key)
{
QByteArray name = channelName.toUtf8();
@ -806,24 +806,24 @@ public:
void encryptBlock(const uint8_t in[16], uint8_t out[16]) const
{
uint8_t state[16];
memcpy(state, in, 16);
std::array<uint8_t, 16> state;
memcpy(state.data(), in, 16);
addRoundKey(state, 0);
addRoundKey(state.data(), 0);
for (int round = 1; round < m_nr; ++round)
{
subBytes(state);
shiftRows(state);
mixColumns(state);
addRoundKey(state, round);
subBytes(state.data());
shiftRows(state.data());
mixColumns(state.data());
addRoundKey(state.data(), round);
}
subBytes(state);
shiftRows(state);
addRoundKey(state, m_nr);
subBytes(state.data());
shiftRows(state.data());
addRoundKey(state.data(), m_nr);
memcpy(out, state, 16);
memcpy(out, state.data(), 16);
}
private:
@ -857,7 +857,7 @@ private:
static uint8_t sub(uint8_t x)
{
static const uint8_t sbox[256] = {
static const std::array<uint8_t, 256> sbox = {
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
@ -950,7 +950,7 @@ private:
void keyExpansion(const uint8_t* key)
{
static const uint8_t rcon[11] = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
static const std::array<uint8_t, 11> rcon = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
const int words = 4 * (m_nr + 1);
std::vector<uint32_t> w(words, 0);
@ -992,7 +992,7 @@ enum class CounterMode
LittleEndian
};
static void incrementCounter4(uint8_t counter[16], CounterMode mode)
void incrementCounter4(uint8_t counter[16], CounterMode mode)
{
if (mode == CounterMode::BigEndian)
{
@ -1016,7 +1016,7 @@ static void incrementCounter4(uint8_t counter[16], CounterMode mode)
}
}
static void initNonce(uint8_t nonce[16], uint32_t fromNode, uint32_t packetId)
void initNonce(uint8_t nonce[16], uint32_t fromNode, uint32_t packetId)
{
memset(nonce, 0, 16);
@ -1025,7 +1025,7 @@ static void initNonce(uint8_t nonce[16], uint32_t fromNode, uint32_t packetId)
memcpy(nonce + sizeof(packetId64), &fromNode, sizeof(fromNode));
}
static QByteArray aesCtrCrypt(const QByteArray& in, const QByteArray& key, uint32_t fromNode, uint32_t packetId, CounterMode mode)
QByteArray aesCtrCrypt(const QByteArray& in, const QByteArray& key, uint32_t fromNode, uint32_t packetId, CounterMode mode)
{
QByteArray out(in);
@ -1039,14 +1039,14 @@ static QByteArray aesCtrCrypt(const QByteArray& in, const QByteArray& key, uint3
return QByteArray();
}
uint8_t counter[16];
initNonce(counter, fromNode, packetId);
std::array<uint8_t, 16> counter;
initNonce(counter.data(), fromNode, packetId);
int pos = 0;
while (pos < out.size())
{
uint8_t keystream[16];
aes.encryptBlock(counter, keystream);
std::array<uint8_t, 16> keystream;
aes.encryptBlock(counter.data(), keystream.data());
const int remain = std::min<int>(16, static_cast<int>(out.size() - pos));
for (int i = 0; i < remain; ++i) {
@ -1054,18 +1054,18 @@ static QByteArray aesCtrCrypt(const QByteArray& in, const QByteArray& key, uint3
}
pos += remain;
incrementCounter4(counter, mode);
incrementCounter4(counter.data(), mode);
}
return out;
}
static QString formatNode(uint32_t node)
QString formatNode(uint32_t node)
{
return QString("0x%1").arg(node, 8, 16, QChar('0'));
}
static QString payloadToText(const QByteArray& payload)
QString payloadToText(const QByteArray& payload)
{
QString s = QString::fromUtf8(payload);
@ -1076,7 +1076,7 @@ static QString payloadToText(const QByteArray& payload)
return s;
}
static QString portToName(uint32_t p)
QString portToName(uint32_t p)
{
for (auto it = kPortMap.constBegin(); it != kPortMap.constEnd(); ++it)
{
@ -1088,7 +1088,7 @@ static QString portToName(uint32_t p)
return QString("PORT_%1").arg(p);
}
static bool addKeyEntry(
bool addKeyEntry(
std::vector<KeyEntry>& keys,
const QString& channelName,
const QString& keySpec,
@ -1120,7 +1120,7 @@ static bool addKeyEntry(
return true;
}
static bool parseKeyListEntry(
bool parseKeyListEntry(
const QString& rawEntry,
QString& channelName,
QString& keySpec,
@ -1174,7 +1174,7 @@ static bool parseKeyListEntry(
return true;
}
static bool parseKeySpecList(
bool parseKeySpecList(
const QString& rawList,
std::vector<KeyEntry>& keys,
QString* error = nullptr,
@ -1232,7 +1232,7 @@ static bool parseKeySpecList(
return true;
}
static std::vector<KeyEntry> defaultKeysFromEnv()
std::vector<KeyEntry> defaultKeysFromEnv()
{
std::vector<KeyEntry> keys;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@ -1260,7 +1260,7 @@ static std::vector<KeyEntry> defaultKeysFromEnv()
return keys;
}
static bool parsePortValue(const QString& raw, uint32_t& port)
bool parsePortValue(const QString& raw, uint32_t& port)
{
uint64_t numeric = 0;
if (parseUInt(raw, numeric)) {
@ -1283,7 +1283,7 @@ static bool parsePortValue(const QString& raw, uint32_t& port)
return false;
}
static bool parsePresetName(const QString& presetValue, QString& presetName)
bool parsePresetName(const QString& presetValue, QString& presetName)
{
QString p = normalizeToken(presetValue);
p.remove('_');
@ -1300,7 +1300,7 @@ static bool parsePresetName(const QString& presetValue, QString& presetName)
return false;
}
static bool presetToChannelName(const QString& presetName, QString& channelName)
bool presetToChannelName(const QString& presetName, QString& channelName)
{
if (presetName == "LONG_FAST") { channelName = "LongFast"; return true; }
if (presetName == "LONG_SLOW") { channelName = "LongSlow"; return true; }
@ -1314,7 +1314,7 @@ static bool presetToChannelName(const QString& presetName, QString& channelName)
return false;
}
static bool presetToParams(const QString& presetName, bool wideLora, int& bandwidthHz, int& spreadFactor, int& parityBits)
bool presetToParams(const QString& presetName, bool wideLora, int& bandwidthHz, int& spreadFactor, int& parityBits)
{
int bwKHz = 0;
int sf = 0;
@ -1339,7 +1339,7 @@ static bool presetToParams(const QString& presetName, bool wideLora, int& bandwi
return true;
}
static QString presetToDisplayName(const QString& presetName)
QString presetToDisplayName(const QString& presetName)
{
QString channelName;
if (presetToChannelName(presetName, channelName)) {
@ -1348,7 +1348,7 @@ static QString presetToDisplayName(const QString& presetName)
return QString("LongFast");
}
static uint32_t meshHashDjb2(const QString& s)
uint32_t meshHashDjb2(const QString& s)
{
const QByteArray bytes = s.toUtf8();
uint32_t h = 5381u;
@ -1358,7 +1358,7 @@ static uint32_t meshHashDjb2(const QString& s)
return h;
}
static const RegionBand* findRegionBand(const QString& regionValue)
const RegionBand* findRegionBand(const QString& regionValue)
{
QString r = normalizeToken(regionValue);
r.remove('_');
@ -1391,7 +1391,7 @@ static const RegionBand* findRegionBand(const QString& regionValue)
return nullptr;
}
static bool parseCommand(const QString& command, CommandConfig& cfg, QString& error)
bool parseCommand(const QString& command, CommandConfig& cfg, QString& error)
{
if (!Packet::isCommand(command)) {
error = "command must start with MESH:";
@ -1669,7 +1669,7 @@ static bool parseCommand(const QString& command, CommandConfig& cfg, QString& er
}
else if (key == "freq_hz" || key == "frequency_hz")
{
if (!parseUInt(value, u) || u < 1000000ull) {
if (!parseUInt(value, u) || u < 1000000ULL) {
error = "invalid frequency_hz";
return false;
}
@ -1772,9 +1772,9 @@ static bool parseCommand(const QString& command, CommandConfig& cfg, QString& er
}
// Forward declaration: summarizePortPayload is defined after the per-port parsers below.
static QString summarizePortPayload(const DataFields& d);
QString summarizePortPayload(const DataFields& d);
static QString summarizeHeader(const Header& h)
QString summarizeHeader(const Header& h)
{
const int hopLimit = h.flags & kFlagHopLimitMask;
const int hopStart = (h.flags & kFlagHopStartMask) >> 5;
@ -1794,7 +1794,7 @@ static QString summarizeHeader(const Header& h)
.arg(h.relayNode);
}
static QString summarizeData(const DataFields& d)
QString summarizeData(const DataFields& d)
{
const QString portName = portToName(d.portnum);
QString s = QString("port=%1(%2)").arg(portName).arg(d.portnum);
@ -1832,7 +1832,7 @@ static QString summarizeData(const DataFields& d)
return s;
}
static void addDecodeField(DecodeResult& result, const QString& path, const QString& value)
void addDecodeField(DecodeResult& result, const QString& path, const QString& value)
{
DecodeResult::Field f;
f.path = path;
@ -1840,17 +1840,17 @@ static void addDecodeField(DecodeResult& result, const QString& path, const QStr
result.fields.append(f);
}
static void addDecodeField(DecodeResult& result, const QString& path, uint32_t value)
void addDecodeField(DecodeResult& result, const QString& path, uint32_t value)
{
addDecodeField(result, path, QString::number(value));
}
static void addDecodeField(DecodeResult& result, const QString& path, bool value)
void addDecodeField(DecodeResult& result, const QString& path, bool value)
{
addDecodeField(result, path, QString(value ? "true" : "false"));
}
static void appendHeaderDecodeFields(const Header& h, DecodeResult& result)
void appendHeaderDecodeFields(const Header& h, DecodeResult& result)
{
const int hopLimit = h.flags & kFlagHopLimitMask;
const int hopStart = (h.flags & kFlagHopStartMask) >> 5;
@ -1881,29 +1881,29 @@ static void appendHeaderDecodeFields(const Header& h, DecodeResult& result)
// --- Shared decode helpers ---
/** Zigzag-decode a protobuf sint32 value. */
static int32_t zigzagDecode32(uint64_t n)
int32_t zigzagDecode32(uint64_t n)
{
return static_cast<int32_t>((n >> 1) ^ static_cast<uint64_t>(-(static_cast<int64_t>(n & 1))));
}
/** Reinterpret the 4 bytes of a protobuf fixed32 field as an IEEE 754 float. */
static float fixed32ToFloat(uint32_t v)
float fixed32ToFloat(uint32_t v)
{
float f;
memcpy(&f, &v, 4);
return f;
}
static double fixed64ToDouble(uint64_t v)
double fixed64ToDouble(uint64_t v)
{
double d;
memcpy(&d, &v, 8);
return d;
}
static bool decodeCoordinateFromFixed32(uint32_t raw, double& coordinate)
bool decodeCoordinateFromFixed32(uint32_t raw, double& coordinate)
{
const int32_t fixedValue = static_cast<int32_t>(raw);
const auto fixedValue = static_cast<int32_t>(raw);
const double scaled = static_cast<double>(fixedValue) / 1e7;
if (std::isfinite(scaled) && std::fabs(scaled) <= 180.0)
@ -1912,7 +1912,7 @@ static bool decodeCoordinateFromFixed32(uint32_t raw, double& coordinate)
return true;
}
const double floatValue = static_cast<double>(fixed32ToFloat(raw));
const auto floatValue = static_cast<double>(fixed32ToFloat(raw));
if (std::isfinite(floatValue) && std::fabs(floatValue) <= 180.0)
{
coordinate = floatValue;
@ -1963,7 +1963,7 @@ struct PositionFields
uint32_t timestamp = 0; // Unix timestamp, preferred (uint32 field 32)
};
static bool parsePositionPayload(const QByteArray& bytes, PositionFields& p)
bool parsePositionPayload(const QByteArray& bytes, PositionFields& p)
{
int pos = 0;
@ -1974,8 +1974,8 @@ static bool parsePositionPayload(const QByteArray& bytes, PositionFields& p)
return false;
}
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2186,7 +2186,7 @@ static bool parsePositionPayload(const QByteArray& bytes, PositionFields& p)
return p.hasLatitude || p.hasLongitude || p.hasAltitude || p.hasTime || p.hasTimestamp;
}
static void appendPositionDecodeFields(const PositionFields& p, DecodeResult& result)
void appendPositionDecodeFields(const PositionFields& p, DecodeResult& result)
{
if (p.hasLatitude) {
addDecodeField(result, "position.latitude",
@ -2249,7 +2249,7 @@ struct UserFields
bool isLicensed = false; // licensed amateur radio operator (bool field 7)
};
static bool parseUserPayload(const QByteArray& bytes, UserFields& u)
bool parseUserPayload(const QByteArray& bytes, UserFields& u)
{
int pos = 0;
@ -2258,8 +2258,8 @@ static bool parseUserPayload(const QByteArray& bytes, UserFields& u)
uint64_t rawTag = 0;
if (!readVarint(bytes, pos, rawTag)) { return false; }
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2365,7 +2365,7 @@ static bool parseUserPayload(const QByteArray& bytes, UserFields& u)
return u.hasId || u.hasLongName || u.hasShortName || u.hasMacaddr || u.hasHwModel || u.hasIsLicensed;
}
static void appendUserDecodeFields(const UserFields& u, DecodeResult& result)
void appendUserDecodeFields(const UserFields& u, DecodeResult& result)
{
if (u.hasId) { addDecodeField(result, "nodeinfo.id", u.id); }
if (u.hasLongName) { addDecodeField(result, "nodeinfo.long_name", u.longName); }
@ -2429,7 +2429,7 @@ struct TelemetryFields
EnvironmentMetrics environmentMetrics;
};
static bool parseDeviceMetrics(const QByteArray& bytes, DeviceMetrics& dm)
bool parseDeviceMetrics(const QByteArray& bytes, DeviceMetrics& dm)
{
int pos = 0;
@ -2438,8 +2438,8 @@ static bool parseDeviceMetrics(const QByteArray& bytes, DeviceMetrics& dm)
uint64_t rawTag = 0;
if (!readVarint(bytes, pos, rawTag)) { return false; }
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2476,7 +2476,7 @@ static bool parseDeviceMetrics(const QByteArray& bytes, DeviceMetrics& dm)
{
uint64_t v = 0;
if (!readVarint(bytes, pos, v)) { return false; }
const double raw = static_cast<double>(v);
const auto raw = static_cast<double>(v);
dm.voltage = static_cast<float>((raw > 1000.0) ? (raw / 1000.0) : raw);
dm.hasVoltage = true;
}
@ -2558,7 +2558,7 @@ static bool parseDeviceMetrics(const QByteArray& bytes, DeviceMetrics& dm)
return true;
}
static bool parseEnvironmentMetrics(const QByteArray& bytes, EnvironmentMetrics& em)
bool parseEnvironmentMetrics(const QByteArray& bytes, EnvironmentMetrics& em)
{
int pos = 0;
@ -2567,8 +2567,8 @@ static bool parseEnvironmentMetrics(const QByteArray& bytes, EnvironmentMetrics&
uint64_t rawTag = 0;
if (!readVarint(bytes, pos, rawTag)) { return false; }
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2660,7 +2660,7 @@ static bool parseEnvironmentMetrics(const QByteArray& bytes, EnvironmentMetrics&
return true;
}
static bool parseTelemetryPayload(const QByteArray& bytes, TelemetryFields& t)
bool parseTelemetryPayload(const QByteArray& bytes, TelemetryFields& t)
{
int pos = 0;
@ -2669,8 +2669,8 @@ static bool parseTelemetryPayload(const QByteArray& bytes, TelemetryFields& t)
uint64_t rawTag = 0;
if (!readVarint(bytes, pos, rawTag)) { return false; }
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2724,7 +2724,7 @@ static bool parseTelemetryPayload(const QByteArray& bytes, TelemetryFields& t)
return t.hasTime || t.hasDeviceMetrics || t.hasEnvironmentMetrics;
}
static void appendTelemetryDecodeFields(const TelemetryFields& t, DecodeResult& result)
void appendTelemetryDecodeFields(const TelemetryFields& t, DecodeResult& result)
{
if (t.hasTime)
{
@ -2798,7 +2798,7 @@ struct RouteDiscoveryFields
};
/** Parse a packed repeated fixed32 block (content only, length already consumed). */
static void parsePackedFixed32(const QByteArray& bytes, QVector<uint32_t>& out)
void parsePackedFixed32(const QByteArray& bytes, QVector<uint32_t>& out)
{
int pos = 0;
while ((pos + 4) <= bytes.size())
@ -2809,7 +2809,7 @@ static void parsePackedFixed32(const QByteArray& bytes, QVector<uint32_t>& out)
}
/** Parse a packed repeated sint32 block (content only, length already consumed). */
static void parsePackedVarintSint32(const QByteArray& bytes, QVector<int32_t>& out)
void parsePackedVarintSint32(const QByteArray& bytes, QVector<int32_t>& out)
{
int pos = 0;
while (pos < bytes.size())
@ -2820,7 +2820,7 @@ static void parsePackedVarintSint32(const QByteArray& bytes, QVector<int32_t>& o
}
}
static bool parseRouteDiscoveryPayload(const QByteArray& bytes, RouteDiscoveryFields& r)
bool parseRouteDiscoveryPayload(const QByteArray& bytes, RouteDiscoveryFields& r)
{
int pos = 0;
@ -2829,8 +2829,8 @@ static bool parseRouteDiscoveryPayload(const QByteArray& bytes, RouteDiscoveryFi
uint64_t rawTag = 0;
if (!readVarint(bytes, pos, rawTag)) { return false; }
const uint32_t field = static_cast<uint32_t>(rawTag >> 3);
const uint32_t wire = static_cast<uint32_t>(rawTag & 0x7);
const auto field = static_cast<uint32_t>(rawTag >> 3);
const auto wire = static_cast<uint32_t>(rawTag & 0x7);
switch (field)
{
@ -2907,7 +2907,7 @@ static bool parseRouteDiscoveryPayload(const QByteArray& bytes, RouteDiscoveryFi
return !r.route.isEmpty() || !r.routeBack.isEmpty();
}
static void appendRouteDiscoveryDecodeFields(const RouteDiscoveryFields& r, DecodeResult& result)
void appendRouteDiscoveryDecodeFields(const RouteDiscoveryFields& r, DecodeResult& result)
{
addDecodeField(result, "traceroute.forward_hops", QString::number(r.route.size()));
@ -2938,13 +2938,13 @@ static void appendRouteDiscoveryDecodeFields(const RouteDiscoveryFields& r, Deco
}
}
static QString summarizePortPayload(const DataFields& d)
QString summarizePortPayload(const DataFields& d)
{
if (d.payload.isEmpty()) {
return " payload=<empty>";
}
const auto appendPayloadHex = [&d]() -> QString {
const auto appendPayloadHex = [&d]() {
const int n = std::min<int>(32, static_cast<int>(d.payload.size()));
QString text = QString(" payload_hex=%1").arg(QString(d.payload.left(n).toHex()));
if (d.payload.size() > n) {
@ -3095,7 +3095,7 @@ static QString summarizePortPayload(const DataFields& d)
// falls back to generic text / hex for everything else.
// =============================================================================
static void appendDataDecodeFields(const DataFields& d, DecodeResult& result)
void appendDataDecodeFields(const DataFields& d, DecodeResult& result)
{
addDecodeField(result, "data.port_name", portToName(d.portnum));
addDecodeField(result, "data.portnum", d.portnum);
@ -3203,7 +3203,7 @@ static void appendDataDecodeFields(const DataFields& d, DecodeResult& result)
}
}
static bool deriveTxRadioSettingsFromConfig(const CommandConfig& cfg, TxRadioSettings& settings, QString& error)
bool deriveTxRadioSettingsFromConfig(const CommandConfig& cfg, TxRadioSettings& settings, QString& error)
{
settings = TxRadioSettings();
settings.hasCommand = true;
@ -3251,14 +3251,14 @@ static bool deriveTxRadioSettingsFromConfig(const CommandConfig& cfg, TxRadioSet
{
const double freqMHz = cfg.overrideFrequencyMHz + (cfg.hasFrequencyOffsetMHz ? cfg.frequencyOffsetMHz : 0.0);
settings.hasCenterFrequency = true;
settings.centerFrequencyHz = static_cast<qint64>(std::llround(freqMHz * 1000000.0));
settings.centerFrequencyHz = std::llround(freqMHz * 1000000.0);
}
else if (region)
{
const double bwMHz = static_cast<double>(bandwidthHz) / 1000000.0;
const double slotWidthMHz = region->spacingMHz + bwMHz;
const double spanMHz = region->freqEndMHz - region->freqStartMHz;
const uint32_t numChannels = static_cast<uint32_t>(std::floor(spanMHz / slotWidthMHz));
const auto numChannels = static_cast<uint32_t>(std::floor(spanMHz / slotWidthMHz));
if (numChannels == 0) {
error = "region span too narrow for selected preset bandwidth";
@ -3284,7 +3284,7 @@ static bool deriveTxRadioSettingsFromConfig(const CommandConfig& cfg, TxRadioSet
+ (cfg.hasFrequencyOffsetMHz ? cfg.frequencyOffsetMHz : 0.0);
settings.hasCenterFrequency = true;
settings.centerFrequencyHz = static_cast<qint64>(std::llround(centerMHz * 1000000.0));
settings.centerFrequencyHz = std::llround(centerMHz * 1000000.0);
}
settings.summary = QString("preset=%1 sf=%2 cr=4/%3 bw=%4kHz de=%5")

View File

@ -262,10 +262,10 @@ void MeshtasticDemod::applyPipelineRuntimeSettings(PipelineRuntime& runtime, con
if (runtime.decoder)
{
runtime.decoder->setCodingScheme(settings.m_codingScheme);
runtime.decoder->setCodingScheme(MeshtasticDemodSettings::m_codingScheme);
runtime.decoder->setNbSymbolBits(settings.m_spreadFactor, settings.m_deBits);
runtime.decoder->setLoRaHasHeader(settings.m_hasHeader);
runtime.decoder->setLoRaHasCRC(settings.m_hasCRC);
runtime.decoder->setLoRaHasHeader(MeshtasticDemodSettings::m_hasHeader);
runtime.decoder->setLoRaHasCRC(MeshtasticDemodSettings::m_hasCRC);
runtime.decoder->setLoRaParityBits(settings.m_nbParityBits);
runtime.decoder->setLoRaPacketLength(settings.m_packetLength);
runtime.decoder->setLoRaBandwidth(MeshtasticDemodSettings::bandwidths[settings.m_bandwidthIndex]);
@ -512,12 +512,10 @@ void MeshtasticDemod::start()
}
qDebug() << "MeshtasticDemod::start";
m_pipelineConfigs.push_back(PipelineConfig());
m_pipelineConfigs.emplace_back();
m_currentPipelineId = 0;
makePipelineConfigFromSettings(m_currentPipelineId, m_pipelineConfigs.back(), m_settings);
startPipelines(m_pipelineConfigs);
// const std::vector<PipelineConfig> configs = buildPipelineConfigs(m_settings);
// startPipelines(configs);
SpectrumSettings spectrumSettings = m_spectrumVis.getSettings();
spectrumSettings.m_ssb = true;
@ -553,7 +551,7 @@ bool MeshtasticDemod::handleMessage(const Message& cmd)
else if (MsgSetExtraPipelineSettings::match(cmd))
{
qDebug() << "MeshtasticDemod::handleMessage: MsgSetExtraPipelineSettings";
const MsgSetExtraPipelineSettings& msg = static_cast<const MsgSetExtraPipelineSettings&>(cmd);
const auto& msg = static_cast<const MsgSetExtraPipelineSettings&>(cmd);
applyExtraPipelineSettings(msg.getSettingsList(), false);
return true;
}
@ -567,132 +565,112 @@ bool MeshtasticDemod::handleMessage(const Message& cmd)
m_lastMsgSyncWord = msg.getSyncWord();
m_lastMsgTimestamp = msg.getMsgTimestamp();
if (m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa)
m_lastMsgBytes = msg.getBytes();
m_lastMsgPacketLength = msg.getPacketSize();
m_lastMsgNbParityBits = msg.getNbParityBits();
m_lastMsgHasCRC = msg.getHasCRC();
m_lastMsgNbSymbols = msg.getNbSymbols();
m_lastMsgNbCodewords = msg.getNbCodewords();
m_lastMsgEarlyEOM = msg.getEarlyEOM();
m_lastMsgHeaderCRC = msg.getHeaderCRCStatus();
m_lastMsgHeaderParityStatus = msg.getHeaderParityStatus();
m_lastMsgPayloadCRC = msg.getPayloadCRCStatus();
m_lastMsgPayloadParityStatus = msg.getPayloadParityStatus();
m_lastMsgPipelineName = msg.getPipelineName();
m_lastFrameType = QStringLiteral("LORA_FRAME");
QByteArray bytesCopy(m_lastMsgBytes);
bytesCopy.truncate(m_lastMsgPacketLength);
bytesCopy.replace('\0', " ");
m_lastMsgString = QString(bytesCopy.toStdString().c_str());
if (m_settings.m_sendViaUDP)
{
m_lastMsgBytes = msg.getBytes();
m_lastMsgPacketLength = msg.getPacketSize();
m_lastMsgNbParityBits = msg.getNbParityBits();
m_lastMsgHasCRC = msg.getHasCRC();
m_lastMsgNbSymbols = msg.getNbSymbols();
m_lastMsgNbCodewords = msg.getNbCodewords();
m_lastMsgEarlyEOM = msg.getEarlyEOM();
m_lastMsgHeaderCRC = msg.getHeaderCRCStatus();
m_lastMsgHeaderParityStatus = msg.getHeaderParityStatus();
m_lastMsgPayloadCRC = msg.getPayloadCRCStatus();
m_lastMsgPayloadParityStatus = msg.getPayloadParityStatus();
m_lastMsgPipelineName = msg.getPipelineName();
m_lastFrameType = QStringLiteral("LORA_FRAME");
uint8_t *bytes = reinterpret_cast<uint8_t*>(m_lastMsgBytes.data());
m_udpSink.writeUnbuffered(bytes, m_lastMsgPacketLength);
}
QByteArray bytesCopy(m_lastMsgBytes);
bytesCopy.truncate(m_lastMsgPacketLength);
bytesCopy.replace('\0', " ");
m_lastMsgString = QString(bytesCopy.toStdString().c_str());
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push(new MeshtasticDemodMsg::MsgReportDecodeBytes(msg)); // make a copy
}
if (m_settings.m_sendViaUDP)
modemmeshtastic::DecodeResult meshResult;
if (modemmeshtastic::Packet::decodeFrame(m_lastMsgBytes, meshResult, m_settings.m_meshtasticKeySpecList))
{
m_lastMsgString = meshResult.summary;
for (const modemmeshtastic::DecodeResult::Field& field : meshResult.fields)
{
uint8_t *bytes = reinterpret_cast<uint8_t*>(m_lastMsgBytes.data());
m_udpSink.writeUnbuffered(bytes, m_lastMsgPacketLength);
}
if (getMessageQueueToGUI()) {
getMessageQueueToGUI()->push(new MeshtasticDemodMsg::MsgReportDecodeBytes(msg)); // make a copy
}
modemmeshtastic::DecodeResult meshResult;
if (modemmeshtastic::Packet::decodeFrame(m_lastMsgBytes, meshResult, m_settings.m_meshtasticKeySpecList))
{
m_lastMsgString = meshResult.summary;
for (const modemmeshtastic::DecodeResult::Field& field : meshResult.fields)
if (field.path == QStringLiteral("data.port_name"))
{
if (field.path == QStringLiteral("data.port_name"))
{
m_lastFrameType = field.value;
break;
}
}
qInfo() << "MeshtasticDemod::handleMessage:" << meshResult.summary;
if (meshResult.dataDecoded && getMessageQueueToGUI())
{
MeshtasticDemodMsg::MsgReportDecodeString *meshMsg = MeshtasticDemodMsg::MsgReportDecodeString::create(meshResult.summary);
meshMsg->setFrameId(msg.getFrameId());
meshMsg->setSyncWord(msg.getSyncWord());
meshMsg->setSignalDb(msg.getSingalDb());
meshMsg->setNoiseDb(msg.getNoiseDb());
meshMsg->setMsgTimestamp(msg.getMsgTimestamp());
meshMsg->setPipelineMetadata(msg.getPipelineId(), msg.getPipelineName(), msg.getPipelinePreset());
QVector<QPair<QString, QString>> structuredFields;
structuredFields.reserve(meshResult.fields.size());
for (const modemmeshtastic::DecodeResult::Field& field : meshResult.fields) {
structuredFields.append(qMakePair(field.path, field.value));
}
meshMsg->setStructuredFields(structuredFields);
getMessageQueueToGUI()->push(meshMsg);
m_lastFrameType = field.value;
break;
}
}
// Is this an APRS packet?
// As per: https://github.com/oe3cjb/TTGO-T-Beam-LoRa-APRS/blob/master/lib/BG_RF95/BG_RF95.cpp
// There is a 3 byte header for LoRa APRS packets. Addressing follows in ASCII: srccall>dst:
int colonIdx = m_lastMsgBytes.indexOf(':');
int greaterThanIdx = m_lastMsgBytes.indexOf('>');
if ( (m_lastMsgBytes[0] == '<')
&& (greaterThanIdx != -1)
&& (colonIdx != -1)
&& ((m_lastMsgHasCRC && m_lastMsgPayloadCRC) || !m_lastMsgHasCRC)
)
qInfo() << "MeshtasticDemod::handleMessage:" << meshResult.summary;
if (meshResult.dataDecoded && getMessageQueueToGUI())
{
QByteArray packet;
MeshtasticDemodMsg::MsgReportDecodeString *meshMsg = MeshtasticDemodMsg::MsgReportDecodeString::create(meshResult.summary);
meshMsg->setFrameId(msg.getFrameId());
meshMsg->setSyncWord(msg.getSyncWord());
meshMsg->setSignalDb(msg.getSingalDb());
meshMsg->setNoiseDb(msg.getNoiseDb());
meshMsg->setMsgTimestamp(msg.getMsgTimestamp());
meshMsg->setPipelineMetadata(msg.getPipelineId(), msg.getPipelineName(), msg.getPipelinePreset());
QVector<QPair<QString, QString>> structuredFields;
structuredFields.reserve(meshResult.fields.size());
// Extract addresses
const char *d = m_lastMsgBytes.data();
QString srcString = QString::fromLatin1(d + 3, greaterThanIdx - 3);
QString dstString = QString::fromLatin1(d + greaterThanIdx + 1, colonIdx - greaterThanIdx - 1);
// Convert to AX.25 format
packet.append(AX25Packet::encodeAddress(dstString));
packet.append(AX25Packet::encodeAddress(srcString, 1));
packet.append(3);
packet.append(-16); // 0xf0
packet.append(m_lastMsgBytes.mid(colonIdx+1));
if (!m_lastMsgHasCRC)
{
packet.append((char)0); // dummy crc
packet.append((char)0);
for (const modemmeshtastic::DecodeResult::Field& field : meshResult.fields) {
structuredFields.append(qMakePair(field.path, field.value));
}
// Forward to APRS and other packet features
QList<ObjectPipe*> packetsPipes;
MainCore::instance()->getMessagePipes().getMessagePipes(this, "packets", packetsPipes);
meshMsg->setStructuredFields(structuredFields);
getMessageQueueToGUI()->push(meshMsg);
}
}
for (const auto& pipe : packetsPipes)
{
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(this, packet, QDateTime::currentDateTime());
messageQueue->push(msg);
}
// Is this an APRS packet?
// As per: https://github.com/oe3cjb/TTGO-T-Beam-LoRa-APRS/blob/master/lib/BG_RF95/BG_RF95.cpp
// There is a 3 byte header for LoRa APRS packets. Addressing follows in ASCII: srccall>dst:
int colonIdx = m_lastMsgBytes.indexOf(':');
int greaterThanIdx = m_lastMsgBytes.indexOf('>');
if ( (m_lastMsgBytes[0] == '<')
&& (greaterThanIdx != -1)
&& (colonIdx != -1)
&& ((m_lastMsgHasCRC && m_lastMsgPayloadCRC) || !m_lastMsgHasCRC)
)
{
QByteArray packet;
// Extract addresses
const char *d = m_lastMsgBytes.data();
QString srcString = QString::fromLatin1(d + 3, greaterThanIdx - 3);
QString dstString = QString::fromLatin1(d + greaterThanIdx + 1, colonIdx - greaterThanIdx - 1);
// Convert to AX.25 format
packet.append(AX25Packet::encodeAddress(dstString));
packet.append(AX25Packet::encodeAddress(srcString, 1));
packet.append(3);
packet.append(-16); // 0xf0
packet.append(m_lastMsgBytes.mid(colonIdx+1));
if (!m_lastMsgHasCRC)
{
packet.append((char)0); // dummy crc
packet.append((char)0);
}
// In explicit-header LoRa mode, frame length is already derived from header
// and may legitimately vary across packets. Auto-clamping nbSymbolsMax to the
// first short frame breaks subsequent longer frames.
if (m_settings.m_autoNbSymbolsMax
&& !((m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa) && m_settings.m_hasHeader))
{
MeshtasticDemodSettings settings = m_settings;
settings.m_nbSymbolsMax = m_lastMsgNbSymbols;
applySettings(settings);
// Forward to APRS and other packet features
QList<ObjectPipe*> packetsPipes;
MainCore::instance()->getMessagePipes().getMessagePipes(this, "packets", packetsPipes);
if (getMessageQueueToGUI()) // forward to GUI if any
{
MsgConfigureMeshtasticDemod *msgToGUI = MsgConfigureMeshtasticDemod::create(settings, false);
getMessageQueueToGUI()->push(msgToGUI);
}
for (const auto& pipe : packetsPipes)
{
MessageQueue *messageQueue = qobject_cast<MessageQueue*>(pipe->m_element);
MainCore::MsgPacket *msg = MainCore::MsgPacket::create(this, packet, QDateTime::currentDateTime());
messageQueue->push(msg);
}
}
@ -799,12 +777,12 @@ void MeshtasticDemod::applySettings(MeshtasticDemodSettings settings, bool force
<< " m_bandwidthIndex: " << settings.m_bandwidthIndex
<< " m_spreadFactor: " << settings.m_spreadFactor
<< " m_deBits: " << settings.m_deBits
<< " m_codingScheme: " << settings.m_codingScheme
<< " m_hasHeader: " << settings.m_hasHeader
<< " m_hasCRC: " << settings.m_hasCRC
<< " m_codingScheme: " << MeshtasticDemodSettings::m_codingScheme
<< " m_hasHeader: " << MeshtasticDemodSettings::m_hasHeader
<< " m_hasCRC: " << MeshtasticDemodSettings::m_hasCRC
<< " m_nbParityBits: " << settings.m_nbParityBits
<< " m_packetLength: " << settings.m_packetLength
<< " m_autoNbSymbolsMax: " << settings.m_autoNbSymbolsMax
<< " m_autoNbSymbolsMax: " << MeshtasticDemodSettings::m_autoNbSymbolsMax
<< " m_sendViaUDP: " << settings.m_sendViaUDP
<< " m_udpAddress: " << settings.m_udpAddress
<< " m_udpPort: " << settings.m_udpPort
@ -917,7 +895,6 @@ void MeshtasticDemod::applySettings(MeshtasticDemodSettings settings, bool force
// settings so that m_settings and the GUI stay in sync with what was actually applied.
// Skip for USER preset: those parameters are controlled entirely by the user via the GUI.
if (m_running && !m_pipelineConfigs.empty() &&
settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa &&
settings.m_meshtasticPresetName.trimmed().compare("USER", Qt::CaseInsensitive) != 0)
{
const MeshtasticDemodSettings& derived = m_pipelineConfigs[0].settings;
@ -932,7 +909,7 @@ void MeshtasticDemod::applySettings(MeshtasticDemodSettings settings, bool force
if (bwChanged)
{
DSPSignalNotification *bwMsg = new DSPSignalNotification(
auto *bwMsg = new DSPSignalNotification(
MeshtasticDemodSettings::bandwidths[settings.m_bandwidthIndex], 0);
m_spectrumVis.getInputMessageQueue()->push(bwMsg);
}

View File

@ -59,7 +59,7 @@ public:
}
private:
QVector<MeshtasticDemodSettings> m_settingsList;
MsgSetExtraPipelineSettings(const QVector<MeshtasticDemodSettings>& settingsList) :
explicit MsgSetExtraPipelineSettings(const QVector<MeshtasticDemodSettings>& settingsList) :
Message(), m_settingsList(settingsList)
{ }
};

View File

@ -201,20 +201,13 @@ bool MeshtasticDemodGUI::handleMessage(const Message& message)
// Populates the upper unstructured view including raw bytes in hex
const MeshtasticDemodMsg::MsgReportDecodeBytes& msg = (MeshtasticDemodMsg::MsgReportDecodeBytes&) message;
handleMeshAutoLockObservation(msg);
if (m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa) {
showLoRaMessage(message);
}
showLoRaMessage(message);
return true;
}
else if (MeshtasticDemodMsg::MsgReportDecodeString::match(message))
{
// Populates the lower structured tree view with decoded fields
if ((m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa)) {
showTextMessage(message);
}
showTextMessage(message);
return true;
}
else if (MeshtasticDemod::MsgConfigureMeshtasticDemod::match(message))
@ -465,18 +458,7 @@ void MeshtasticDemodGUI::startMeshAutoLock()
return;
}
if (m_settings.m_codingScheme != MeshtasticDemodSettings::CodingLoRa)
{
displayStatus(tr("MESH LOCK|switch decoder scheme to LoRa before auto-lock"));
ui->meshAutoLock->blockSignals(true);
ui->meshAutoLock->setChecked(false);
ui->meshAutoLock->blockSignals(false);
return;
}
const int bandwidthHz = MeshtasticDemodSettings::bandwidths[m_settings.m_bandwidthIndex];
const int bandwidthHz = MeshtasticDemodSettings::bandwidths[m_settings.m_bandwidthIndex];
const int sf = std::max(1, m_settings.m_spreadFactor);
const int symbolBins = 1 << std::min(15, sf);
const int stepHz = std::max(100, bandwidthHz / symbolBins);
@ -1064,7 +1046,7 @@ void MeshtasticDemodGUI::pushExtraPipelineSettingsToDemod()
void MeshtasticDemodGUI::on_conf_valueChanged(int value)
{
const int maxFocus = static_cast<int>(m_extraPipelineSettings.size());
const auto maxFocus = static_cast<int>(m_extraPipelineSettings.size());
const int newFocus = std::clamp(value, 0, maxFocus);
if (newFocus == m_focusedPipelineIndex) {
@ -1928,7 +1910,7 @@ void MeshtasticDemodGUI::applySettings(bool force)
void MeshtasticDemodGUI::updateControlAvailabilityHints()
{
const bool loRaMode = m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa;
const bool explicitHeaderMode = loRaMode && m_settings.m_hasHeader;
const bool explicitHeaderMode = loRaMode && MeshtasticDemodSettings::m_hasHeader;
const QString fftWindowEnabledTip = tr("FFT window used by the de-chirping stage.");
const QString fftWindowDisabledTip = tr("Ignored in LoRa mode. The LoRa demodulator uses a fixed internal FFT window.");
@ -1969,7 +1951,7 @@ void MeshtasticDemodGUI::updateControlAvailabilityHints()
setSliderDimmed(ui->deBits, !isUserPreset);
setSliderDimmed(ui->preambleChirps, !isUserPreset);
const bool headerControlsEnabled = !m_settings.m_hasHeader;
const bool headerControlsEnabled = !MeshtasticDemodSettings::m_hasHeader;
ui->fecParity->setEnabled(headerControlsEnabled);
ui->packetLength->setEnabled(headerControlsEnabled);
@ -2029,15 +2011,6 @@ void MeshtasticDemodGUI::displaySettings()
ui->udpSend->setChecked(m_settings.m_sendViaUDP);
ui->udpAddress->setText(m_settings.m_udpAddress);
ui->udpPort->setText(tr("%1").arg(m_settings.m_udpPort));
if (!m_settings.m_hasHeader)
{
ui->fecParity->setValue(m_settings.m_nbParityBits);
ui->fecParityText->setText(tr("%1").arg(m_settings.m_nbParityBits));
ui->packetLength->setValue(m_settings.m_packetLength);
ui->spectrumGUI->setFFTSize(m_settings.m_spreadFactor);
}
ui->invertRamps->setChecked(s.m_invertRamps);
displaySquelch();
@ -2116,19 +2089,19 @@ void MeshtasticDemodGUI::displaySquelch()
void MeshtasticDemodGUI::displayLoRaStatus(int headerParityStatus, bool headerCRCStatus, int payloadParityStatus, bool payloadCRCStatus)
{
if (m_settings.m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityOK)) {
if (MeshtasticDemodSettings::m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityOK)) {
ui->headerHammingStatus->setStyleSheet("QLabel { background-color : green; }");
} else if (m_settings.m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityError)) {
} else if (MeshtasticDemodSettings::m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityError)) {
ui->headerHammingStatus->setStyleSheet("QLabel { background-color : red; }");
} else if (m_settings.m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityCorrected)) {
} else if (MeshtasticDemodSettings::m_hasHeader && (headerParityStatus == (int) MeshtasticDemodSettings::ParityCorrected)) {
ui->headerHammingStatus->setStyleSheet("QLabel { background-color : blue; }");
} else {
ui->headerHammingStatus->setStyleSheet("QLabel { background:rgb(79,79,79); }");
}
if (m_settings.m_hasHeader && headerCRCStatus) {
if (MeshtasticDemodSettings::m_hasHeader && headerCRCStatus) {
ui->headerCRCStatus->setStyleSheet("QLabel { background-color : green; }");
} else if (m_settings.m_hasHeader && !headerCRCStatus) {
} else if (MeshtasticDemodSettings::m_hasHeader && !headerCRCStatus) {
ui->headerCRCStatus->setStyleSheet("QLabel { background-color : red; }");
} else {
ui->headerCRCStatus->setStyleSheet("QLabel { background:rgb(79,79,79); }");
@ -3142,18 +3115,11 @@ void MeshtasticDemodGUI::showLoRaMessage(const Message& message)
ui->snrText->setText(tr("%1").arg(msg.getSingalDb() - msg.getNoiseDb(), 0, 'f', 1));
unsigned int packetLength;
if (m_settings.m_hasHeader)
{
ui->fecParity->setValue(msg.getNbParityBits());
ui->fecParityText->setText(tr("%1").arg(msg.getNbParityBits()));
ui->packetLength->setValue(msg.getPacketSize());
ui->packetLengthText->setText(tr("%1").arg(msg.getPacketSize()));
packetLength = msg.getPacketSize();
}
else
{
packetLength = m_settings.m_packetLength;
}
ui->fecParity->setValue(msg.getNbParityBits());
ui->fecParityText->setText(tr("%1").arg(msg.getNbParityBits()));
ui->packetLength->setValue(msg.getPacketSize());
ui->packetLengthText->setText(tr("%1").arg(msg.getPacketSize()));
packetLength = msg.getPacketSize();
QDateTime dt = QDateTime::currentDateTime();
QString dateStr = dt.toString("HH:mm:ss");
@ -3257,7 +3223,7 @@ void MeshtasticDemodGUI::showTextMessage(const Message& message)
const QString messageBaseKey = buildPipelineMessageBaseKey(pipelineId, msg.getFrameId(), msg.getMsgTimestamp());
QString messageKey = resolvePipelineMessageKey(messageBaseKey);
if (messageKey.isEmpty() && (m_settings.m_codingScheme != MeshtasticDemodSettings::CodingLoRa)) {
if (messageKey.isEmpty()) {
messageKey = allocatePipelineMessageKey(messageBaseKey);
}

View File

@ -34,22 +34,6 @@
#include "meshtasticdemoddecoderlora.h"
#include "meshtasticdemodsink.h"
// namespace { // For [LOOPBACK] debug only
// QString symbolPreview(const std::vector<unsigned short>& symbols, unsigned int maxCount)
// {
// QStringList parts;
// const unsigned int count = std::min<unsigned int>(maxCount, static_cast<unsigned int>(symbols.size()));
// for (unsigned int i = 0; i < count; i++) {
// parts.append(QString::number(symbols[i]));
// }
// return parts.join(",");
// }
// } // namespace
MeshtasticDemodSink::MeshtasticDemodSink() :
m_decodeMsg(nullptr),
m_decoderMsgQueue(nullptr),
@ -209,7 +193,7 @@ void MeshtasticDemodSink::feed(const SampleVector::const_iterator& begin, const
if (m_interpolator.decimate(&m_sampleDistanceRemain, c, &ci))
{
if (m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa)
if (MeshtasticDemodSettings::m_codingScheme == MeshtasticDemodSettings::CodingLoRa)
{
processSampleLoRa(ci);
}
@ -443,7 +427,7 @@ bool MeshtasticDemodSink::sendLoRaHeaderProbe()
const std::vector<unsigned short>& symbols = m_decodeMsg->getSymbols();
if (symbols.size() < 8U || !m_settings.m_hasHeader) {
if (symbols.size() < 8U) {
return false;
}
@ -462,21 +446,11 @@ bool MeshtasticDemodSink::sendLoRaHeaderProbe()
headerNbSymbolBits,
m_settings.m_spreadFactor,
static_cast<unsigned int>(std::max(1, m_bandwidth)),
m_settings.m_hasHeader,
m_settings.m_hasCRC
MeshtasticDemodSettings::m_hasHeader,
MeshtasticDemodSettings::m_hasCRC
);
m_decoderMsgQueue->push(probe);
// qDebug().noquote() << QString(
// "[LOOPBACK][RX] header_probe token=%1 frameId=%2 sf=%3 de=%4 bw=%5 headerSymbols=[%6]"
// )
// .arg(m_loRaFrameId)
// .arg(m_loRaFrameId)
// .arg(m_settings.m_spreadFactor)
// .arg(m_settings.m_deBits)
// .arg(m_bandwidth)
// .arg(symbolPreview(headerSymbols, 8U));
return true;
}
@ -495,8 +469,7 @@ void MeshtasticDemodSink::applyLoRaHeaderFeedback(
(void) ldro;
(void) headerParityStatus;
if ((m_settings.m_codingScheme != MeshtasticDemodSettings::CodingLoRa)
|| (m_loRaState != LoRaStateSFOCompensation))
if (m_loRaState != LoRaStateSFOCompensation)
{
return;
}
@ -525,14 +498,6 @@ void MeshtasticDemodSink::applyLoRaHeaderFeedback(
m_expectedSymbols = expectedSymbols;
m_headerLocked = true;
m_loRaReceivedHeader = true;
// qDebug("[LOOPBACK][RX] header_lock token=%u frameId=%u len=%u cr=%u expected=%u frameSymbols=%u",
// frameId,
// frameId,
// packetLength,
// nbParityBits,
// expectedSymbols,
// m_loRaFrameSymbolCount);
}
int MeshtasticDemodSink::loRaMod(int a, int b) const
@ -551,9 +516,7 @@ int MeshtasticDemodSink::loRaRound(float number) const
void MeshtasticDemodSink::resetLoRaFrameSync()
{
if ((m_settings.m_codingScheme == MeshtasticDemodSettings::CodingLoRa)
&& m_decodeMsg
&& (m_loRaState != LoRaStateDetect))
if (m_decodeMsg && (m_loRaState != LoRaStateDetect))
{
delete m_decodeMsg;
m_decodeMsg = nullptr;
@ -799,12 +762,6 @@ void MeshtasticDemodSink::finalizeLoRaFrame()
return;
}
// const bool hitExpected = m_headerLocked && (m_loRaFrameSymbolCount >= m_expectedSymbols);
// const bool hitMax = (!m_headerLocked) && (m_loRaFrameSymbolCount >= m_settings.m_nbSymbolsMax);
// const char *endReason = hitExpected
// ? "expected"
// : (hitMax ? "max" : "other");
qDebug(
"MeshtasticDemodSink::finalizeLoRaFrame: frameId=%u symbols=%u headerLocked=%d expected=%u",
m_loRaFrameId,
@ -813,15 +770,6 @@ void MeshtasticDemodSink::finalizeLoRaFrame()
m_expectedSymbols
);
// qDebug("[LOOPBACK][RX] frame_finalize token=%u frameId=%u reason=%s locked=%d expected=%u actual=%u waitHeader=%d",
// m_loRaFrameId,
// m_loRaFrameId,
// endReason,
// m_headerLocked ? 1 : 0,
// m_expectedSymbols,
// m_loRaFrameSymbolCount,
// m_waitHeaderFeedback ? 1 : 0);
m_decodeMsg->setSignalDb(CalcDb::dbPower(m_magsqOnAvg.asDouble() / (1 << m_settings.m_spreadFactor)));
m_decodeMsg->setNoiseDb(CalcDb::dbPower(m_magsqOffAvg.asDouble() / (1 << m_settings.m_spreadFactor)));
@ -1205,7 +1153,7 @@ int MeshtasticDemodSink::processLoRaFrameSyncStep()
std::vector<float> symbolMags;
const unsigned int rawSymbol = getLoRaSymbolVal(m_loRaInDown.data(), m_loRaPayloadDownchirp.data(), &symbolMags, true);
const bool headerSymbol = m_settings.m_hasHeader && (m_loRaFrameSymbolCount < 8U);
const bool headerSymbol = m_loRaFrameSymbolCount < 8U;
const unsigned short symbol = evalSymbol(rawSymbol, headerSymbol) % m_nbSymbolsEff;
m_decodeMsg->pushBackSymbol(symbol);
m_decodeMsg->pushBackMagnitudes(symbolMags);
@ -1237,7 +1185,6 @@ int MeshtasticDemodSink::processLoRaFrameSyncStep()
m_loRaFrameSymbolCount++;
if (!m_headerLocked
&& m_settings.m_hasHeader
&& (m_loRaFrameSymbolCount >= 8U))
{
tryHeaderLock();

View File

@ -1,3 +1,19 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019-2026 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QMessageBox>
#include "meshtastickeysdialog.h"

View File

@ -1,3 +1,19 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2019-2026 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_MESHTASTICKEYSDIALOG_H
#define INCLUDE_MESHTASTICKEYSDIALOG_H
@ -13,7 +29,7 @@ class MeshtasticKeysDialog : public QDialog
public:
explicit MeshtasticKeysDialog(QWidget* parent = nullptr);
~MeshtasticKeysDialog();
~MeshtasticKeysDialog() override;
void setKeySpecList(const QString& keySpecList);
QString getKeySpecList() const;

View File

@ -218,11 +218,11 @@ void MeshtasticMod::applySettings(const MeshtasticModSettings& incomingSettings,
<< " m_bytesMessage: " << settings.m_bytesMessage.toHex()
<< " m_spreadFactor: " << settings.m_spreadFactor
<< " m_deBits: " << settings.m_deBits
<< " m_codingScheme: " << settings.m_codingScheme
<< " m_codingScheme: " << MeshtasticModSettings::m_codingScheme
<< " m_nbParityBits: " << settings.m_nbParityBits
<< " m_hasCRC: " << settings.m_hasCRC
<< " m_hasHeader: " << settings.m_hasHeader
<< " m_messageType: " << settings.m_messageType
<< " m_hasCRC: " << MeshtasticModSettings::m_hasCRC
<< " m_hasHeader: " << MeshtasticModSettings::m_hasHeader
<< " m_messageType: " << MeshtasticModSettings::m_messageType
<< " m_preambleChirps: " << settings.m_preambleChirps
<< " m_quietMillis: " << settings.m_quietMillis
<< " m_messageRepeat: " << settings.m_messageRepeat

View File

@ -153,7 +153,7 @@ void MeshtasticModGUI::handleSourceMessages()
QString MeshtasticModGUI::getActivePayloadText() const
{
switch (m_settings.m_messageType)
switch (MeshtasticModSettings::m_messageType)
{
case MeshtasticModSettings::MessageText:
return m_settings.m_textMessage;
@ -528,7 +528,7 @@ void MeshtasticModGUI::on_repeatMessage_valueChanged(int value)
void MeshtasticModGUI::on_messageText_editingFinished()
{
if (m_settings.m_messageType == MeshtasticModSettings::MessageText) {
if (MeshtasticModSettings::m_messageType == MeshtasticModSettings::MessageText) {
m_settings.m_textMessage = ui->messageText->toPlainText();
}
@ -809,7 +809,7 @@ void MeshtasticModGUI::displaySettings()
displayCurrentPayloadMessage();
displayBinaryMessage();
ui->fecParity->setEnabled(m_settings.m_codingScheme == MeshtasticModSettings::CodingLoRa);
ui->fecParity->setEnabled(MeshtasticModSettings::m_codingScheme == MeshtasticModSettings::CodingLoRa);
blockApplySettings(true);
ui->deltaFrequency->setValue(m_channelMarker.getCenterFrequency());
@ -874,7 +874,7 @@ void MeshtasticModGUI::displayCurrentPayloadMessage()
{
ui->messageText->blockSignals(true);
if (m_settings.m_messageType == MeshtasticModSettings::MessageText) {
if (MeshtasticModSettings::m_messageType == MeshtasticModSettings::MessageText) {
ui->messageText->setText(m_settings.m_textMessage);
}

View File

@ -20,22 +20,6 @@
#include "meshtasticmodsource.h"
// namespace { // For [LOOPBACK] debug only
// QString symbolPreview(const std::vector<unsigned short>& symbols, unsigned int maxCount)
// {
// QStringList parts;
// const unsigned int count = std::min<unsigned int>(maxCount, static_cast<unsigned int>(symbols.size()));
// for (unsigned int i = 0; i < count; i++) {
// parts.append(QString::number(symbols[i]));
// }
// return parts.join(",");
// }
// } // namespace
const int MeshtasticModSource::m_levelNbSamples = 480; // every 10ms
MeshtasticModSource::MeshtasticModSource() :
@ -300,7 +284,7 @@ void MeshtasticModSource::modulateSample()
{
m_fftCounter = 0;
m_chirpCount = 0;
m_chirp0 = encodeSymbol(m_symbols[m_chirpCount], m_settings.m_hasHeader && (m_chirpCount < 8U));
m_chirp0 = encodeSymbol(m_symbols[m_chirpCount], MeshtasticModSettings::m_hasHeader && (m_chirpCount < 8U));
m_txFrameToken++;
std::vector<unsigned short> mappedPreview;
@ -308,21 +292,9 @@ void MeshtasticModSource::modulateSample()
mappedPreview.reserve(previewCount);
for (unsigned int i = 0; i < previewCount; i++) {
mappedPreview.push_back(encodeSymbol(m_symbols[i], m_settings.m_hasHeader && (i < 8U)));
mappedPreview.push_back(encodeSymbol(m_symbols[i], MeshtasticModSettings::m_hasHeader && (i < 8U)));
}
// qDebug().noquote() << QString(
// "[LOOPBACK][TX] frame_start token=%1 sf=%2 de=%3 bw=%4 preamble=%5 symbols=%6 hdrRaw=[%7] hdrMapped=[%8]"
// )
// .arg(m_txFrameToken)
// .arg(m_settings.m_spreadFactor)
// .arg(m_settings.m_deBits)
// .arg(m_bandwidth)
// .arg(m_settings.m_preambleChirps)
// .arg(m_symbols.size())
// .arg(symbolPreview(m_symbols, previewCount))
// .arg(symbolPreview(mappedPreview, previewCount));
m_chirp = (m_chirp0 + m_fftLength)*MeshtasticModSettings::oversampling - 1;
m_state = ChirpChatStatePayload;
}
@ -344,7 +316,7 @@ void MeshtasticModSource::modulateSample()
}
else
{
m_chirp0 = encodeSymbol(m_symbols[m_chirpCount], m_settings.m_hasHeader && (m_chirpCount < 8U));
m_chirp0 = encodeSymbol(m_symbols[m_chirpCount], MeshtasticModSettings::m_hasHeader && (m_chirpCount < 8U));
m_chirp = (m_chirp0 + m_fftLength)*MeshtasticModSettings::oversampling - 1;
m_fftCounter = 0;
}
@ -363,9 +335,9 @@ void MeshtasticModSource::modulateSample()
}
}
unsigned short MeshtasticModSource::encodeSymbol(unsigned short symbol, bool headerSymbol)
unsigned short MeshtasticModSource::encodeSymbol(unsigned short symbol, bool headerSymbol) const
{
unsigned int deBits = static_cast<unsigned int>(std::max(0, m_settings.m_deBits));
auto deBits = static_cast<unsigned int>(std::max(0, m_settings.m_deBits));
if (headerSymbol && deBits < 2U) {
deBits = 2U;

View File

@ -108,7 +108,7 @@ private:
void reset();
void calculateLevel(Real& sample);
void modulateSample();
unsigned short encodeSymbol(unsigned short symbol, bool headerSymbol); //!< Encodes symbol with payload/header DE spacing
unsigned short encodeSymbol(unsigned short symbol, bool headerSymbol) const; //!< Encodes symbol with payload/header DE spacing
};
#endif // INCLUDE_MESHTASTICMODSOURCE_H

View File

@ -28,7 +28,7 @@ namespace
using modemmeshtastic::DecodeResult;
using modemmeshtastic::Packet;
static QMap<QString, QString> toFieldMap(const DecodeResult& result)
QMap<QString, QString> toFieldMap(const DecodeResult& result)
{
QMap<QString, QString> map;
@ -42,7 +42,7 @@ static QMap<QString, QString> toFieldMap(const DecodeResult& result)
return map;
}
static bool compareField(
bool compareField(
const QMap<QString, QString>& fields,
const QString& path,
const QString& expected,