@alteriom/painlessmesh 1.8.2 → 1.8.3
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 +32 -0
- package/README.md +62 -11
- package/RELEASE_GUIDE.md +57 -16
- package/docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md +331 -0
- package/docs/features/DIAGNOSTICS_API.md +534 -0
- package/docs/getting-started/arduino-manual-install.md +313 -0
- package/docs/implementation/BRIDGE_ARCHITECTURE_IMPLEMENTATION.md +340 -0
- package/docs/implementation/BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md +213 -0
- package/docs/implementation/BRIDGE_STATUS_FEATURE.md +635 -0
- package/docs/implementation/DIAGNOSTICS_API_IMPLEMENTATION.md +232 -0
- package/docs/implementation/IMPLEMENTATION_COMPLETE.md +228 -0
- package/docs/implementation/IMPLEMENTATION_NTP_TIME_SYNC.md +325 -0
- package/docs/implementation/IMPLEMENTATION_SUMMARY.md +316 -0
- package/docs/implementation/MESSAGE_QUEUE_IMPLEMENTATION.md +405 -0
- package/docs/implementation/MULTI_BRIDGE_IMPLEMENTATION.md +520 -0
- package/docs/implementation/NTP_TIME_SYNC_FEATURE.md +392 -0
- package/docs/internal/CUSTOM_AGENT_ANALYSIS.md +391 -0
- package/docs/internal/ISSUE_65_VERIFICATION.md +947 -0
- package/docs/internal/ISSUE_66_CLOSURE.md +249 -0
- package/docs/internal/ISSUE_66_STATUS.md +316 -0
- package/docs/internal/PR_SUMMARY.md +315 -0
- package/docs/internal/REVIEW_SUMMARY.md +332 -0
- package/docs/releases/PUBLISH_v1.8.0_INSTRUCTIONS.md +163 -0
- package/docs/releases/QUICK_START_RELEASES.md +113 -0
- package/docs/releases/RELEASE_CHECKLIST_v1.8.0.md +331 -0
- package/docs/releases/RELEASE_CHECKLIST_v1.8.2.md +309 -0
- package/docs/releases/RELEASE_NOTES_v1.8.0.md +685 -0
- package/docs/releases/RELEASE_NOTES_v1.8.1.md +221 -0
- package/docs/releases/RELEASE_NOTES_v1.8.2.md +421 -0
- package/docs/releases/RELEASE_NOTES_v1.8.3.md +292 -0
- package/docs/troubleshooting/ARDUINO_IDE_VERSION_FIX_SUMMARY.md +229 -0
- package/docs/troubleshooting/ARDUINO_LIBRARY_NAME_FIX.md +197 -0
- package/docs/troubleshooting/NPM_PUBLISHING_ISSUE_SUMMARY.md +110 -0
- package/docs/troubleshooting/station-reconnection-issues.md +172 -0
- package/examples/priority/README.md +274 -0
- package/examples/priority/priority_basic_example.ino +115 -0
- package/examples/priority/priority_with_queue.ino +249 -0
- package/examples/routing_demo/README.md +172 -0
- package/examples/routing_demo/routing_demo.ino +102 -0
- package/library.json +1 -1
- package/library.properties +3 -3
- package/package.json +1 -1
- package/src/arduino/wifi.hpp +49 -16
- package/src/painlessMesh.h +15 -0
- package/src/painlessMeshSTA.cpp +7 -1
- package/src/painlessmesh/buffer.hpp +218 -37
- package/src/painlessmesh/connection.hpp +21 -1
- package/src/painlessmesh/mesh.hpp +253 -19
- package/src/painlessmesh/router.hpp +31 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Multi-Hop Routing Demo
|
|
2
|
+
|
|
3
|
+
This example demonstrates the new multi-hop routing capabilities implemented in painlessMesh.
|
|
4
|
+
|
|
5
|
+
## Features Demonstrated
|
|
6
|
+
|
|
7
|
+
### 1. Hop Count Calculation (`getHopCount()`)
|
|
8
|
+
- Calculates the actual number of hops to reach any node in the mesh
|
|
9
|
+
- Returns 0 for self, 1 for direct connections, actual count for multi-hop paths
|
|
10
|
+
- Returns -1 if the node is unreachable
|
|
11
|
+
|
|
12
|
+
### 2. Routing Table (`getRoutingTable()`)
|
|
13
|
+
- Returns a complete routing table mapping each destination to its next hop
|
|
14
|
+
- For direct connections, destination equals next hop
|
|
15
|
+
- For multi-hop paths, shows which neighbor to route through
|
|
16
|
+
|
|
17
|
+
### 3. Path Discovery (`getPathToNode()`)
|
|
18
|
+
- Finds the complete path from this node to any target node
|
|
19
|
+
- Returns a vector of node IDs representing the shortest path
|
|
20
|
+
- Useful for visualizing mesh topology and debugging connectivity
|
|
21
|
+
|
|
22
|
+
## How It Works
|
|
23
|
+
|
|
24
|
+
The implementation uses **Breadth-First Search (BFS)** to:
|
|
25
|
+
- Find shortest paths in the mesh topology
|
|
26
|
+
- Build accurate routing tables
|
|
27
|
+
- Calculate hop counts efficiently
|
|
28
|
+
|
|
29
|
+
### Algorithm Complexity
|
|
30
|
+
- **Time**: O(V + E) where V = nodes, E = edges
|
|
31
|
+
- **Space**: O(V) for visited set and queue
|
|
32
|
+
- **Suitable for**: ESP8266 (80KB RAM) and ESP32 (320KB RAM)
|
|
33
|
+
|
|
34
|
+
## Running the Example
|
|
35
|
+
|
|
36
|
+
### Hardware Requirements
|
|
37
|
+
- 2 or more ESP32 or ESP8266 boards
|
|
38
|
+
- No additional hardware needed
|
|
39
|
+
|
|
40
|
+
### Software Requirements
|
|
41
|
+
- painlessMesh library (with multi-hop routing support)
|
|
42
|
+
- TaskScheduler library
|
|
43
|
+
- ArduinoJson library
|
|
44
|
+
|
|
45
|
+
### Setup Instructions
|
|
46
|
+
|
|
47
|
+
1. Upload this sketch to multiple ESP devices
|
|
48
|
+
2. Each device will automatically join the mesh
|
|
49
|
+
3. Open Serial Monitor (115200 baud) on any device
|
|
50
|
+
4. Observe routing information every 10 seconds
|
|
51
|
+
|
|
52
|
+
### Expected Output
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
Routing Demo Started
|
|
56
|
+
Node ID: 123456789
|
|
57
|
+
|
|
58
|
+
=== Routing Information ===
|
|
59
|
+
Mesh contains 3 nodes (plus this node)
|
|
60
|
+
|
|
61
|
+
Hop Counts:
|
|
62
|
+
Node 234567890: 1 hop
|
|
63
|
+
Node 345678901: 2 hops
|
|
64
|
+
Node 456789012: 3 hops
|
|
65
|
+
|
|
66
|
+
Routing Table (Destination -> Next Hop):
|
|
67
|
+
To 234567890 -> via 234567890 (direct connection)
|
|
68
|
+
To 345678901 -> via 234567890
|
|
69
|
+
To 456789012 -> via 234567890
|
|
70
|
+
|
|
71
|
+
Path to node 456789012:
|
|
72
|
+
123456789 -> 234567890 -> 345678901 -> 456789012
|
|
73
|
+
(Total: 3 hops)
|
|
74
|
+
========================
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Use Cases
|
|
78
|
+
|
|
79
|
+
### Network Diagnostics
|
|
80
|
+
- Monitor mesh topology changes in real-time
|
|
81
|
+
- Identify connectivity issues
|
|
82
|
+
- Measure network depth
|
|
83
|
+
|
|
84
|
+
### Load Balancing
|
|
85
|
+
- Choose optimal paths for data transmission
|
|
86
|
+
- Distribute traffic across multiple routes
|
|
87
|
+
- Avoid overloading single-hop nodes
|
|
88
|
+
|
|
89
|
+
### Network Visualization
|
|
90
|
+
- Build visual representations of mesh topology
|
|
91
|
+
- Display on OLED/LCD screens
|
|
92
|
+
- Create web-based network maps
|
|
93
|
+
|
|
94
|
+
## Performance Considerations
|
|
95
|
+
|
|
96
|
+
### Memory Usage
|
|
97
|
+
- Routing table size: ~8 bytes per node
|
|
98
|
+
- BFS temporary storage: ~16 bytes per node
|
|
99
|
+
- Example mesh of 50 nodes: ~1.2KB total
|
|
100
|
+
|
|
101
|
+
### CPU Usage
|
|
102
|
+
- Routing calculation: ~1-5ms for typical meshes
|
|
103
|
+
- Triggered only on topology changes
|
|
104
|
+
- No continuous overhead
|
|
105
|
+
|
|
106
|
+
## Advanced Usage
|
|
107
|
+
|
|
108
|
+
### Custom Routing Logic
|
|
109
|
+
|
|
110
|
+
```cpp
|
|
111
|
+
// Find nodes within N hops
|
|
112
|
+
std::vector<uint32_t> findNodesWithinRange(int maxHops) {
|
|
113
|
+
std::vector<uint32_t> nearby;
|
|
114
|
+
auto nodeList = mesh.getNodeList(false);
|
|
115
|
+
|
|
116
|
+
for (auto nodeId : nodeList) {
|
|
117
|
+
int hops = mesh.getHopCount(nodeId);
|
|
118
|
+
if (hops > 0 && hops <= maxHops) {
|
|
119
|
+
nearby.push_back(nodeId);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return nearby;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Route Optimization
|
|
128
|
+
|
|
129
|
+
```cpp
|
|
130
|
+
// Select best route based on hop count
|
|
131
|
+
uint32_t selectBestRoute(std::vector<uint32_t> candidates) {
|
|
132
|
+
uint32_t best = 0;
|
|
133
|
+
int minHops = 999;
|
|
134
|
+
|
|
135
|
+
for (auto candidate : candidates) {
|
|
136
|
+
int hops = mesh.getHopCount(candidate);
|
|
137
|
+
if (hops > 0 && hops < minHops) {
|
|
138
|
+
minHops = hops;
|
|
139
|
+
best = candidate;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return best;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Troubleshooting
|
|
148
|
+
|
|
149
|
+
### "All nodes show 2 hops"
|
|
150
|
+
- Old firmware without multi-hop support
|
|
151
|
+
- Update to latest painlessMesh version
|
|
152
|
+
|
|
153
|
+
### "Routing table is empty"
|
|
154
|
+
- No other nodes in the mesh
|
|
155
|
+
- Check mesh credentials (SSID/password)
|
|
156
|
+
- Verify mesh is initialized
|
|
157
|
+
|
|
158
|
+
### "Path discovery returns empty vector"
|
|
159
|
+
- Target node is unreachable or left the mesh
|
|
160
|
+
- Check connectivity with `getHopCount()` first
|
|
161
|
+
|
|
162
|
+
## Related Examples
|
|
163
|
+
|
|
164
|
+
- `namedMesh.ino` - Basic mesh setup
|
|
165
|
+
- `diagnosticsExample.ino` - Advanced diagnostics
|
|
166
|
+
- `bridge_failover.ino` - Multi-bridge routing
|
|
167
|
+
|
|
168
|
+
## References
|
|
169
|
+
|
|
170
|
+
- [painlessMesh Documentation](https://alteriom.github.io/painlessMesh/)
|
|
171
|
+
- [Multi-Hop Routing Issue #XXX](https://github.com/Alteriom/painlessMesh/issues/XXX)
|
|
172
|
+
- BFS Algorithm: [Wikipedia](https://en.wikipedia.org/wiki/Breadth-first_search)
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Hop Routing Demo
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates the new multi-hop routing capabilities of painlessMesh.
|
|
5
|
+
* It shows how to:
|
|
6
|
+
* - Calculate hop count to any node in the mesh
|
|
7
|
+
* - Get the complete routing table
|
|
8
|
+
* - Find the path from this node to any other node
|
|
9
|
+
*
|
|
10
|
+
* The functions work automatically with any mesh topology - linear chains,
|
|
11
|
+
* star configurations, or complex multi-hop meshes.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#include "painlessMesh.h"
|
|
15
|
+
|
|
16
|
+
#define MESH_PREFIX "routingDemo"
|
|
17
|
+
#define MESH_PASSWORD "meshPassword"
|
|
18
|
+
#define MESH_PORT 5555
|
|
19
|
+
|
|
20
|
+
Scheduler userScheduler;
|
|
21
|
+
painlessMesh mesh;
|
|
22
|
+
|
|
23
|
+
// Task to periodically display routing information
|
|
24
|
+
Task taskShowRouting(10000, TASK_FOREVER, []() {
|
|
25
|
+
Serial.println("\n=== Routing Information ===");
|
|
26
|
+
|
|
27
|
+
// Get list of all nodes in the mesh
|
|
28
|
+
auto nodeList = mesh.getNodeList(false); // false = don't include self
|
|
29
|
+
Serial.printf("Mesh contains %d nodes (plus this node)\n", nodeList.size());
|
|
30
|
+
|
|
31
|
+
// Display hop count to each node
|
|
32
|
+
Serial.println("\nHop Counts:");
|
|
33
|
+
for (auto nodeId : nodeList) {
|
|
34
|
+
int hops = mesh.getHopCount(nodeId);
|
|
35
|
+
Serial.printf(" Node %u: %d hop%s\n", nodeId, hops, hops == 1 ? "" : "s");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Display complete routing table
|
|
39
|
+
Serial.println("\nRouting Table (Destination -> Next Hop):");
|
|
40
|
+
auto routingTable = mesh.getRoutingTable();
|
|
41
|
+
for (auto& entry : routingTable) {
|
|
42
|
+
Serial.printf(" To %u -> via %u", entry.first, entry.second);
|
|
43
|
+
if (entry.first == entry.second) {
|
|
44
|
+
Serial.print(" (direct connection)");
|
|
45
|
+
}
|
|
46
|
+
Serial.println();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Example: Show path to first node in list
|
|
50
|
+
if (!nodeList.empty()) {
|
|
51
|
+
uint32_t targetNode = nodeList.front();
|
|
52
|
+
auto path = mesh.getPathToNode(targetNode);
|
|
53
|
+
|
|
54
|
+
if (!path.empty()) {
|
|
55
|
+
Serial.printf("\nPath to node %u:\n ", targetNode);
|
|
56
|
+
for (size_t i = 0; i < path.size(); i++) {
|
|
57
|
+
Serial.printf("%u", path[i]);
|
|
58
|
+
if (i < path.size() - 1) {
|
|
59
|
+
Serial.print(" -> ");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
Serial.printf("\n (Total: %d hop%s)\n", path.size() - 1,
|
|
63
|
+
path.size() - 1 == 1 ? "" : "s");
|
|
64
|
+
} else {
|
|
65
|
+
Serial.printf("\nNode %u is unreachable\n", targetNode);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Serial.println("========================\n");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
void setup() {
|
|
73
|
+
Serial.begin(115200);
|
|
74
|
+
|
|
75
|
+
// Initialize mesh
|
|
76
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
77
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
78
|
+
|
|
79
|
+
// Setup callbacks
|
|
80
|
+
mesh.onNewConnection([](uint32_t nodeId) {
|
|
81
|
+
Serial.printf("\nNew connection: Node %u joined the mesh\n", nodeId);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
mesh.onDroppedConnection([](uint32_t nodeId) {
|
|
85
|
+
Serial.printf("\nConnection dropped: Node %u left the mesh\n", nodeId);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
mesh.onChangedConnections([]() {
|
|
89
|
+
Serial.println("\nMesh topology changed - routing tables updated");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Add routing display task
|
|
93
|
+
userScheduler.addTask(taskShowRouting);
|
|
94
|
+
taskShowRouting.enable();
|
|
95
|
+
|
|
96
|
+
Serial.println("\nRouting Demo Started");
|
|
97
|
+
Serial.printf("Node ID: %u\n", mesh.getNodeId());
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
void loop() {
|
|
101
|
+
mesh.update();
|
|
102
|
+
}
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
name=
|
|
2
|
-
version=1.8.
|
|
1
|
+
name=Alteriom PainlessMesh
|
|
2
|
+
version=1.8.3
|
|
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
|
|
@@ -7,5 +7,5 @@ paragraph=painlessMesh is a user-friendly library for creating mesh networks wit
|
|
|
7
7
|
category=Communication
|
|
8
8
|
url=https://github.com/Alteriom/painlessMesh
|
|
9
9
|
architectures=esp8266,esp32
|
|
10
|
-
includes=painlessMesh.h
|
|
10
|
+
includes=painlessMesh.h,AlteriomPainlessMesh.h
|
|
11
11
|
depends=ArduinoJson, TaskScheduler
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alteriom/painlessmesh",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.3",
|
|
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
|
@@ -367,16 +367,33 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
367
367
|
this->droppedConnectionCallbacks.push_back(
|
|
368
368
|
[this](uint32_t nodeId, bool station) {
|
|
369
369
|
if (station) {
|
|
370
|
-
if (WiFi.status() == WL_CONNECTED)
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
370
|
+
if (WiFi.status() == WL_CONNECTED) {
|
|
371
|
+
WiFi.disconnect();
|
|
372
|
+
// Schedule reconnection after disconnect completes
|
|
373
|
+
// The WiFi event handler will signal when disconnect is complete
|
|
374
|
+
_pendingStationReconnect = true;
|
|
375
|
+
} else {
|
|
376
|
+
// Already disconnected, reconnect immediately
|
|
377
|
+
handleStationDisconnectComplete();
|
|
378
|
+
}
|
|
376
379
|
}
|
|
377
380
|
});
|
|
378
381
|
}
|
|
379
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Handle station disconnect completion
|
|
385
|
+
* Called after WiFi disconnect event is fully processed
|
|
386
|
+
* This ensures proper sequencing: disconnect -> event -> reconnect
|
|
387
|
+
*/
|
|
388
|
+
void handleStationDisconnectComplete() {
|
|
389
|
+
if (_pendingStationReconnect) {
|
|
390
|
+
_pendingStationReconnect = false;
|
|
391
|
+
this->stationScan.yieldConnectToAP();
|
|
392
|
+
// Re-enable scanning if it was disabled
|
|
393
|
+
this->stationScan.task.enableIfNot();
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
380
397
|
void tcpServerInit() {
|
|
381
398
|
using namespace logger;
|
|
382
399
|
Log(GENERAL, "tcpServerInit():\n");
|
|
@@ -387,26 +404,35 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
387
404
|
return;
|
|
388
405
|
}
|
|
389
406
|
|
|
407
|
+
/**
|
|
408
|
+
* Establish TCP connection to mesh network
|
|
409
|
+
*
|
|
410
|
+
* This method is called by WiFi event handlers when station gets IP address.
|
|
411
|
+
* It creates a TCP client connection to the mesh network gateway.
|
|
412
|
+
*
|
|
413
|
+
* Architecture Note: This is intentionally kept in the Mesh class rather than
|
|
414
|
+
* extracted to a separate StationConnection class because:
|
|
415
|
+
* - It's tightly coupled with WiFi event lifecycle
|
|
416
|
+
* - Needs access to mesh state and callbacks
|
|
417
|
+
* - Moving it would increase complexity without clear benefits
|
|
418
|
+
* - The existing design keeps connection logic cohesive with WiFi management
|
|
419
|
+
*/
|
|
390
420
|
void tcpConnect() {
|
|
391
421
|
using namespace logger;
|
|
392
|
-
// TODO: move to Connection or StationConnection?
|
|
393
422
|
Log(GENERAL, "tcpConnect():\n");
|
|
394
423
|
if (stationScan.manual && stationScan.port == 0)
|
|
395
424
|
return; // We have been configured not to connect to the mesh
|
|
396
425
|
|
|
397
|
-
// TODO: We could pass this to tcpConnect instead of loading it here
|
|
398
426
|
if (WiFi.status() == WL_CONNECTED && WiFi.localIP()) {
|
|
427
|
+
// Determine target IP and port for connection
|
|
428
|
+
IPAddress targetIP = stationScan.manualIP ? stationScan.manualIP : WiFi.gatewayIP();
|
|
429
|
+
uint16_t targetPort = stationScan.port;
|
|
430
|
+
|
|
399
431
|
AsyncClient *pConn = new AsyncClient();
|
|
400
|
-
|
|
401
|
-
IPAddress ip = WiFi.gatewayIP();
|
|
402
|
-
if (stationScan.manualIP) {
|
|
403
|
-
ip = stationScan.manualIP;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
432
|
painlessmesh::tcp::connect<Connection, painlessmesh::Mesh<Connection>>(
|
|
407
|
-
(*pConn),
|
|
433
|
+
(*pConn), targetIP, targetPort, (*this));
|
|
408
434
|
} else {
|
|
409
|
-
Log(ERROR, "tcpConnect(): err Something
|
|
435
|
+
Log(ERROR, "tcpConnect(): err Something unexpected in tcpConnect()\n");
|
|
410
436
|
}
|
|
411
437
|
}
|
|
412
438
|
|
|
@@ -1153,6 +1179,8 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1153
1179
|
"eventSTADisconnectedHandler: "
|
|
1154
1180
|
"ARDUINO_EVENT_WIFI_STA_DISCONNECTED\n");
|
|
1155
1181
|
this->droppedConnectionCallbacks.execute(0, true);
|
|
1182
|
+
// Handle station disconnect completion after callbacks
|
|
1183
|
+
this->handleStationDisconnectComplete();
|
|
1156
1184
|
this->semaphoreGive();
|
|
1157
1185
|
}
|
|
1158
1186
|
},
|
|
@@ -1189,6 +1217,8 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1189
1217
|
[&](const WiFiEventStationModeDisconnected &event) {
|
|
1190
1218
|
Log(CONNECTION, "Event: Station Mode Disconnected\n");
|
|
1191
1219
|
this->droppedConnectionCallbacks.execute(0, true);
|
|
1220
|
+
// Handle station disconnect completion after callbacks
|
|
1221
|
+
this->handleStationDisconnectComplete();
|
|
1192
1222
|
});
|
|
1193
1223
|
|
|
1194
1224
|
eventSTAGotIPHandler =
|
|
@@ -1215,6 +1245,9 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1215
1245
|
#endif // ESP8266
|
|
1216
1246
|
AsyncServer *_tcpListener;
|
|
1217
1247
|
std::shared_ptr<Task> bridgeStatusTask;
|
|
1248
|
+
|
|
1249
|
+
// Station disconnect handling state
|
|
1250
|
+
bool _pendingStationReconnect = false;
|
|
1218
1251
|
|
|
1219
1252
|
// Bridge failover state and configuration
|
|
1220
1253
|
enum ElectionState {
|
package/src/painlessMesh.h
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
#ifndef _EASY_MESH_H_
|
|
2
2
|
#define _EASY_MESH_H_
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @file painlessMesh.h
|
|
6
|
+
* @brief Main header file for Alteriom painlessMesh library
|
|
7
|
+
*
|
|
8
|
+
* @version 1.8.3
|
|
9
|
+
* @date 2025-11-11
|
|
10
|
+
*
|
|
11
|
+
* painlessMesh is a user-friendly library for creating mesh networks with
|
|
12
|
+
* ESP8266 and ESP32 devices. This Alteriom fork includes additional packages
|
|
13
|
+
* for sensor data, device commands, and status monitoring.
|
|
14
|
+
*
|
|
15
|
+
* For the latest version and updates, visit:
|
|
16
|
+
* https://github.com/Alteriom/painlessMesh
|
|
17
|
+
*/
|
|
18
|
+
|
|
4
19
|
#include "painlessTaskOptions.h"
|
|
5
20
|
|
|
6
21
|
#include <Arduino.h>
|
package/src/painlessMeshSTA.cpp
CHANGED
|
@@ -189,7 +189,13 @@ void ICACHE_FLASH_ATTR StationScan::connectToAP() {
|
|
|
189
189
|
mesh->closeConnectionSTA();
|
|
190
190
|
task.enableDelayed(10 * SCAN_INTERVAL);
|
|
191
191
|
return;
|
|
192
|
-
} else
|
|
192
|
+
} else {
|
|
193
|
+
// For manual router connections, reconnect directly using WiFi.begin()
|
|
194
|
+
// Don't rely on scan results since router may be on different channel
|
|
195
|
+
Log(CONNECTION,
|
|
196
|
+
"connectToAP(): Manual connection - attempting to reconnect to %s\n",
|
|
197
|
+
ssid.c_str());
|
|
198
|
+
WiFi.begin(ssid.c_str(), password.c_str());
|
|
193
199
|
task.enableDelayed(SCAN_INTERVAL);
|
|
194
200
|
return;
|
|
195
201
|
}
|