mirror of
https://github.com/f4exb/sdrangel.git
synced 2026-05-07 14:44:07 -04:00
expose demod fields for plaintext packets, gate on header CRC
This commit is contained in:
parent
3da5bff59b
commit
c368600b52
@ -1,8 +1,3 @@
|
||||
## meshtasticdemodwebapiadapter.cpp:35
|
||||
Initializes SWGChirpChatDemodSettings instead of SWGMeshtasticDemodSettings.
|
||||
Copy-paste artifact from ChirpChat plugin. Fix separately in its own commit.
|
||||
Branch: feature-meshtastic-more-udp or open a dedicated bug-fix branch.
|
||||
|
||||
## meshtasticdemodgui.cpp - checkbox signal pattern
|
||||
All checkboxes currently use stateChanged(int) pattern.
|
||||
Consider refactoring all to clicked(bool) for simplicity in a future cleanup commit.
|
||||
@ -12,3 +7,12 @@ Affects: sendViaUDP, sendJsonViaUDP, and likely other checkboxes in the same fil
|
||||
m_lastMsgBytes[0] is read without an explicit non-empty size check before the APRS detection block.
|
||||
Pre-existing issue, not introduced by JSON UDP feature. Fix separately in its own commit.
|
||||
Safe fix: add `&& !m_lastMsgBytes.isEmpty()` to the APRS condition.
|
||||
|
||||
## meshtasticdemod.cpp:658 - hash_matching_index fabricated
|
||||
hash_matching_index is hardcoded to 0 for decrypted packets and "none"
|
||||
for all others. The decoder sorts key candidates by hash match but does
|
||||
not expose the actual index used in DecodeResult. The field is therefore
|
||||
inaccurate for multi-key configurations. Fix requires extending
|
||||
DecodeResult to expose the matched key index, then wiring it through
|
||||
buildMeshtasticJsonPacket. For now the field remains but should not be
|
||||
relied upon.
|
||||
|
||||
@ -25,7 +25,6 @@
|
||||
rf.snr_db Signal minus noise in dB
|
||||
lora.packet_type meshtastic, lorawan, helium, unset, or custom
|
||||
lora.sync_word Hex string e.g. 0x2b
|
||||
lora.frame_id Hex string e.g. 0x1
|
||||
lora.header_fec ok, fix, err, or n/a
|
||||
lora.header_crc ok or err
|
||||
lora.payload_fec ok, fix, err, or n/a (n/a when early_eom is true)
|
||||
@ -40,6 +39,7 @@
|
||||
## Fields Present Only When lora.packet_type Is meshtastic
|
||||
|
||||
meshtastic.channel_hash Hex string e.g. 0x08
|
||||
meshtastic.packet_id Meshtastic 32-bit unique packet ID hex string e.g. 0x5a42f351
|
||||
meshtastic.hash_matching_index Integer index of matched key, or none
|
||||
meshtastic.decryption decrypted, plaintext, or not_decrypted
|
||||
meshtastic.key_label Key name, no_key, or unknown_key
|
||||
@ -78,6 +78,14 @@
|
||||
n/a Not applicable, packet ended early before payload was received
|
||||
|
||||
|
||||
## Note on packet_id
|
||||
|
||||
The Meshtastic packet ID is a large random 32-bit value generated by the originating node.
|
||||
Its primary purpose is to serve as a cryptographic nonce component for AES-CTR decryption,
|
||||
combined with the from node ID. It also serves as a deduplication key in the mesh so that
|
||||
relay nodes can discard copies of already-forwarded packets. It is not a sequential counter.
|
||||
|
||||
|
||||
## Example: Fully Decoded Meshtastic Packet
|
||||
|
||||
{
|
||||
@ -89,12 +97,11 @@
|
||||
"spreading_factor": 11,
|
||||
"signal_db": -46.0,
|
||||
"noise_db": -84.2,
|
||||
"snr_db": 38.2
|
||||
"snr_db": 13.6
|
||||
},
|
||||
"lora": {
|
||||
"packet_type": "meshtastic",
|
||||
"sync_word": "0x2b",
|
||||
"frame_id": "0x1",
|
||||
"header_fec": "ok",
|
||||
"header_crc": "ok",
|
||||
"payload_fec": "ok",
|
||||
@ -107,6 +114,7 @@
|
||||
},
|
||||
"meshtastic": {
|
||||
"channel_hash": "0x08",
|
||||
"packet_id": "0x5a42f351",
|
||||
"hash_matching_index": 0,
|
||||
"decryption": "decrypted",
|
||||
"key_label": "LongFast:default",
|
||||
@ -144,6 +152,7 @@
|
||||
},
|
||||
"meshtastic": {
|
||||
"channel_hash": "0x08",
|
||||
"packet_id": "unknown",
|
||||
"hash_matching_index": "none",
|
||||
"decryption": "not_decrypted",
|
||||
"key_label": "unknown_key",
|
||||
|
||||
@ -632,12 +632,59 @@ QString MeshtasticDemod::buildMeshtasticJsonPacket(
|
||||
if (syncWord == 0x2B)
|
||||
{
|
||||
QJsonObject mesh;
|
||||
const bool headerCrcOk = msg.getHeaderCRCStatus();
|
||||
|
||||
const QString channelHash = getMeshField(meshResult, "header.channel_hash");
|
||||
mesh["channel_hash"] = channelHash.isEmpty() ? QStringLiteral("unknown") : channelHash;
|
||||
if (headerCrcOk && !channelHash.isEmpty()) {
|
||||
mesh["channel_hash"] = channelHash;
|
||||
} else {
|
||||
mesh["channel_hash"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
const QString packetId = getMeshField(meshResult, "header.id");
|
||||
mesh["packet_id"] = packetId.isEmpty() ? QStringLiteral("unknown") : packetId;
|
||||
if (headerCrcOk && !packetId.isEmpty()) {
|
||||
mesh["packet_id"] = packetId;
|
||||
} else {
|
||||
mesh["packet_id"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
const QString hopStart = getMeshField(meshResult, "header.hop_start");
|
||||
const QString hopLimit = getMeshField(meshResult, "header.hop_limit");
|
||||
const QString relayNode = getMeshField(meshResult, "header.relay_node");
|
||||
|
||||
if (headerCrcOk)
|
||||
{
|
||||
if (!hopStart.isEmpty()) {
|
||||
mesh["hop_start"] = hopStart.toInt();
|
||||
} else {
|
||||
mesh["hop_start"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
if (!hopLimit.isEmpty()) {
|
||||
mesh["hop_limit"] = hopLimit.toInt();
|
||||
} else {
|
||||
mesh["hop_limit"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
if (!hopStart.isEmpty() && !hopLimit.isEmpty()) {
|
||||
mesh["hops_consumed"] = hopStart.toInt() - hopLimit.toInt();
|
||||
} else {
|
||||
mesh["hops_consumed"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
if (!relayNode.isEmpty()) {
|
||||
mesh["relay_node"] = relayNode.toInt();
|
||||
} else {
|
||||
mesh["relay_node"] = QStringLiteral("unknown");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh["hop_start"] = QStringLiteral("unknown");
|
||||
mesh["hop_limit"] = QStringLiteral("unknown");
|
||||
mesh["hops_consumed"] = QStringLiteral("unknown");
|
||||
mesh["relay_node"] = QStringLiteral("unknown");
|
||||
}
|
||||
|
||||
const QString decodePath = getMeshField(meshResult, "decode.path");
|
||||
const QString keyLabel = getMeshField(meshResult, "decode.key_label");
|
||||
@ -672,17 +719,6 @@ QString MeshtasticDemod::buildMeshtasticJsonPacket(
|
||||
{
|
||||
mesh["channel_type"] = m_settings.m_meshtasticPresetName;
|
||||
|
||||
const QString hopStart = getMeshField(meshResult, "header.hop_start");
|
||||
const QString hopLimit = getMeshField(meshResult, "header.hop_limit");
|
||||
const QString relayNode = getMeshField(meshResult, "header.relay_node");
|
||||
|
||||
if (!hopStart.isEmpty()) { mesh["hop_start"] = hopStart.toInt(); }
|
||||
if (!hopLimit.isEmpty()) { mesh["hop_limit"] = hopLimit.toInt(); }
|
||||
if (!hopStart.isEmpty() && !hopLimit.isEmpty()) {
|
||||
mesh["hops_consumed"] = hopStart.toInt() - hopLimit.toInt();
|
||||
}
|
||||
if (!relayNode.isEmpty()) { mesh["relay_node"] = relayNode.toInt(); }
|
||||
|
||||
QJsonObject fields;
|
||||
for (const auto& field : meshResult.fields)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user