@alteriom/painlessmesh 1.7.2 → 1.7.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +58 -4
  2. package/README.md +17 -3
  3. package/docs/README.md +62 -10
  4. package/docs/archive/DOCUSAURUS_DEPLOYMENT.md +166 -0
  5. package/docs/archive/LIBRARY_JSON_FIX.md +98 -0
  6. package/docs/archive/LIBRARY_STRUCTURE_FIX.md +215 -0
  7. package/docs/archive/RELEASE_SUMMARY.md +173 -0
  8. package/docs/archive/SCONS_BUILD_FIX.md +313 -0
  9. package/docs/archive/TRIGGER_RELEASE.md +280 -0
  10. package/docs/archive/VECTOR_INCLUDE_FIX.md +129 -0
  11. package/docs/development/ARDUINO_COMPLIANCE_SUMMARY.md +71 -0
  12. package/docs/development/CODE_REFACTORING_RECOMMENDATIONS.md +1011 -0
  13. package/docs/development/DOCKER_TESTING.md +196 -0
  14. package/docs/development/PLATFORMIO_USAGE.md +180 -0
  15. package/docs/development/TESTING_SUMMARY.md +126 -0
  16. package/docs/development/contributing.md +301 -0
  17. package/docs/development/documentation.md +583 -0
  18. package/docs/improvements/FUTURE_PROPOSALS.md +1016 -0
  19. package/docs/improvements/IMPLEMENTATION_HISTORY.md +1091 -0
  20. package/docs/improvements/OTA_STATUS_ENHANCEMENTS.md +709 -0
  21. package/docs/improvements/README.md +171 -46
  22. package/docs/releases/FEATURE_HISTORY.md +543 -0
  23. package/docs/releases/PATCH_v1.7.3.md +262 -0
  24. package/docs/releases/PHASE1_SUMMARY.md +246 -0
  25. package/docs/releases/PHASE2_SUMMARY.md +499 -0
  26. package/docs/releases/RELEASE_NOTES_1.7.0.md +539 -0
  27. package/docs/troubleshooting/debugging.md +455 -0
  28. package/library.json +1 -1
  29. package/library.properties +1 -1
  30. package/package.json +1 -1
  31. package/src/painlessmesh/router.hpp +35 -19
  32. /package/docs/{improvements → archive}/FEATURE_PROPOSALS.md +0 -0
  33. /package/docs/{improvements → archive}/PHASE1_IMPLEMENTATION.md +0 -0
  34. /package/docs/{improvements → archive}/PHASE2_IMPLEMENTATION.md +0 -0
  35. /package/docs/{improvements → archive}/ota-and-status-enhancements.md +0 -0
  36. /package/docs/{improvements → archive}/ota-status-architecture-diagrams.md +0 -0
  37. /package/docs/{improvements → archive}/ota-status-quick-reference.md +0 -0
@@ -0,0 +1,455 @@
1
+ # Debugging Guide
2
+
3
+ This guide provides tools and techniques for debugging painlessMesh applications.
4
+
5
+ ## Debug Message Types
6
+
7
+ painlessMesh includes a built-in debugging system that lets you control which types of messages are logged.
8
+
9
+ ### Setting Debug Message Types
10
+
11
+ ```cpp
12
+ #include "painlessMesh.h"
13
+
14
+ painlessMesh mesh;
15
+
16
+ void setup() {
17
+ Serial.begin(115200);
18
+
19
+ // Set which message types to display
20
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
21
+
22
+ // Initialize mesh
23
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
24
+ }
25
+ ```
26
+
27
+ ### Available Debug Message Types
28
+
29
+ | Type | Description |
30
+ |------|-------------|
31
+ | `ERROR` | Critical errors and failures |
32
+ | `STARTUP` | Initialization and startup messages |
33
+ | `CONNECTION` | Connection and disconnection events |
34
+ | `SYNC` | Time synchronization messages |
35
+ | `COMMUNICATION` | Message sending/receiving |
36
+ | `GENERAL` | General informational messages |
37
+ | `MSG_TYPES` | Message type information |
38
+ | `REMOTE` | Remote node messages |
39
+ | `APPLICATION` | Application-level messages |
40
+ | `DEBUG` | Detailed debugging information |
41
+
42
+ ### Common Debug Configurations
43
+
44
+ **Minimal (Production):**
45
+
46
+ ```cpp
47
+ mesh.setDebugMsgTypes(ERROR | STARTUP);
48
+ ```
49
+
50
+ **Standard (Development):**
51
+
52
+ ```cpp
53
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
54
+ ```
55
+
56
+ **Verbose (Troubleshooting):**
57
+
58
+ ```cpp
59
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION | SYNC | COMMUNICATION);
60
+ ```
61
+
62
+ **Full Debug (Deep Dive):**
63
+
64
+ ```cpp
65
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION | SYNC |
66
+ COMMUNICATION | GENERAL | MSG_TYPES |
67
+ REMOTE | APPLICATION | DEBUG);
68
+ ```
69
+
70
+ ## Common Debugging Scenarios
71
+
72
+ ### 1. Nodes Not Connecting
73
+
74
+ **Symptoms:**
75
+
76
+ - Nodes don't appear in `mesh.getNodeList()`
77
+ - `onNewConnection` callback never fires
78
+ - Mesh appears to run but no communication
79
+
80
+ **Debugging Steps:**
81
+
82
+ ```cpp
83
+ // Enable connection debugging
84
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION | SYNC);
85
+
86
+ void setup() {
87
+ Serial.begin(115200);
88
+
89
+ // Add connection callbacks
90
+ mesh.onNewConnection([](uint32_t nodeId) {
91
+ Serial.printf("New connection: %u\n", nodeId);
92
+ Serial.printf("Total nodes: %d\n", mesh.getNodeList().size());
93
+ });
94
+
95
+ mesh.onChangedConnections([]() {
96
+ Serial.printf("Connections changed. Current nodes: %d\n",
97
+ mesh.getNodeList().size());
98
+ auto nodes = mesh.getNodeList();
99
+ for (auto node : nodes) {
100
+ Serial.printf(" - Node: %u\n", node);
101
+ }
102
+ });
103
+
104
+ mesh.onDroppedConnection([](uint32_t nodeId) {
105
+ Serial.printf("Lost connection: %u\n", nodeId);
106
+ });
107
+ }
108
+ ```
109
+
110
+ **Common Causes:**
111
+
112
+ - Mismatched `MESH_PREFIX` or `MESH_PASSWORD`
113
+ - Different `MESH_PORT` values
114
+ - Wi-Fi channel conflicts
115
+ - Power supply issues (voltage drops during connection)
116
+ - Too many nodes (exceeds platform limits)
117
+
118
+ ### 2. Messages Not Received
119
+
120
+ **Symptoms:**
121
+
122
+ - `mesh.sendBroadcast()` or `mesh.sendSingle()` returns true but messages not received
123
+ - `onReceive` callback never fires
124
+
125
+ **Debugging Steps:**
126
+
127
+ ```cpp
128
+ // Enable communication debugging
129
+ mesh.setDebugMsgTypes(ERROR | COMMUNICATION | MSG_TYPES);
130
+
131
+ void setup() {
132
+ Serial.begin(115200);
133
+
134
+ mesh.onReceive([](uint32_t from, String& msg) {
135
+ Serial.printf("Received from %u: %s\n", from, msg.c_str());
136
+ });
137
+
138
+ // Add send status checking
139
+ if (mesh.sendBroadcast(msg)) {
140
+ Serial.println("Broadcast sent successfully");
141
+ } else {
142
+ Serial.println("ERROR: Broadcast failed to send");
143
+ }
144
+ }
145
+ ```
146
+
147
+ **Common Causes:**
148
+
149
+ - Message buffer overflow (message too large)
150
+ - Network congestion (too many messages)
151
+ - JSON parsing errors (malformed messages)
152
+ - Node ID mismatch for `sendSingle()`
153
+ - Memory constraints on receiving node
154
+
155
+ ### 3. Time Synchronization Issues
156
+
157
+ **Symptoms:**
158
+
159
+ - `mesh.getNodeTime()` returns unexpected values
160
+ - Time-dependent features not working
161
+ - `onNodeTimeAdjusted` fires frequently
162
+
163
+ **Debugging Steps:**
164
+
165
+ ```cpp
166
+ // Enable time sync debugging
167
+ mesh.setDebugMsgTypes(ERROR | SYNC);
168
+
169
+ void setup() {
170
+ Serial.begin(115200);
171
+
172
+ mesh.onNodeTimeAdjusted([](int32_t offset) {
173
+ Serial.printf("Time adjusted by: %d microseconds\n", offset);
174
+ Serial.printf("Current mesh time: %u\n", mesh.getNodeTime());
175
+ });
176
+
177
+ // Periodically check time
178
+ Task checkTime(TASK_SECOND * 10, TASK_FOREVER, []() {
179
+ Serial.printf("Mesh time: %u, System: %u\n",
180
+ mesh.getNodeTime(), micros());
181
+ });
182
+ userScheduler.addTask(checkTime);
183
+ checkTime.enable();
184
+ }
185
+ ```
186
+
187
+ ### 4. Memory Issues
188
+
189
+ **Symptoms:**
190
+
191
+ - Random crashes or reboots
192
+ - Mesh stops responding
193
+ - `heap_caps_check_integrity` failures on ESP32
194
+
195
+ **Debugging Steps:**
196
+
197
+ ```cpp
198
+ void setup() {
199
+ Serial.begin(115200);
200
+
201
+ // Monitor free memory
202
+ Task memoryCheck(TASK_SECOND * 5, TASK_FOREVER, []() {
203
+ Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
204
+ #ifdef ESP32
205
+ Serial.printf("Free PSRAM: %u bytes\n", ESP.getFreePsram());
206
+ Serial.printf("Largest free block: %u bytes\n",
207
+ heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
208
+ #endif
209
+ });
210
+ userScheduler.addTask(memoryCheck);
211
+ memoryCheck.enable();
212
+ }
213
+ ```
214
+
215
+ **Memory Optimization Tips:**
216
+
217
+ - Use `String` sparingly, prefer `const char*`
218
+ - Limit broadcast message frequency
219
+ - Reduce node count for ESP8266
220
+ - Clear unused tasks from scheduler
221
+ - Use `F()` macro for string literals
222
+
223
+ ### 5. OTA Update Failures
224
+
225
+ **Symptoms:**
226
+
227
+ - OTA updates don't start
228
+ - Updates fail partway through
229
+ - Nodes become unresponsive during update
230
+
231
+ **Debugging Steps:**
232
+
233
+ ```cpp
234
+ // Enable OTA debugging
235
+ mesh.setDebugMsgTypes(ERROR | STARTUP | COMMUNICATION);
236
+
237
+ void setup() {
238
+ Serial.begin(115200);
239
+
240
+ // Add OTA callbacks if using broadcast OTA
241
+ mesh.onOTAProgress([](size_t progress, size_t total) {
242
+ Serial.printf("OTA Progress: %u/%u bytes (%.1f%%)\n",
243
+ progress, total, (progress * 100.0) / total);
244
+ });
245
+
246
+ mesh.onOTAComplete([]() {
247
+ Serial.println("OTA Update Complete - Rebooting...");
248
+ });
249
+
250
+ mesh.onOTAError([](int error) {
251
+ Serial.printf("OTA Error: %d\n", error);
252
+ });
253
+ }
254
+ ```
255
+
256
+ **Common Causes:**
257
+
258
+ - Insufficient flash memory
259
+ - Power interruption during update
260
+ - Network instability
261
+ - Firmware size exceeds partition size
262
+ - Memory fragmentation
263
+
264
+ ## Debugging Tools
265
+
266
+ ### 1. Serial Monitor
267
+
268
+ **Arduino IDE:**
269
+
270
+ - Tools → Serial Monitor
271
+ - Set baud rate to 115200
272
+ - Enable newline and carriage return
273
+
274
+ **PlatformIO:**
275
+
276
+ ```bash
277
+ pio device monitor --baud 115200
278
+ ```
279
+
280
+ **Screen (Linux/Mac):**
281
+
282
+ ```bash
283
+ screen /dev/ttyUSB0 115200
284
+ ```
285
+
286
+ ### 2. Network Analyzer
287
+
288
+ **Wireshark:**
289
+
290
+ - Capture Wi-Fi traffic to see mesh packets
291
+ - Filter by ESP32/ESP8266 MAC addresses
292
+ - Analyze packet timing and retransmissions
293
+
294
+ ### 3. Mesh Topology Visualization
295
+
296
+ For MQTT-enabled setups:
297
+
298
+ - Use MQTT Explorer to view mesh topology
299
+ - Monitor `alteriom/mesh/topology` topic
300
+ - Visualize node connections and status
301
+
302
+ ### 4. Remote Logging
303
+
304
+ **Log Server Example:**
305
+
306
+ ```cpp
307
+ // On one node, set up as log server
308
+ mesh.onReceive([](uint32_t from, String& msg) {
309
+ DynamicJsonDocument doc(1024);
310
+ deserializeJson(doc, msg);
311
+
312
+ if (doc["type"] == "log") {
313
+ Serial.printf("[%u] %s\n", from, doc["msg"].as<const char*>());
314
+ }
315
+ });
316
+
317
+ // On other nodes, send logs
318
+ void logToServer(const char* message) {
319
+ DynamicJsonDocument doc(256);
320
+ doc["type"] = "log";
321
+ doc["msg"] = message;
322
+
323
+ String msg;
324
+ serializeJson(doc, msg);
325
+ mesh.sendBroadcast(msg);
326
+ }
327
+ ```
328
+
329
+ ## Performance Profiling
330
+
331
+ ### Measure Message Latency
332
+
333
+ ```cpp
334
+ uint32_t sendTime = 0;
335
+
336
+ void sendMessage() {
337
+ DynamicJsonDocument doc(256);
338
+ doc["type"] = "ping";
339
+ doc["timestamp"] = mesh.getNodeTime();
340
+
341
+ String msg;
342
+ serializeJson(doc, msg);
343
+
344
+ sendTime = millis();
345
+ mesh.sendBroadcast(msg);
346
+ }
347
+
348
+ void onMessageReceived(uint32_t from, String& msg) {
349
+ DynamicJsonDocument doc(256);
350
+ deserializeJson(doc, msg);
351
+
352
+ if (doc["type"] == "ping") {
353
+ uint32_t latency = millis() - sendTime;
354
+ Serial.printf("Ping latency: %u ms\n", latency);
355
+ }
356
+ }
357
+ ```
358
+
359
+ ### Monitor Task Execution
360
+
361
+ ```cpp
362
+ void setup() {
363
+ // Enable TaskScheduler debugging
364
+ userScheduler.enableAll();
365
+
366
+ Task debugTask(TASK_SECOND * 10, TASK_FOREVER, []() {
367
+ Serial.printf("Active tasks: %d\n", userScheduler.size());
368
+ // List all tasks
369
+ for (auto task = userScheduler.getFirstTask();
370
+ task != nullptr;
371
+ task = task->getNext()) {
372
+ Serial.printf(" Task ID: %d, Enabled: %d\n",
373
+ task->getId(), task->isEnabled());
374
+ }
375
+ });
376
+ userScheduler.addTask(debugTask);
377
+ debugTask.enable();
378
+ }
379
+ ```
380
+
381
+ ## Best Practices
382
+
383
+ 1. **Start Minimal:** Enable only ERROR and STARTUP for initial testing
384
+ 2. **Add Incrementally:** Add more debug types as needed
385
+ 3. **Use Callbacks:** Implement all mesh callbacks to catch events
386
+ 4. **Monitor Memory:** Regularly check free heap, especially on ESP8266
387
+ 5. **Test Incrementally:** Test with 2 nodes before scaling to larger networks
388
+ 6. **Power Management:** Ensure stable power supply during debugging
389
+ 7. **Version Control:** Use consistent firmware versions across all nodes
390
+ 8. **Document Issues:** Keep notes on error patterns and solutions
391
+
392
+ ## Advanced Debugging
393
+
394
+ ### Enable TaskScheduler Debug Mode
395
+
396
+ ```cpp
397
+ // Add to top of sketch BEFORE including headers
398
+ #define _TASK_DEBUG
399
+
400
+ #include <TaskScheduler.h>
401
+ #include "painlessMesh.h"
402
+ ```
403
+
404
+ ### Enable ArduinoJson Debug
405
+
406
+ ```cpp
407
+ #define ARDUINOJSON_DEBUG 1
408
+ #include <ArduinoJson.h>
409
+ ```
410
+
411
+ ### ESP32 Core Debug Level
412
+
413
+ In `platformio.ini`:
414
+
415
+ ```ini
416
+ build_flags =
417
+ -DCORE_DEBUG_LEVEL=5 ; 0=None, 5=Verbose
418
+ ```
419
+
420
+ ## Troubleshooting Checklist
421
+
422
+ - [ ] All nodes use same MESH_PREFIX, MESH_PASSWORD, MESH_PORT
423
+ - [ ] Serial baud rate set to 115200
424
+ - [ ] Debug messages enabled for relevant types
425
+ - [ ] Callbacks implemented (onReceive, onNewConnection, etc.)
426
+ - [ ] Free heap monitored (especially on ESP8266)
427
+ - [ ] Power supply stable (2A+ recommended)
428
+ - [ ] Firmware versions consistent across nodes
429
+ - [ ] JSON messages properly formatted
430
+ - [ ] Message sizes within limits (< 1KB recommended)
431
+ - [ ] Network not oversaturated (reasonable message frequency)
432
+
433
+ ## Getting Help
434
+
435
+ If you're still experiencing issues:
436
+
437
+ 1. **Search Existing Issues:** Check [GitHub Issues](https://github.com/Alteriom/painlessMesh/issues)
438
+ 2. **Community Forum:** Post on [painlessMesh Discussions](https://github.com/Alteriom/painlessMesh/discussions)
439
+ 3. **Include Details:**
440
+ - Hardware (ESP32/ESP8266 model)
441
+ - Firmware version
442
+ - Number of nodes
443
+ - Debug output
444
+ - Minimal reproducible example
445
+ 4. **Check Documentation:**
446
+ - [Common Issues](common-issues.md)
447
+ - [FAQ](faq.md)
448
+ - [API Reference](../api/core-api.md)
449
+
450
+ ## See Also
451
+
452
+ - [Common Issues](common-issues.md) - Known problems and solutions
453
+ - [FAQ](faq.md) - Frequently asked questions
454
+ - [Performance Optimization](../architecture/mesh-architecture.md) - Scaling best practices
455
+ - [MQTT Bridge Commands](../MQTT_BRIDGE_COMMANDS.md) - MQTT debugging
package/library.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "type": "git",
7
7
  "url": "https://github.com/Alteriom/painlessMesh"
8
8
  },
9
- "version": "1.7.2",
9
+ "version": "1.7.3",
10
10
  "frameworks": ["arduino"],
11
11
  "platforms": ["espressif8266", "espressif32"],
12
12
  "srcDir": "src",
@@ -1,5 +1,5 @@
1
1
  name=AlteriomPainlessMesh
2
- version=1.7.2
2
+ version=1.7.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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alteriom/painlessmesh",
3
- "version": "1.7.2",
3
+ "version": "1.7.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",
@@ -190,26 +190,42 @@ void routePackage(layout::Layout<T> layout, std::shared_ptr<T> connection,
190
190
  Log(DEBUG, "routePackage(): No callbacks executed; %u, %s\n",
191
191
  variant.type(), pkg.c_str());
192
192
  #else
193
- static size_t baseCapacity = 512;
194
- // Using a ptr so we can overwrite it if we need to grow capacity.
195
- // Bug in copy constructor with grown capacity can cause segmentation fault
196
- auto variant =
197
- std::make_shared<protocol::Variant>(pkg, pkg.length() + baseCapacity);
198
- while (variant->error == DeserializationError::NoMemory &&
199
- baseCapacity <= 20480) {
200
- // Not enough memory, adapt scaling (variant::capacityScaling) and log the
201
- // new value
202
- Log(DEBUG,
203
- "routePackage(): parsing failed. err=%u, increasing capacity: %u\n",
204
- variant->error, baseCapacity);
205
- baseCapacity += 256;
206
- variant =
207
- std::make_shared<protocol::Variant>(pkg, pkg.length() + baseCapacity);
208
- }
193
+ // Calculate required capacity based on message size and nesting depth
194
+ // Fixed capacity approach to avoid segmentation fault issues with
195
+ // dynamic reallocation (see issue #521 and CODE_REFACTORING_RECOMMENDATIONS.md)
196
+ size_t nestingDepth = std::count(pkg.begin(), pkg.end(), '{') +
197
+ std::count(pkg.begin(), pkg.end(), '[');
198
+
199
+ #if ARDUINOJSON_VERSION_MAJOR >= 7
200
+ // ArduinoJson v7: automatic capacity management, use generous buffer
201
+ size_t calculatedCapacity = pkg.length() + 1024;
202
+ #else
203
+ // ArduinoJson v6: manual capacity calculation required
204
+ // Base capacity: message length + overhead for JSON structure
205
+ // Each nesting level adds overhead for pointers and metadata
206
+ size_t calculatedCapacity = pkg.length() +
207
+ JSON_OBJECT_SIZE(10) * std::max(nestingDepth, size_t(1)) +
208
+ 512; // Additional buffer for strings and padding
209
+ #endif
210
+
211
+ // Cap at 8KB for safety on ESP8266 (which has ~80KB total heap)
212
+ // Messages larger than this should be rejected
213
+ constexpr size_t MAX_MESSAGE_CAPACITY = 8192;
214
+ size_t capacity = std::min(calculatedCapacity, MAX_MESSAGE_CAPACITY);
215
+
216
+ auto variant = std::make_shared<protocol::Variant>(pkg, capacity);
217
+
209
218
  if (variant->error) {
210
- Log(ERROR,
211
- "routePackage(): parsing failed. err=%u, total_length=%d, data=%s<--\n",
212
- variant->error, pkg.length(), pkg.c_str());
219
+ if (variant->error == DeserializationError::NoMemory) {
220
+ Log(ERROR,
221
+ "routePackage(): Message too large. length=%d, calculated_capacity=%u, "
222
+ "nesting_depth=%u. Consider increasing MAX_MESSAGE_CAPACITY if needed.\n",
223
+ pkg.length(), calculatedCapacity, nestingDepth);
224
+ } else {
225
+ Log(ERROR,
226
+ "routePackage(): parsing failed. err=%u, length=%d, data=%s<--\n",
227
+ variant->error, pkg.length(), pkg.c_str());
228
+ }
213
229
  return;
214
230
  }
215
231