From 627c0145e7df9f52109a822a73c35f08a2951a43 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Mon, 6 Oct 2025 07:56:27 -0500 Subject: [PATCH] Centralize getNodeId and fix references to owner.id (#8230) --- src/mesh/NodeDB.cpp | 7 ++++ src/mesh/NodeDB.h | 4 ++ src/mesh/PhoneAPI.cpp | 2 + src/mesh/wifi/WiFiAPClient.cpp | 4 +- src/mqtt/MQTT.cpp | 38 ++++++++++++++----- src/serialization/MeshPacketSerializer.cpp | 2 +- .../MeshPacketSerializer_nRF52.cpp | 2 +- test/test_mqtt/MQTT.cpp | 4 +- 8 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index e3240462d..dec8411fe 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1874,6 +1874,13 @@ uint8_t NodeDB::getMeshNodeChannel(NodeNum n) return info->channel; } +std::string NodeDB::getNodeId() const +{ + char nodeId[16]; + snprintf(nodeId, sizeof(nodeId), "!%08x", myNodeInfo.my_node_num); + return std::string(nodeId); +} + /// Find a node in our DB, return null for missing /// NOTE: This function might be called from an ISR meshtastic_NodeInfoLite *NodeDB::getMeshNode(NodeNum n) diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index f73f64f92..e8724f2c9 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "MeshTypes.h" @@ -203,6 +204,9 @@ class NodeDB /// @return our node number NodeNum getNodeNum() { return myNodeInfo.my_node_num; } + /// @return our node ID as a string in the format "!xxxxxxxx" + std::string getNodeId() const; + // @return last byte of a NodeNum, 0xFF if it ended at 0x00 uint8_t getLastByteOfNodeNum(NodeNum num) { return (uint8_t)((num & 0xFF) ? (num & 0xFF) : 0xFF); } diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 07f314415..210e0ba06 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -433,6 +433,8 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) case STATE_SEND_OTHER_NODEINFOS: { LOG_DEBUG("Send known nodes"); if (nodeInfoForPhone.num != 0) { + // Just in case we stored a different user.id in the past, but should never happen going forward + sprintf(nodeInfoForPhone.user.id, "!%08x", nodeInfoForPhone.num); LOG_INFO("nodeinfo: num=0x%x, lastseen=%u, id=%s, name=%s", nodeInfoForPhone.num, nodeInfoForPhone.last_heard, nodeInfoForPhone.user.id, nodeInfoForPhone.user.long_name); fromRadioScratch.which_payload_variant = meshtastic_FromRadio_node_info_tag; diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 1133ad424..7d210dd33 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -94,11 +94,11 @@ static void onNetworkConnected() // ESPmDNS (ESP32) and SimpleMDNS (RP2040) have slightly different APIs for adding TXT records #ifdef ARCH_ESP32 MDNS.addServiceTxt("meshtastic", "tcp", "shortname", String(owner.short_name)); - MDNS.addServiceTxt("meshtastic", "tcp", "id", String(owner.id)); + MDNS.addServiceTxt("meshtastic", "tcp", "id", String(nodeDB->getNodeId().c_str())); // ESP32 prints obtained IP address in WiFiEvent #elif defined(ARCH_RP2040) MDNS.addServiceTxt("meshtastic", "shortname", owner.short_name); - MDNS.addServiceTxt("meshtastic", "id", owner.id); + MDNS.addServiceTxt("meshtastic", "id", nodeDB->getNodeId().c_str()); LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str()); #endif } diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 7f7a9d511..8ce352f14 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -60,7 +60,9 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length) return; } const meshtastic_Channel &ch = channels.getByName(e.channel_id); - if (strcmp(e.gateway_id, owner.id) == 0) { + // Generate node ID from nodenum for comparison + std::string nodeId = nodeDB->getNodeId(); + if (strcmp(e.gateway_id, nodeId.c_str()) == 0) { // Generate an implicit ACK towards ourselves (handled and processed only locally!) for this message. // We do this because packets are not rebroadcasted back into MQTT anymore and we assume that at least one node // receives it when we get our own packet back. Then we'll stop our retransmissions. @@ -128,8 +130,10 @@ inline void onReceiveProto(char *topic, byte *payload, size_t length) // returns true if this is a valid JSON envelope which we accept on downlink inline bool isValidJsonEnvelope(JSONObject &json) { + // Generate node ID from nodenum for comparison + std::string nodeId = nodeDB->getNodeId(); // if "sender" is provided, avoid processing packets we uplinked - return (json.find("sender") != json.end() ? (json["sender"]->AsString().compare(owner.id) != 0) : true) && + return (json.find("sender") != json.end() ? (json["sender"]->AsString().compare(nodeId) != 0) : true) && (json.find("hopLimit") != json.end() ? json["hopLimit"]->IsNumber() : true) && // hop limit should be a number (json.find("from") != json.end()) && json["from"]->IsNumber() && (json["from"]->AsNumber() == nodeDB->getNodeNum()) && // only accept message if the "from" is us @@ -297,7 +301,9 @@ bool connectPubSub(const PubSubConfig &config, PubSubClient &pubSub, Client &cli LOG_INFO("Connecting directly to MQTT server %s, port: %d, username: %s, password: %s", config.serverAddr.c_str(), config.serverPort, config.mqttUsername, config.mqttPassword); - const bool connected = pubSub.connect(owner.id, config.mqttUsername, config.mqttPassword); + // Generate node ID from nodenum for client identification + std::string nodeId = nodeDB->getNodeId(); + const bool connected = pubSub.connect(nodeId.c_str(), config.mqttUsername, config.mqttPassword); if (connected) { LOG_INFO("MQTT connected"); } else { @@ -687,11 +693,14 @@ void MQTT::publishQueuedMessages() if (jsonString.length() == 0) return; + // Generate node ID from nodenum for topic + std::string nodeId = nodeDB->getNodeId(); + std::string topicJson; if (env.packet->pki_encrypted) { - topicJson = jsonTopic + "PKI/" + owner.id; + topicJson = jsonTopic + "PKI/" + nodeId; } else { - topicJson = jsonTopic + env.channel_id + "/" + owner.id; + topicJson = jsonTopic + env.channel_id + "/" + nodeId; } LOG_INFO("JSON publish message to %s, %u bytes: %s", topicJson.c_str(), jsonString.length(), jsonString.c_str()); publish(topicJson.c_str(), jsonString.c_str(), false); @@ -749,10 +758,14 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me return; // Don't upload a still-encrypted PKI packet if not encryption_enabled } - const meshtastic_ServiceEnvelope env = { - .packet = const_cast(p), .channel_id = const_cast(channelId), .gateway_id = owner.id}; + // Generate node ID from nodenum for service envelope + std::string nodeId = nodeDB->getNodeId(); + + const meshtastic_ServiceEnvelope env = {.packet = const_cast(p), + .channel_id = const_cast(channelId), + .gateway_id = const_cast(nodeId.c_str())}; size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, &env); - std::string topic = cryptTopic + channelId + "/" + owner.id; + std::string topic = cryptTopic + channelId + "/" + nodeId; if (moduleConfig.mqtt.proxy_to_client_enabled || this->isConnectedDirectly()) { LOG_DEBUG("MQTT Publish %s, %u bytes", topic.c_str(), numBytes); @@ -766,7 +779,9 @@ void MQTT::onSend(const meshtastic_MeshPacket &mp_encrypted, const meshtastic_Me auto jsonString = MeshPacketSerializer::JsonSerialize(&mp_decoded); if (jsonString.length() == 0) return; - std::string topicJson = jsonTopic + channelId + "/" + owner.id; + // Generate node ID from nodenum for JSON topic + std::string nodeIdForJson = nodeDB->getNodeId(); + std::string topicJson = jsonTopic + channelId + "/" + nodeIdForJson; LOG_INFO("JSON publish message to %s, %u bytes: %s", topicJson.c_str(), jsonString.length(), jsonString.c_str()); publish(topicJson.c_str(), jsonString.c_str(), false); #endif // ARCH_NRF52 NRF52_USE_JSON @@ -845,11 +860,14 @@ void MQTT::perhapsReportToMap() mp->decoded.payload.size = pb_encode_to_bytes(mp->decoded.payload.bytes, sizeof(mp->decoded.payload.bytes), &meshtastic_MapReport_msg, &mapReport); + // Generate node ID from nodenum for service envelope + std::string nodeId = nodeDB->getNodeId(); + // Encode the MeshPacket into a binary ServiceEnvelope and publish const meshtastic_ServiceEnvelope se = { .packet = mp, .channel_id = (char *)channels.getGlobalId(channels.getPrimaryIndex()), // Use primary channel as the channel_id - .gateway_id = owner.id}; + .gateway_id = const_cast(nodeId.c_str())}; size_t numBytes = pb_encode_to_bytes(bytes, sizeof(bytes), &meshtastic_ServiceEnvelope_msg, &se); LOG_INFO("MQTT Publish map report to %s", mapTopic.c_str()); diff --git a/src/serialization/MeshPacketSerializer.cpp b/src/serialization/MeshPacketSerializer.cpp index 5a1f8ed7e..b31d2dc2e 100644 --- a/src/serialization/MeshPacketSerializer.cpp +++ b/src/serialization/MeshPacketSerializer.cpp @@ -413,7 +413,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp, jsonObj["from"] = new JSONValue((unsigned int)mp->from); jsonObj["channel"] = new JSONValue((unsigned int)mp->channel); jsonObj["type"] = new JSONValue(msgType.c_str()); - jsonObj["sender"] = new JSONValue(owner.id); + jsonObj["sender"] = new JSONValue(nodeDB->getNodeId().c_str()); if (mp->rx_rssi != 0) jsonObj["rssi"] = new JSONValue((int)mp->rx_rssi); if (mp->rx_snr != 0) diff --git a/src/serialization/MeshPacketSerializer_nRF52.cpp b/src/serialization/MeshPacketSerializer_nRF52.cpp index e0daa1a88..353c710a1 100644 --- a/src/serialization/MeshPacketSerializer_nRF52.cpp +++ b/src/serialization/MeshPacketSerializer_nRF52.cpp @@ -353,7 +353,7 @@ std::string MeshPacketSerializer::JsonSerialize(const meshtastic_MeshPacket *mp, jsonObj["from"] = (unsigned int)mp->from; jsonObj["channel"] = (unsigned int)mp->channel; jsonObj["type"] = msgType.c_str(); - jsonObj["sender"] = owner.id; + jsonObj["sender"] = nodeDB->getNodeId().c_str(); if (mp->rx_rssi != 0) jsonObj["rssi"] = (int)mp->rx_rssi; if (mp->rx_snr != 0) diff --git a/test/test_mqtt/MQTT.cpp b/test/test_mqtt/MQTT.cpp index ede3d22b7..8726d1ccb 100644 --- a/test/test_mqtt/MQTT.cpp +++ b/test/test_mqtt/MQTT.cpp @@ -591,7 +591,7 @@ void test_receiveEncryptedPKITopicToUs(void) // Should ignore messages published to MQTT by this gateway. void test_receiveIgnoresOwnPublishedMessages(void) { - unitTest->publish(&decoded, owner.id); + unitTest->publish(&decoded, nodeDB->getNodeId().c_str()); TEST_ASSERT_TRUE(mockRouter->packets_.empty()); TEST_ASSERT_TRUE(mockRoutingModule->ackNacks_.empty()); @@ -603,7 +603,7 @@ void test_receiveAcksOwnSentMessages(void) meshtastic_MeshPacket p = decoded; p.from = myNodeInfo.my_node_num; - unitTest->publish(&p, owner.id); + unitTest->publish(&p, nodeDB->getNodeId().c_str()); TEST_ASSERT_TRUE(mockRouter->packets_.empty()); TEST_ASSERT_EQUAL(1, mockRoutingModule->ackNacks_.size());