@alteriom/painlessmesh 1.8.14 → 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 +89 -1
- package/CONTRIBUTING.md +79 -0
- package/README.md +70 -143
- package/docs/README.md +1 -0
- package/docs/api/shared-gateway.md +1207 -0
- package/docs/troubleshooting/common-issues.md +28 -0
- package/docs/troubleshooting/faq.md +113 -12
- package/examples/basic/test/simulator/CMakeLists.txt +40 -0
- package/examples/basic/test/simulator/README.md +149 -0
- package/examples/basic/test/simulator/firmware/basic_firmware.hpp +117 -0
- package/examples/basic/test/simulator/scenarios/basic_mesh_test.yaml +81 -0
- package/examples/bridge/bridge.ino +17 -4
- package/examples/bridge_failover/README.md +81 -0
- package/examples/bridge_failover/bridge_failover.ino +51 -6
- 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 -3
- package/src/arduino/wifi.hpp +380 -13
- 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/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/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/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/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 -96
- package/examples/multi_bridge/regular_node.ino +0 -141
- package/examples/multi_bridge/secondary_bridge.ino +0 -111
- 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
|
@@ -2,6 +2,34 @@
|
|
|
2
2
|
|
|
3
3
|
This guide covers the most frequently encountered problems when working with painlessMesh and their solutions.
|
|
4
4
|
|
|
5
|
+
## Architecture & Design Issues
|
|
6
|
+
|
|
7
|
+
### Regular Nodes Cannot Access Internet / HTTP Requests Fail
|
|
8
|
+
|
|
9
|
+
**Symptoms:**
|
|
10
|
+
- HTTP/HTTPS requests fail with "connection refused"
|
|
11
|
+
- `WiFi.status()` shows disconnected on regular mesh nodes
|
|
12
|
+
- Internet services (APIs, WhatsApp bot, etc.) only work on bridge node
|
|
13
|
+
|
|
14
|
+
**Cause:**
|
|
15
|
+
|
|
16
|
+
This is **expected behavior**, not a bug. Only bridge nodes have internet access.
|
|
17
|
+
|
|
18
|
+
**Solution:**
|
|
19
|
+
|
|
20
|
+
See the dedicated guide for this common architecture mistake:
|
|
21
|
+
|
|
22
|
+
📖 **[Common Architecture Mistakes](common-architecture-mistakes.md)**
|
|
23
|
+
|
|
24
|
+
**Quick Summary:**
|
|
25
|
+
|
|
26
|
+
painlessMesh uses a bridge-forwarding pattern:
|
|
27
|
+
- **Bridge node**: Has internet access, forwards data to/from internet
|
|
28
|
+
- **Regular nodes**: No internet access, send data to bridge
|
|
29
|
+
- **Architecture**: Regular nodes → Bridge → Internet
|
|
30
|
+
|
|
31
|
+
Regular nodes must send data to the bridge, which then forwards to internet services.
|
|
32
|
+
|
|
5
33
|
## Platform-Specific Issues
|
|
6
34
|
|
|
7
35
|
### ESP32-C6 Crashes on Startup
|
|
@@ -293,30 +293,131 @@ String createSecureMessage(String data) {
|
|
|
293
293
|
|
|
294
294
|
### Q: Can I connect the mesh to the internet?
|
|
295
295
|
|
|
296
|
-
**A:** Yes, using bridge nodes
|
|
296
|
+
**A:** Yes, using bridge nodes. **Important:** Only the bridge node has internet access - regular mesh nodes do NOT have internet access.
|
|
297
|
+
|
|
298
|
+
**Architecture:**
|
|
299
|
+
```text
|
|
300
|
+
Internet
|
|
301
|
+
|
|
|
302
|
+
Router (WiFi)
|
|
303
|
+
|
|
|
304
|
+
Bridge Node (AP+STA mode) ← Only this node has internet access
|
|
305
|
+
|
|
|
306
|
+
Mesh Network
|
|
307
|
+
/ | \
|
|
308
|
+
Node1 Node2 Node3... ← These nodes do NOT have internet access
|
|
309
|
+
```
|
|
297
310
|
|
|
311
|
+
**Bridge Node Setup:**
|
|
298
312
|
```cpp
|
|
299
313
|
// Bridge node connects to both mesh and internet
|
|
300
314
|
void setup() {
|
|
301
|
-
//
|
|
315
|
+
// Modern approach: Auto-detect channel and connect
|
|
316
|
+
mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
|
|
317
|
+
ROUTER_SSID, ROUTER_PASSWORD,
|
|
318
|
+
&userScheduler, MESH_PORT);
|
|
319
|
+
|
|
320
|
+
mesh.onReceive(&receivedCallback);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Forward mesh data to internet services
|
|
324
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
325
|
+
// Bridge forwards messages to HTTP server, MQTT broker, etc.
|
|
326
|
+
if (WiFi.status() == WL_CONNECTED) {
|
|
327
|
+
httpClient.POST("http://myserver.com/api/data", msg);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Regular Nodes:**
|
|
333
|
+
```cpp
|
|
334
|
+
// Regular nodes send data TO the bridge (no direct internet access)
|
|
335
|
+
void setup() {
|
|
302
336
|
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
337
|
+
mesh.onReceive(&receivedCallback);
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
void sendDataToInternet() {
|
|
341
|
+
// Regular nodes send to bridge, which forwards to internet
|
|
342
|
+
String data = "{\"sensor\":\"temp\",\"value\":25.5}";
|
|
343
|
+
mesh.sendSingle(bridgeNodeId, data);
|
|
344
|
+
// Bridge will forward this to internet services
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
See [BRIDGE_TO_INTERNET.md](../../BRIDGE_TO_INTERNET.md) for complete documentation.
|
|
349
|
+
|
|
350
|
+
### Q: Why can't my regular mesh nodes access the Internet / make HTTP requests?
|
|
351
|
+
|
|
352
|
+
**A:** This is expected behavior. **Only the bridge node has internet access** - regular mesh nodes only communicate with other mesh nodes.
|
|
353
|
+
|
|
354
|
+
**Why this happens:**
|
|
355
|
+
|
|
356
|
+
ESP8266/ESP32 WiFi hardware can only operate on one channel at a time. In a mesh network:
|
|
357
|
+
|
|
358
|
+
- **Bridge node** uses `WIFI_AP_STA` mode:
|
|
359
|
+
- Access Point (AP) for mesh on channel X
|
|
360
|
+
- Station (STA) connected to router on channel X
|
|
361
|
+
- Has internet access via router
|
|
362
|
+
|
|
363
|
+
- **Regular nodes** use `WIFI_AP` mode:
|
|
364
|
+
- Access Point (AP) for mesh only
|
|
365
|
+
- No router connection
|
|
366
|
+
- No internet access
|
|
367
|
+
|
|
368
|
+
**Solution - Forward through bridge:**
|
|
369
|
+
|
|
370
|
+
```cpp
|
|
371
|
+
// ==== BRIDGE NODE ====
|
|
372
|
+
#include "HTTPClient.h"
|
|
373
|
+
|
|
374
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
375
|
+
// Parse message from mesh nodes
|
|
376
|
+
DynamicJsonDocument doc(1024);
|
|
377
|
+
deserializeJson(doc, msg);
|
|
303
378
|
|
|
304
|
-
//
|
|
305
|
-
WiFi.
|
|
306
|
-
|
|
307
|
-
|
|
379
|
+
// Forward to internet service
|
|
380
|
+
if (WiFi.status() == WL_CONNECTED) {
|
|
381
|
+
HTTPClient http;
|
|
382
|
+
http.begin("http://api.example.com/data");
|
|
383
|
+
http.addHeader("Content-Type", "application/json");
|
|
384
|
+
http.POST(msg);
|
|
385
|
+
http.end();
|
|
308
386
|
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// ==== REGULAR NODE ====
|
|
390
|
+
void sendDataToCloud() {
|
|
391
|
+
// Create message
|
|
392
|
+
String msg = "{\"sensor\":\"temp\",\"value\":25.5}";
|
|
393
|
+
|
|
394
|
+
// Send to bridge (NOT directly to internet!)
|
|
395
|
+
mesh.sendSingle(bridgeNodeId, msg);
|
|
309
396
|
|
|
310
|
-
|
|
397
|
+
// Bridge will forward to internet service
|
|
311
398
|
}
|
|
399
|
+
```
|
|
312
400
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
401
|
+
**Common mistake:**
|
|
402
|
+
|
|
403
|
+
```cpp
|
|
404
|
+
// ❌ This will NOT work on regular mesh nodes:
|
|
405
|
+
HTTPClient http;
|
|
406
|
+
http.begin("http://api.example.com/data");
|
|
407
|
+
http.POST(data); // ERROR: No internet connection!
|
|
408
|
+
|
|
409
|
+
// ✅ Correct approach - send to bridge:
|
|
410
|
+
mesh.sendSingle(bridgeNodeId, data); // Bridge forwards to internet
|
|
318
411
|
```
|
|
319
412
|
|
|
413
|
+
**Architecture patterns:**
|
|
414
|
+
|
|
415
|
+
1. **Single bridge**: One node connects to router, others forward through it
|
|
416
|
+
2. **Bridge failover**: Multiple nodes have router credentials, automatic failover
|
|
417
|
+
3. **Multi-bridge**: Multiple simultaneous bridges for load balancing
|
|
418
|
+
|
|
419
|
+
See [BRIDGE_TO_INTERNET.md](../../BRIDGE_TO_INTERNET.md) and [BRIDGE_FAILOVER.md](../BRIDGE_FAILOVER.md).
|
|
420
|
+
|
|
320
421
|
### Q: Can I use MQTT with painlessMesh?
|
|
321
422
|
|
|
322
423
|
**A:** Yes, through bridge nodes or by running MQTT alongside the mesh:
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.10)
|
|
2
|
+
project(BasicExampleSimulatorTests)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_CXX_STANDARD 14)
|
|
5
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
6
|
+
|
|
7
|
+
# Path to the simulator (submodule)
|
|
8
|
+
set(SIMULATOR_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/simulator")
|
|
9
|
+
|
|
10
|
+
# Include simulator's CMake configuration
|
|
11
|
+
if(EXISTS "${SIMULATOR_ROOT}/CMakeLists.txt")
|
|
12
|
+
# Add simulator as subdirectory
|
|
13
|
+
add_subdirectory(${SIMULATOR_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/simulator)
|
|
14
|
+
else()
|
|
15
|
+
message(FATAL_ERROR "Simulator not found at ${SIMULATOR_ROOT}. Did you initialize the submodule?")
|
|
16
|
+
endif()
|
|
17
|
+
|
|
18
|
+
# Include painlessMesh library
|
|
19
|
+
set(PAINLESS_MESH_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../..")
|
|
20
|
+
include_directories(
|
|
21
|
+
${PAINLESS_MESH_ROOT}/src
|
|
22
|
+
${CMAKE_CURRENT_SOURCE_DIR}/firmware
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
# Register our custom firmware with the simulator
|
|
26
|
+
# This allows the YAML scenarios to reference "basic_example" template
|
|
27
|
+
add_library(basic_example_firmware INTERFACE)
|
|
28
|
+
target_include_directories(basic_example_firmware INTERFACE
|
|
29
|
+
${CMAKE_CURRENT_SOURCE_DIR}/firmware
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Link with simulator
|
|
33
|
+
target_link_libraries(basic_example_firmware INTERFACE
|
|
34
|
+
painlessmesh_simulator
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# The simulator executable will be built by the simulator's CMakeLists.txt
|
|
38
|
+
# We just need to ensure our firmware headers are available
|
|
39
|
+
message(STATUS "Basic example firmware tests configured")
|
|
40
|
+
message(STATUS "Run tests with: ./painlessmesh-simulator --config scenarios/basic_mesh_test.yaml")
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Basic Example - Simulator Tests
|
|
2
|
+
|
|
3
|
+
This directory contains simulator-based tests for the `basic.ino` example using the [painlessMesh-simulator](https://github.com/Alteriom/painlessMesh-simulator).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The simulator allows testing the basic example with 10+ virtual nodes without physical hardware, validating:
|
|
8
|
+
- Mesh formation with multiple nodes
|
|
9
|
+
- Message broadcasting to all nodes
|
|
10
|
+
- Callback functionality
|
|
11
|
+
- Dynamic node joining
|
|
12
|
+
- Time synchronization
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
### Prerequisites
|
|
17
|
+
|
|
18
|
+
Install dependencies (Ubuntu/Debian):
|
|
19
|
+
```bash
|
|
20
|
+
sudo apt-get install cmake ninja-build libboost-dev libboost-program-options-dev libyaml-cpp-dev
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Initialize Submodule
|
|
24
|
+
|
|
25
|
+
If not already done:
|
|
26
|
+
```bash
|
|
27
|
+
cd ../../../../test
|
|
28
|
+
git submodule update --init simulator
|
|
29
|
+
cd -
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Build and Run
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Build simulator
|
|
36
|
+
mkdir build && cd build
|
|
37
|
+
cmake -G Ninja ..
|
|
38
|
+
ninja
|
|
39
|
+
|
|
40
|
+
# Run test scenario
|
|
41
|
+
bin/painlessmesh-simulator --config ../scenarios/basic_mesh_test.yaml
|
|
42
|
+
|
|
43
|
+
# Or using the simulator from test/simulator
|
|
44
|
+
cd ../../../../test/simulator
|
|
45
|
+
mkdir -p build && cd build
|
|
46
|
+
cmake -G Ninja ..
|
|
47
|
+
ninja
|
|
48
|
+
bin/painlessmesh-simulator --config ../../../examples/basic/test/simulator/scenarios/basic_mesh_test.yaml
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Test Scenarios
|
|
52
|
+
|
|
53
|
+
### basic_mesh_test.yaml
|
|
54
|
+
|
|
55
|
+
Tests basic functionality with 10 nodes:
|
|
56
|
+
- ✓ Mesh formation
|
|
57
|
+
- ✓ Message broadcasting
|
|
58
|
+
- ✓ Callback triggering
|
|
59
|
+
- ✓ Dynamic node joining (node added at 30s)
|
|
60
|
+
- ✓ Time synchronization
|
|
61
|
+
|
|
62
|
+
**Expected Results:**
|
|
63
|
+
- All nodes connect within 30 seconds
|
|
64
|
+
- Each node receives 5+ messages within 60 seconds
|
|
65
|
+
- Time differences < 10ms after 45 seconds
|
|
66
|
+
|
|
67
|
+
## Firmware Adapter
|
|
68
|
+
|
|
69
|
+
The `firmware/basic_firmware.hpp` file wraps the `basic.ino` logic for simulation:
|
|
70
|
+
|
|
71
|
+
```cpp
|
|
72
|
+
#include "simulator/firmware/firmware_base.hpp"
|
|
73
|
+
|
|
74
|
+
class BasicFirmware : public FirmwareBase {
|
|
75
|
+
// Implements same logic as basic.ino
|
|
76
|
+
// - setup() initializes mesh and callbacks
|
|
77
|
+
// - loop() calls mesh.update()
|
|
78
|
+
// - sendMessage() broadcasts periodically
|
|
79
|
+
};
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This allows running the **exact same code** that runs on hardware.
|
|
83
|
+
|
|
84
|
+
## Adding More Tests
|
|
85
|
+
|
|
86
|
+
Create new YAML scenarios in `scenarios/`:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
simulation:
|
|
90
|
+
name: "Stress Test"
|
|
91
|
+
duration: 120
|
|
92
|
+
|
|
93
|
+
nodes:
|
|
94
|
+
- template: "basic_example"
|
|
95
|
+
count: 50 # Test with 50 nodes
|
|
96
|
+
|
|
97
|
+
topology:
|
|
98
|
+
type: "ring" # Different topology
|
|
99
|
+
|
|
100
|
+
events:
|
|
101
|
+
- type: "network_partition" # Inject failures
|
|
102
|
+
time: 60
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Metrics and Validation
|
|
106
|
+
|
|
107
|
+
Test results are saved to `results/basic_test_results.csv`:
|
|
108
|
+
|
|
109
|
+
```csv
|
|
110
|
+
timestamp,node_id,messages_sent,messages_received,topology_changes
|
|
111
|
+
0,6481,0,0,1
|
|
112
|
+
1,6481,1,0,1
|
|
113
|
+
2,6481,1,2,1
|
|
114
|
+
...
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Analyze with:
|
|
118
|
+
```python
|
|
119
|
+
import pandas as pd
|
|
120
|
+
df = pd.read_csv('results/basic_test_results.csv')
|
|
121
|
+
print(df.groupby('node_id')['messages_received'].sum())
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Documentation
|
|
125
|
+
|
|
126
|
+
- [Simulator Documentation](../../../../test/simulator/README.md)
|
|
127
|
+
- [Integration Guide](../../../../test/simulator/docs/INTEGRATING_INTO_YOUR_PROJECT.md)
|
|
128
|
+
- [Configuration Reference](../../../../test/simulator/docs/CONFIGURATION_GUIDE.md)
|
|
129
|
+
|
|
130
|
+
## Troubleshooting
|
|
131
|
+
|
|
132
|
+
**Simulator not found:**
|
|
133
|
+
```bash
|
|
134
|
+
cd ../../../../test
|
|
135
|
+
git submodule update --init simulator
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Build errors:**
|
|
139
|
+
```bash
|
|
140
|
+
# Check dependencies
|
|
141
|
+
sudo apt-get install libboost-dev libyaml-cpp-dev
|
|
142
|
+
|
|
143
|
+
# Clean build
|
|
144
|
+
rm -rf build && mkdir build && cd build
|
|
145
|
+
cmake -G Ninja ..
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Test failures:**
|
|
149
|
+
Check the simulator output for details on which validation failed.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "simulator/firmware/firmware_base.hpp"
|
|
4
|
+
#include <painlessMesh.h>
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @brief Firmware adapter for basic.ino example
|
|
8
|
+
*
|
|
9
|
+
* This wraps the basic example sketch logic for testing with the simulator.
|
|
10
|
+
* It allows running the exact same code that runs on ESP32/ESP8266 hardware
|
|
11
|
+
* in a simulated environment with 100+ virtual nodes.
|
|
12
|
+
*/
|
|
13
|
+
class BasicFirmware : public FirmwareBase {
|
|
14
|
+
public:
|
|
15
|
+
BasicFirmware() : mesh_(nullptr), userScheduler_(nullptr) {}
|
|
16
|
+
|
|
17
|
+
~BasicFirmware() override {
|
|
18
|
+
if (taskSendMessage_) {
|
|
19
|
+
delete taskSendMessage_;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
void setup(painlessMesh* mesh, Scheduler* userScheduler) override {
|
|
24
|
+
mesh_ = mesh;
|
|
25
|
+
userScheduler_ = userScheduler;
|
|
26
|
+
|
|
27
|
+
// Same configuration as basic.ino
|
|
28
|
+
const char* MESH_PREFIX = "whateverYouLike";
|
|
29
|
+
const char* MESH_PASSWORD = "somethingSneaky";
|
|
30
|
+
const uint16_t MESH_PORT = 5555;
|
|
31
|
+
|
|
32
|
+
// Set debug message types (same as basic.ino)
|
|
33
|
+
mesh_->setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
34
|
+
|
|
35
|
+
// Initialize mesh
|
|
36
|
+
mesh_->init(MESH_PREFIX, MESH_PASSWORD, userScheduler_, MESH_PORT);
|
|
37
|
+
|
|
38
|
+
// Register callbacks
|
|
39
|
+
mesh_->onReceive([this](uint32_t from, String& msg) {
|
|
40
|
+
this->receivedCallback(from, msg);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
mesh_->onNewConnection([this](uint32_t nodeId) {
|
|
44
|
+
this->newConnectionCallback(nodeId);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
mesh_->onChangedConnections([this]() {
|
|
48
|
+
this->changedConnectionCallback();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
mesh_->onNodeTimeAdjusted([this](int32_t offset) {
|
|
52
|
+
this->nodeTimeAdjustedCallback(offset);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Setup periodic message sending task
|
|
56
|
+
taskSendMessage_ = new Task(TASK_SECOND * 1, TASK_FOREVER,
|
|
57
|
+
[this]() { this->sendMessage(); });
|
|
58
|
+
userScheduler_->addTask(*taskSendMessage_);
|
|
59
|
+
taskSendMessage_->enable();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void loop() override {
|
|
63
|
+
if (mesh_) {
|
|
64
|
+
mesh_->update();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const char* getName() const override {
|
|
69
|
+
return "BasicExample";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private:
|
|
73
|
+
painlessMesh* mesh_;
|
|
74
|
+
Scheduler* userScheduler_;
|
|
75
|
+
Task* taskSendMessage_ = nullptr;
|
|
76
|
+
|
|
77
|
+
void sendMessage() {
|
|
78
|
+
if (!mesh_) return;
|
|
79
|
+
|
|
80
|
+
String msg = "Hello from node ";
|
|
81
|
+
msg += mesh_->getNodeId();
|
|
82
|
+
mesh_->sendBroadcast(msg);
|
|
83
|
+
|
|
84
|
+
// Random interval between 1 and 5 seconds (same as basic.ino)
|
|
85
|
+
taskSendMessage_->setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
89
|
+
// In simulator, we can log to stdout or collect metrics
|
|
90
|
+
printf("Node %u: Received from %u msg=%s\n",
|
|
91
|
+
mesh_->getNodeId(), from, msg.c_str());
|
|
92
|
+
|
|
93
|
+
// Track metrics for validation
|
|
94
|
+
messagesReceived_++;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
98
|
+
printf("Node %u: New Connection, nodeId = %u\n",
|
|
99
|
+
mesh_->getNodeId(), nodeId);
|
|
100
|
+
connectionsEstablished_++;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void changedConnectionCallback() {
|
|
104
|
+
printf("Node %u: Changed connections\n", mesh_->getNodeId());
|
|
105
|
+
topologyChanges_++;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void nodeTimeAdjustedCallback(int32_t offset) {
|
|
109
|
+
printf("Node %u: Adjusted time %u. Offset = %d\n",
|
|
110
|
+
mesh_->getNodeId(), mesh_->getNodeTime(), offset);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Metrics for test validation
|
|
114
|
+
uint32_t messagesReceived_ = 0;
|
|
115
|
+
uint32_t connectionsEstablished_ = 0;
|
|
116
|
+
uint32_t topologyChanges_ = 0;
|
|
117
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Test scenario for basic.ino example
|
|
2
|
+
# This validates that the basic example works correctly with multiple nodes
|
|
3
|
+
|
|
4
|
+
simulation:
|
|
5
|
+
name: "Basic Example - Mesh Formation and Broadcasting"
|
|
6
|
+
description: "Validates basic.ino with 10 nodes forming a mesh and exchanging messages"
|
|
7
|
+
duration: 60 # seconds
|
|
8
|
+
time_scale: 1.0
|
|
9
|
+
seed: 12345
|
|
10
|
+
|
|
11
|
+
network:
|
|
12
|
+
default_latency:
|
|
13
|
+
min_ms: 1
|
|
14
|
+
max_ms: 10
|
|
15
|
+
default_packet_loss:
|
|
16
|
+
rate: 0.0
|
|
17
|
+
default_bandwidth:
|
|
18
|
+
bits_per_second: 1000000
|
|
19
|
+
|
|
20
|
+
nodes:
|
|
21
|
+
# Create individual nodes - simulator doesn't support template/count syntax
|
|
22
|
+
- id: "node1"
|
|
23
|
+
firmware: "SimpleBroadcast"
|
|
24
|
+
config:
|
|
25
|
+
mesh_prefix: "whateverYouLike"
|
|
26
|
+
mesh_password: "somethingSneaky"
|
|
27
|
+
mesh_port: 5555
|
|
28
|
+
broadcast_interval: "1000"
|
|
29
|
+
broadcast_message: "Hello from node"
|
|
30
|
+
|
|
31
|
+
- id: "node2"
|
|
32
|
+
firmware: "SimpleBroadcast"
|
|
33
|
+
config:
|
|
34
|
+
mesh_prefix: "whateverYouLike"
|
|
35
|
+
mesh_password: "somethingSneaky"
|
|
36
|
+
mesh_port: 5555
|
|
37
|
+
broadcast_interval: "1000"
|
|
38
|
+
broadcast_message: "Hello from node"
|
|
39
|
+
|
|
40
|
+
- id: "node3"
|
|
41
|
+
firmware: "SimpleBroadcast"
|
|
42
|
+
config:
|
|
43
|
+
mesh_prefix: "whateverYouLike"
|
|
44
|
+
mesh_password: "somethingSneaky"
|
|
45
|
+
mesh_port: 5555
|
|
46
|
+
broadcast_interval: "1000"
|
|
47
|
+
broadcast_message: "Hello from node"
|
|
48
|
+
|
|
49
|
+
- id: "node4"
|
|
50
|
+
firmware: "SimpleBroadcast"
|
|
51
|
+
config:
|
|
52
|
+
mesh_prefix: "whateverYouLike"
|
|
53
|
+
mesh_password: "somethingSneaky"
|
|
54
|
+
mesh_port: 5555
|
|
55
|
+
broadcast_interval: "1000"
|
|
56
|
+
broadcast_message: "Hello from node"
|
|
57
|
+
|
|
58
|
+
- id: "node5"
|
|
59
|
+
firmware: "SimpleBroadcast"
|
|
60
|
+
config:
|
|
61
|
+
mesh_prefix: "whateverYouLike"
|
|
62
|
+
mesh_password: "somethingSneaky"
|
|
63
|
+
mesh_port: 5555
|
|
64
|
+
broadcast_interval: "1000"
|
|
65
|
+
broadcast_message: "Hello from node"
|
|
66
|
+
|
|
67
|
+
topology:
|
|
68
|
+
type: "mesh" # Full mesh - all nodes connected
|
|
69
|
+
|
|
70
|
+
# No events - nodes start automatically
|
|
71
|
+
events: []
|
|
72
|
+
|
|
73
|
+
# Metrics to collect
|
|
74
|
+
metrics:
|
|
75
|
+
output: "basic_test_results.csv"
|
|
76
|
+
interval: 5
|
|
77
|
+
collect:
|
|
78
|
+
- "messages_sent"
|
|
79
|
+
- "messages_received"
|
|
80
|
+
- "bytes_sent"
|
|
81
|
+
- "bytes_received"
|
|
@@ -47,9 +47,22 @@ void setup() {
|
|
|
47
47
|
// 3. Set this node as root
|
|
48
48
|
// 4. Maintain router connection
|
|
49
49
|
// 5. Start broadcasting bridge status (Type 610) every 30 seconds
|
|
50
|
-
mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
bool bridgeSuccess = mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
|
|
51
|
+
ROUTER_SSID, ROUTER_PASSWORD,
|
|
52
|
+
&userScheduler, MESH_PORT);
|
|
53
|
+
|
|
54
|
+
if (!bridgeSuccess) {
|
|
55
|
+
Serial.println("✗ Failed to initialize as bridge!");
|
|
56
|
+
Serial.println("Router unreachable - falling back to regular mesh node");
|
|
57
|
+
Serial.println("The node will join the mesh without bridge functionality");
|
|
58
|
+
|
|
59
|
+
// Fallback: Initialize as regular mesh node
|
|
60
|
+
// This allows the device to still participate in the mesh
|
|
61
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
62
|
+
|
|
63
|
+
Serial.println("✓ Initialized as regular mesh node");
|
|
64
|
+
Serial.println("Note: To function as a bridge, fix router connectivity and restart");
|
|
65
|
+
}
|
|
53
66
|
|
|
54
67
|
// Optional: Configure bridge status broadcasting
|
|
55
68
|
// mesh.setBridgeStatusInterval(60000); // Change to 60 seconds
|
|
@@ -61,7 +74,7 @@ void setup() {
|
|
|
61
74
|
// Set up message callback
|
|
62
75
|
mesh.onReceive(&receivedCallback);
|
|
63
76
|
|
|
64
|
-
Serial.println("Bridge node initialized and ready!");
|
|
77
|
+
Serial.println("✓ Bridge node initialized and ready!");
|
|
65
78
|
Serial.println("Broadcasting bridge status to mesh every 30 seconds");
|
|
66
79
|
}
|
|
67
80
|
|