@alteriom/painlessmesh 1.9.3 → 1.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/arduino/wifi.hpp +29 -5
- package/src/painlessMeshSTA.cpp +14 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.9.5] - 2025-12-03
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Bridge Status Send Race Condition** (#224) - Fixed sendToInternet failures caused by race condition
|
|
13
|
+
- **Root Cause**: Bridge would attempt to send status messages to nodes that had already disconnected during the 500ms delay after `changedConnectionCallbacks`
|
|
14
|
+
- **Symptom**: Silent failures when the connection times out before the delayed task executes, causing sendToInternet to fail
|
|
15
|
+
- **Solution**: Added connection validation before sending bridge status:
|
|
16
|
+
- Check `findRoute()` and `conn->connected()` before attempting to send
|
|
17
|
+
- Use direct high-priority send via `conn->addMessage(msg, true)` to avoid redundant routing lookup
|
|
18
|
+
- Added debug logging for cancelled sends to aid troubleshooting
|
|
19
|
+
- **Impact**: Improved reliability of sendToInternet by ensuring bridge status is only sent to active connections
|
|
20
|
+
|
|
21
|
+
- **Isolated Bridge Retry Mechanism** (#225) - Fixed isolated bridge retry when mesh network not found
|
|
22
|
+
- Nodes that fail initial bridge setup can now retry automatically via mesh connection monitoring
|
|
23
|
+
- **Impact**: More reliable bridge establishment in challenging network conditions
|
|
24
|
+
|
|
25
|
+
## [1.9.4] - 2025-12-03
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- **TCP Server Initialization Order** (#219) - Fixed TCP connection error -14 when mesh nodes connect to bridge
|
|
30
|
+
- **Root Cause**: TCP server was being initialized before the AP interface was configured in `init()`, causing it to bind incorrectly and reject incoming connections from mesh nodes
|
|
31
|
+
- **Symptom**: Regular mesh nodes could discover the bridge AP and get an IP, but TCP connections failed with error -14 (connection refused)
|
|
32
|
+
- **Solution**: Reordered initialization in `init()` to start TCP server after AP is configured:
|
|
33
|
+
- `eventHandleInit()` → `apInit(nodeId)` → `tcpServerInit()` (previously tcpServerInit was first)
|
|
34
|
+
- Added 100ms stabilization delay in `initAsBridge()` and `initAsSharedGateway()` after mesh init
|
|
35
|
+
- **Impact**: Fixes `sendToInternet` not working because nodes couldn't establish mesh connections to the bridge
|
|
36
|
+
|
|
8
37
|
## [1.9.3] - 2025-12-02
|
|
9
38
|
|
|
10
39
|
### Fixed
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name=Alteriom PainlessMesh
|
|
2
|
-
version=1.9.
|
|
2
|
+
version=1.9.5
|
|
3
3
|
author=Coopdis,Scotty Franzyshen,Edwin van Leeuwen,Germán Martín,Maximilian Schwarz,Doanh Doanh,Alteriom
|
|
4
4
|
maintainer=Alteriom
|
|
5
5
|
sentence=A painless way to setup a mesh with ESP8266 and ESP32 devices with Alteriom extensions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alteriom/painlessmesh",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.5",
|
|
4
4
|
"description": "painlessMesh is a user-friendly library for creating mesh networks with ESP8266 and ESP32 devices. This Alteriom fork includes additional packages for sensor data (SensorPackage), device commands (CommandPackage), and status monitoring (StatusPackage). It handles routing and network management automatically, so you can focus on your application. The library uses JSON-based messaging and syncs time across all nodes, making it ideal for coordinated behaviour like synchronized light displays or sensor networks reporting to a central node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arduino",
|
package/src/arduino/wifi.hpp
CHANGED
|
@@ -270,7 +270,6 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
270
270
|
}
|
|
271
271
|
});
|
|
272
272
|
|
|
273
|
-
tcpServerInit();
|
|
274
273
|
eventHandleInit();
|
|
275
274
|
|
|
276
275
|
_apIp = IPAddress(0, 0, 0, 0);
|
|
@@ -278,6 +277,12 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
278
277
|
if (connectMode & WIFI_AP) {
|
|
279
278
|
apInit(nodeId); // setup AP
|
|
280
279
|
}
|
|
280
|
+
|
|
281
|
+
// Initialize TCP server AFTER AP is configured
|
|
282
|
+
// This ensures the network interfaces are ready when the server starts
|
|
283
|
+
// Fixes TCP connection error -14 when nodes try to connect to bridge
|
|
284
|
+
tcpServerInit();
|
|
285
|
+
|
|
281
286
|
if (connectMode & WIFI_STA) {
|
|
282
287
|
this->initStation();
|
|
283
288
|
}
|
|
@@ -394,6 +399,10 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
394
399
|
init(meshSSID, meshPassword, baseScheduler, port, WIFI_AP_STA,
|
|
395
400
|
detectedChannel, 0, MAX_CONN);
|
|
396
401
|
|
|
402
|
+
// Allow network stack to stabilize after AP and TCP server initialization
|
|
403
|
+
// This prevents TCP connection errors (-14) when nodes connect
|
|
404
|
+
delay(100);
|
|
405
|
+
|
|
397
406
|
Log(STARTUP, "Step 3: Establishing bridge connection...\n");
|
|
398
407
|
|
|
399
408
|
// Step 3: Re-establish router connection using stationManual
|
|
@@ -565,6 +574,10 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
565
574
|
this->setScheduler(userScheduler);
|
|
566
575
|
init(meshPrefix, meshPassword, port, WIFI_AP_STA, detectedChannel, 0, MAX_CONN);
|
|
567
576
|
|
|
577
|
+
// Allow network stack to stabilize after AP and TCP server initialization
|
|
578
|
+
// This prevents TCP connection errors (-14) when nodes connect
|
|
579
|
+
delay(100);
|
|
580
|
+
|
|
568
581
|
Log(STARTUP, "Step 3: Establishing router connection in shared gateway mode...\n");
|
|
569
582
|
|
|
570
583
|
// Step 3: Establish router connection using stationManual
|
|
@@ -1116,6 +1129,16 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1116
1129
|
// Small delay to ensure connection is fully stable, then send directly to the new node
|
|
1117
1130
|
// This avoids issues with time sync blocking broadcast messages
|
|
1118
1131
|
this->addTask(500, TASK_ONCE, [this, nodeId]() {
|
|
1132
|
+
// Check if the connection is still valid - the node may have disconnected
|
|
1133
|
+
// during the 500ms delay (e.g., due to timeout or network issues)
|
|
1134
|
+
// This prevents attempting to send messages to dropped connections
|
|
1135
|
+
// findRoute returns nullptr if node is not in the routing table
|
|
1136
|
+
auto conn = router::findRoute<Connection>((*this), nodeId);
|
|
1137
|
+
if (!conn || !conn->connected()) {
|
|
1138
|
+
Log(CONNECTION, "Bridge status send cancelled: Node %u no longer connected\n", nodeId);
|
|
1139
|
+
return;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1119
1142
|
// Create bridge status message
|
|
1120
1143
|
JsonDocument doc;
|
|
1121
1144
|
JsonObject obj = doc.to<JsonObject>();
|
|
@@ -1141,10 +1164,11 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1141
1164
|
Log(CONNECTION, "Sending bridge status directly to node %u (Internet: %s)\n",
|
|
1142
1165
|
nodeId, hasInternet ? "YES" : "NO");
|
|
1143
1166
|
|
|
1144
|
-
// Send directly to the
|
|
1145
|
-
//
|
|
1146
|
-
|
|
1147
|
-
|
|
1167
|
+
// Send directly to the connection with high priority
|
|
1168
|
+
// This ensures the message is sent immediately rather than queued
|
|
1169
|
+
// The JSON message format is the same as what router::send() produces
|
|
1170
|
+
// (Variant serializes to the same JSON format we built manually)
|
|
1171
|
+
conn->addMessage(msg, true);
|
|
1148
1172
|
});
|
|
1149
1173
|
});
|
|
1150
1174
|
|
package/src/painlessMeshSTA.cpp
CHANGED
|
@@ -239,13 +239,24 @@ void ICACHE_FLASH_ATTR StationScan::connectToAP() {
|
|
|
239
239
|
mesh->apInit(mesh->getNodeId());
|
|
240
240
|
Log(CONNECTION, "connectToAP(): AP restarted on channel %d\n", detectedChannel);
|
|
241
241
|
}
|
|
242
|
+
// Reset counter only when mesh is found on a new channel
|
|
243
|
+
// This allows isolated bridge retry to continue when mesh is truly absent
|
|
244
|
+
consecutiveEmptyScans = 0;
|
|
242
245
|
} else if (detectedChannel == 0) {
|
|
243
246
|
Log(CONNECTION,
|
|
244
247
|
"connectToAP(): Mesh not found on any channel during re-scan\n");
|
|
248
|
+
// Do NOT reset consecutiveEmptyScans here - mesh is still absent
|
|
249
|
+
// This allows isolated bridge retry mechanism to trigger when
|
|
250
|
+
// the counter exceeds ISOLATED_BRIDGE_RETRY_SCAN_THRESHOLD
|
|
251
|
+
} else {
|
|
252
|
+
// detectedChannel == mesh->_meshChannel
|
|
253
|
+
// Mesh found on same channel we're already on - no channel change needed
|
|
254
|
+
// Reset counter since mesh exists, nodes may appear in subsequent scans
|
|
255
|
+
Log(CONNECTION,
|
|
256
|
+
"connectToAP(): Mesh found on current channel %d, no channel change needed\n",
|
|
257
|
+
detectedChannel);
|
|
258
|
+
consecutiveEmptyScans = 0;
|
|
245
259
|
}
|
|
246
|
-
|
|
247
|
-
// Reset counter after re-scan attempt
|
|
248
|
-
consecutiveEmptyScans = 0;
|
|
249
260
|
}
|
|
250
261
|
|
|
251
262
|
if (WiFi.status() == WL_CONNECTED &&
|