Public Access
The 16-byte clear header (hops away, channel hash, relay node), the EU_868 presets and their frequency slots, and the channel hash, all checked against Meshtastic's source. Captures are pcap with LoRaTap v0, read back with TShark 4.2.5; packet RSSI is plain dBm, as Wireshark reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
37 lines
1.3 KiB
C++
37 lines
1.3 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
namespace roro::meshtastic {
|
|
|
|
constexpr uint32_t kBroadcast = 0xFFFFFFFF;
|
|
|
|
// The 16 bytes every Meshtastic packet starts with, sent in clear (little-endian). The payload
|
|
// after it is encrypted with the Channel's key.
|
|
struct PacketHeader {
|
|
uint32_t to = 0, from = 0, id = 0;
|
|
uint8_t flags = 0;
|
|
uint8_t channelHash = 0; // the Channel's name and key folded into a byte (see channelHash())
|
|
uint8_t nextHop = 0; // last byte of the Node meant to relay it next; 0 when flooding
|
|
uint8_t relayNode = 0; // last byte of the Node that relayed it to us
|
|
|
|
uint8_t hopLimit() const { return flags & 0x07; }
|
|
bool wantAck() const { return flags & 0x08; }
|
|
bool viaMqtt() const { return flags & 0x10; }
|
|
uint8_t hopStart() const { return flags >> 5; }
|
|
bool broadcast() const { return to == kBroadcast; }
|
|
// How many times it was relayed before we heard it; -1 when the sender didn't say (hop start 0).
|
|
int hopsAway() const { return hopStart() == 0 ? -1 : hopStart() - hopLimit(); }
|
|
};
|
|
|
|
constexpr size_t kHeaderSize = 16;
|
|
|
|
bool parseHeader(const uint8_t* data, size_t len, PacketHeader& out);
|
|
|
|
// "!12345678", as Meshtastic writes node numbers; "all" for broadcast.
|
|
std::string nodeId(uint32_t node);
|
|
|
|
} // namespace roro::meshtastic
|