diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index d6a9554d..dfd407b6 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -1123,6 +1123,27 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc memset(default_scope.key, 0, sizeof(default_scope.key)); } +#if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) +// Only an automatic link carries a hostname today (see the header note). The +// value reaches DHCP when the link next starts or reconnects: IDF 4.4 states +// plainly that a hostname changed after the interface is up "would only be +// reflected once the interface restarts/reconnects", and Arduino 2.x's +// WiFi.setHostname() does not even touch a running netif — it writes a static +// string the netif reads at bring-up. So this cannot rename a live lease, and +// deliberately does not bounce the link to force one: dropping an observer's +// route mid-operation costs every MQTT slot a reconnect, which is not a +// reasonable price for a cosmetic rename. +void MyMesh::applyNetworkHostname(const char* when) { + NetworkLink& link = activeNetworkLink(); + if (!link.isAutomatic()) return; + char network_hostname[NetworkHostname::kBufferSize]; + NetworkHostname::build(network_hostname, sizeof(network_hostname), + _prefs.node_name, self_id.pub_key, PUB_KEY_SIZE); + link.setHostname(network_hostname); + Serial.printf("Network: hostname %s%s\n", network_hostname, when); +} +#endif + void MyMesh::begin(FILESYSTEM *fs) { mesh::Mesh::begin(); _fs = fs; @@ -1151,11 +1172,7 @@ void MyMesh::begin(FILESYSTEM *fs) { #if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) NetworkLink& boot_network = activeNetworkLink(); if (boot_network.isAutomatic()) { - char network_hostname[NetworkHostname::kBufferSize]; - NetworkHostname::build(network_hostname, sizeof(network_hostname), - _prefs.node_name, self_id.pub_key, PUB_KEY_SIZE); - boot_network.setHostname(network_hostname); - Serial.printf("Network: hostname %s\n", network_hostname); + applyNetworkHostname(""); MQTTPrefs* obs = _cli.getObserverPrefs(); Serial.printf("Network: probing Ethernet for up to %lums\n", (unsigned long)NETWORK_ETHERNET_BOOT_WAIT_MS); diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index aebfa2e6..344d4932 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -274,10 +274,23 @@ protected: void sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size); + // Build the DHCP hostname from the current node name and hand it to the + // link. Only automatic links carry one: a plain Wi-Fi observer keeps the + // framework default, and changing that for the existing fleet is a separate + // decision. + void applyNetworkHostname(const char* when); + public: MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables); void begin(FILESYSTEM* fs); + + // CommonCLICallbacks: `set name` has just rewritten node_name. + void onNodeNameChanged() override { +#if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) + applyNetworkHostname(" (renamed)"); +#endif + } void sendNodeDiscoverReq(); const char* getFirmwareVer() override { return FIRMWARE_VERSION; } const char* getBuildDate() override { return FIRMWARE_BUILD_DATE; } diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 146c547e..1eba3892 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -943,6 +943,27 @@ MyMesh::MyMesh(mesh::MainBoard &board, mesh::Radio &radio, mesh::MillisecondCloc memset(default_scope.key, 0, sizeof(default_scope.key)); } +#if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) +// Only an automatic link carries a hostname today (see the header note). The +// value reaches DHCP when the link next starts or reconnects: IDF 4.4 states +// plainly that a hostname changed after the interface is up "would only be +// reflected once the interface restarts/reconnects", and Arduino 2.x's +// WiFi.setHostname() does not even touch a running netif — it writes a static +// string the netif reads at bring-up. So this cannot rename a live lease, and +// deliberately does not bounce the link to force one: dropping an observer's +// route mid-operation costs every MQTT slot a reconnect, which is not a +// reasonable price for a cosmetic rename. +void MyMesh::applyNetworkHostname(const char* when) { + NetworkLink& link = activeNetworkLink(); + if (!link.isAutomatic()) return; + char network_hostname[NetworkHostname::kBufferSize]; + NetworkHostname::build(network_hostname, sizeof(network_hostname), + _prefs.node_name, self_id.pub_key, PUB_KEY_SIZE); + link.setHostname(network_hostname); + Serial.printf("Network: hostname %s%s\n", network_hostname, when); +} +#endif + void MyMesh::begin(FILESYSTEM *fs) { mesh::Mesh::begin(); _fs = fs; @@ -952,11 +973,7 @@ void MyMesh::begin(FILESYSTEM *fs) { #if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) NetworkLink& boot_network = activeNetworkLink(); if (boot_network.isAutomatic()) { - char network_hostname[NetworkHostname::kBufferSize]; - NetworkHostname::build(network_hostname, sizeof(network_hostname), - _prefs.node_name, self_id.pub_key, PUB_KEY_SIZE); - boot_network.setHostname(network_hostname); - Serial.printf("Network: hostname %s\n", network_hostname); + applyNetworkHostname(""); MQTTPrefs* obs = _cli.getObserverPrefs(); Serial.printf("Network: probing Ethernet for up to %lums\n", (unsigned long)NETWORK_ETHERNET_BOOT_WAIT_MS); diff --git a/examples/simple_room_server/MyMesh.h b/examples/simple_room_server/MyMesh.h index bfcfe362..1870df79 100644 --- a/examples/simple_room_server/MyMesh.h +++ b/examples/simple_room_server/MyMesh.h @@ -281,10 +281,23 @@ protected: void sendFloodReply(mesh::Packet* packet, unsigned long delay_millis, uint8_t path_hash_size); + // Build the DHCP hostname from the current node name and hand it to the + // link. Only automatic links carry one: a plain Wi-Fi observer keeps the + // framework default, and changing that for the existing fleet is a separate + // decision. + void applyNetworkHostname(const char* when); + public: MyMesh(mesh::MainBoard& board, mesh::Radio& radio, mesh::MillisecondClock& ms, mesh::RNG& rng, mesh::RTCClock& rtc, mesh::MeshTables& tables); void begin(FILESYSTEM* fs); + + // CommonCLICallbacks: `set name` has just rewritten node_name. + void onNodeNameChanged() override { +#if defined(WITH_MQTT_BRIDGE) && defined(ESP_PLATFORM) + applyNetworkHostname(" (renamed)"); +#endif + } void addSystemPost(const char* postData); const char* getFirmwareVer() override { return FIRMWARE_VERSION; } diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 244db25b..657157d1 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -1583,6 +1583,7 @@ void CommonCLI::handleSetCmd(uint32_t sender_timestamp, char* command, char* rep if (isValidName(&config[5])) { StrHelper::strncpy(_prefs->node_name, &config[5], sizeof(_prefs->node_name)); savePrefs(); + _callbacks->onNodeNameChanged(); strcpy(reply, "OK"); } else { strcpy(reply, "Error, bad chars"); diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 040e845f..34912525 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -274,6 +274,10 @@ struct LegacyObserverTail { class CommonCLICallbacks { public: virtual void savePrefs() = 0; + // The node name feeds the DHCP hostname, which is built once when the link + // starts. Renaming a running node has to rebuild it or the node keeps + // advertising the old name to DHCP until the next reflash. + virtual void onNodeNameChanged() {} #ifdef WITH_MQTT_BRIDGE virtual bool saveObserverPrefs() = 0; #else