refactor: relocate MeshCore tools to examples/meshcore/

MeshCore is a protocol implementation ON TOP of DongLoRa, not part of the
dongle itself. Moving it to examples/ makes the separation clear while
keeping it accessible as a real-world usage example.
This commit is contained in:
swaits committed 2026-03-29 20:42:58 -06:00
1 parent 8790ebfd7b
commit 8a5d8c419e
36 files changed
+29 -3

No files matched your search

@@ -0,0 +1,22 @@
{
"description": "ACK flood, simple acknowledgment",
"tags": [
"ack",
"flood"
],
"packet_hex": "0d00efbeadde",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ACK",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"ack_crc": 3735928559
}
}
}
@@ -0,0 +1,26 @@
{
"description": "ACK flood, 2 hops with 1-byte hashes",
"tags": [
"ack",
"flood",
"path"
],
"packet_hex": "0d02d1ac9fc28d00",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ACK",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": [
"d1",
"ac"
]
},
"payload": {
"ack_crc": 9290399
}
}
}
@@ -0,0 +1,31 @@
{
"description": "ADVERT flood, chat node with simple ASCII name",
"tags": [
"advert",
"flood",
"name",
"chat"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc6690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081546573744e6f6465",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 129,
"node_type": "chat",
"location": null,
"name": "TestNode"
}
}
}
}
@@ -0,0 +1,32 @@
{
"description": "ADVERT flood, chat node with emoji in name (multi-byte UTF-8)",
"tags": [
"advert",
"flood",
"emoji",
"name",
"utf8"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc6690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081f09fa68520526170746f72",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 129,
"node_type": "chat",
"location": null,
"name": "🦅 Raptor"
}
}
}
}
@@ -0,0 +1,32 @@
{
"description": "ADVERT flood, feat1+feat2 bits set but bytes are actually the name",
"tags": [
"advert",
"flood",
"feat",
"scoring",
"emoji"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc66900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1f09f8f94efb88f204d746e4e6f6465",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 225,
"node_type": "chat",
"location": null,
"name": "🏔️ MtnNode"
}
}
}
}
@@ -0,0 +1,34 @@
{
"description": "ADVERT flood, repeater with valid GPS coords and name",
"tags": [
"advert",
"flood",
"location",
"repeater"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc6690000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000092346640023807b4f848696c6c746f7052707472",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 146,
"node_type": "repeater",
"location": {
"lat": 37.7749,
"lon": -122.4194
},
"name": "HilltopRptr"
}
}
}
}
@@ -0,0 +1,25 @@
{
"description": "ADVERT flood, bare minimum (no app_data)",
"tags": [
"advert",
"flood",
"minimal"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc66900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": null
}
}
}
@@ -0,0 +1,30 @@
{
"description": "ADVERT flood, sensor node type",
"tags": [
"advert",
"flood",
"sensor"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc669000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008454656d7053656e736f72",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 132,
"node_type": "sensor",
"location": null,
"name": "TempSensor"
}
}
}
}
@@ -0,0 +1,20 @@
{
"description": "ADVERT flood, truncated mid-signature (50 bytes)",
"tags": [
"invalid",
"advert",
"truncated"
],
"packet_hex": "1100000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc669000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
}
}
}
@@ -0,0 +1,35 @@
{
"description": "ADVERT flood, 4 hops with 1-byte hashes",
"tags": [
"advert",
"flood",
"path"
],
"packet_hex": "11042a3d35ed000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f403fc669000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008152656c617965644e6f6465",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": [
"2a",
"3d",
"35",
"ed"
]
},
"payload": {
"pubkey_prefix": "00010203",
"timestamp": 1774600000,
"advert": {
"flags": 129,
"node_type": "chat",
"location": null,
"name": "RelayedNode"
}
}
}
}
@@ -0,0 +1,30 @@
{
"description": "ANON_REQ tdirect header but NO transport codes (older firmware)",
"tags": [
"anon_req",
"tdirect",
"tc_fallback"
],
"packet_hex": "1f03133542d9202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3fb2e2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "tdirect",
"payload_type": "ANON_REQ",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": [
"13",
"35",
"42"
]
},
"payload": {
"dst": "d9",
"ephem_prefix": "20212223",
"mac": "b2e2",
"ciphertext_len": 48
}
}
}
@@ -0,0 +1,15 @@
{
"description": "TXT_MSG flood, path_len claims 33 hops (4B hash) but data is too short",
"tags": [
"invalid",
"bad_framing",
"path"
],
"packet_hex": "09e1000000000000000000000000000000000000000000000000",
"valid": false,
"expected": {
"route_type": "flood",
"payload_type": "TXT_MSG",
"error": "bad_framing"
}
}
@@ -0,0 +1,23 @@
{
"description": "CONTROL flood, DISCOVER_REQ sub-type",
"tags": [
"control",
"flood",
"discover"
],
"packet_hex": "2d0080033412cdab",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "CONTROL",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"control_subtype": "DISCOVER_REQ"
}
}
}
@@ -0,0 +1,14 @@
{
"description": "Empty packet (0 bytes)",
"tags": [
"invalid",
"too_short"
],
"packet_hex": "",
"valid": false,
"expected": {
"route_type": "flood",
"payload_type": "REQ",
"error": "too_short"
}
}
@@ -0,0 +1,26 @@
{
"description": "GRP_TXT flood, group text message",
"tags": [
"grp_txt",
"flood",
"group",
"encrypted"
],
"packet_hex": "1500ccabcd0000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "GRP_TXT",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"channel_hash": "cc",
"mac": "abcd",
"ciphertext_len": 32
}
}
}
@@ -0,0 +1,24 @@
{
"description": "MULTIPART flood, remaining=3, inner type=ACK",
"tags": [
"multipart",
"flood",
"ack"
],
"packet_hex": "290033bebafeca",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "MULTIPART",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"multipart_remaining": 3,
"multipart_inner": "ACK"
}
}
}
@@ -0,0 +1,14 @@
{
"description": "Random bytes, not a valid MeshCore packet",
"tags": [
"invalid",
"noise"
],
"packet_hex": "03d135839fc28d00",
"valid": false,
"expected": {
"route_type": "tdirect",
"payload_type": "REQ",
"error": "not_meshcore"
}
}
@@ -0,0 +1,29 @@
{
"description": "PATH flood, 1 hop with 3-byte hash",
"tags": [
"path",
"flood",
"3byte_hash",
"encrypted"
],
"packet_hex": "21811afff3e6e92e4700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "PATH",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 3,
"hops": [
"1afff3"
]
},
"payload": {
"dst": "e6",
"src": "e9",
"mac": "2e47",
"ciphertext_len": 46
}
}
}
@@ -0,0 +1,29 @@
{
"description": "PATH flood, 1 hop with 4-byte hash",
"tags": [
"path",
"flood",
"4byte_hash",
"encrypted"
],
"packet_hex": "21c1aabbccdde6e92e4700000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "PATH",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 4,
"hops": [
"aabbccdd"
]
},
"payload": {
"dst": "e6",
"src": "e9",
"mac": "2e47",
"ciphertext_len": 16
}
}
}
@@ -0,0 +1,33 @@
{
"description": "REQ transport-direct with transport codes and 1-byte path",
"tags": [
"req",
"tdirect",
"transport_codes",
"encrypted"
],
"packet_hex": "033412785602ccdda1b2ef010000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "tdirect",
"payload_type": "REQ",
"payload_ver": 0,
"transport_codes": {
"tc1": 4660,
"tc2": 22136
},
"path": {
"hash_size": 1,
"hops": [
"cc",
"dd"
]
},
"payload": {
"dst": "a1",
"src": "b2",
"mac": "ef01",
"ciphertext_len": 32
}
}
}
@@ -0,0 +1,11 @@
{
"description": "RESPONSE flood, bit-corrupted path_len (0xc7 should be small), LoRa bit error",
"tags": ["invalid", "response", "flood", "corrupted", "real_capture", "bit_error"],
"packet_hex": "05c735935ed17863f6ec7bbbd9bf8e5ea7d44b6a0e8f6318",
"valid": false,
"expected": {
"route_type": "flood",
"payload_type": "RESPONSE",
"error": "bad_framing"
}
}
@@ -0,0 +1,11 @@
{
"description": "RESPONSE flood, bit-corrupted path_len (0x32 should be 0x02 — bits 4,5 flipped), LoRa bit error",
"tags": ["invalid", "response", "flood", "corrupted", "real_capture", "bit_error"],
"packet_hex": "0532af1a5bd17863f6ec7bbbd9bfbe5ea7d44b6a0e8f6318",
"valid": false,
"expected": {
"route_type": "flood",
"payload_type": "RESPONSE",
"error": "bad_framing"
}
}
@@ -0,0 +1,14 @@
{
"description": "RESPONSE flood, 1 hop (real capture — same message as corrupted variants)",
"tags": ["response", "flood", "path", "real_capture"],
"packet_hex": "0501ac5bd17863f6ec7bbbd9bf8e5ea7d44b6a0e8f6318",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "RESPONSE",
"payload_ver": 0,
"transport_codes": null,
"path": {"hash_size": 1, "hops": ["ac"]},
"payload": {"dst": "5b", "src": "d1", "mac": "7863", "ciphertext_len": 16}
}
}
@@ -0,0 +1,14 @@
{
"description": "RESPONSE flood, 2 hops [ac>ea] (real capture — same message as corrupted variants)",
"tags": ["response", "flood", "path", "real_capture"],
"packet_hex": "0502acea5bd17863f6ec7bbbd9bf8e5ea7d44b6a0e8f6318",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "RESPONSE",
"payload_ver": 0,
"transport_codes": null,
"path": {"hash_size": 1, "hops": ["ac", "ea"]},
"payload": {"dst": "5b", "src": "d1", "mac": "7863", "ciphertext_len": 16}
}
}
@@ -0,0 +1,14 @@
{
"description": "Packet too short (1 byte)",
"tags": [
"invalid",
"too_short"
],
"packet_hex": "11",
"valid": false,
"expected": {
"route_type": "flood",
"payload_type": "ADVERT",
"error": "too_short"
}
}
@@ -0,0 +1,23 @@
{
"description": "TRACE flood with tag, auth, and 2 trace hops",
"tags": [
"trace",
"flood"
],
"packet_hex": "250078563412ddccbbaa001122",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "TRACE",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 1,
"hops": []
},
"payload": {
"trace_tag": 305419896,
"trace_hops": 2
}
}
}
@@ -0,0 +1,30 @@
{
"description": "TXT_MSG direct, 2-byte hashes, 2 hops",
"tags": [
"txt_msg",
"direct",
"2byte_hash",
"encrypted"
],
"packet_hex": "0a42ac98d14d5b43abcd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "direct",
"payload_type": "TXT_MSG",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 2,
"hops": [
"ac98",
"d14d"
]
},
"payload": {
"dst": "5b",
"src": "43",
"mac": "abcd",
"ciphertext_len": 48
}
}
}
@@ -0,0 +1,33 @@
{
"description": "TXT_MSG flood with routing loop (ac98 appears 3x)",
"tags": [
"txt_msg",
"flood",
"loop",
"2byte_hash"
],
"packet_hex": "0945ac98d14dac98ff01ac985b43abcd0000000000000000000000000000000000000000000000000000000000000000",
"valid": true,
"expected": {
"route_type": "flood",
"payload_type": "TXT_MSG",
"payload_ver": 0,
"transport_codes": null,
"path": {
"hash_size": 2,
"hops": [
"ac98",
"d14d",
"ac98",
"ff01",
"ac98"
]
},
"payload": {
"dst": "5b",
"src": "43",
"mac": "abcd",
"ciphertext_len": 32
}
}
}