#include "packet_view.h" #include #include #include "meshtastic_header.h" #include "meshtastic_presets.h" namespace roro::lora { using namespace meshtastic; std::string row(const PacketSummary& p, const std::string& time) { char s[64]; int n = std::snprintf(s, sizeof s, "%s %ld %.1f ", time.c_str(), std::lround(p.rssi), p.snr); std::string out(s, n); PacketHeader h; if (!p.crcOk) return out + "bad CRC, " + std::to_string(p.len) + " B"; if (!p.meshtastic || !parseHeader(p.data, p.len, h)) return out + std::to_string(p.len) + " B"; auto shortId = [](uint32_t node) { if (node == kBroadcast) return std::string("all"); char id[8]; std::snprintf(id, sizeof id, "%04x", static_cast(node & 0xFFFF)); return std::string(id); }; out += shortId(h.from) + ">" + shortId(h.to); if (h.hopsAway() >= 0) out += " " + std::to_string(h.hopsAway()) + "/" + std::to_string(h.hopStart()); return out; } std::vector hexDump(const uint8_t* data, size_t len) { std::vector lines; for (size_t at = 0; at < len; at += 8) { char s[48]; int n = std::snprintf(s, sizeof s, "%04x", static_cast(at)); std::string text; for (size_t i = 0; i < 8; ++i) { if (at + i < len) { n += std::snprintf(s + n, sizeof s - n, " %02x", data[at + i]); uint8_t b = data[at + i]; text += b >= 0x20 && b < 0x7F ? static_cast(b) : '.'; } else { n += std::snprintf(s + n, sizeof s - n, " "); } } lines.push_back(std::string(s, n) + " " + text); } return lines; } std::vector headerLines(const uint8_t* data, size_t len) { PacketHeader h; if (!parseHeader(data, len, h)) return {}; char s[64]; std::vector lines; lines.push_back("From " + nodeId(h.from) + " to " + nodeId(h.to)); std::snprintf(s, sizeof s, "Packet %08x%s%s", static_cast(h.id), h.wantAck() ? ", wants an ack" : "", h.viaMqtt() ? ", via MQTT" : ""); lines.push_back(s); if (h.hopsAway() >= 0) std::snprintf(s, sizeof s, "Hops %d of %u, limit %u left", h.hopsAway(), h.hopStart(), h.hopLimit()); else std::snprintf(s, sizeof s, "Hop limit %u left (old firmware)", h.hopLimit()); lines.push_back(s); // Which preset's default Channel (named after it, with the public key) has this hash. std::string channel; for (size_t i = 0; i < kEu868PresetCount && channel.empty(); ++i) if (channelHash(kEu868Presets[i].name, kDefaultKey, sizeof kDefaultKey) == h.channelHash) channel = std::string(" (") + kEu868Presets[i].name + ", default key)"; std::snprintf(s, sizeof s, "Channel 0x%02x%s", h.channelHash, channel.c_str()); lines.push_back(s); if (h.relayNode) { std::snprintf(s, sizeof s, "Relayed by ..%02x", h.relayNode); lines.push_back(s); } if (h.nextHop) { std::snprintf(s, sizeof s, "Next hop ..%02x", h.nextHop); lines.push_back(s); } return lines; } } // namespace roro::lora