From efa232db882e4e5b83bf8e6c709b7dfc13f81d37 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 27 Mar 2026 21:17:46 +0100 Subject: [PATCH] Meshtastic: some Sonar fixes --- modemmeshtastic/meshtasticpacket.cpp | 236 +++++++++--------- .../demodmeshtastic/meshtasticdemod.cpp | 223 ++++++++--------- .../demodmeshtastic/meshtasticdemod.h | 2 +- .../demodmeshtastic/meshtasticdemodgui.cpp | 68 ++--- .../demodmeshtastic/meshtasticdemodsink.cpp | 67 +---- .../demodmeshtastic/meshtastickeysdialog.cpp | 16 ++ .../demodmeshtastic/meshtastickeysdialog.h | 18 +- .../channeltx/modmeshtastic/meshtasticmod.cpp | 8 +- .../modmeshtastic/meshtasticmodgui.cpp | 8 +- .../modmeshtastic/meshtasticmodsource.cpp | 38 +-- .../modmeshtastic/meshtasticmodsource.h | 2 +- sdrbench/test_meshtastic.cpp | 4 +- 12 files changed, 292 insertions(+), 398 deletions(-) diff --git a/modemmeshtastic/meshtasticpacket.cpp b/modemmeshtastic/meshtasticpacket.cpp index 0d6bdcccd..4f92cea1e 100644 --- a/modemmeshtastic/meshtasticpacket.cpp +++ b/modemmeshtastic/meshtasticpacket.cpp @@ -120,13 +120,13 @@ struct RegionBand bool wideLora; }; -static const uint8_t kDefaultChannelKey[16] = { +const std::array 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 makePortMap() +QMap makePortMap() { QMap m; m.insert("UNKNOWN_APP", 0); @@ -160,9 +160,9 @@ static QMap makePortMap() return m; } -static const QMap kPortMap = makePortMap(); +const QMap kPortMap = makePortMap(); -static const RegionBand kRegionBands[] = { +const std::array 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(sizeof(kRegionBands) / sizeof(kRegionBands[0])); +const int kRegionBandsCount = static_cast(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(kDefaultChannelKey), sizeof(kDefaultChannelKey)); + QByteArray key(reinterpret_cast(kDefaultChannelKey.data()), static_cast(kDefaultChannelKey.size())); if (simple > 1) { - const int offset = static_cast(simple - 1); + const auto offset = static_cast(simple - 1); key[15] = static_cast(static_cast(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(static_cast(p[0])) | (static_cast(static_cast(p[1])) << 8) @@ -393,7 +393,7 @@ static uint32_t readU32LE(const char* p) | (static_cast(static_cast(p[3])) << 24); } -static void writeU32LE(char* p, uint32_t v) +void writeU32LE(char* p, uint32_t v) { p[0] = static_cast(v & 0xFF); p[1] = static_cast((v >> 8) & 0xFF); @@ -401,7 +401,7 @@ static void writeU32LE(char* p, uint32_t v) p[3] = static_cast((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(bytes[pos++]); + const auto b = static_cast(bytes[pos++]); value |= static_cast(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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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(value & 0x7F); + auto b = static_cast(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(field) << 3) | static_cast(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 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 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 rcon = {0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36}; const int words = 4 * (m_nr + 1); std::vector 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 counter; + initNonce(counter.data(), fromNode, packetId); int pos = 0; while (pos < out.size()) { - uint8_t keystream[16]; - aes.encryptBlock(counter, keystream); + std::array keystream; + aes.encryptBlock(counter.data(), keystream.data()); const int remain = std::min(16, static_cast(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& 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& keys, QString* error = nullptr, @@ -1232,7 +1232,7 @@ static bool parseKeySpecList( return true; } -static std::vector defaultKeysFromEnv() +std::vector defaultKeysFromEnv() { std::vector keys; QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); @@ -1260,7 +1260,7 @@ static std::vector 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((n >> 1) ^ static_cast(-(static_cast(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(raw); + const auto fixedValue = static_cast(raw); const double scaled = static_cast(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(fixed32ToFloat(raw)); + const auto floatValue = static_cast(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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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(v); + const auto raw = static_cast(v); dm.voltage = static_cast((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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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& out) +void parsePackedFixed32(const QByteArray& bytes, QVector& out) { int pos = 0; while ((pos + 4) <= bytes.size()) @@ -2809,7 +2809,7 @@ static void parsePackedFixed32(const QByteArray& bytes, QVector& out) } /** Parse a packed repeated sint32 block (content only, length already consumed). */ -static void parsePackedVarintSint32(const QByteArray& bytes, QVector& out) +void parsePackedVarintSint32(const QByteArray& bytes, QVector& out) { int pos = 0; while (pos < bytes.size()) @@ -2820,7 +2820,7 @@ static void parsePackedVarintSint32(const QByteArray& bytes, QVector& 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(rawTag >> 3); - const uint32_t wire = static_cast(rawTag & 0x7); + const auto field = static_cast(rawTag >> 3); + const auto wire = static_cast(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="; } - const auto appendPayloadHex = [&d]() -> QString { + const auto appendPayloadHex = [&d]() { const int n = std::min(32, static_cast(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(std::llround(freqMHz * 1000000.0)); + settings.centerFrequencyHz = std::llround(freqMHz * 1000000.0); } else if (region) { const double bwMHz = static_cast(bandwidthHz) / 1000000.0; const double slotWidthMHz = region->spacingMHz + bwMHz; const double spanMHz = region->freqEndMHz - region->freqStartMHz; - const uint32_t numChannels = static_cast(std::floor(spanMHz / slotWidthMHz)); + const auto numChannels = static_cast(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(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") diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemod.cpp b/plugins/channelrx/demodmeshtastic/meshtasticdemod.cpp index 4aec2ab28..eb1fa0293 100644 --- a/plugins/channelrx/demodmeshtastic/meshtasticdemod.cpp +++ b/plugins/channelrx/demodmeshtastic/meshtasticdemod.cpp @@ -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 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(cmd); + const auto& msg = static_cast(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(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(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> 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> 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 packetsPipes; - MainCore::instance()->getMessagePipes().getMessagePipes(this, "packets", packetsPipes); + meshMsg->setStructuredFields(structuredFields); + getMessageQueueToGUI()->push(meshMsg); + } + } - for (const auto& pipe : packetsPipes) - { - MessageQueue *messageQueue = qobject_cast(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 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(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); } diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemod.h b/plugins/channelrx/demodmeshtastic/meshtasticdemod.h index ee952d82a..014102539 100644 --- a/plugins/channelrx/demodmeshtastic/meshtasticdemod.h +++ b/plugins/channelrx/demodmeshtastic/meshtasticdemod.h @@ -59,7 +59,7 @@ public: } private: QVector m_settingsList; - MsgSetExtraPipelineSettings(const QVector& settingsList) : + explicit MsgSetExtraPipelineSettings(const QVector& settingsList) : Message(), m_settingsList(settingsList) { } }; diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp index b24ed0031..825bb0536 100644 --- a/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp +++ b/plugins/channelrx/demodmeshtastic/meshtasticdemodgui.cpp @@ -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(m_extraPipelineSettings.size()); + const auto maxFocus = static_cast(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); } diff --git a/plugins/channelrx/demodmeshtastic/meshtasticdemodsink.cpp b/plugins/channelrx/demodmeshtastic/meshtasticdemodsink.cpp index 57106643b..3cd3021c5 100644 --- a/plugins/channelrx/demodmeshtastic/meshtasticdemodsink.cpp +++ b/plugins/channelrx/demodmeshtastic/meshtasticdemodsink.cpp @@ -34,22 +34,6 @@ #include "meshtasticdemoddecoderlora.h" #include "meshtasticdemodsink.h" -// namespace { // For [LOOPBACK] debug only - -// QString symbolPreview(const std::vector& symbols, unsigned int maxCount) -// { -// QStringList parts; -// const unsigned int count = std::min(maxCount, static_cast(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& 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(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 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(); diff --git a/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.cpp b/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.cpp index 44471510a..8218605f1 100644 --- a/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.cpp +++ b/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.cpp @@ -1,3 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019-2026 Edouard Griffiths, F4EXB // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// #include #include "meshtastickeysdialog.h" diff --git a/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.h b/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.h index f47cec29c..477e126cd 100644 --- a/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.h +++ b/plugins/channelrx/demodmeshtastic/meshtastickeysdialog.h @@ -1,3 +1,19 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2019-2026 Edouard Griffiths, F4EXB // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// #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; diff --git a/plugins/channeltx/modmeshtastic/meshtasticmod.cpp b/plugins/channeltx/modmeshtastic/meshtasticmod.cpp index 2670982e8..cb88c5727 100644 --- a/plugins/channeltx/modmeshtastic/meshtasticmod.cpp +++ b/plugins/channeltx/modmeshtastic/meshtasticmod.cpp @@ -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 diff --git a/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp b/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp index de8914959..c7cbdecbe 100644 --- a/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp +++ b/plugins/channeltx/modmeshtastic/meshtasticmodgui.cpp @@ -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); } diff --git a/plugins/channeltx/modmeshtastic/meshtasticmodsource.cpp b/plugins/channeltx/modmeshtastic/meshtasticmodsource.cpp index eb33e501b..28bd5d2bb 100644 --- a/plugins/channeltx/modmeshtastic/meshtasticmodsource.cpp +++ b/plugins/channeltx/modmeshtastic/meshtasticmodsource.cpp @@ -20,22 +20,6 @@ #include "meshtasticmodsource.h" -// namespace { // For [LOOPBACK] debug only - -// QString symbolPreview(const std::vector& symbols, unsigned int maxCount) -// { -// QStringList parts; -// const unsigned int count = std::min(maxCount, static_cast(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 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(std::max(0, m_settings.m_deBits)); + auto deBits = static_cast(std::max(0, m_settings.m_deBits)); if (headerSymbol && deBits < 2U) { deBits = 2U; diff --git a/plugins/channeltx/modmeshtastic/meshtasticmodsource.h b/plugins/channeltx/modmeshtastic/meshtasticmodsource.h index d52e945c2..a8cbf24f7 100644 --- a/plugins/channeltx/modmeshtastic/meshtasticmodsource.h +++ b/plugins/channeltx/modmeshtastic/meshtasticmodsource.h @@ -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 diff --git a/sdrbench/test_meshtastic.cpp b/sdrbench/test_meshtastic.cpp index cff725b2b..96d272c12 100644 --- a/sdrbench/test_meshtastic.cpp +++ b/sdrbench/test_meshtastic.cpp @@ -28,7 +28,7 @@ namespace using modemmeshtastic::DecodeResult; using modemmeshtastic::Packet; -static QMap toFieldMap(const DecodeResult& result) +QMap toFieldMap(const DecodeResult& result) { QMap map; @@ -42,7 +42,7 @@ static QMap toFieldMap(const DecodeResult& result) return map; } -static bool compareField( +bool compareField( const QMap& fields, const QString& path, const QString& expected,