@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,512 +0,0 @@
1
- # Bridge Failover with RSSI-Based Election
2
-
3
- ## Overview
4
-
5
- Bridge failover enables painlessMesh networks to automatically recover from bridge node failures by electing a new bridge based on router signal strength (RSSI). This ensures continuous Internet connectivity for critical applications like fish farm monitoring, industrial IoT, and smart building systems.
6
-
7
- ## Problem Statement
8
-
9
- In a typical mesh network, the bridge node connecting to the Internet represents a single point of failure:
10
-
11
- - **Bridge goes offline**: Entire mesh loses Internet access
12
- - **Bridge loses Internet**: Gateway unavailable for data upload
13
- - **Manual recovery**: Requires human intervention to restore connectivity
14
-
15
- Without automatic failover, critical systems can miss alarms, lose sensor data, or fail to respond to urgent conditions.
16
-
17
- ## Solution: Distributed Bridge Election
18
-
19
- painlessMesh implements a distributed consensus protocol that:
20
-
21
- 1. **Detects failures**: Monitors bridge heartbeats (Type 610 status broadcasts)
22
- 2. **Triggers elections**: Starts election when primary bridge fails
23
- 3. **Selects winner**: Deterministically chooses node with best router signal
24
- 4. **Promotes bridge**: Winner automatically becomes new bridge
25
- 5. **Announces takeover**: Informs mesh of new bridge
26
-
27
- ## Architecture
28
-
29
- ### Message Types
30
-
31
- #### Type 610: BRIDGE_STATUS (Existing)
32
- Bridge nodes broadcast their status every 30 seconds:
33
- ```json
34
- {
35
- "type": 610,
36
- "from": 1234567890,
37
- "routing": 2,
38
- "internetConnected": true,
39
- "routerRSSI": -42,
40
- "routerChannel": 6,
41
- "uptime": 3600000,
42
- "gatewayIP": "192.168.1.1",
43
- "timestamp": 1609459200
44
- }
45
- ```
46
-
47
- #### Type 611: BRIDGE_ELECTION (New)
48
- Candidates broadcast their router signal strength:
49
- ```json
50
- {
51
- "type": 611,
52
- "from": 2886734890,
53
- "routing": 2,
54
- "routerRSSI": -35,
55
- "uptime": 3600000,
56
- "freeMemory": 150000,
57
- "timestamp": 1609459300,
58
- "routerSSID": "MyRouter"
59
- }
60
- ```
61
-
62
- #### Type 612: BRIDGE_TAKEOVER (New)
63
- Winner announces bridge role assumption:
64
- ```json
65
- {
66
- "type": 612,
67
- "from": 2886734890,
68
- "routing": 2,
69
- "previousBridge": 1234567890,
70
- "reason": "Election winner - best router signal",
71
- "routerRSSI": -35,
72
- "timestamp": 1609459400
73
- }
74
- ```
75
-
76
- ### Election Protocol
77
-
78
- ```
79
- ┌──────────────────────────────────────────────────────┐
80
- │ NORMAL OPERATION │
81
- │ Bridge broadcasts status every 30s (Type 610) │
82
- └──────────────────────────────────────────────────────┘
83
- ↓
84
- Bridge fails
85
- (60s timeout)
86
- ↓
87
- ┌──────────────────────────────────────────────────────┐
88
- │ ELECTION PHASE (5 seconds) │
89
- │ 1. Each node scans for router RSSI │
90
- │ 2. Broadcasts candidacy (Type 611) │
91
- │ 3. Collects all candidates │
92
- └──────────────────────────────────────────────────────┘
93
- ↓
94
- ┌──────────────────────────────────────────────────────┐
95
- │ EVALUATION PHASE (Instant) │
96
- │ All nodes independently evaluate candidates using: │
97
- │ 1. Best RSSI wins │
98
- │ 2. Tiebreaker: Highest uptime │
99
- │ 3. Tiebreaker: Most free memory │
100
- │ 4. Tiebreaker: Lowest node ID │
101
- └──────────────────────────────────────────────────────┘
102
- ↓
103
- ┌──────────────────────────────────────────────────────┐
104
- │ PROMOTION PHASE (5 seconds) │
105
- │ Winner: │
106
- │ 1. Calls initAsBridge() │
107
- │ 2. Connects to router │
108
- │ 3. Broadcasts takeover (Type 612) │
109
- └──────────────────────────────────────────────────────┘
110
- ↓
111
- ┌──────────────────────────────────────────────────────┐
112
- │ NEW NORMAL OPERATION │
113
- │ New bridge broadcasts status (Type 610) │
114
- └──────────────────────────────────────────────────────┘
115
- ```
116
-
117
- ### Winner Selection Algorithm
118
-
119
- All nodes execute identical deterministic evaluation:
120
-
121
- ```cpp
122
- BridgeCandidate* winner = nullptr;
123
- int8_t bestRSSI = -127;
124
-
125
- for (auto& candidate : candidates) {
126
- if (candidate.routerRSSI > bestRSSI) {
127
- // Better signal strength
128
- bestRSSI = candidate.routerRSSI;
129
- winner = &candidate;
130
- } else if (candidate.routerRSSI == bestRSSI) {
131
- // Tiebreaker 1: Higher uptime (more stable)
132
- if (candidate.uptime > winner->uptime) {
133
- winner = &candidate;
134
- } else if (candidate.uptime == winner->uptime) {
135
- // Tiebreaker 2: More memory (more capable)
136
- if (candidate.freeMemory > winner->freeMemory) {
137
- winner = &candidate;
138
- } else if (candidate.freeMemory == winner->freeMemory) {
139
- // Tiebreaker 3: Lower node ID (deterministic)
140
- if (candidate.nodeId < winner->nodeId) {
141
- winner = &candidate;
142
- }
143
- }
144
- }
145
- }
146
- }
147
- ```
148
-
149
- ## API Reference
150
-
151
- ### Configuration
152
-
153
- ```cpp
154
- // Set router credentials (required for election participation)
155
- mesh.setRouterCredentials(ROUTER_SSID, ROUTER_PASSWORD);
156
-
157
- // Enable automatic failover (default: enabled)
158
- mesh.enableBridgeFailover(true);
159
-
160
- // Set election timeout in milliseconds (default: 5000)
161
- mesh.setElectionTimeout(5000);
162
-
163
- // Set bridge timeout for failure detection (default: 60000)
164
- mesh.setBridgeTimeout(60000);
165
-
166
- // Set bridge status broadcast interval (default: 30000)
167
- mesh.setBridgeStatusInterval(30000);
168
- ```
169
-
170
- ### Callbacks
171
-
172
- ```cpp
173
- // Called when bridge status changes
174
- void onBridgeStatusChanged(uint32_t bridgeNodeId, bool hasInternet) {
175
- if (!hasInternet) {
176
- Serial.println("Bridge lost Internet - election may start");
177
- }
178
- }
179
-
180
- // Called when this node's role changes
181
- void onBridgeRoleChanged(bool isBridge, String reason) {
182
- if (isBridge) {
183
- Serial.printf("Promoted to bridge: %s\n", reason.c_str());
184
- }
185
- }
186
-
187
- // Register callbacks
188
- mesh.onBridgeStatusChanged(&onBridgeStatusChanged);
189
- mesh.onBridgeRoleChanged(&onBridgeRoleChanged);
190
- ```
191
-
192
- ### Status Methods
193
-
194
- ```cpp
195
- // Check if this node is a bridge
196
- bool isBridge = mesh.isBridge();
197
-
198
- // Check if any bridge has Internet connectivity
199
- bool hasInternet = mesh.hasInternetConnection();
200
-
201
- // Get primary (best) bridge
202
- BridgeInfo* primary = mesh.getPrimaryBridge();
203
- if (primary) {
204
- Serial.printf("Primary bridge: %u (RSSI: %d dBm)\n",
205
- primary->nodeId, primary->routerRSSI);
206
- }
207
-
208
- // Get all known bridges
209
- std::vector<BridgeInfo> bridges = mesh.getBridges();
210
- for (const auto& bridge : bridges) {
211
- Serial.printf("Bridge %u: Internet=%s, RSSI=%d\n",
212
- bridge.nodeId,
213
- bridge.internetConnected ? "YES" : "NO",
214
- bridge.routerRSSI);
215
- }
216
- ```
217
-
218
- ## Usage Example
219
-
220
- ### Basic Setup
221
-
222
- ```cpp
223
- #include "painlessMesh.h"
224
-
225
- #define MESH_PREFIX "MyMesh"
226
- #define MESH_PASSWORD "password"
227
- #define ROUTER_SSID "MyRouter"
228
- #define ROUTER_PASSWORD "routerpass"
229
-
230
- painlessMesh mesh;
231
-
232
- void setup() {
233
- // Initialize as regular node
234
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler);
235
-
236
- // Enable automatic failover
237
- mesh.setRouterCredentials(ROUTER_SSID, ROUTER_PASSWORD);
238
- mesh.enableBridgeFailover(true);
239
-
240
- // Register callbacks
241
- mesh.onBridgeStatusChanged(&bridgeStatusCallback);
242
- mesh.onBridgeRoleChanged(&bridgeRoleCallback);
243
- }
244
- ```
245
-
246
- ### Initial Bridge Setup
247
-
248
- ```cpp
249
- void setup() {
250
- // Initialize as bridge with automatic channel detection
251
- mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
252
- ROUTER_SSID, ROUTER_PASSWORD,
253
- &userScheduler);
254
- }
255
- ```
256
-
257
- See `examples/bridge_failover/` for complete working example.
258
-
259
- ## Failure Scenarios
260
-
261
- ### Scenario 1: Bridge Goes Offline
262
-
263
- **Timeline:**
264
- - T+0s: Bridge node powers off
265
- - T+30s: Last status broadcast expires
266
- - T+60s: Nodes detect failure (timeout threshold)
267
- - T+62s: Election starts (2s coordination delay)
268
- - T+67s: Election completes (5s collection window)
269
- - T+72s: Winner promoted to bridge (5s promotion)
270
-
271
- **Total Failover Time:** ~70 seconds
272
-
273
- ### Scenario 2: Bridge Loses Internet
274
-
275
- **Timeline:**
276
- - T+0s: Router Internet connection fails
277
- - T+30s: Bridge broadcasts `internetConnected: false`
278
- - T+30s: Nodes receive status, consider election
279
- - T+32s: Election starts (if no recovery detected)
280
- - T+37s: Election completes
281
- - T+42s: Winner promoted to bridge
282
-
283
- **Total Failover Time:** ~42 seconds
284
-
285
- ### Scenario 3: Sequential Bridge Failures
286
-
287
- **Timeline:**
288
- - T+0s: Primary bridge fails, election starts
289
- - T+70s: Node A wins, becomes bridge
290
- - T+120s: Node A also fails
291
- - T+180s: Failure detected (60s timeout)
292
- - T+250s: New election completes, Node B becomes bridge
293
-
294
- **Recovery:** Continues indefinitely until stable bridge found
295
-
296
- ## Performance Characteristics
297
-
298
- ### Timing
299
- - **Failure detection:** 60 seconds (configurable)
300
- - **Election duration:** 5 seconds (configurable)
301
- - **Promotion delay:** 5 seconds (WiFi reconnection)
302
- - **Total failover:** 60-70 seconds typical
303
-
304
- ### Network Overhead
305
- - **Status broadcasts:** 256 bytes per bridge every 30s
306
- - **Election messages:** 256 bytes per candidate (one-time)
307
- - **Takeover announcement:** 256 bytes (one-time)
308
-
309
- ### Memory Usage
310
- - **Per candidate:** ~12 bytes during election
311
- - **Bridge tracking:** ~48 bytes per bridge
312
- - **State machine:** ~100 bytes
313
-
314
- ### Scalability
315
- - **Tested:** Up to 10 nodes
316
- - **Theoretical:** 50+ nodes (limited by election timeout)
317
- - **Recommended:** 5-10 nodes per mesh
318
-
319
- ## Edge Cases and Prevention
320
-
321
- ### Split-Brain Prevention
322
-
323
- **Problem:** Multiple nodes promote themselves simultaneously
324
-
325
- **Solution:**
326
- - State machine prevents concurrent elections
327
- - Deterministic evaluation ensures consensus
328
- - All nodes reach same conclusion independently
329
-
330
- ### Rapid Failover Prevention
331
-
332
- **Problem:** Bridge roles oscillate rapidly
333
-
334
- **Solution:**
335
- - Minimum 60 seconds between role changes
336
- - RSSI hysteresis (winner must be significantly better)
337
- - Uptime tiebreaker favors stable nodes
338
-
339
- ### Phantom Election Prevention
340
-
341
- **Problem:** Election starts when bridge is healthy
342
-
343
- **Solution:**
344
- - Only trigger on confirmed failure (60s no heartbeat)
345
- - Check `hasInternetConnection()` before starting
346
- - Verify router is visible before participating
347
-
348
- ### Router Visibility Issues
349
-
350
- **Problem:** Candidate can't see router during scan
351
-
352
- **Solution:**
353
- - Return RSSI=0 if router not found
354
- - Candidate excluded from winner consideration
355
- - Election continues with remaining candidates
356
-
357
- ## Troubleshooting
358
-
359
- ### Elections Don't Start
360
-
361
- **Check:**
362
- - Router credentials configured: `setRouterCredentials()`
363
- - Failover enabled: `enableBridgeFailover(true)`
364
- - Bridge timeout exceeded (60 seconds)
365
- - At least one node can see router
366
-
367
- **Debug:**
368
- ```cpp
369
- Serial.printf("Credentials: %s\n", routerCredentialsConfigured ? "YES" : "NO");
370
- Serial.printf("Failover: %s\n", bridgeFailoverEnabled ? "ON" : "OFF");
371
- Serial.printf("Last bridge seen: %u ms ago\n", millis() - lastBridgeSeen);
372
- ```
373
-
374
- ### Wrong Node Wins Election
375
-
376
- **Check:**
377
- - RSSI measurement accuracy (WiFi scan)
378
- - Router placement and interference
379
- - Tiebreaker criteria (uptime, memory, node ID)
380
-
381
- **Debug:**
382
- ```cpp
383
- Serial.printf("My RSSI: %d dBm\n", scanRouterSignalStrength(ROUTER_SSID));
384
- Serial.printf("My uptime: %u ms\n", millis());
385
- Serial.printf("My free memory: %u bytes\n", ESP.getFreeHeap());
386
- ```
387
-
388
- ### Bridge Promotion Fails
389
-
390
- **Check:**
391
- - Router password correct
392
- - Router channel compatible
393
- - Node can reach router physically
394
- - Sufficient memory for bridge mode
395
-
396
- **Debug:**
397
- ```cpp
398
- Serial.printf("WiFi status: %d\n", WiFi.status());
399
- Serial.printf("Router channel: %d\n", WiFi.channel());
400
- Serial.printf("Free heap: %u bytes\n", ESP.getFreeHeap());
401
- ```
402
-
403
- ## Security Considerations
404
-
405
- ### Router Credentials
406
-
407
- **Risk:** Router password stored in node memory
408
-
409
- **Mitigation:**
410
- - Use separate guest network for mesh bridges
411
- - Limit router permissions (no admin access)
412
- - Consider WPA2-Enterprise for stronger security
413
-
414
- ### Rogue Bridge Prevention
415
-
416
- **Risk:** Malicious node claims bridge role with fake RSSI
417
-
418
- **Mitigation:**
419
- - Physical security of mesh nodes
420
- - Verify bridge Internet connectivity post-election
421
- - Monitor bridge status broadcasts for anomalies
422
-
423
- ### Denial of Service
424
-
425
- **Risk:** Attacker triggers repeated elections
426
-
427
- **Mitigation:**
428
- - Minimum 60s between role changes
429
- - Rate limiting on election start triggers
430
- - Monitor for excessive election activity
431
-
432
- ## Best Practices
433
-
434
- ### 1. Configure Redundancy
435
- ```cpp
436
- // At least 2 nodes with router credentials
437
- mesh.setRouterCredentials(ROUTER_SSID, ROUTER_PASSWORD);
438
- ```
439
-
440
- ### 2. Monitor Bridge Health
441
- ```cpp
442
- void loop() {
443
- if (!mesh.hasInternetConnection()) {
444
- // Queue critical data locally
445
- queueMessage(msg);
446
- }
447
- }
448
- ```
449
-
450
- ### 3. Log Election Activity
451
- ```cpp
452
- void onBridgeRoleChanged(bool isBridge, String reason) {
453
- logToSD(millis(), isBridge, reason); // Audit trail
454
- }
455
- ```
456
-
457
- ### 4. Test Failover Regularly
458
- ```cpp
459
- // Scheduled failover test (monthly)
460
- if (shouldTestFailover()) {
461
- // Temporarily disable primary bridge
462
- testBridgeFailover();
463
- }
464
- ```
465
-
466
- ### 5. Optimize Router Placement
467
- - Position router centrally in mesh coverage area
468
- - Minimize physical obstructions
469
- - Avoid interference from other 2.4GHz devices
470
-
471
- ## Comparison with Alternatives
472
-
473
- ### Manual Failover
474
- - **Pro:** Full control, predictable behavior
475
- - **Con:** Requires human intervention, slow recovery
476
-
477
- ### Pre-designated Backup
478
- - **Pro:** Fast failover to known secondary
479
- - **Con:** Backup may have poor signal, not optimal
480
-
481
- ### RSSI-Based Election (painlessMesh)
482
- - **Pro:** Automatic, optimal selection, distributed
483
- - **Con:** 60-70s failover time, requires router visibility
484
-
485
- ## Future Enhancements
486
-
487
- ### Potential Improvements
488
- 1. **Faster failover:** Reduce detection timeout to 30s
489
- 2. **Predictive failover:** Detect degrading bridges before failure
490
- 3. **Multi-router support:** Failover between different routers
491
- 4. **Quality of Service:** Prioritize critical traffic during failover
492
- 5. **Geographic awareness:** Consider physical location in selection
493
-
494
- ### Experimental Features
495
- - Load-based selection (choose least-loaded node)
496
- - Battery-aware (exclude low-battery nodes)
497
- - Historical reliability (favor nodes with uptime track record)
498
-
499
- ## References
500
-
501
- - Issue: Alteriom/painlessMesh#XX (Bridge Failover Request)
502
- - Related: Alteriom/painlessMesh#63 (Bridge Status Broadcast)
503
- - Related: Alteriom/painlessMesh#59 (initAsBridge Method)
504
- - Example: `examples/bridge_failover/`
505
- - Test: `test/catch/catch_alteriom_packages.cpp`
506
-
507
- ## Credits
508
-
509
- - **Requested by:** @woodlist (fish farm alarm system)
510
- - **Implemented:** painlessMesh v1.8.0
511
- - **Consensus model:** Based on Raft algorithm principles
512
- - **RSSI selection:** Adapted from WiFi mesh best practices