mirror of
https://github.com/alexhopeoconnor/firmware.git
synced 2026-10-13 23:21:19 +10:00
* logging: strip redundant punctuation, level prefixes, and 'successfully' from log strings The logger already appends a newline and prints the level tag, so trailing '.', '!', '...', literal \n, and 'Error:'/'Warning:' prefixes inside format strings are wasted flash bytes. Same for 'successfully' (the affirmative form already implies it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in modules, radio, platform, and system code Rewrite wordy log messages to terser equivalents - drop filler words (articles, 'attempting', 'due to', 'please'), use 'Can't X'/'X failed' phrasing, and abbreviate where the codebase already does (config, init, msg, BT). Format specifiers and argument lists are unchanged; distinctive greppable tokens are preserved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in telemetry sensors and GPS Same terseness pass: drop filler, 'Can't X'/'X failed' phrasing, common abbreviations (temp, msg). Specifiers, arguments, and sensor-name prefixes unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in mesh core Same terseness pass over NodeDB, Router, MeshService, PhoneAPI, RadioInterface, NextHopRouter, and PacketHistory: 'X failed'/'Can't X' phrasing, imperative verbs, dropped filler. Specifiers and arguments unchanged; duplicate literals kept identical to preserve linker string dedup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: 'Unable to/Could not/Cannot' -> "Can't" in log strings Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: clang-format rewrap after string shortening Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: restore boot-logo trailing newline and progress-dot strings The terseness pass over-trimmed: the Meshtastic ASCII boot logo kept its blank line via a trailing \n, and three bare "." progress ticks were reduced to empty strings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * Update src/mesh/wifi/WiFiAPClient.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * logging: address review feedback on the terseness audit - Node/packet IDs use the repo's 0x%08x convention in NextHopRouter, NodeDB, AdminModule and CannedMessageModule. The sibling log in each if/else pair is converted too, so a pair isn't split across two formats. next_hop stays 0x%x - it's the last-byte relay hint, not a NodeNum. - RTC: the read-path and set-path "not found" warnings were byte-identical, so the linker deduped them and the log couldn't say which one fired. Split into "RTC read:" / "RTC set:". (The four sites live in mutually exclusive #ifdef branches, so the RTC family was never ambiguous.) - SCD4X getAmbientPressure()/setAmbientPressure() logged "altitude", and SCD30 getASC() logged "Can't send command" for a read. Both now name the operation they actually perform. - LOG_ERROR already carries the level: ". Error: %u" -> ", rc=%u" (matching the existing rc=%d house style) and "Error executing X()" -> "X() failed". - Typos and wording: "OTA partiton. (Reason" -> "OTA partition (reason", "CST3530 not response ~" -> "CST3530 no response", "Packet received with to: of 0" -> "to=0", HostMetrics "Error decoding" -> "Can't decode", and the dangling ": " on the NextHopRouter retransmission line. Printf specifier sequences are byte-identical on all 37 touched lines apart from the 6 deliberate %x/%u -> %08x node-ID widenings, all on uint32_t args. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
481 lines
24 KiB
C++
481 lines
24 KiB
C++
#if ARCH_PORTDUINO
|
|
#include "MeshPacketSerializer.h"
|
|
#include "NodeDB.h"
|
|
#include "mesh/generated/meshtastic/mqtt.pb.h"
|
|
#include "mesh/generated/meshtastic/telemetry.pb.h"
|
|
#include "modules/RoutingModule.h"
|
|
#include <DebugConfiguration.h>
|
|
#include <json/json.h>
|
|
#include <memory>
|
|
#include <mesh-pb-constants.h>
|
|
#if defined(ARCH_ESP32)
|
|
#include "../mesh/generated/meshtastic/paxcount.pb.h"
|
|
#endif
|
|
#include "mesh/generated/meshtastic/remote_hardware.pb.h"
|
|
#include <sys/types.h>
|
|
|
|
static const char *errStr = "Error decoding proto for %s message!";
|
|
|
|
static std::string writeCompact(const Json::Value &v)
|
|
{
|
|
Json::StreamWriterBuilder b;
|
|
b["indentation"] = "";
|
|
b["emitUTF8"] = true;
|
|
return Json::writeString(b, v);
|
|
}
|
|
|
|
static bool tryParseJson(const char *s, Json::Value &out)
|
|
{
|
|
Json::CharReaderBuilder b;
|
|
std::unique_ptr<Json::CharReader> reader(b.newCharReader());
|
|
std::string errs;
|
|
const char *end = s + strlen(s);
|
|
return reader->parse(s, end, &out, &errs);
|
|
}
|
|
|
|
std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp, bool shouldLog)
|
|
{
|
|
std::string msgType;
|
|
Json::Value jsonObj(Json::objectValue);
|
|
|
|
if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag) {
|
|
Json::Value msgPayload(Json::objectValue);
|
|
switch (mp->decoded.portnum) {
|
|
case meshtastic_PortNum_TEXT_MESSAGE_APP: {
|
|
msgType = "text";
|
|
if (shouldLog)
|
|
LOG_DEBUG("got text message of size %u", mp->decoded.payload.size);
|
|
|
|
char payloadStr[(mp->decoded.payload.size) + 1];
|
|
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
|
|
payloadStr[mp->decoded.payload.size] = 0;
|
|
Json::Value parsed;
|
|
if (tryParseJson(payloadStr, parsed)) {
|
|
if (shouldLog)
|
|
LOG_INFO("text message payload is of type json");
|
|
jsonObj["payload"] = parsed;
|
|
} else {
|
|
if (shouldLog)
|
|
LOG_INFO("text message payload is of type plaintext");
|
|
msgPayload["text"] = payloadStr;
|
|
jsonObj["payload"] = msgPayload;
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_TELEMETRY_APP: {
|
|
msgType = "telemetry";
|
|
meshtastic_Telemetry scratch;
|
|
meshtastic_Telemetry *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Telemetry_msg, &scratch)) {
|
|
decoded = &scratch;
|
|
if (decoded->which_variant == meshtastic_Telemetry_device_metrics_tag) {
|
|
if (decoded->variant.device_metrics.has_battery_level) {
|
|
msgPayload["battery_level"] = (int)decoded->variant.device_metrics.battery_level;
|
|
}
|
|
msgPayload["voltage"] = decoded->variant.device_metrics.voltage;
|
|
msgPayload["channel_utilization"] = decoded->variant.device_metrics.channel_utilization;
|
|
msgPayload["air_util_tx"] = decoded->variant.device_metrics.air_util_tx;
|
|
msgPayload["uptime_seconds"] = (Json::UInt)decoded->variant.device_metrics.uptime_seconds;
|
|
} else if (decoded->which_variant == meshtastic_Telemetry_environment_metrics_tag) {
|
|
if (decoded->variant.environment_metrics.has_temperature) {
|
|
msgPayload["temperature"] = decoded->variant.environment_metrics.temperature;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_relative_humidity) {
|
|
msgPayload["relative_humidity"] = decoded->variant.environment_metrics.relative_humidity;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_barometric_pressure) {
|
|
msgPayload["barometric_pressure"] = decoded->variant.environment_metrics.barometric_pressure;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_gas_resistance) {
|
|
msgPayload["gas_resistance"] = decoded->variant.environment_metrics.gas_resistance;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_voltage) {
|
|
msgPayload["voltage"] = decoded->variant.environment_metrics.voltage;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_current) {
|
|
msgPayload["current"] = decoded->variant.environment_metrics.current;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_lux) {
|
|
msgPayload["lux"] = decoded->variant.environment_metrics.lux;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_white_lux) {
|
|
msgPayload["white_lux"] = decoded->variant.environment_metrics.white_lux;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_iaq) {
|
|
msgPayload["iaq"] = (Json::UInt)decoded->variant.environment_metrics.iaq;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_distance) {
|
|
msgPayload["distance"] = decoded->variant.environment_metrics.distance;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_wind_speed) {
|
|
msgPayload["wind_speed"] = decoded->variant.environment_metrics.wind_speed;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_wind_direction) {
|
|
msgPayload["wind_direction"] = (Json::UInt)decoded->variant.environment_metrics.wind_direction;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_wind_gust) {
|
|
msgPayload["wind_gust"] = decoded->variant.environment_metrics.wind_gust;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_wind_lull) {
|
|
msgPayload["wind_lull"] = decoded->variant.environment_metrics.wind_lull;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_radiation) {
|
|
msgPayload["radiation"] = decoded->variant.environment_metrics.radiation;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_ir_lux) {
|
|
msgPayload["ir_lux"] = decoded->variant.environment_metrics.ir_lux;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_uv_lux) {
|
|
msgPayload["uv_lux"] = decoded->variant.environment_metrics.uv_lux;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_weight) {
|
|
msgPayload["weight"] = decoded->variant.environment_metrics.weight;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_rainfall_1h) {
|
|
msgPayload["rainfall_1h"] = decoded->variant.environment_metrics.rainfall_1h;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_rainfall_24h) {
|
|
msgPayload["rainfall_24h"] = decoded->variant.environment_metrics.rainfall_24h;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_soil_moisture) {
|
|
msgPayload["soil_moisture"] = (Json::UInt)decoded->variant.environment_metrics.soil_moisture;
|
|
}
|
|
if (decoded->variant.environment_metrics.has_soil_temperature) {
|
|
msgPayload["soil_temperature"] = decoded->variant.environment_metrics.soil_temperature;
|
|
}
|
|
} else if (decoded->which_variant == meshtastic_Telemetry_air_quality_metrics_tag) {
|
|
if (decoded->variant.air_quality_metrics.has_pm10_standard) {
|
|
msgPayload["pm10"] = (Json::UInt)decoded->variant.air_quality_metrics.pm10_standard;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_pm25_standard) {
|
|
msgPayload["pm25"] = (Json::UInt)decoded->variant.air_quality_metrics.pm25_standard;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_pm100_standard) {
|
|
msgPayload["pm100"] = (Json::UInt)decoded->variant.air_quality_metrics.pm100_standard;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_co2) {
|
|
msgPayload["co2"] = (Json::UInt)decoded->variant.air_quality_metrics.co2;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_co2_temperature) {
|
|
msgPayload["co2_temperature"] = decoded->variant.air_quality_metrics.co2_temperature;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_co2_humidity) {
|
|
msgPayload["co2_humidity"] = decoded->variant.air_quality_metrics.co2_humidity;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_form_formaldehyde) {
|
|
msgPayload["form_formaldehyde"] = decoded->variant.air_quality_metrics.form_formaldehyde;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_form_temperature) {
|
|
msgPayload["form_temperature"] = decoded->variant.air_quality_metrics.form_temperature;
|
|
}
|
|
if (decoded->variant.air_quality_metrics.has_form_humidity) {
|
|
msgPayload["form_humidity"] = decoded->variant.air_quality_metrics.form_humidity;
|
|
}
|
|
} else if (decoded->which_variant == meshtastic_Telemetry_power_metrics_tag) {
|
|
if (decoded->variant.power_metrics.has_ch1_voltage) {
|
|
msgPayload["voltage_ch1"] = decoded->variant.power_metrics.ch1_voltage;
|
|
}
|
|
if (decoded->variant.power_metrics.has_ch1_current) {
|
|
msgPayload["current_ch1"] = decoded->variant.power_metrics.ch1_current;
|
|
}
|
|
if (decoded->variant.power_metrics.has_ch2_voltage) {
|
|
msgPayload["voltage_ch2"] = decoded->variant.power_metrics.ch2_voltage;
|
|
}
|
|
if (decoded->variant.power_metrics.has_ch2_current) {
|
|
msgPayload["current_ch2"] = decoded->variant.power_metrics.ch2_current;
|
|
}
|
|
if (decoded->variant.power_metrics.has_ch3_voltage) {
|
|
msgPayload["voltage_ch3"] = decoded->variant.power_metrics.ch3_voltage;
|
|
}
|
|
if (decoded->variant.power_metrics.has_ch3_current) {
|
|
msgPayload["current_ch3"] = decoded->variant.power_metrics.ch3_current;
|
|
}
|
|
}
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_NODEINFO_APP: {
|
|
msgType = "nodeinfo";
|
|
meshtastic_User scratch;
|
|
meshtastic_User *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_User_msg, &scratch)) {
|
|
decoded = &scratch;
|
|
msgPayload["id"] = decoded->id;
|
|
msgPayload["longname"] = decoded->long_name;
|
|
msgPayload["shortname"] = decoded->short_name;
|
|
msgPayload["hardware"] = (int)decoded->hw_model;
|
|
msgPayload["role"] = (int)decoded->role;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_POSITION_APP: {
|
|
msgType = "position";
|
|
meshtastic_Position scratch;
|
|
meshtastic_Position *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Position_msg, &scratch)) {
|
|
decoded = &scratch;
|
|
if ((int)decoded->time) {
|
|
msgPayload["time"] = (Json::UInt)decoded->time;
|
|
}
|
|
if ((int)decoded->timestamp) {
|
|
msgPayload["timestamp"] = (Json::UInt)decoded->timestamp;
|
|
}
|
|
msgPayload["latitude_i"] = (int)decoded->latitude_i;
|
|
msgPayload["longitude_i"] = (int)decoded->longitude_i;
|
|
if ((int)decoded->altitude) {
|
|
msgPayload["altitude"] = (int)decoded->altitude;
|
|
}
|
|
if ((int)decoded->ground_speed) {
|
|
msgPayload["ground_speed"] = (Json::UInt)decoded->ground_speed;
|
|
}
|
|
if (int(decoded->ground_track)) {
|
|
msgPayload["ground_track"] = (Json::UInt)decoded->ground_track;
|
|
}
|
|
if (int(decoded->sats_in_view)) {
|
|
msgPayload["sats_in_view"] = (Json::UInt)decoded->sats_in_view;
|
|
}
|
|
if ((int)decoded->PDOP) {
|
|
msgPayload["PDOP"] = (int)decoded->PDOP;
|
|
}
|
|
if ((int)decoded->HDOP) {
|
|
msgPayload["HDOP"] = (int)decoded->HDOP;
|
|
}
|
|
if ((int)decoded->VDOP) {
|
|
msgPayload["VDOP"] = (int)decoded->VDOP;
|
|
}
|
|
if ((int)decoded->precision_bits) {
|
|
msgPayload["precision_bits"] = (int)decoded->precision_bits;
|
|
}
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_WAYPOINT_APP: {
|
|
msgType = "waypoint";
|
|
meshtastic_Waypoint scratch;
|
|
meshtastic_Waypoint *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Waypoint_msg, &scratch)) {
|
|
decoded = &scratch;
|
|
msgPayload["id"] = (Json::UInt)decoded->id;
|
|
msgPayload["name"] = decoded->name;
|
|
msgPayload["description"] = decoded->description;
|
|
msgPayload["expire"] = (Json::UInt)decoded->expire;
|
|
msgPayload["locked_to"] = (Json::UInt)decoded->locked_to;
|
|
msgPayload["latitude_i"] = (int)decoded->latitude_i;
|
|
msgPayload["longitude_i"] = (int)decoded->longitude_i;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_NEIGHBORINFO_APP: {
|
|
msgType = "neighborinfo";
|
|
meshtastic_NeighborInfo scratch;
|
|
meshtastic_NeighborInfo *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_NeighborInfo_msg,
|
|
&scratch)) {
|
|
decoded = &scratch;
|
|
msgPayload["node_id"] = (Json::UInt)decoded->node_id;
|
|
msgPayload["node_broadcast_interval_secs"] = (Json::UInt)decoded->node_broadcast_interval_secs;
|
|
msgPayload["last_sent_by_id"] = (Json::UInt)decoded->last_sent_by_id;
|
|
msgPayload["neighbors_count"] = (Json::UInt)decoded->neighbors_count;
|
|
Json::Value neighbors(Json::arrayValue);
|
|
for (uint8_t i = 0; i < decoded->neighbors_count; i++) {
|
|
Json::Value neighborObj(Json::objectValue);
|
|
neighborObj["node_id"] = (Json::UInt)decoded->neighbors[i].node_id;
|
|
neighborObj["snr"] = (int)decoded->neighbors[i].snr;
|
|
neighbors.append(neighborObj);
|
|
}
|
|
msgPayload["neighbors"] = neighbors;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_TRACEROUTE_APP: {
|
|
if (mp->decoded.request_id) {
|
|
msgType = "traceroute";
|
|
meshtastic_RouteDiscovery scratch;
|
|
meshtastic_RouteDiscovery *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_RouteDiscovery_msg,
|
|
&scratch)) {
|
|
decoded = &scratch;
|
|
Json::Value route(Json::arrayValue);
|
|
Json::Value routeBack(Json::arrayValue);
|
|
Json::Value snrTowards(Json::arrayValue);
|
|
Json::Value snrBack(Json::arrayValue);
|
|
|
|
auto addToRoute = [](Json::Value *r, NodeNum num) {
|
|
char long_name[40] = "Unknown";
|
|
const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(num);
|
|
bool name_known = nodeInfoLiteHasUser(node);
|
|
if (name_known) {
|
|
const size_t copy_len =
|
|
(sizeof(node->long_name) < sizeof(long_name)) ? sizeof(node->long_name) : sizeof(long_name) - 1;
|
|
memcpy(long_name, node->long_name, copy_len);
|
|
long_name[copy_len] = '\0';
|
|
}
|
|
r->append(long_name);
|
|
};
|
|
addToRoute(&route, mp->to);
|
|
for (uint8_t i = 0; i < decoded->route_count; i++) {
|
|
addToRoute(&route, decoded->route[i]);
|
|
}
|
|
addToRoute(&route, mp->from);
|
|
|
|
addToRoute(&routeBack, mp->from);
|
|
for (uint8_t i = 0; i < decoded->route_back_count; i++) {
|
|
addToRoute(&routeBack, decoded->route_back[i]);
|
|
}
|
|
addToRoute(&routeBack, mp->to);
|
|
|
|
for (uint8_t i = 0; i < decoded->snr_back_count; i++) {
|
|
snrBack.append((float)decoded->snr_back[i] / 4);
|
|
}
|
|
for (uint8_t i = 0; i < decoded->snr_towards_count; i++) {
|
|
snrTowards.append((float)decoded->snr_towards[i] / 4);
|
|
}
|
|
|
|
msgPayload["route"] = route;
|
|
msgPayload["route_back"] = routeBack;
|
|
msgPayload["snr_back"] = snrBack;
|
|
msgPayload["snr_towards"] = snrTowards;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case meshtastic_PortNum_DETECTION_SENSOR_APP: {
|
|
msgType = "detection";
|
|
char payloadStr[(mp->decoded.payload.size) + 1];
|
|
memcpy(payloadStr, mp->decoded.payload.bytes, mp->decoded.payload.size);
|
|
payloadStr[mp->decoded.payload.size] = 0;
|
|
msgPayload["text"] = payloadStr;
|
|
jsonObj["payload"] = msgPayload;
|
|
break;
|
|
}
|
|
#ifdef ARCH_ESP32
|
|
case meshtastic_PortNum_PAXCOUNTER_APP: {
|
|
msgType = "paxcounter";
|
|
meshtastic_Paxcount scratch;
|
|
meshtastic_Paxcount *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_Paxcount_msg, &scratch)) {
|
|
decoded = &scratch;
|
|
msgPayload["wifi_count"] = (Json::UInt)decoded->wifi;
|
|
msgPayload["ble_count"] = (Json::UInt)decoded->ble;
|
|
msgPayload["uptime"] = (Json::UInt)decoded->uptime;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, msgType.c_str());
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
case meshtastic_PortNum_REMOTE_HARDWARE_APP: {
|
|
meshtastic_HardwareMessage scratch;
|
|
meshtastic_HardwareMessage *decoded = NULL;
|
|
memset(&scratch, 0, sizeof(scratch));
|
|
if (pb_decode_from_bytes(mp->decoded.payload.bytes, mp->decoded.payload.size, &meshtastic_HardwareMessage_msg,
|
|
&scratch)) {
|
|
decoded = &scratch;
|
|
if (decoded->type == meshtastic_HardwareMessage_Type_GPIOS_CHANGED) {
|
|
msgType = "gpios_changed";
|
|
msgPayload["gpio_value"] = (Json::UInt)decoded->gpio_value;
|
|
jsonObj["payload"] = msgPayload;
|
|
} else if (decoded->type == meshtastic_HardwareMessage_Type_READ_GPIOS_REPLY) {
|
|
msgType = "gpios_read_reply";
|
|
msgPayload["gpio_value"] = (Json::UInt)decoded->gpio_value;
|
|
msgPayload["gpio_mask"] = (Json::UInt)decoded->gpio_mask;
|
|
jsonObj["payload"] = msgPayload;
|
|
}
|
|
} else if (shouldLog) {
|
|
LOG_ERROR(errStr, "RemoteHardware");
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
} else if (shouldLog) {
|
|
LOG_WARN("Can't convert encrypted payload of MeshPacket to JSON");
|
|
}
|
|
|
|
jsonObj["id"] = (Json::UInt)mp->id;
|
|
// Emit 0 rather than leak a millis() placeholder when has_rx_time is false.
|
|
jsonObj["timestamp"] = mp->has_rx_time ? (Json::UInt)mp->rx_time : 0;
|
|
jsonObj["to"] = (Json::UInt)mp->to;
|
|
jsonObj["from"] = (Json::UInt)mp->from;
|
|
jsonObj["channel"] = (Json::UInt)mp->channel;
|
|
jsonObj["type"] = msgType;
|
|
jsonObj["sender"] = nodeDB->getNodeId();
|
|
// rx_rssi has explicit presence on the wire (unlike rx_snr): trust has_rx_rssi rather than a
|
|
// != 0 heuristic, since 0 dBm is a legitimate reading on some radios.
|
|
if (mp->has_rx_rssi)
|
|
jsonObj["rssi"] = (int)mp->rx_rssi;
|
|
if (mp->rx_snr != 0)
|
|
jsonObj["snr"] = (float)mp->rx_snr;
|
|
const int8_t hopsAway = getHopsAway(*mp);
|
|
if (hopsAway >= 0) {
|
|
jsonObj["hops_away"] = (Json::UInt)(hopsAway);
|
|
jsonObj["hop_start"] = (Json::UInt)(mp->hop_start);
|
|
}
|
|
|
|
std::string jsonStr = writeCompact(jsonObj);
|
|
|
|
if (shouldLog)
|
|
LOG_INFO("serialized json message: %s", jsonStr.c_str());
|
|
|
|
return jsonStr;
|
|
}
|
|
|
|
std::string MeshPacketSerializer::JsonSerializeEncrypted(const meshtastic_MeshPacket *mp)
|
|
{
|
|
Json::Value jsonObj(Json::objectValue);
|
|
|
|
jsonObj["id"] = (Json::UInt)mp->id;
|
|
jsonObj["time_ms"] = (double)millis();
|
|
// Emit 0 rather than leak a millis() placeholder when has_rx_time is false.
|
|
jsonObj["timestamp"] = mp->has_rx_time ? (Json::UInt)mp->rx_time : 0;
|
|
jsonObj["to"] = (Json::UInt)mp->to;
|
|
jsonObj["from"] = (Json::UInt)mp->from;
|
|
jsonObj["channel"] = (Json::UInt)mp->channel;
|
|
jsonObj["want_ack"] = mp->want_ack;
|
|
|
|
// rx_rssi has explicit presence on the wire (unlike rx_snr): trust has_rx_rssi rather than a
|
|
// != 0 heuristic, since 0 dBm is a legitimate reading on some radios.
|
|
if (mp->has_rx_rssi)
|
|
jsonObj["rssi"] = (int)mp->rx_rssi;
|
|
if (mp->rx_snr != 0)
|
|
jsonObj["snr"] = (float)mp->rx_snr;
|
|
const int8_t hopsAway = getHopsAway(*mp);
|
|
if (hopsAway >= 0) {
|
|
jsonObj["hops_away"] = (Json::UInt)(hopsAway);
|
|
jsonObj["hop_start"] = (Json::UInt)(mp->hop_start);
|
|
}
|
|
jsonObj["size"] = (Json::UInt)mp->encrypted.size;
|
|
auto encryptedStr = bytesToHex(mp->encrypted.bytes, mp->encrypted.size);
|
|
jsonObj["bytes"] = encryptedStr;
|
|
|
|
return writeCompact(jsonObj);
|
|
}
|
|
#endif
|