@alteriom/painlessmesh 1.8.15 → 1.9.0

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 (208) hide show
  1. package/BRIDGE_TO_INTERNET.md +229 -0
  2. package/CHANGELOG.md +61 -1
  3. package/CONTRIBUTING.md +79 -0
  4. package/README.md +69 -144
  5. package/docs/README.md +1 -0
  6. package/docs/api/shared-gateway.md +1207 -0
  7. package/examples/bridge_failover/README.md +81 -0
  8. package/examples/bridge_failover/bridge_failover.ino +35 -4
  9. package/examples/sharedGateway/README.md +235 -0
  10. package/examples/{meshCommandNode → sharedGateway}/platformio.ini +3 -2
  11. package/examples/sharedGateway/sharedGateway.ino +303 -0
  12. package/library.json +3 -22
  13. package/library.properties +1 -1
  14. package/package.json +3 -6
  15. package/src/arduino/wifi.hpp +342 -4
  16. package/src/painlessmesh/gateway.hpp +2120 -0
  17. package/src/painlessmesh/mesh.hpp +1034 -6
  18. package/src/painlessmesh/message_tracker.hpp +311 -0
  19. package/src/painlessmesh/protocol.hpp +6 -0
  20. package/DOCUMENTATION_INDEX.md +0 -146
  21. package/RELEASE_NOTES_1.8.15.md +0 -160
  22. package/RELEASE_READINESS_PLAN.md +0 -323
  23. package/TESTING_WITH_SIMULATOR.md +0 -259
  24. package/docs/API_DESIGN_GUIDELINES.md +0 -414
  25. package/docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md +0 -331
  26. package/docs/BOOLEAN_NAMING_CONVENTION.md +0 -235
  27. package/docs/BRIDGE_FAILOVER.md +0 -512
  28. package/docs/BRIDGE_HEALTH_MONITORING.md +0 -293
  29. package/docs/BRIDGE_INITIALIZATION_FALLBACK.md +0 -357
  30. package/docs/CHANNEL_SYNCHRONIZATION.md +0 -209
  31. package/docs/CREATE_MISSING_RELEASES.md +0 -321
  32. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +0 -176
  33. package/docs/FAQ_VERSION_NUMBERS.md +0 -152
  34. package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +0 -1062
  35. package/docs/MESH_TOPOLOGY_GUIDE.md +0 -992
  36. package/docs/MESH_TOPOLOGY_PROGRESS.md +0 -422
  37. package/docs/MQTT_BRIDGE_COMMANDS.md +0 -894
  38. package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +0 -324
  39. package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +0 -576
  40. package/docs/MQTT_SCHEMA_COMPLIANCE.md +0 -340
  41. package/docs/MQTT_SCHEMA_PROPOSALS.md +0 -446
  42. package/docs/MQTT_SCHEMA_REVIEW.md +0 -690
  43. package/docs/OTA_COMMANDS_REFERENCE.md +0 -554
  44. package/docs/PHASE1_GUIDE.md +0 -349
  45. package/docs/PHASE2_GUIDE.md +0 -543
  46. package/docs/QUICK_REFERENCE_VERSIONING.md +0 -127
  47. package/docs/RELEASE_AGENT_SUMMARY.md +0 -386
  48. package/docs/SCHEMA_VALIDATION_CHECKLIST.md +0 -222
  49. package/docs/SIMULATOR_TESTING.md +0 -408
  50. package/docs/VERSION_MANAGEMENT.md +0 -213
  51. package/docs/archive/DOCUSAURUS_DEPLOYMENT.md +0 -166
  52. package/docs/archive/FEATURE_PROPOSALS.md +0 -337
  53. package/docs/archive/LIBRARY_JSON_FIX.md +0 -98
  54. package/docs/archive/LIBRARY_STRUCTURE_FIX.md +0 -215
  55. package/docs/archive/PHASE1_IMPLEMENTATION.md +0 -325
  56. package/docs/archive/PHASE2_IMPLEMENTATION.md +0 -567
  57. package/docs/archive/RELEASE_SUMMARY.md +0 -173
  58. package/docs/archive/SCONS_BUILD_FIX.md +0 -313
  59. package/docs/archive/TRIGGER_RELEASE.md +0 -280
  60. package/docs/archive/VECTOR_INCLUDE_FIX.md +0 -129
  61. package/docs/archive/ota-and-status-enhancements.md +0 -911
  62. package/docs/archive/ota-status-architecture-diagrams.md +0 -658
  63. package/docs/archive/ota-status-quick-reference.md +0 -284
  64. package/docs/design/.gitkeep +0 -1
  65. package/docs/design/STATION_CREDENTIALS_DESIGN.md +0 -182
  66. package/docs/development/ARDUINO_COMPLIANCE_SUMMARY.md +0 -71
  67. package/docs/development/CODE_REFACTORING_RECOMMENDATIONS.md +0 -1011
  68. package/docs/development/DOCKER_TESTING.md +0 -196
  69. package/docs/development/PLATFORMIO_USAGE.md +0 -180
  70. package/docs/development/TESTING_SUMMARY.md +0 -126
  71. package/docs/development/contributing.md +0 -301
  72. package/docs/development/documentation.md +0 -583
  73. package/docs/features/DIAGNOSTICS_API.md +0 -534
  74. package/docs/implementation/BRIDGE_ARCHITECTURE_IMPLEMENTATION.md +0 -340
  75. package/docs/implementation/BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md +0 -213
  76. package/docs/implementation/BRIDGE_STATUS_FEATURE.md +0 -635
  77. package/docs/implementation/DIAGNOSTICS_API_IMPLEMENTATION.md +0 -232
  78. package/docs/implementation/IMPLEMENTATION_COMPLETE.md +0 -228
  79. package/docs/implementation/IMPLEMENTATION_NTP_TIME_SYNC.md +0 -325
  80. package/docs/implementation/IMPLEMENTATION_SUMMARY.md +0 -316
  81. package/docs/implementation/MESSAGE_QUEUE_IMPLEMENTATION.md +0 -405
  82. package/docs/implementation/MULTI_BRIDGE_IMPLEMENTATION.md +0 -520
  83. package/docs/implementation/NTP_TIME_SYNC_FEATURE.md +0 -392
  84. package/docs/improvements/FUTURE_PROPOSALS.md +0 -1016
  85. package/docs/improvements/IMPLEMENTATION_HISTORY.md +0 -1091
  86. package/docs/improvements/OTA_STATUS_ENHANCEMENTS.md +0 -709
  87. package/docs/improvements/README.md +0 -212
  88. package/docs/internal/CUSTOM_AGENT_ANALYSIS.md +0 -391
  89. package/docs/internal/ISSUE_65_VERIFICATION.md +0 -947
  90. package/docs/internal/ISSUE_66_CLOSURE.md +0 -249
  91. package/docs/internal/ISSUE_66_STATUS.md +0 -316
  92. package/docs/internal/PR_SUMMARY.md +0 -315
  93. package/docs/internal/REVIEW_SUMMARY.md +0 -332
  94. package/docs/multi-bridge-setup.md +0 -1025
  95. package/docs/platformio-publishing.md +0 -255
  96. package/docs/platformio-setup-summary.md +0 -121
  97. package/docs/releases/ANNOUNCEMENT_v1.8.6.md +0 -63
  98. package/docs/releases/ANNOUNCEMENT_v1.8.7.md +0 -113
  99. package/docs/releases/BRIDGE_STATUS_SELF_REGISTRATION_FIX.md +0 -221
  100. package/docs/releases/FEATURE_HISTORY.md +0 -543
  101. package/docs/releases/GITHUB_RELEASE_v1.8.6.md +0 -71
  102. package/docs/releases/GITHUB_RELEASE_v1.8.7.md +0 -90
  103. package/docs/releases/PATCH_v1.7.2.md +0 -262
  104. package/docs/releases/PATCH_v1.7.3.md +0 -262
  105. package/docs/releases/PATCH_v1.7.4.md +0 -219
  106. package/docs/releases/PHASE1_SUMMARY.md +0 -246
  107. package/docs/releases/PHASE2_SUMMARY.md +0 -499
  108. package/docs/releases/PUBLISH_v1.8.0_INSTRUCTIONS.md +0 -163
  109. package/docs/releases/QUICK_START_RELEASES.md +0 -113
  110. package/docs/releases/RELEASE_CHECKLIST_1.8.10.md +0 -331
  111. package/docs/releases/RELEASE_CHECKLIST_1.8.9.md +0 -207
  112. package/docs/releases/RELEASE_CHECKLIST_v1.7.4.md +0 -253
  113. package/docs/releases/RELEASE_CHECKLIST_v1.7.5.md +0 -315
  114. package/docs/releases/RELEASE_CHECKLIST_v1.7.6.md +0 -389
  115. package/docs/releases/RELEASE_CHECKLIST_v1.8.0.md +0 -331
  116. package/docs/releases/RELEASE_CHECKLIST_v1.8.2.md +0 -309
  117. package/docs/releases/RELEASE_NOTES_1.7.0.md +0 -539
  118. package/docs/releases/RELEASE_NOTES_1.8.10.md +0 -239
  119. package/docs/releases/RELEASE_NOTES_1.8.9.md +0 -213
  120. package/docs/releases/RELEASE_NOTES_v1.8.0.md +0 -685
  121. package/docs/releases/RELEASE_NOTES_v1.8.1.md +0 -221
  122. package/docs/releases/RELEASE_NOTES_v1.8.2.md +0 -421
  123. package/docs/releases/RELEASE_NOTES_v1.8.3.md +0 -292
  124. package/docs/releases/RELEASE_NOTES_v1.8.4.md +0 -277
  125. package/docs/releases/RELEASE_NOTES_v1.8.6.md +0 -205
  126. package/docs/releases/RELEASE_NOTES_v1.8.7.md +0 -184
  127. package/docs/releases/RELEASE_PLAN_v1.7.6.md +0 -816
  128. package/docs/releases/RELEASE_SUMMARY_1.8.10.md +0 -193
  129. package/docs/releases/RELEASE_SUMMARY_v1.7.4.md +0 -276
  130. package/docs/releases/RELEASE_SUMMARY_v1.7.5.md +0 -322
  131. package/docs/releases/RELEASE_SUMMARY_v1.7.6.md +0 -436
  132. package/docs/releases/RELEASE_SUMMARY_v1.7.7.md +0 -391
  133. package/docs/releases/RELEASE_SUMMARY_v1.7.8.md +0 -523
  134. package/docs/releases/RELEASE_SUMMARY_v1.7.9.md +0 -542
  135. package/docs/troubleshooting/ARDUINO_IDE_VERSION_FIX_SUMMARY.md +0 -229
  136. package/docs/troubleshooting/ARDUINO_LIBRARY_NAME_FIX.md +0 -197
  137. package/docs/troubleshooting/CRASH_QUICK_REF.md +0 -93
  138. package/docs/troubleshooting/ESP32_C6_COMPATIBILITY.md +0 -157
  139. package/docs/troubleshooting/FREERTOS_ASSERTION_FAILURE.md +0 -288
  140. package/docs/troubleshooting/FREERTOS_FIX_IMPLEMENTATION.md +0 -267
  141. package/docs/troubleshooting/NPM_PUBLISHING_ISSUE_SUMMARY.md +0 -110
  142. package/docs/troubleshooting/PAINLESSMESH_V1.7.4_COMPILATION_ISSUES.md +0 -547
  143. package/docs/troubleshooting/QUICK_FIX_FREERTOS.md +0 -164
  144. package/docs/troubleshooting/SENSOR_NODE_CONNECTION_CRASH.md +0 -264
  145. package/docs/troubleshooting/common-architecture-mistakes.md +0 -438
  146. package/docs/troubleshooting/internet-access-faq.md +0 -299
  147. package/docs/troubleshooting/station-reconnection-issues.md +0 -172
  148. package/docs/v1.7.7_MQTT_IMPROVEMENTS.md +0 -794
  149. package/docs/wiki/API-Reference.md +0 -246
  150. package/docs/wiki/Complete-Documentation.md +0 -123
  151. package/examples/alteriomImproved/alteriom_sensor_package.hpp +0 -224
  152. package/examples/alteriomImproved/improved_sensor_node.ino +0 -248
  153. package/examples/alteriomImproved/platformio.ini +0 -32
  154. package/examples/alteriomMetricsHealth/alteriom_sensor_package.hpp +0 -796
  155. package/examples/alteriomMetricsHealth/metrics_health_node.ino +0 -429
  156. package/examples/alteriomMetricsHealth/platformio.ini +0 -26
  157. package/examples/alteriomPhase1/alteriom_sensor_package.hpp +0 -224
  158. package/examples/alteriomPhase1/phase1_features.ino +0 -242
  159. package/examples/alteriomPhase1/platformio.ini +0 -26
  160. package/examples/alteriomPhase2/alteriom_sensor_package.hpp +0 -224
  161. package/examples/alteriomPhase2/phase2_features.ino +0 -186
  162. package/examples/alteriomPhase2/platformio.ini +0 -26
  163. package/examples/alteriomSensorNode/alteriom_sensor_node.ino +0 -186
  164. package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +0 -1227
  165. package/examples/alteriomSensorNode/platformio.ini +0 -26
  166. package/examples/bridge/alteriom_sensor_package.hpp +0 -1170
  167. package/examples/bridge/bridge_health_monitoring_example.ino +0 -188
  168. package/examples/bridge/enhanced_mqtt_bridge.hpp +0 -610
  169. package/examples/bridge/enhanced_mqtt_bridge_example.ino +0 -226
  170. package/examples/bridge/mesh_event_publisher.hpp +0 -253
  171. package/examples/bridge/mesh_topology_reporter.hpp +0 -303
  172. package/examples/bridge/mqtt_command_bridge.hpp +0 -459
  173. package/examples/bridge/mqtt_status_bridge.hpp +0 -519
  174. package/examples/bridgeAwareSensorNode/alteriom_sensor_package.hpp +0 -1227
  175. package/examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino +0 -342
  176. package/examples/bridgeAwareSensorNode/platformio.ini +0 -26
  177. package/examples/diagnosticsExample/diagnosticsExample.ino +0 -171
  178. package/examples/diagnosticsExample/platformio.ini +0 -26
  179. package/examples/echoNode/echoNode.ino +0 -33
  180. package/examples/echoNode/platformio.ini +0 -26
  181. package/examples/meshCommandNode/alteriom_sensor_package.hpp +0 -235
  182. package/examples/meshCommandNode/meshCommandNode.ino +0 -265
  183. package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +0 -235
  184. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +0 -253
  185. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +0 -303
  186. package/examples/mqttCommandBridge/mqttCommandBridge.ino +0 -254
  187. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +0 -462
  188. package/examples/mqttCommandBridge/platformio.ini +0 -27
  189. package/examples/mqttStatusBridge/mqttStatusBridge.ino +0 -218
  190. package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +0 -522
  191. package/examples/mqttStatusBridge/platformio.ini +0 -27
  192. package/examples/mqttTopologyTest/README.md +0 -467
  193. package/examples/mqttTopologyTest/mqttTopologyTest.ino +0 -754
  194. package/examples/mqttTopologyTest/platformio.ini +0 -27
  195. package/examples/multi_bridge/README.md +0 -346
  196. package/examples/multi_bridge/primary_bridge.ino +0 -108
  197. package/examples/multi_bridge/regular_node.ino +0 -141
  198. package/examples/multi_bridge/secondary_bridge.ino +0 -123
  199. package/examples/ntpTimeSyncBridge/alteriom_sensor_package.hpp +0 -1383
  200. package/examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino +0 -86
  201. package/examples/ntpTimeSyncNode/alteriom_sensor_package.hpp +0 -1383
  202. package/examples/ntpTimeSyncNode/ntpTimeSyncNode.ino +0 -109
  203. package/examples/queued_alarms/README.md +0 -390
  204. package/examples/queued_alarms/queued_alarms.ino +0 -265
  205. package/examples/routing_demo/README.md +0 -172
  206. package/examples/routing_demo/routing_demo.ino +0 -102
  207. package/examples/rtcIntegration/README.md +0 -294
  208. package/examples/rtcIntegration/rtcIntegration.ino +0 -210
@@ -1,264 +0,0 @@
1
- # Sensor Node Connection Crash - Action Plan
2
-
3
- ## ✅ STATUS: FIXED (October 19, 2025)
4
-
5
- **Fix Implemented:** Commit [7391717](https://github.com/Alteriom/painlessMesh/commit/7391717)
6
- **Released:** painlessMesh v1.7.4
7
- **Implementation:** See [FREERTOS_FIX_IMPLEMENTATION.md](FREERTOS_FIX_IMPLEMENTATION.md)
8
-
9
- The complete dual-approach fix (Option A + Option B) is now available in v1.7.4. Update to the latest version to automatically apply the fix when building for ESP32 platforms.
10
-
11
- **Installation:**
12
-
13
- - **PlatformIO:** `pio pkg update sparck75/AlteriomPainlessMesh`
14
- - **NPM:** `npm install @alteriom/painlessmesh@1.7.4`
15
- - **Arduino IDE:** Library Manager → Search "painlessMesh" → Update to 1.7.4
16
- - **GitHub:** [Release v1.7.4](https://github.com/Alteriom/painlessMesh/releases/tag/v1.7.4)
17
-
18
- ---
19
-
20
- ## Issue Summary
21
-
22
- **Symptom:** FreeRTOS assertion failure when sensor nodes connect to mesh
23
- **Error:** `assert failed: vTaskPriorityDisinheritAfterTimeout`
24
- **Platform:** ESP32 only (ESP8266 unaffected)
25
- **Scope:** painlessMesh library issue - NOT related to Build 8015 or Phase 2 changes
26
-
27
- **Important:** This is a known painlessMesh + AsyncTCP + FreeRTOS interaction issue that requires mesh library fixes, separate from your application code.
28
-
29
- ## Immediate Action Plan
30
-
31
- ### Step 1: Apply Quick Fix (Choose ONE)
32
-
33
- #### Option A: Increase Semaphore Timeout ⭐ RECOMMENDED FOR TESTING
34
-
35
- **Fastest fix - 5 minutes:**
36
-
37
- 1. **Edit:** `src/painlessmesh/mesh.hpp` line 544
38
- 2. **Change:** `(TickType_t)10` → `(TickType_t)100`
39
- 3. **Rebuild & Upload:** `pio run -t upload`
40
- 4. **Test:** Connect sensor nodes and monitor for crashes
41
-
42
- **Rationale:** Gives more time for semaphore acquisition, prevents timeout-related assertions.
43
-
44
- #### Option B: Enable Thread-Safe Scheduler ⭐ RECOMMENDED FOR PRODUCTION
45
-
46
- **Better long-term solution - 10 minutes:**
47
-
48
- 1. **Create:** `src/painlessTaskOptions.h` (if doesn't exist)
49
- ```cpp
50
- #ifndef _PAINLESS_TASK_OPTIONS_H_
51
- #define _PAINLESS_TASK_OPTIONS_H_
52
-
53
- #ifdef ESP32
54
- #define _TASK_THREAD_SAFE // FreeRTOS queue-based task control
55
- #define _TASK_PRIORITY // Priority scheduling support
56
- #endif
57
-
58
- #endif
59
- ```
60
-
61
- 2. **Modify:** Your main sketch BEFORE `#include <painlessMesh.h>`:
62
- ```cpp
63
- #include "painlessTaskOptions.h"
64
- #include <painlessMesh.h>
65
- ```
66
-
67
- 3. **Rebuild & Upload**
68
-
69
- **Rationale:** Uses FreeRTOS queue for thread-safe task management, eliminates race conditions.
70
-
71
- ### Step 2: Monitor & Verify
72
-
73
- Add this monitoring code to track connection health:
74
-
75
- ```cpp
76
- void setup() {
77
- Serial.begin(115200);
78
-
79
- // Enable mesh debugging
80
- mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
81
-
82
- // Connection monitoring
83
- mesh.onNewConnection([](uint32_t nodeId) {
84
- Serial.printf("[MONITOR] Node connected: %u\n", nodeId);
85
- Serial.printf(" Free heap: %d bytes\n", ESP.getFreeHeap());
86
- Serial.printf(" Min heap: %d bytes\n", ESP.getMinFreeHeap());
87
- Serial.printf(" Stack HWM: %d bytes\n", uxTaskGetStackHighWaterMark(NULL));
88
- Serial.printf(" Total nodes: %d\n", mesh.getNodeList().size() + 1);
89
- });
90
-
91
- mesh.onDroppedConnection([](uint32_t nodeId, bool isStation) {
92
- Serial.printf("[MONITOR] Node dropped: %u (station=%d)\n", nodeId, isStation);
93
- });
94
- }
95
-
96
- void loop() {
97
- mesh.update();
98
-
99
- // Periodic health check every 30 seconds
100
- static uint32_t lastCheck = 0;
101
- if (millis() - lastCheck > 30000) {
102
- lastCheck = millis();
103
- Serial.printf("[HEALTH] Heap: %d, Min: %d, Stack: %d, Nodes: %d\n",
104
- ESP.getFreeHeap(),
105
- ESP.getMinFreeHeap(),
106
- uxTaskGetStackHighWaterMark(NULL),
107
- mesh.getNodeList().size() + 1);
108
- }
109
- }
110
- ```
111
-
112
- ### Step 3: Test Scenarios
113
-
114
- **Critical Test Cases:**
115
-
116
- 1. **Single Node Connection**
117
- - Start gateway
118
- - Connect 1 sensor node
119
- - Verify: No crash, stable connection
120
-
121
- 2. **Multiple Simultaneous Connections**
122
- - Start gateway
123
- - Power on 3-5 sensor nodes simultaneously
124
- - Verify: All connect without crashes
125
-
126
- 3. **Rapid Connect/Disconnect**
127
- - Connect sensor node
128
- - Wait 10 seconds
129
- - Power cycle sensor
130
- - Repeat 10 times
131
- - Verify: No cumulative issues or crashes
132
-
133
- 4. **Sustained Operation**
134
- - Run mesh network for 1+ hour
135
- - Monitor free heap and stack
136
- - Verify: No memory leaks or gradual degradation
137
-
138
- ### Step 4: Collect Diagnostic Data
139
-
140
- If crashes persist after applying fixes, collect:
141
-
142
- ```cpp
143
- // Enable detailed FreeRTOS logging
144
- #define CORE_DEBUG_LEVEL 5 // Verbose
145
-
146
- // In platformio.ini
147
- build_flags =
148
- -DCORE_DEBUG_LEVEL=5
149
- -DCONFIG_FREERTOS_ASSERT_FAIL_ABORT=0 // Don't abort on assert
150
- -DCONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=1
151
- ```
152
-
153
- **Capture:**
154
- - Full serial output during crash
155
- - Heap/stack watermarks before crash
156
- - Number of connected nodes at crash time
157
- - WiFi RSSI values
158
- - Mesh topology (node IDs and connections)
159
-
160
- ## Root Cause Analysis
161
-
162
- **Why This Happens:**
163
-
164
- 1. **AsyncTCP** uses FreeRTOS mutexes internally for WiFi callbacks
165
- 2. **painlessMesh** uses its own mutex (`xSemaphore`) for mesh operations
166
- 3. **TaskScheduler** runs cooperative multitasking on top of FreeRTOS
167
- 4. When sensor connects:
168
- - WiFi callback fires (high priority FreeRTOS task)
169
- - Mesh code tries to acquire semaphore
170
- - 10ms timeout too short for WiFi operations
171
- - FreeRTOS tries to restore task priority after timeout
172
- - Priority inheritance state is inconsistent → ASSERTION FAILURE
173
-
174
- **Key Insight:** This is a timing/synchronization issue in the mesh library itself, not your sensor/gateway code.
175
-
176
- ## Long-Term Solutions (For Next Release)
177
-
178
- These require mesh library changes and should be tracked separately from Build 8015:
179
-
180
- ### 1. Implement Thread-Safe TaskScheduler (HIGH PRIORITY)
181
-
182
- **Status:** ⚠️ Requires painlessMesh library modification
183
- **Effort:** 2-4 hours
184
- **Impact:** Eliminates root cause
185
-
186
- **Implementation:**
187
- - Enable `_TASK_THREAD_SAFE` by default for ESP32 builds
188
- - Implement FreeRTOS queue for task control requests
189
- - Add proper mutex guards around critical sections
190
-
191
- **Files to modify:**
192
- - `src/painlessmesh/configuration.hpp` - Add `#define _TASK_THREAD_SAFE` for ESP32
193
- - `src/painlessmesh/mesh.hpp` - Update semaphore timeout to 100ms
194
- - Test with full suite
195
-
196
- ### 2. Replace Mutex with Binary Semaphore (MEDIUM PRIORITY)
197
-
198
- **Status:** ⚠️ Alternative approach
199
- **Effort:** 1 hour
200
- **Impact:** Reduces priority inheritance issues
201
-
202
- **Trade-off:** Loses priority inheritance protection (acceptable for mesh use case)
203
-
204
- ### 3. Add Connection Rate Limiting (LOW PRIORITY)
205
-
206
- **Status:** Workaround
207
- **Effort:** 30 minutes
208
- **Impact:** Prevents simultaneous connection storm
209
-
210
- ```cpp
211
- // In mesh.hpp - connection handling
212
- static uint32_t lastConnectionTime = 0;
213
- if (millis() - lastConnectionTime < 1000) {
214
- delay(100); // Rate limit connections
215
- }
216
- lastConnectionTime = millis();
217
- ```
218
-
219
- ## Integration with Build 8015
220
-
221
- **Important Separation:**
222
-
223
- | Aspect | Build 8015 (Phase 2) | Mesh Connection Crash |
224
- |--------|---------------------|----------------------|
225
- | **Scope** | MQTT command bridge, topology reporting | painlessMesh + FreeRTOS timing |
226
- | **Root Cause** | Application code | Library interaction issue |
227
- | **Testing** | Functional tests for commands | Stress tests for connections |
228
- | **Priority** | HIGH (feature delivery) | HIGH (stability) |
229
- | **Timeline** | Current sprint | Parallel investigation |
230
- | **Dependencies** | None on mesh fix | None on Build 8015 |
231
-
232
- **Recommendation:** Apply Quick Fix (Option A or B) immediately to unblock Build 8015 testing. Schedule library fix as separate work item.
233
-
234
- ## Success Criteria
235
-
236
- After applying fixes, you should observe:
237
-
238
- ✅ **Zero crashes** during sensor node connections
239
- ✅ **Stable memory** - no heap degradation over time
240
- ✅ **Fast connections** - nodes join within 5-10 seconds
241
- ✅ **No disconnects** - sustained connections for hours
242
- ✅ **Scales reliably** - supports 4-10 nodes depending on ESP32 model
243
-
244
- ## Related Documentation
245
-
246
- - [FREERTOS_ASSERTION_FAILURE.md](./FREERTOS_ASSERTION_FAILURE.md) - Complete technical analysis
247
- - [QUICK_FIX_FREERTOS.md](./QUICK_FIX_FREERTOS.md) - Emergency fixes reference
248
- - [TaskScheduler Thread Safety Example](../../test/TaskScheduler/examples/Scheduler_example30_THREAD_SAFE/) - Reference implementation
249
-
250
- ## Decision Log
251
-
252
- **Date:** 2025-10-19
253
- **Decision:** Apply Option A (timeout increase) for immediate testing
254
- **Rationale:** Fastest unblock for Build 8015 validation
255
- **Next Step:** Evaluate Option B for production deployment
256
- **Owner:** [Your Name]
257
- **Status:** 🟡 In Progress
258
-
259
- ---
260
-
261
- **Last Updated:** 2025-10-19
262
- **Severity:** HIGH (blocks production deployment)
263
- **Workaround Available:** YES (Option A/B)
264
- **Permanent Fix Required:** YES (library modification)
@@ -1,438 +0,0 @@
1
- # Common Architecture Mistakes
2
-
3
- This document explains common misunderstandings about painlessMesh architecture and how to fix them.
4
-
5
- ## Mistake #1: Expecting Regular Nodes to Have Internet Access
6
-
7
- ### The Problem
8
-
9
- **What users expect:**
10
- ```cpp
11
- // Regular mesh node trying to make HTTP requests
12
- void sendSensorData() {
13
- HTTPClient http;
14
- http.begin("http://api.example.com/sensor");
15
- http.POST("{\"temp\":25.5}"); // ❌ This fails!
16
- http.end();
17
- }
18
- ```
19
-
20
- **Error message:**
21
- ```
22
- [HTTPS] GET... failed, error: connection refused
23
- ```
24
-
25
- ### Why This Fails
26
-
27
- painlessMesh creates a **mesh network**, not a mesh-routed internet gateway. Only the bridge node connects to your WiFi router.
28
-
29
- **Architecture:**
30
- ```text
31
- Internet
32
- |
33
- Router (WiFi - Channel 6)
34
- |
35
- Bridge Node (WIFI_AP_STA mode)
36
- | ← Only this node has internet!
37
- |
38
- Mesh Network (Channel 6)
39
- / | \
40
- Node1 Node2 Node3 ← These nodes do NOT have internet!
41
- ```
42
-
43
- **Technical explanation:**
44
-
45
- 1. **Bridge node** (`WIFI_AP_STA` mode):
46
- - Acts as Access Point (AP) for mesh
47
- - Acts as Station (STA) connected to router
48
- - Has internet access via router connection
49
- - Can make HTTP/HTTPS requests
50
-
51
- 2. **Regular nodes** (`WIFI_AP` mode):
52
- - Only act as Access Points for mesh
53
- - No router connection
54
- - No internet access
55
- - Cannot make HTTP/HTTPS requests directly
56
-
57
- ESP8266/ESP32 WiFi hardware can only operate on one channel at a time. Regular nodes use their WiFi radio to create the mesh AP - they cannot simultaneously connect to your router.
58
-
59
- ### The Solution
60
-
61
- **Pattern 1: Forward through bridge (Recommended)**
62
-
63
- ```cpp
64
- // ==== BRIDGE NODE ====
65
- #include "painlessMesh.h"
66
- #include "HTTPClient.h"
67
-
68
- painlessMesh mesh;
69
-
70
- void setup() {
71
- // Initialize as bridge with internet access
72
- mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
73
- ROUTER_SSID, ROUTER_PASSWORD,
74
- &userScheduler, 5555);
75
-
76
- mesh.onReceive(&receivedCallback);
77
- }
78
-
79
- void receivedCallback(uint32_t from, String& msg) {
80
- // Parse message from mesh nodes
81
- DynamicJsonDocument doc(1024);
82
- deserializeJson(doc, msg);
83
-
84
- // Forward to internet service
85
- if (WiFi.status() == WL_CONNECTED) {
86
- HTTPClient http;
87
- http.begin("http://api.example.com/sensor");
88
- http.addHeader("Content-Type", "application/json");
89
- int httpCode = http.POST(msg);
90
-
91
- if (httpCode > 0) {
92
- Serial.printf("Data forwarded to cloud: %d\n", httpCode);
93
- } else {
94
- Serial.printf("HTTP POST failed: %s\n", http.errorToString(httpCode).c_str());
95
- }
96
-
97
- http.end();
98
- } else {
99
- Serial.println("No internet connection - data not forwarded");
100
- }
101
- }
102
-
103
- // ==== REGULAR SENSOR NODE ====
104
- #include "painlessMesh.h"
105
-
106
- painlessMesh mesh;
107
- uint32_t bridgeNodeId = 0;
108
-
109
- void setup() {
110
- // Regular node - no router connection
111
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, 5555);
112
- mesh.onReceive(&receivedCallback);
113
- mesh.onNewConnection(&newConnectionCallback);
114
- }
115
-
116
- void loop() {
117
- mesh.update();
118
-
119
- // Read sensor
120
- float temperature = readTemperatureSensor();
121
-
122
- // Send to bridge (NOT directly to internet!)
123
- if (bridgeNodeId != 0) {
124
- String msg = "{\"sensor\":\"temp\",\"value\":" + String(temperature) + "}";
125
- mesh.sendSingle(bridgeNodeId, msg);
126
- Serial.println("Data sent to bridge for forwarding");
127
- }
128
- }
129
-
130
- void newConnectionCallback(uint32_t nodeId) {
131
- // You could implement bridge discovery here
132
- // For now, configure bridge ID manually or via broadcast discovery
133
- }
134
- ```
135
-
136
- **Pattern 2: Bridge failover (High availability)**
137
-
138
- ```cpp
139
- // All nodes configured with router credentials
140
- mesh.setRouterCredentials(ROUTER_SSID, ROUTER_PASSWORD);
141
- mesh.enableBridgeFailover(true);
142
-
143
- mesh.onBridgeRoleChanged(&bridgeRoleCallback);
144
-
145
- void bridgeRoleCallback(bool isBridge, String reason) {
146
- if (isBridge) {
147
- Serial.printf("I am now bridge: %s\n", reason.c_str());
148
- // This node now has internet access
149
- startForwardingToCloud();
150
- } else {
151
- Serial.println("I am a regular node - no internet access");
152
- // This node must forward through bridge
153
- }
154
- }
155
- ```
156
-
157
- See [BRIDGE_FAILOVER.md](../BRIDGE_FAILOVER.md) for details.
158
-
159
- ## Mistake #2: Thinking All Nodes Should Be Bridges
160
-
161
- ### The Problem
162
-
163
- Some users try to make every node a bridge:
164
-
165
- ```cpp
166
- // ❌ Bad idea: Making all nodes bridges
167
- void setup() {
168
- // Every node connects to router
169
- mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
170
- ROUTER_SSID, ROUTER_PASSWORD,
171
- &userScheduler, 5555);
172
- }
173
- ```
174
-
175
- ### Why This Is Problematic
176
-
177
- 1. **Memory overhead**: Each router connection uses 5-10KB RAM
178
- 2. **Performance**: All nodes compete for router bandwidth
179
- 3. **Complexity**: Loses benefits of mesh architecture
180
- 4. **Channel conflicts**: All nodes must match router channel
181
- 5. **Connection limit**: Router has max client limit
182
-
183
- ### The Solution
184
-
185
- **Use the bridge-forwarding pattern:**
186
-
187
- - **1 bridge node**: Connects to router and mesh
188
- - **N regular nodes**: Connect to mesh only, forward data to bridge
189
- - **Bridge forwards**: Takes messages and forwards to internet
190
-
191
- This is the intended architecture and scales much better.
192
-
193
- ## Mistake #3: Not Identifying the Bridge Node
194
-
195
- ### The Problem
196
-
197
- Regular nodes send data but don't know which node is the bridge:
198
-
199
- ```cpp
200
- // ❌ How do I know which node is the bridge?
201
- void sendData() {
202
- String msg = "{\"data\":\"value\"}";
203
- mesh.sendBroadcast(msg); // Wasteful - sends to everyone!
204
- }
205
- ```
206
-
207
- ### The Solution
208
-
209
- **Option 1: Bridge discovery via status broadcasts**
210
-
211
- ```cpp
212
- // Bridge node broadcasts status
213
- #include "examples/alteriom/alteriom_sensor_package.hpp"
214
- using namespace alteriom;
215
-
216
- // Bridge node
217
- Task taskBridgeStatus(30000, TASK_FOREVER, []() {
218
- if (mesh.isRoot()) {
219
- BridgeStatusPackage status;
220
- status.from = mesh.getNodeId();
221
- status.internetConnected = (WiFi.status() == WL_CONNECTED);
222
- status.routerRSSI = WiFi.RSSI();
223
-
224
- mesh.sendBroadcast(status.toJsonString());
225
- }
226
- });
227
-
228
- // Regular node
229
- uint32_t bridgeNodeId = 0;
230
-
231
- void receivedCallback(uint32_t from, String& msg) {
232
- DynamicJsonDocument doc(1024);
233
- deserializeJson(doc, msg);
234
-
235
- if (doc["type"] == 610) { // BridgeStatusPackage
236
- bridgeNodeId = from;
237
- Serial.printf("Bridge node discovered: %u\n", bridgeNodeId);
238
- }
239
- }
240
-
241
- void sendDataToBridge() {
242
- if (bridgeNodeId != 0) {
243
- mesh.sendSingle(bridgeNodeId, myData);
244
- } else {
245
- Serial.println("Bridge not yet discovered");
246
- }
247
- }
248
- ```
249
-
250
- **Option 2: Hardcode bridge ID (simple approach)**
251
-
252
- ```cpp
253
- // Configure bridge ID on all nodes
254
- #define BRIDGE_NODE_ID 1234567890
255
-
256
- void sendDataToBridge() {
257
- mesh.sendSingle(BRIDGE_NODE_ID, myData);
258
- }
259
- ```
260
-
261
- **Option 3: Use root node as bridge**
262
-
263
- ```cpp
264
- void setup() {
265
- mesh.setRoot(true); // Bridge should be root
266
- mesh.setContainsRoot(true); // Tell all nodes
267
- }
268
-
269
- void sendDataToBridge() {
270
- // Send to root node (which is the bridge)
271
- auto nodeList = mesh.getNodeList();
272
- for (auto nodeId : nodeList) {
273
- // Check if this node is root
274
- // (painlessMesh automatically routes toward root)
275
- }
276
- }
277
- ```
278
-
279
- ## Mistake #4: Using Wrong WiFi Mode
280
-
281
- ### The Problem
282
-
283
- ```cpp
284
- // ❌ Regular node trying to use AP+STA mode
285
- void setup() {
286
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, 5555,
287
- WIFI_AP_STA); // This is for bridges!
288
-
289
- // Then trying to connect to router
290
- WiFi.begin(ROUTER_SSID, ROUTER_PASSWORD); // Conflicts with mesh!
291
- }
292
- ```
293
-
294
- ### The Solution
295
-
296
- **Bridge nodes:**
297
- ```cpp
298
- // Use initAsBridge() which handles AP+STA mode correctly
299
- mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
300
- ROUTER_SSID, ROUTER_PASSWORD,
301
- &userScheduler, 5555);
302
- ```
303
-
304
- **Regular nodes:**
305
- ```cpp
306
- // Use default WIFI_AP mode (or let init() choose)
307
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, 5555);
308
- // No router connection needed
309
- ```
310
-
311
- ## Mistake #5: Blocking Code on Regular Nodes Waiting for Internet
312
-
313
- ### The Problem
314
-
315
- ```cpp
316
- // ❌ Regular node waiting forever for internet that never comes
317
- void sendToCloud() {
318
- HTTPClient http;
319
- http.begin("http://api.example.com");
320
- http.setTimeout(30000); // Waits 30 seconds
321
- http.POST(data); // Will always timeout!
322
- }
323
- ```
324
-
325
- ### The Solution
326
-
327
- **Check your node role:**
328
-
329
- ```cpp
330
- bool isBridgeNode = false;
331
-
332
- void setup() {
333
- if (shouldBeBridge()) {
334
- mesh.initAsBridge(...);
335
- isBridgeNode = true;
336
- } else {
337
- mesh.init(...);
338
- isBridgeNode = false;
339
- }
340
- }
341
-
342
- void sendData() {
343
- if (isBridgeNode && WiFi.status() == WL_CONNECTED) {
344
- // Bridge can send directly to internet
345
- http.POST("http://api.example.com", data);
346
- } else {
347
- // Regular node forwards to bridge
348
- mesh.sendSingle(bridgeNodeId, data);
349
- }
350
- }
351
- ```
352
-
353
- ## Real-World Example: WhatsApp Notifications
354
-
355
- This is a real issue reported by a user trying to use the Callmebot-ESP32 library with painlessMesh.
356
-
357
- ### Original (Incorrect) Approach
358
-
359
- ```cpp
360
- // ❌ Regular mesh node trying to send WhatsApp messages
361
- #include "Callmebot_ESP32.h"
362
-
363
- Callmebot_ESP32 whatsapp;
364
-
365
- void sendAlarm() {
366
- // This fails on regular nodes: "connection refused"
367
- whatsapp.sendMessage("Sensor alarm!"); // ❌ No internet!
368
- }
369
- ```
370
-
371
- ### Corrected Approach
372
-
373
- ```cpp
374
- // ==== BRIDGE NODE ====
375
- #include "painlessMesh.h"
376
- #include "Callmebot_ESP32.h"
377
-
378
- Callmebot_ESP32 whatsapp;
379
-
380
- void setup() {
381
- // Bridge has internet access
382
- mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
383
- ROUTER_SSID, ROUTER_PASSWORD,
384
- &userScheduler, 5555);
385
-
386
- whatsapp.begin(PHONE_NUMBER, API_KEY);
387
- mesh.onReceive(&receivedCallback);
388
- }
389
-
390
- void receivedCallback(uint32_t from, String& msg) {
391
- DynamicJsonDocument doc(1024);
392
- deserializeJson(doc, msg);
393
-
394
- // Check for alarm messages from mesh nodes
395
- if (doc["alarm"] == true) {
396
- String alertMsg = "ALARM from sensor " + String(from);
397
- alertMsg += ": " + doc["message"].as<String>();
398
-
399
- // Bridge can send WhatsApp messages
400
- if (WiFi.status() == WL_CONNECTED) {
401
- whatsapp.sendMessage(alertMsg);
402
- Serial.println("WhatsApp alert sent!");
403
- }
404
- }
405
- }
406
-
407
- // ==== SENSOR NODE ====
408
- void checkSensorAndAlert() {
409
- float oxygenLevel = readO2Sensor();
410
-
411
- if (oxygenLevel < CRITICAL_THRESHOLD) {
412
- // Send alarm to bridge (not directly to WhatsApp!)
413
- String alarm = "{\"alarm\":true,\"sensor\":\"O2\",";
414
- alarm += "\"value\":" + String(oxygenLevel) + ",";
415
- alarm += "\"message\":\"Critical O2 level!\"}";
416
-
417
- mesh.sendSingle(bridgeNodeId, alarm);
418
- Serial.println("Alarm sent to bridge for WhatsApp notification");
419
- }
420
- }
421
- ```
422
-
423
- ## Summary: Architecture Best Practices
424
-
425
- 1. ✅ **One bridge node**: Connects to router and mesh, has internet access
426
- 2. ✅ **Regular nodes**: Connect to mesh only, NO internet access
427
- 3. ✅ **Forward pattern**: Regular nodes send data to bridge, bridge forwards to internet
428
- 4. ✅ **Bridge discovery**: Implement mechanism for nodes to find the bridge
429
- 5. ✅ **Error handling**: Bridge checks internet connectivity before forwarding
430
- 6. ✅ **Failover option**: Use bridge failover for high availability (v1.8.0+)
431
-
432
- ## Additional Resources
433
-
434
- - [BRIDGE_TO_INTERNET.md](../../BRIDGE_TO_INTERNET.md) - Complete bridge setup guide
435
- - [BRIDGE_FAILOVER.md](../BRIDGE_FAILOVER.md) - Automatic failover for reliability
436
- - [examples/mqttBridge/](../../examples/mqttBridge/) - Working example of bridge pattern
437
- - [Mesh Architecture](../architecture/mesh-architecture.md) - Understanding mesh design
438
- - [FAQ](faq.md) - Common questions and answers