@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.
- package/BRIDGE_TO_INTERNET.md +229 -0
- package/CHANGELOG.md +61 -1
- package/CONTRIBUTING.md +79 -0
- package/README.md +69 -144
- package/docs/README.md +1 -0
- package/docs/api/shared-gateway.md +1207 -0
- package/examples/bridge_failover/README.md +81 -0
- package/examples/bridge_failover/bridge_failover.ino +35 -4
- package/examples/sharedGateway/README.md +235 -0
- package/examples/{meshCommandNode → sharedGateway}/platformio.ini +3 -2
- package/examples/sharedGateway/sharedGateway.ino +303 -0
- package/library.json +3 -22
- package/library.properties +1 -1
- package/package.json +3 -6
- package/src/arduino/wifi.hpp +342 -4
- package/src/painlessmesh/gateway.hpp +2120 -0
- package/src/painlessmesh/mesh.hpp +1034 -6
- package/src/painlessmesh/message_tracker.hpp +311 -0
- package/src/painlessmesh/protocol.hpp +6 -0
- package/DOCUMENTATION_INDEX.md +0 -146
- package/RELEASE_NOTES_1.8.15.md +0 -160
- package/RELEASE_READINESS_PLAN.md +0 -323
- package/TESTING_WITH_SIMULATOR.md +0 -259
- package/docs/API_DESIGN_GUIDELINES.md +0 -414
- package/docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md +0 -331
- package/docs/BOOLEAN_NAMING_CONVENTION.md +0 -235
- package/docs/BRIDGE_FAILOVER.md +0 -512
- package/docs/BRIDGE_HEALTH_MONITORING.md +0 -293
- package/docs/BRIDGE_INITIALIZATION_FALLBACK.md +0 -357
- package/docs/CHANNEL_SYNCHRONIZATION.md +0 -209
- package/docs/CREATE_MISSING_RELEASES.md +0 -321
- package/docs/DOCUMENTATION_MIGRATION_PLAN.md +0 -176
- package/docs/FAQ_VERSION_NUMBERS.md +0 -152
- package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +0 -1062
- package/docs/MESH_TOPOLOGY_GUIDE.md +0 -992
- package/docs/MESH_TOPOLOGY_PROGRESS.md +0 -422
- package/docs/MQTT_BRIDGE_COMMANDS.md +0 -894
- package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +0 -324
- package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +0 -576
- package/docs/MQTT_SCHEMA_COMPLIANCE.md +0 -340
- package/docs/MQTT_SCHEMA_PROPOSALS.md +0 -446
- package/docs/MQTT_SCHEMA_REVIEW.md +0 -690
- package/docs/OTA_COMMANDS_REFERENCE.md +0 -554
- package/docs/PHASE1_GUIDE.md +0 -349
- package/docs/PHASE2_GUIDE.md +0 -543
- package/docs/QUICK_REFERENCE_VERSIONING.md +0 -127
- package/docs/RELEASE_AGENT_SUMMARY.md +0 -386
- package/docs/SCHEMA_VALIDATION_CHECKLIST.md +0 -222
- package/docs/SIMULATOR_TESTING.md +0 -408
- package/docs/VERSION_MANAGEMENT.md +0 -213
- package/docs/archive/DOCUSAURUS_DEPLOYMENT.md +0 -166
- package/docs/archive/FEATURE_PROPOSALS.md +0 -337
- package/docs/archive/LIBRARY_JSON_FIX.md +0 -98
- package/docs/archive/LIBRARY_STRUCTURE_FIX.md +0 -215
- package/docs/archive/PHASE1_IMPLEMENTATION.md +0 -325
- package/docs/archive/PHASE2_IMPLEMENTATION.md +0 -567
- package/docs/archive/RELEASE_SUMMARY.md +0 -173
- package/docs/archive/SCONS_BUILD_FIX.md +0 -313
- package/docs/archive/TRIGGER_RELEASE.md +0 -280
- package/docs/archive/VECTOR_INCLUDE_FIX.md +0 -129
- package/docs/archive/ota-and-status-enhancements.md +0 -911
- package/docs/archive/ota-status-architecture-diagrams.md +0 -658
- package/docs/archive/ota-status-quick-reference.md +0 -284
- package/docs/design/.gitkeep +0 -1
- package/docs/design/STATION_CREDENTIALS_DESIGN.md +0 -182
- package/docs/development/ARDUINO_COMPLIANCE_SUMMARY.md +0 -71
- package/docs/development/CODE_REFACTORING_RECOMMENDATIONS.md +0 -1011
- package/docs/development/DOCKER_TESTING.md +0 -196
- package/docs/development/PLATFORMIO_USAGE.md +0 -180
- package/docs/development/TESTING_SUMMARY.md +0 -126
- package/docs/development/contributing.md +0 -301
- package/docs/development/documentation.md +0 -583
- package/docs/features/DIAGNOSTICS_API.md +0 -534
- package/docs/implementation/BRIDGE_ARCHITECTURE_IMPLEMENTATION.md +0 -340
- package/docs/implementation/BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md +0 -213
- package/docs/implementation/BRIDGE_STATUS_FEATURE.md +0 -635
- package/docs/implementation/DIAGNOSTICS_API_IMPLEMENTATION.md +0 -232
- package/docs/implementation/IMPLEMENTATION_COMPLETE.md +0 -228
- package/docs/implementation/IMPLEMENTATION_NTP_TIME_SYNC.md +0 -325
- package/docs/implementation/IMPLEMENTATION_SUMMARY.md +0 -316
- package/docs/implementation/MESSAGE_QUEUE_IMPLEMENTATION.md +0 -405
- package/docs/implementation/MULTI_BRIDGE_IMPLEMENTATION.md +0 -520
- package/docs/implementation/NTP_TIME_SYNC_FEATURE.md +0 -392
- package/docs/improvements/FUTURE_PROPOSALS.md +0 -1016
- package/docs/improvements/IMPLEMENTATION_HISTORY.md +0 -1091
- package/docs/improvements/OTA_STATUS_ENHANCEMENTS.md +0 -709
- package/docs/improvements/README.md +0 -212
- package/docs/internal/CUSTOM_AGENT_ANALYSIS.md +0 -391
- package/docs/internal/ISSUE_65_VERIFICATION.md +0 -947
- package/docs/internal/ISSUE_66_CLOSURE.md +0 -249
- package/docs/internal/ISSUE_66_STATUS.md +0 -316
- package/docs/internal/PR_SUMMARY.md +0 -315
- package/docs/internal/REVIEW_SUMMARY.md +0 -332
- package/docs/multi-bridge-setup.md +0 -1025
- package/docs/platformio-publishing.md +0 -255
- package/docs/platformio-setup-summary.md +0 -121
- package/docs/releases/ANNOUNCEMENT_v1.8.6.md +0 -63
- package/docs/releases/ANNOUNCEMENT_v1.8.7.md +0 -113
- package/docs/releases/BRIDGE_STATUS_SELF_REGISTRATION_FIX.md +0 -221
- package/docs/releases/FEATURE_HISTORY.md +0 -543
- package/docs/releases/GITHUB_RELEASE_v1.8.6.md +0 -71
- package/docs/releases/GITHUB_RELEASE_v1.8.7.md +0 -90
- package/docs/releases/PATCH_v1.7.2.md +0 -262
- package/docs/releases/PATCH_v1.7.3.md +0 -262
- package/docs/releases/PATCH_v1.7.4.md +0 -219
- package/docs/releases/PHASE1_SUMMARY.md +0 -246
- package/docs/releases/PHASE2_SUMMARY.md +0 -499
- package/docs/releases/PUBLISH_v1.8.0_INSTRUCTIONS.md +0 -163
- package/docs/releases/QUICK_START_RELEASES.md +0 -113
- package/docs/releases/RELEASE_CHECKLIST_1.8.10.md +0 -331
- package/docs/releases/RELEASE_CHECKLIST_1.8.9.md +0 -207
- package/docs/releases/RELEASE_CHECKLIST_v1.7.4.md +0 -253
- package/docs/releases/RELEASE_CHECKLIST_v1.7.5.md +0 -315
- package/docs/releases/RELEASE_CHECKLIST_v1.7.6.md +0 -389
- package/docs/releases/RELEASE_CHECKLIST_v1.8.0.md +0 -331
- package/docs/releases/RELEASE_CHECKLIST_v1.8.2.md +0 -309
- package/docs/releases/RELEASE_NOTES_1.7.0.md +0 -539
- package/docs/releases/RELEASE_NOTES_1.8.10.md +0 -239
- package/docs/releases/RELEASE_NOTES_1.8.9.md +0 -213
- package/docs/releases/RELEASE_NOTES_v1.8.0.md +0 -685
- package/docs/releases/RELEASE_NOTES_v1.8.1.md +0 -221
- package/docs/releases/RELEASE_NOTES_v1.8.2.md +0 -421
- package/docs/releases/RELEASE_NOTES_v1.8.3.md +0 -292
- package/docs/releases/RELEASE_NOTES_v1.8.4.md +0 -277
- package/docs/releases/RELEASE_NOTES_v1.8.6.md +0 -205
- package/docs/releases/RELEASE_NOTES_v1.8.7.md +0 -184
- package/docs/releases/RELEASE_PLAN_v1.7.6.md +0 -816
- package/docs/releases/RELEASE_SUMMARY_1.8.10.md +0 -193
- package/docs/releases/RELEASE_SUMMARY_v1.7.4.md +0 -276
- package/docs/releases/RELEASE_SUMMARY_v1.7.5.md +0 -322
- package/docs/releases/RELEASE_SUMMARY_v1.7.6.md +0 -436
- package/docs/releases/RELEASE_SUMMARY_v1.7.7.md +0 -391
- package/docs/releases/RELEASE_SUMMARY_v1.7.8.md +0 -523
- package/docs/releases/RELEASE_SUMMARY_v1.7.9.md +0 -542
- package/docs/troubleshooting/ARDUINO_IDE_VERSION_FIX_SUMMARY.md +0 -229
- package/docs/troubleshooting/ARDUINO_LIBRARY_NAME_FIX.md +0 -197
- package/docs/troubleshooting/CRASH_QUICK_REF.md +0 -93
- package/docs/troubleshooting/ESP32_C6_COMPATIBILITY.md +0 -157
- package/docs/troubleshooting/FREERTOS_ASSERTION_FAILURE.md +0 -288
- package/docs/troubleshooting/FREERTOS_FIX_IMPLEMENTATION.md +0 -267
- package/docs/troubleshooting/NPM_PUBLISHING_ISSUE_SUMMARY.md +0 -110
- package/docs/troubleshooting/PAINLESSMESH_V1.7.4_COMPILATION_ISSUES.md +0 -547
- package/docs/troubleshooting/QUICK_FIX_FREERTOS.md +0 -164
- package/docs/troubleshooting/SENSOR_NODE_CONNECTION_CRASH.md +0 -264
- package/docs/troubleshooting/common-architecture-mistakes.md +0 -438
- package/docs/troubleshooting/internet-access-faq.md +0 -299
- package/docs/troubleshooting/station-reconnection-issues.md +0 -172
- package/docs/v1.7.7_MQTT_IMPROVEMENTS.md +0 -794
- package/docs/wiki/API-Reference.md +0 -246
- package/docs/wiki/Complete-Documentation.md +0 -123
- package/examples/alteriomImproved/alteriom_sensor_package.hpp +0 -224
- package/examples/alteriomImproved/improved_sensor_node.ino +0 -248
- package/examples/alteriomImproved/platformio.ini +0 -32
- package/examples/alteriomMetricsHealth/alteriom_sensor_package.hpp +0 -796
- package/examples/alteriomMetricsHealth/metrics_health_node.ino +0 -429
- package/examples/alteriomMetricsHealth/platformio.ini +0 -26
- package/examples/alteriomPhase1/alteriom_sensor_package.hpp +0 -224
- package/examples/alteriomPhase1/phase1_features.ino +0 -242
- package/examples/alteriomPhase1/platformio.ini +0 -26
- package/examples/alteriomPhase2/alteriom_sensor_package.hpp +0 -224
- package/examples/alteriomPhase2/phase2_features.ino +0 -186
- package/examples/alteriomPhase2/platformio.ini +0 -26
- package/examples/alteriomSensorNode/alteriom_sensor_node.ino +0 -186
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +0 -1227
- package/examples/alteriomSensorNode/platformio.ini +0 -26
- package/examples/bridge/alteriom_sensor_package.hpp +0 -1170
- package/examples/bridge/bridge_health_monitoring_example.ino +0 -188
- package/examples/bridge/enhanced_mqtt_bridge.hpp +0 -610
- package/examples/bridge/enhanced_mqtt_bridge_example.ino +0 -226
- package/examples/bridge/mesh_event_publisher.hpp +0 -253
- package/examples/bridge/mesh_topology_reporter.hpp +0 -303
- package/examples/bridge/mqtt_command_bridge.hpp +0 -459
- package/examples/bridge/mqtt_status_bridge.hpp +0 -519
- package/examples/bridgeAwareSensorNode/alteriom_sensor_package.hpp +0 -1227
- package/examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino +0 -342
- package/examples/bridgeAwareSensorNode/platformio.ini +0 -26
- package/examples/diagnosticsExample/diagnosticsExample.ino +0 -171
- package/examples/diagnosticsExample/platformio.ini +0 -26
- package/examples/echoNode/echoNode.ino +0 -33
- package/examples/echoNode/platformio.ini +0 -26
- package/examples/meshCommandNode/alteriom_sensor_package.hpp +0 -235
- package/examples/meshCommandNode/meshCommandNode.ino +0 -265
- package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +0 -235
- package/examples/mqttCommandBridge/mesh_event_publisher.hpp +0 -253
- package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +0 -303
- package/examples/mqttCommandBridge/mqttCommandBridge.ino +0 -254
- package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +0 -462
- package/examples/mqttCommandBridge/platformio.ini +0 -27
- package/examples/mqttStatusBridge/mqttStatusBridge.ino +0 -218
- package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +0 -522
- package/examples/mqttStatusBridge/platformio.ini +0 -27
- package/examples/mqttTopologyTest/README.md +0 -467
- package/examples/mqttTopologyTest/mqttTopologyTest.ino +0 -754
- package/examples/mqttTopologyTest/platformio.ini +0 -27
- package/examples/multi_bridge/README.md +0 -346
- package/examples/multi_bridge/primary_bridge.ino +0 -108
- package/examples/multi_bridge/regular_node.ino +0 -141
- package/examples/multi_bridge/secondary_bridge.ino +0 -123
- package/examples/ntpTimeSyncBridge/alteriom_sensor_package.hpp +0 -1383
- package/examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino +0 -86
- package/examples/ntpTimeSyncNode/alteriom_sensor_package.hpp +0 -1383
- package/examples/ntpTimeSyncNode/ntpTimeSyncNode.ino +0 -109
- package/examples/queued_alarms/README.md +0 -390
- package/examples/queued_alarms/queued_alarms.ino +0 -265
- package/examples/routing_demo/README.md +0 -172
- package/examples/routing_demo/routing_demo.ino +0 -102
- package/examples/rtcIntegration/README.md +0 -294
- 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
|