@alteriom/painlessmesh 1.8.2 → 1.8.4

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +74 -11
  3. package/RELEASE_GUIDE.md +57 -16
  4. package/docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md +331 -0
  5. package/docs/features/DIAGNOSTICS_API.md +534 -0
  6. package/docs/getting-started/arduino-manual-install.md +313 -0
  7. package/docs/implementation/BRIDGE_ARCHITECTURE_IMPLEMENTATION.md +340 -0
  8. package/docs/implementation/BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md +213 -0
  9. package/docs/implementation/BRIDGE_STATUS_FEATURE.md +635 -0
  10. package/docs/implementation/DIAGNOSTICS_API_IMPLEMENTATION.md +232 -0
  11. package/docs/implementation/IMPLEMENTATION_COMPLETE.md +228 -0
  12. package/docs/implementation/IMPLEMENTATION_NTP_TIME_SYNC.md +325 -0
  13. package/docs/implementation/IMPLEMENTATION_SUMMARY.md +316 -0
  14. package/docs/implementation/MESSAGE_QUEUE_IMPLEMENTATION.md +405 -0
  15. package/docs/implementation/MULTI_BRIDGE_IMPLEMENTATION.md +520 -0
  16. package/docs/implementation/NTP_TIME_SYNC_FEATURE.md +392 -0
  17. package/docs/internal/CUSTOM_AGENT_ANALYSIS.md +391 -0
  18. package/docs/internal/ISSUE_65_VERIFICATION.md +947 -0
  19. package/docs/internal/ISSUE_66_CLOSURE.md +249 -0
  20. package/docs/internal/ISSUE_66_STATUS.md +316 -0
  21. package/docs/internal/PR_SUMMARY.md +315 -0
  22. package/docs/internal/REVIEW_SUMMARY.md +332 -0
  23. package/docs/releases/PUBLISH_v1.8.0_INSTRUCTIONS.md +163 -0
  24. package/docs/releases/QUICK_START_RELEASES.md +113 -0
  25. package/docs/releases/RELEASE_CHECKLIST_v1.8.0.md +331 -0
  26. package/docs/releases/RELEASE_CHECKLIST_v1.8.2.md +309 -0
  27. package/docs/releases/RELEASE_NOTES_v1.8.0.md +685 -0
  28. package/docs/releases/RELEASE_NOTES_v1.8.1.md +221 -0
  29. package/docs/releases/RELEASE_NOTES_v1.8.2.md +421 -0
  30. package/docs/releases/RELEASE_NOTES_v1.8.3.md +292 -0
  31. package/docs/releases/RELEASE_NOTES_v1.8.4.md +277 -0
  32. package/docs/troubleshooting/ARDUINO_IDE_VERSION_FIX_SUMMARY.md +229 -0
  33. package/docs/troubleshooting/ARDUINO_LIBRARY_NAME_FIX.md +197 -0
  34. package/docs/troubleshooting/NPM_PUBLISHING_ISSUE_SUMMARY.md +110 -0
  35. package/docs/troubleshooting/station-reconnection-issues.md +172 -0
  36. package/examples/bridge_failover/README.md +17 -1
  37. package/examples/priority/README.md +274 -0
  38. package/examples/priority/priority_basic_example.ino +115 -0
  39. package/examples/priority/priority_with_queue.ino +249 -0
  40. package/examples/routing_demo/README.md +172 -0
  41. package/examples/routing_demo/routing_demo.ino +102 -0
  42. package/library.json +1 -1
  43. package/library.properties +3 -3
  44. package/package.json +1 -1
  45. package/src/arduino/wifi.hpp +62 -16
  46. package/src/painlessMesh.h +15 -0
  47. package/src/painlessMeshSTA.cpp +7 -1
  48. package/src/painlessmesh/buffer.hpp +218 -37
  49. package/src/painlessmesh/connection.hpp +21 -1
  50. package/src/painlessmesh/mesh.hpp +253 -19
  51. package/src/painlessmesh/router.hpp +31 -0
@@ -0,0 +1,534 @@
1
+ # Enhanced Diagnostics API for Bridge Operations
2
+
3
+ ## Overview
4
+
5
+ The Enhanced Diagnostics API provides comprehensive tools for monitoring, debugging, and analyzing painlessMesh bridge operations. This API gives developers programmatic access to bridge state, election history, network topology, and connectivity testing.
6
+
7
+ ## Features
8
+
9
+ ✅ Bridge status monitoring
10
+ ✅ Election history tracking
11
+ ✅ Network topology visualization
12
+ ✅ Connectivity testing
13
+ ✅ Comprehensive diagnostic reports
14
+ ✅ Minimal overhead when enabled
15
+
16
+ ## Table of Contents
17
+
18
+ - [Getting Started](#getting-started)
19
+ - [Bridge State API](#bridge-state-api)
20
+ - [Network Topology API](#network-topology-api)
21
+ - [Diagnostics API](#diagnostics-api)
22
+ - [Data Structures](#data-structures)
23
+ - [Examples](#examples)
24
+ - [Best Practices](#best-practices)
25
+
26
+ ## Getting Started
27
+
28
+ ### Enable Diagnostics
29
+
30
+ Diagnostics must be explicitly enabled to track election history and bridge changes:
31
+
32
+ ```cpp
33
+ void setup() {
34
+ mesh.init(MESH_SSID, MESH_PASSWORD, &scheduler, MESH_PORT);
35
+
36
+ // Enable diagnostics tracking
37
+ mesh.enableDiagnostics(true);
38
+ }
39
+ ```
40
+
41
+ **Note:** Diagnostics have minimal overhead and only track data when enabled.
42
+
43
+ ## Bridge State API
44
+
45
+ ### getBridgeStatus()
46
+
47
+ Get current bridge status and role information for this node.
48
+
49
+ ```cpp
50
+ BridgeStatus status = mesh.getBridgeStatus();
51
+
52
+ Serial.printf("Role: %s\n", status.role.c_str());
53
+ Serial.printf("Is Bridge: %s\n", status.isBridge ? "Yes" : "No");
54
+ Serial.printf("Internet: %s\n", status.internetConnected ? "Yes" : "No");
55
+
56
+ if (status.bridgeNodeId != 0) {
57
+ Serial.printf("Bridge Node: %u (RSSI: %d dBm)\n",
58
+ status.bridgeNodeId, status.bridgeRSSI);
59
+ }
60
+ ```
61
+
62
+ **Returns:** `BridgeStatus` structure containing:
63
+ - `isBridge` - Is this node acting as a bridge?
64
+ - `internetConnected` - Is Internet available?
65
+ - `role` - Node role: "regular", "bridge", or "root"
66
+ - `bridgeNodeId` - Current bridge node ID (0 if none)
67
+ - `bridgeRSSI` - Signal strength to bridge/router (dBm)
68
+ - `timeSinceBridgeChange` - Time since last bridge change (ms)
69
+
70
+ ### getElectionHistory()
71
+
72
+ Get list of recent bridge elections (requires diagnostics enabled).
73
+
74
+ ```cpp
75
+ auto history = mesh.getElectionHistory();
76
+
77
+ for (const auto& election : history) {
78
+ Serial.printf("Election: Winner=%u, RSSI=%d dBm, Candidates=%u\n",
79
+ election.winnerNodeId, election.winnerRSSI,
80
+ election.candidateCount);
81
+ Serial.printf(" Reason: %s\n", election.reason.c_str());
82
+ }
83
+ ```
84
+
85
+ **Returns:** `std::vector<ElectionRecord>` (limited to last 10 elections)
86
+
87
+ **Note:** Returns empty vector if diagnostics are not enabled.
88
+
89
+ ### getLastBridgeChange()
90
+
91
+ Get information about the most recent bridge change event.
92
+
93
+ ```cpp
94
+ auto event = mesh.getLastBridgeChange();
95
+
96
+ if (event.timestamp > 0) {
97
+ Serial.printf("Bridge changed from %u to %u\n",
98
+ event.oldBridgeId, event.newBridgeId);
99
+ Serial.printf("Reason: %s\n", event.reason.c_str());
100
+ Serial.printf("Internet available: %s\n",
101
+ event.internetAvailable ? "Yes" : "No");
102
+ }
103
+ ```
104
+
105
+ **Returns:** `BridgeChangeEvent` structure
106
+
107
+ ## Network Topology API
108
+
109
+ ### getInternetPath(nodeId)
110
+
111
+ Find the routing path from a specific node to the Internet bridge.
112
+
113
+ ```cpp
114
+ auto path = mesh.getInternetPath(targetNodeId);
115
+
116
+ if (path.size() > 0) {
117
+ Serial.print("Path to Internet: ");
118
+ for (auto nodeId : path) {
119
+ Serial.printf("%u -> ", nodeId);
120
+ }
121
+ Serial.println("Internet");
122
+ } else {
123
+ Serial.println("No path to Internet available");
124
+ }
125
+ ```
126
+
127
+ **Parameters:**
128
+ - `nodeId` - Node to find path from
129
+
130
+ **Returns:** `std::vector<uint32_t>` containing node IDs in the path (empty if no path)
131
+
132
+ ### getBridgeForNodeId(nodeId)
133
+
134
+ Get the bridge node ID that a specific node should use to reach the Internet.
135
+
136
+ ```cpp
137
+ uint32_t bridgeId = mesh.getBridgeForNodeId(targetNodeId);
138
+
139
+ if (bridgeId != 0) {
140
+ Serial.printf("Node %u uses bridge %u\n", targetNodeId, bridgeId);
141
+ } else {
142
+ Serial.println("No bridge available");
143
+ }
144
+ ```
145
+
146
+ **Parameters:**
147
+ - `nodeId` - Node to find bridge for
148
+
149
+ **Returns:** Bridge node ID, or 0 if no bridge available
150
+
151
+ ### exportTopologyDOT()
152
+
153
+ Export mesh topology in GraphViz DOT format for visualization.
154
+
155
+ ```cpp
156
+ String dot = mesh.exportTopologyDOT();
157
+ Serial.println(dot);
158
+
159
+ // Save to file or send to visualization tool
160
+ // Visualize at: http://www.webgraphviz.com/
161
+ ```
162
+
163
+ **Returns:** String containing DOT format graph
164
+
165
+ **Example Output:**
166
+ ```dot
167
+ digraph mesh {
168
+ rankdir=TB;
169
+ node [shape=box];
170
+
171
+ "12345" [style=filled,fillcolor=lightblue,label="12345\nBridge"];
172
+ "Internet" [shape=cloud,style=filled,fillcolor=lightgreen];
173
+ "12345" -> "Internet" [style=dashed,color=green];
174
+ "67890";
175
+ "12345" -> "67890" [label="25ms"];
176
+ }
177
+ ```
178
+
179
+ ## Diagnostics API
180
+
181
+ ### enableDiagnostics(enabled)
182
+
183
+ Enable or disable diagnostics collection.
184
+
185
+ ```cpp
186
+ // Enable diagnostics
187
+ mesh.enableDiagnostics(true);
188
+
189
+ // Disable diagnostics
190
+ mesh.enableDiagnostics(false);
191
+ ```
192
+
193
+ **Parameters:**
194
+ - `enabled` - true to enable, false to disable
195
+
196
+ **Note:** Must be enabled before calling `getElectionHistory()` or to track bridge changes.
197
+
198
+ ### testBridgeConnectivity()
199
+
200
+ Test connectivity to the primary bridge and measure latency.
201
+
202
+ ```cpp
203
+ auto result = mesh.testBridgeConnectivity();
204
+
205
+ if (result.success) {
206
+ Serial.printf("✓ Bridge test PASSED: %s\n", result.message.c_str());
207
+ Serial.printf(" Latency: %u ms\n", result.latencyMs);
208
+ Serial.printf(" Internet reachable: %s\n",
209
+ result.internetReachable ? "Yes" : "No");
210
+ } else {
211
+ Serial.printf("✗ Bridge test FAILED: %s\n", result.message.c_str());
212
+ }
213
+ ```
214
+
215
+ **Returns:** `BridgeTestResult` structure containing:
216
+ - `success` - Overall test success
217
+ - `bridgeReachable` - Can reach bridge node
218
+ - `internetReachable` - Can reach Internet through bridge
219
+ - `latencyMs` - Round-trip latency to bridge
220
+ - `message` - Detailed test message
221
+
222
+ ### isBridgeReachable(bridgeNodeId)
223
+
224
+ Check if a specific bridge node is reachable from this node.
225
+
226
+ ```cpp
227
+ if (mesh.isBridgeReachable(bridgeNodeId)) {
228
+ Serial.println("Bridge is reachable");
229
+ } else {
230
+ Serial.println("Bridge is NOT reachable");
231
+ }
232
+ ```
233
+
234
+ **Parameters:**
235
+ - `bridgeNodeId` - Bridge node ID to test
236
+
237
+ **Returns:** true if reachable, false otherwise
238
+
239
+ ### getDiagnosticReport()
240
+
241
+ Generate a comprehensive, human-readable diagnostic report.
242
+
243
+ ```cpp
244
+ Serial.println(mesh.getDiagnosticReport());
245
+ ```
246
+
247
+ **Example Output:**
248
+ ```
249
+ === painlessMesh Diagnostics ===
250
+ Node ID: 12345
251
+ Mode: regular
252
+ Mesh Nodes: 5
253
+ Bridge: 99999 (RSSI: -45 dBm, Internet: ✓)
254
+ Direct Connections: 2
255
+ Messages RX: 1234
256
+ Messages TX: 987
257
+ Messages Dropped: 5
258
+ Avg Latency: 25 ms
259
+ Uptime: 02:15:33
260
+ Last Election: 00:45:12 ago (Winner: 99999, 3 candidates)
261
+ ================================
262
+ ```
263
+
264
+ **Returns:** String containing formatted diagnostic report
265
+
266
+ ## Data Structures
267
+
268
+ ### BridgeStatus
269
+
270
+ ```cpp
271
+ struct BridgeStatus {
272
+ bool isBridge; // Is this node acting as a bridge?
273
+ bool internetConnected; // Is Internet available?
274
+ TSTRING role; // "regular", "bridge", or "root"
275
+ uint32_t bridgeNodeId; // Current bridge node ID (0 if none)
276
+ int8_t bridgeRSSI; // Signal strength to bridge (dBm)
277
+ uint32_t timeSinceBridgeChange; // Time since last bridge change (ms)
278
+ };
279
+ ```
280
+
281
+ ### ElectionRecord
282
+
283
+ ```cpp
284
+ struct ElectionRecord {
285
+ uint32_t timestamp; // When election occurred (millis)
286
+ uint32_t winnerNodeId; // Node that won election
287
+ int8_t winnerRSSI; // Winner's router RSSI
288
+ uint32_t candidateCount; // Number of candidates
289
+ TSTRING reason; // Why election was triggered
290
+ };
291
+ ```
292
+
293
+ ### BridgeChangeEvent
294
+
295
+ ```cpp
296
+ struct BridgeChangeEvent {
297
+ uint32_t timestamp; // When change occurred (millis)
298
+ uint32_t oldBridgeId; // Previous bridge node ID
299
+ uint32_t newBridgeId; // New bridge node ID
300
+ TSTRING reason; // Reason for change
301
+ bool internetAvailable; // Internet available after change
302
+ };
303
+ ```
304
+
305
+ ### BridgeTestResult
306
+
307
+ ```cpp
308
+ struct BridgeTestResult {
309
+ bool success; // Overall test success
310
+ bool bridgeReachable; // Can reach bridge node
311
+ bool internetReachable; // Can reach Internet
312
+ uint32_t latencyMs; // Round-trip latency (ms)
313
+ TSTRING message; // Detailed test message
314
+ };
315
+ ```
316
+
317
+ ## Examples
318
+
319
+ ### Basic Diagnostics Monitoring
320
+
321
+ ```cpp
322
+ void setup() {
323
+ mesh.init(MESH_SSID, MESH_PASSWORD, &scheduler, MESH_PORT);
324
+ mesh.enableDiagnostics(true);
325
+
326
+ // Print diagnostics every 30 seconds
327
+ userScheduler.addTask(Task(30000, TASK_FOREVER, []() {
328
+ Serial.println(mesh.getDiagnosticReport());
329
+ }));
330
+ }
331
+ ```
332
+
333
+ ### Bridge Status Monitoring with Callback
334
+
335
+ ```cpp
336
+ void setup() {
337
+ mesh.onBridgeStatusChanged([](uint32_t bridgeId, bool hasInternet) {
338
+ if (hasInternet) {
339
+ Serial.println("Internet available - sending queued data");
340
+ sendQueuedMessages();
341
+ } else {
342
+ Serial.println("Internet offline - queueing messages");
343
+ }
344
+ });
345
+ }
346
+ ```
347
+
348
+ ### Periodic Bridge Connectivity Testing
349
+
350
+ ```cpp
351
+ Task testTask(60000, TASK_FOREVER, []() {
352
+ auto result = mesh.testBridgeConnectivity();
353
+
354
+ if (!result.success) {
355
+ Serial.printf("Bridge issue: %s\n", result.message.c_str());
356
+ // Trigger failover or alert
357
+ } else if (result.latencyMs > 100) {
358
+ Serial.println("Warning: High latency to bridge");
359
+ }
360
+ });
361
+ ```
362
+
363
+ ### Topology Visualization Export
364
+
365
+ ```cpp
366
+ // Export topology every 5 minutes for external visualization
367
+ Task exportTask(300000, TASK_FOREVER, []() {
368
+ String dot = mesh.exportTopologyDOT();
369
+
370
+ // Send to monitoring server or save to SD card
371
+ sendToMonitoringServer(dot);
372
+
373
+ // Or save locally
374
+ File file = SD.open("/topology.dot", FILE_WRITE);
375
+ file.print(dot);
376
+ file.close();
377
+ });
378
+ ```
379
+
380
+ ## Best Practices
381
+
382
+ ### 1. Enable Diagnostics Selectively
383
+
384
+ Only enable diagnostics when needed for debugging or monitoring:
385
+
386
+ ```cpp
387
+ #ifdef DEBUG
388
+ mesh.enableDiagnostics(true);
389
+ #endif
390
+ ```
391
+
392
+ ### 2. Monitor Bridge Changes
393
+
394
+ Always set up a bridge status callback to react to connectivity changes:
395
+
396
+ ```cpp
397
+ mesh.onBridgeStatusChanged([](uint32_t bridgeId, bool hasInternet) {
398
+ // Handle bridge state changes
399
+ if (!hasInternet) {
400
+ startOfflineMode();
401
+ } else {
402
+ resumeOnlineMode();
403
+ }
404
+ });
405
+ ```
406
+
407
+ ### 3. Test Connectivity Before Critical Operations
408
+
409
+ Before sending important data, test bridge connectivity:
410
+
411
+ ```cpp
412
+ void sendCriticalData(String data) {
413
+ auto result = mesh.testBridgeConnectivity();
414
+
415
+ if (result.success && result.internetReachable) {
416
+ mesh.sendSingle(bridgeId, data);
417
+ } else {
418
+ queueForLater(data);
419
+ }
420
+ }
421
+ ```
422
+
423
+ ### 4. Use Diagnostic Reports for Troubleshooting
424
+
425
+ When users report issues, ask them to copy the diagnostic report:
426
+
427
+ ```cpp
428
+ // Add a command to print diagnostics on demand
429
+ if (Serial.available()) {
430
+ char cmd = Serial.read();
431
+ if (cmd == 'd') {
432
+ Serial.println(mesh.getDiagnosticReport());
433
+ }
434
+ }
435
+ ```
436
+
437
+ ### 5. Export Topology for Visualization
438
+
439
+ Regularly export topology to understand mesh structure:
440
+
441
+ ```cpp
442
+ // Export topology to help visualize network issues
443
+ void exportTopology() {
444
+ String dot = mesh.exportTopologyDOT();
445
+
446
+ // Save or transmit for later analysis
447
+ // Visualize at http://www.webgraphviz.com/
448
+ }
449
+ ```
450
+
451
+ ## Performance Considerations
452
+
453
+ - **Memory:** Election history limited to 10 records (approximately 200 bytes)
454
+ - **CPU:** Minimal overhead when diagnostics enabled (<1% CPU)
455
+ - **Network:** No additional network traffic (uses existing bridge status messages)
456
+
457
+ ## Integration with Monitoring Systems
458
+
459
+ ### MQTT Example
460
+
461
+ ```cpp
462
+ void publishDiagnostics() {
463
+ String report = mesh.getDiagnosticReport();
464
+ mqttClient.publish("mesh/diagnostics", report.c_str());
465
+
466
+ auto status = mesh.getBridgeStatus();
467
+ String json = String("{\"role\":\"") + status.role +
468
+ "\",\"internet\":" + (status.internetConnected ? "true" : "false") +
469
+ ",\"bridge\":" + status.bridgeNodeId + "}";
470
+ mqttClient.publish("mesh/status", json.c_str());
471
+ }
472
+ ```
473
+
474
+ ### HTTP REST API Example
475
+
476
+ ```cpp
477
+ void handleDiagnosticsRequest() {
478
+ server.send(200, "text/plain", mesh.getDiagnosticReport());
479
+ }
480
+
481
+ void handleTopologyRequest() {
482
+ server.send(200, "text/plain", mesh.exportTopologyDOT());
483
+ }
484
+ ```
485
+
486
+ ## Troubleshooting
487
+
488
+ ### Q: getElectionHistory() returns empty vector
489
+
490
+ **A:** Ensure diagnostics are enabled with `mesh.enableDiagnostics(true)` before elections occur.
491
+
492
+ ### Q: testBridgeConnectivity() always fails
493
+
494
+ **A:** Check that:
495
+ 1. A bridge node exists in the mesh
496
+ 2. The bridge is broadcasting status (enabled by default)
497
+ 3. Your node can route to the bridge
498
+
499
+ ### Q: getDiagnosticReport() shows "Bridge: None available"
500
+
501
+ **A:** This means no healthy bridge with Internet connection was found. Check:
502
+ 1. Bridge node is running and configured correctly
503
+ 2. Bridge has Internet connectivity
504
+ 3. Bridge status broadcasts are enabled
505
+
506
+ ## API Reference Summary
507
+
508
+ | Method | Description | Returns |
509
+ |--------|-------------|---------|
510
+ | `enableDiagnostics(bool)` | Enable/disable diagnostics tracking | void |
511
+ | `getBridgeStatus()` | Get current bridge status | BridgeStatus |
512
+ | `getElectionHistory()` | Get recent elections | vector<ElectionRecord> |
513
+ | `getLastBridgeChange()` | Get last bridge change | BridgeChangeEvent |
514
+ | `getInternetPath(nodeId)` | Get path to Internet | vector<uint32_t> |
515
+ | `getBridgeForNodeId(nodeId)` | Get bridge for node | uint32_t |
516
+ | `exportTopologyDOT()` | Export topology | String |
517
+ | `testBridgeConnectivity()` | Test bridge connection | BridgeTestResult |
518
+ | `isBridgeReachable(id)` | Check bridge reachability | bool |
519
+ | `getDiagnosticReport()` | Get comprehensive report | String |
520
+
521
+ ## See Also
522
+
523
+ - [Bridge Architecture](BRIDGE_ARCHITECTURE_IMPLEMENTATION.md)
524
+ - [Bridge Health Monitoring](BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md)
525
+ - [Example Sketch](examples/diagnosticsExample/diagnosticsExample.ino)
526
+ - [API Documentation](docs/)
527
+
528
+ ## Version History
529
+
530
+ - **v1.8.1** - Initial release of Enhanced Diagnostics API
531
+
532
+ ## License
533
+
534
+ This feature is part of painlessMesh and follows the same license terms.