@alteriom/painlessmesh 1.6.1 → 1.7.2

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 (129) hide show
  1. package/CHANGELOG.md +380 -143
  2. package/LICENSE +674 -674
  3. package/README.md +477 -434
  4. package/RELEASE_GUIDE.md +504 -418
  5. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +175 -175
  6. package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +1062 -0
  7. package/docs/MESH_TOPOLOGY_GUIDE.md +992 -0
  8. package/docs/MESH_TOPOLOGY_PROGRESS.md +422 -0
  9. package/docs/MQTT_BRIDGE_COMMANDS.md +894 -0
  10. package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +324 -0
  11. package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +576 -0
  12. package/docs/MQTT_SCHEMA_COMPLIANCE.md +285 -0
  13. package/docs/MQTT_SCHEMA_PROPOSALS.md +446 -0
  14. package/docs/MQTT_SCHEMA_REVIEW.md +690 -0
  15. package/docs/OTA_COMMANDS_REFERENCE.md +554 -0
  16. package/docs/PHASE1_GUIDE.md +349 -0
  17. package/docs/PHASE2_GUIDE.md +543 -0
  18. package/docs/README.md +77 -70
  19. package/docs/SCHEMA_VALIDATION_CHECKLIST.md +222 -0
  20. package/docs/alteriom/overview.md +507 -507
  21. package/docs/api/core-api.md +606 -606
  22. package/docs/architecture/mesh-architecture.md +378 -378
  23. package/docs/architecture/plugin-system.md +516 -516
  24. package/docs/getting-started/first-mesh.md +409 -409
  25. package/docs/getting-started/installation.md +274 -274
  26. package/docs/getting-started/quickstart.md +157 -157
  27. package/docs/improvements/FEATURE_PROPOSALS.md +337 -0
  28. package/docs/improvements/PHASE1_IMPLEMENTATION.md +325 -0
  29. package/docs/improvements/PHASE2_IMPLEMENTATION.md +567 -0
  30. package/docs/improvements/README.md +86 -68
  31. package/docs/improvements/ota-and-status-enhancements.md +911 -0
  32. package/docs/improvements/ota-status-architecture-diagrams.md +658 -0
  33. package/docs/improvements/ota-status-quick-reference.md +284 -0
  34. package/docs/platformio-publishing.md +255 -0
  35. package/docs/platformio-setup-summary.md +121 -0
  36. package/docs/troubleshooting/common-issues.md +520 -520
  37. package/docs/troubleshooting/faq.md +472 -472
  38. package/docs/tutorials/basic-examples.md +717 -717
  39. package/docs/wiki/API-Reference.md +245 -245
  40. package/docs/wiki/Complete-Documentation.md +122 -122
  41. package/examples/alteriom/README.md +139 -81
  42. package/examples/alteriom/alteriom.ino +186 -185
  43. package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
  44. package/examples/alteriom/platformio.ini +24 -24
  45. package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
  46. package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
  47. package/examples/alteriomImproved/platformio.ini +25 -0
  48. package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
  49. package/examples/alteriomPhase1/phase1_features.ino +242 -0
  50. package/examples/alteriomPhase1/platformio.ini +25 -0
  51. package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
  52. package/examples/alteriomPhase2/phase2_features.ino +186 -0
  53. package/examples/alteriomPhase2/platformio.ini +25 -0
  54. package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
  55. package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
  56. package/examples/alteriomSensorNode/platformio.ini +25 -0
  57. package/examples/basic/basic.ino +66 -66
  58. package/examples/basic/platformio.ini +25 -25
  59. package/examples/bridge/bridge.ino +51 -51
  60. package/examples/bridge/mesh_event_publisher.hpp +253 -0
  61. package/examples/bridge/mesh_topology_reporter.hpp +303 -0
  62. package/examples/bridge/mqtt_command_bridge.hpp +459 -0
  63. package/examples/bridge/mqtt_status_bridge.hpp +519 -0
  64. package/examples/bridge/platformio.ini +25 -25
  65. package/examples/echoNode/echoNode.ino +33 -33
  66. package/examples/echoNode/platformio.ini +25 -25
  67. package/examples/logClient/logClient.ino +109 -109
  68. package/examples/logClient/platformio.ini +25 -25
  69. package/examples/logServer/logServer.ino +81 -81
  70. package/examples/logServer/platformio.ini +25 -25
  71. package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
  72. package/examples/meshCommandNode/meshCommandNode.ino +263 -0
  73. package/examples/meshCommandNode/platformio.ini +25 -0
  74. package/examples/mqttBridge/mqttBridge.ino +118 -118
  75. package/examples/mqttBridge/platformio.ini +26 -26
  76. package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
  77. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
  78. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
  79. package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
  80. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
  81. package/examples/mqttCommandBridge/platformio.ini +26 -0
  82. package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
  83. package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
  84. package/examples/mqttStatusBridge/platformio.ini +26 -0
  85. package/examples/mqttTopologyTest/README.md +467 -0
  86. package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
  87. package/examples/mqttTopologyTest/platformio.ini +26 -0
  88. package/examples/namedMesh/namedMesh.ino +97 -97
  89. package/examples/namedMesh/platformio.ini +25 -25
  90. package/examples/otaReceiver/otaReceiver.ino +79 -79
  91. package/examples/otaReceiver/platformio.ini +25 -25
  92. package/examples/otaSender/otaSender.ino +160 -151
  93. package/examples/otaSender/platformio.ini +25 -25
  94. package/examples/startHere/platformio.ini +25 -25
  95. package/examples/startHere/startHere.ino +159 -159
  96. package/examples/webServer/platformio.ini +27 -27
  97. package/examples/webServer/webServer.ino +89 -89
  98. package/keywords.txt +48 -48
  99. package/library.json +55 -34
  100. package/library.properties +10 -10
  101. package/package.json +86 -78
  102. package/src/AlteriomPainlessMesh.h +97 -97
  103. package/src/arduino/wifi.hpp +365 -365
  104. package/src/boost/asynctcp.hpp +279 -279
  105. package/src/painlessMesh.h +70 -70
  106. package/src/painlessMeshSTA.cpp +236 -236
  107. package/src/painlessMeshSTA.h +58 -58
  108. package/src/painlessTaskOptions.h +4 -4
  109. package/src/painlessmesh/base64.hpp +111 -111
  110. package/src/painlessmesh/buffer.hpp +229 -229
  111. package/src/painlessmesh/callback.hpp +91 -91
  112. package/src/painlessmesh/configuration.hpp +77 -77
  113. package/src/painlessmesh/connection.hpp +192 -192
  114. package/src/painlessmesh/layout.hpp +188 -188
  115. package/src/painlessmesh/logger.hpp +158 -158
  116. package/src/painlessmesh/memory.hpp +119 -119
  117. package/src/painlessmesh/mesh.hpp +761 -560
  118. package/src/painlessmesh/metrics.hpp +322 -322
  119. package/src/painlessmesh/ntp.hpp +263 -263
  120. package/src/painlessmesh/ota.hpp +582 -553
  121. package/src/painlessmesh/plugin.hpp +188 -188
  122. package/src/painlessmesh/protocol.hpp +813 -813
  123. package/src/painlessmesh/router.hpp +322 -322
  124. package/src/painlessmesh/tcp.hpp +71 -71
  125. package/src/painlessmesh/validation.hpp +238 -238
  126. package/src/plugin/performance.hpp +214 -214
  127. package/src/plugin/remote.hpp +64 -64
  128. package/src/scheduler.cpp +10 -10
  129. package/src/wifi.cpp +2 -2
@@ -1,410 +1,410 @@
1
- # Your First Mesh Network
2
-
3
- This tutorial builds on the [Quick Start Guide](quickstart.md) to create a more comprehensive mesh network with multiple types of nodes and practical functionality.
4
-
5
- ## Overview
6
-
7
- We'll build a mesh network with three types of nodes:
8
- 1. **Sensor Node** - Collects and broadcasts environmental data
9
- 2. **Controller Node** - Receives sensor data and controls devices
10
- 3. **Bridge Node** - Connects mesh to external networks (WiFi/Internet)
11
-
12
- ## Node 1: Sensor Node
13
-
14
- This node simulates environmental sensors and broadcasts data to the mesh.
15
-
16
- ```cpp
17
- #include "painlessMesh.h"
18
-
19
- #define MESH_PREFIX "MyMeshNetwork"
20
- #define MESH_PASSWORD "somethingSneaky"
21
- #define MESH_PORT 5555
22
-
23
- Scheduler userScheduler;
24
- painlessMesh mesh;
25
-
26
- // Sensor simulation
27
- float temperature = 22.5;
28
- float humidity = 65.0;
29
- uint32_t sensorId = 1001;
30
-
31
- // Task to send sensor data every 30 seconds
32
- Task taskSendSensor(30000, TASK_FOREVER, [](){
33
- // Simulate sensor readings with some variation
34
- temperature += random(-10, 10) / 10.0;
35
- humidity += random(-50, 50) / 10.0;
36
-
37
- // Keep values in reasonable ranges
38
- temperature = constrain(temperature, 15.0, 35.0);
39
- humidity = constrain(humidity, 30.0, 90.0);
40
-
41
- // Create JSON message
42
- String msg = "{";
43
- msg += "\"type\":\"sensor\",";
44
- msg += "\"nodeId\":" + String(mesh.getNodeId()) + ",";
45
- msg += "\"sensorId\":" + String(sensorId) + ",";
46
- msg += "\"temperature\":" + String(temperature, 1) + ",";
47
- msg += "\"humidity\":" + String(humidity, 1) + ",";
48
- msg += "\"timestamp\":" + String(mesh.getNodeTime());
49
- msg += "}";
50
-
51
- mesh.sendBroadcast(msg);
52
- Serial.printf("Sent sensor data: T=%.1f°C, H=%.1f%%\n", temperature, humidity);
53
- });
54
-
55
- void receivedCallback(uint32_t from, String &msg) {
56
- Serial.printf("Sensor Node: Received from %u: %s\n", from, msg.c_str());
57
-
58
- // Sensor nodes can respond to commands
59
- if (msg.indexOf("\"command\":\"read_sensor\"") > 0) {
60
- // Force immediate sensor reading
61
- taskSendSensor.forceNextIteration();
62
- Serial.println("Forced sensor reading requested");
63
- }
64
- }
65
-
66
- void newConnectionCallback(uint32_t nodeId) {
67
- Serial.printf("Sensor Node: New connection to %u\n", nodeId);
68
- }
69
-
70
- void changedConnectionCallback() {
71
- Serial.printf("Sensor Node: Changed connections. Nodes: %s\n",
72
- mesh.subConnectionJson().c_str());
73
- }
74
-
75
- void setup() {
76
- Serial.begin(115200);
77
- Serial.println("=== Sensor Node Starting ===");
78
-
79
- mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
80
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
81
- mesh.onReceive(&receivedCallback);
82
- mesh.onNewConnection(&newConnectionCallback);
83
- mesh.onChangedConnections(&changedConnectionCallback);
84
-
85
- userScheduler.addTask(taskSendSensor);
86
- taskSendSensor.enable();
87
-
88
- Serial.printf("Sensor Node initialized. Node ID: %u\n", mesh.getNodeId());
89
- }
90
-
91
- void loop() {
92
- mesh.update();
93
- }
94
- ```
95
-
96
- ## Node 2: Controller Node
97
-
98
- This node receives sensor data and can send commands to other nodes.
99
-
100
- ```cpp
101
- #include "painlessMesh.h"
102
-
103
- #define MESH_PREFIX "MyMeshNetwork"
104
- #define MESH_PASSWORD "somethingSneaky"
105
- #define MESH_PORT 5555
106
-
107
- Scheduler userScheduler;
108
- painlessMesh mesh;
109
-
110
- // Storage for sensor data
111
- struct SensorData {
112
- uint32_t nodeId;
113
- uint32_t sensorId;
114
- float temperature;
115
- float humidity;
116
- uint32_t timestamp;
117
- bool valid;
118
- };
119
-
120
- SensorData sensors[10]; // Store data from up to 10 sensors
121
- int sensorCount = 0;
122
-
123
- // Task to request sensor data every 60 seconds
124
- Task taskRequestData(60000, TASK_FOREVER, [](){
125
- String cmd = "{";
126
- cmd += "\"type\":\"command\",";
127
- cmd += "\"command\":\"read_sensor\",";
128
- cmd += "\"from\":" + String(mesh.getNodeId());
129
- cmd += "}";
130
-
131
- mesh.sendBroadcast(cmd);
132
- Serial.println("Requested sensor data from all nodes");
133
- });
134
-
135
- // Task to display collected data every 45 seconds
136
- Task taskDisplayData(45000, TASK_FOREVER, [](){
137
- Serial.println("=== Collected Sensor Data ===");
138
- for (int i = 0; i < sensorCount; i++) {
139
- if (sensors[i].valid) {
140
- Serial.printf("Node %u (Sensor %u): T=%.1f°C, H=%.1f%%, Age=%u seconds\n",
141
- sensors[i].nodeId, sensors[i].sensorId,
142
- sensors[i].temperature, sensors[i].humidity,
143
- (mesh.getNodeTime() - sensors[i].timestamp) / 1000000);
144
- }
145
- }
146
- Serial.println("============================");
147
- });
148
-
149
- void storeSensorData(uint32_t nodeId, uint32_t sensorId, float temp, float hum, uint32_t timestamp) {
150
- // Find existing entry or create new one
151
- int index = -1;
152
- for (int i = 0; i < sensorCount; i++) {
153
- if (sensors[i].nodeId == nodeId && sensors[i].sensorId == sensorId) {
154
- index = i;
155
- break;
156
- }
157
- }
158
-
159
- if (index == -1 && sensorCount < 10) {
160
- index = sensorCount++;
161
- }
162
-
163
- if (index != -1) {
164
- sensors[index].nodeId = nodeId;
165
- sensors[index].sensorId = sensorId;
166
- sensors[index].temperature = temp;
167
- sensors[index].humidity = hum;
168
- sensors[index].timestamp = timestamp;
169
- sensors[index].valid = true;
170
- }
171
- }
172
-
173
- void receivedCallback(uint32_t from, String &msg) {
174
- Serial.printf("Controller: Received from %u: %s\n", from, msg.c_str());
175
-
176
- // Parse sensor data
177
- if (msg.indexOf("\"type\":\"sensor\"") > 0) {
178
- // Simple JSON parsing (in production, use ArduinoJson library)
179
- int tempStart = msg.indexOf("\"temperature\":") + 14;
180
- int tempEnd = msg.indexOf(",", tempStart);
181
- float temperature = msg.substring(tempStart, tempEnd).toFloat();
182
-
183
- int humStart = msg.indexOf("\"humidity\":") + 11;
184
- int humEnd = msg.indexOf(",", humStart);
185
- float humidity = msg.substring(humStart, humEnd).toFloat();
186
-
187
- int sensorStart = msg.indexOf("\"sensorId\":") + 11;
188
- int sensorEnd = msg.indexOf(",", sensorStart);
189
- uint32_t sensorId = msg.substring(sensorStart, sensorEnd).toInt();
190
-
191
- int timeStart = msg.indexOf("\"timestamp\":") + 12;
192
- int timeEnd = msg.indexOf("}", timeStart);
193
- uint32_t timestamp = msg.substring(timeStart, timeEnd).toInt();
194
-
195
- storeSensorData(from, sensorId, temperature, humidity, timestamp);
196
-
197
- // Trigger actions based on sensor data
198
- if (temperature > 30.0) {
199
- Serial.println("WARNING: High temperature detected!");
200
- // Could send cooling command here
201
- }
202
- if (humidity > 80.0) {
203
- Serial.println("WARNING: High humidity detected!");
204
- // Could trigger ventilation here
205
- }
206
- }
207
- }
208
-
209
- void newConnectionCallback(uint32_t nodeId) {
210
- Serial.printf("Controller: New connection to %u\n", nodeId);
211
- }
212
-
213
- void changedConnectionCallback() {
214
- Serial.printf("Controller: Changed connections. Nodes: %s\n",
215
- mesh.subConnectionJson().c_str());
216
- }
217
-
218
- void setup() {
219
- Serial.begin(115200);
220
- Serial.println("=== Controller Node Starting ===");
221
-
222
- // Initialize sensor storage
223
- for (int i = 0; i < 10; i++) {
224
- sensors[i].valid = false;
225
- }
226
-
227
- mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
228
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
229
- mesh.onReceive(&receivedCallback);
230
- mesh.onNewConnection(&newConnectionCallback);
231
- mesh.onChangedConnections(&changedConnectionCallback);
232
-
233
- userScheduler.addTask(taskRequestData);
234
- userScheduler.addTask(taskDisplayData);
235
- taskRequestData.enable();
236
- taskDisplayData.enable();
237
-
238
- Serial.printf("Controller Node initialized. Node ID: %u\n", mesh.getNodeId());
239
- }
240
-
241
- void loop() {
242
- mesh.update();
243
- }
244
- ```
245
-
246
- ## Node 3: Bridge Node
247
-
248
- This node connects the mesh to WiFi/Internet for external connectivity.
249
-
250
- ```cpp
251
- #include "painlessMesh.h"
252
- #include <WiFi.h> // Use <ESP8266WiFi.h> for ESP8266
253
-
254
- #define MESH_PREFIX "MyMeshNetwork"
255
- #define MESH_PASSWORD "somethingSneaky"
256
- #define MESH_PORT 5555
257
-
258
- // External WiFi credentials
259
- #define STATION_SSID "YourHomeWiFi"
260
- #define STATION_PASSWORD "YourWiFiPassword"
261
-
262
- Scheduler userScheduler;
263
- painlessMesh mesh;
264
-
265
- // Task to report bridge status
266
- Task taskBridgeStatus(30000, TASK_FOREVER, [](){
267
- String status = "{";
268
- status += "\"type\":\"bridge_status\",";
269
- status += "\"nodeId\":" + String(mesh.getNodeId()) + ",";
270
- status += "\"wifi_connected\":" + String(WiFi.status() == WL_CONNECTED ? "true" : "false") + ",";
271
- status += "\"wifi_rssi\":" + String(WiFi.RSSI()) + ",";
272
- status += "\"mesh_connections\":" + String(mesh.getNodeList().size()) + ",";
273
- status += "\"timestamp\":" + String(mesh.getNodeTime());
274
- status += "}";
275
-
276
- mesh.sendBroadcast(status);
277
- Serial.printf("Bridge Status: WiFi=%s, RSSI=%d, Mesh Nodes=%d\n",
278
- WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected",
279
- WiFi.RSSI(), mesh.getNodeList().size());
280
- });
281
-
282
- void receivedCallback(uint32_t from, String &msg) {
283
- Serial.printf("Bridge: Received from %u: %s\n", from, msg.c_str());
284
-
285
- // Forward sensor data to external server (example)
286
- if (msg.indexOf("\"type\":\"sensor\"") > 0 && WiFi.status() == WL_CONNECTED) {
287
- // Here you could forward to HTTP/MQTT/etc
288
- Serial.println("Would forward sensor data to external server");
289
- }
290
- }
291
-
292
- void newConnectionCallback(uint32_t nodeId) {
293
- Serial.printf("Bridge: New mesh connection to %u\n", nodeId);
294
- }
295
-
296
- void changedConnectionCallback() {
297
- Serial.printf("Bridge: Mesh topology changed. Nodes: %s\n",
298
- mesh.subConnectionJson().c_str());
299
- }
300
-
301
- void setup() {
302
- Serial.begin(115200);
303
- Serial.println("=== Bridge Node Starting ===");
304
-
305
- // Initialize mesh
306
- mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
307
- mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
308
- mesh.onReceive(&receivedCallback);
309
- mesh.onNewConnection(&newConnectionCallback);
310
- mesh.onChangedConnections(&changedConnectionCallback);
311
-
312
- // Connect to external WiFi
313
- WiFi.begin(STATION_SSID, STATION_PASSWORD);
314
- Serial.printf("Connecting to WiFi: %s", STATION_SSID);
315
-
316
- while (WiFi.status() != WL_CONNECTED) {
317
- delay(500);
318
- Serial.print(".");
319
- }
320
- Serial.println();
321
- Serial.printf("WiFi connected! IP: %s\n", WiFi.localIP().toString().c_str());
322
-
323
- userScheduler.addTask(taskBridgeStatus);
324
- taskBridgeStatus.enable();
325
-
326
- Serial.printf("Bridge Node initialized. Node ID: %u\n", mesh.getNodeId());
327
- }
328
-
329
- void loop() {
330
- mesh.update();
331
- }
332
- ```
333
-
334
- ## Deployment Steps
335
-
336
- 1. **Upload Sensor Node code** to your first ESP32/ESP8266
337
- 2. **Upload Controller Node code** to your second device
338
- 3. **Upload Bridge Node code** to your third device (update WiFi credentials first!)
339
- 4. **Power up all devices** and open Serial Monitors to watch them connect
340
- 5. **Observe the mesh in action**:
341
- - Sensor nodes broadcast environmental data
342
- - Controller receives and processes sensor data
343
- - Bridge provides external connectivity and status updates
344
-
345
- ## What You'll See
346
-
347
- ### Sensor Node Output
348
- ```
349
- === Sensor Node Starting ===
350
- Sensor Node initialized. Node ID: 123456789
351
- Sensor Node: New connection to 987654321
352
- Sent sensor data: T=23.2°C, H=67.4%
353
- ```
354
-
355
- ### Controller Node Output
356
- ```
357
- === Controller Node Starting ===
358
- Controller Node initialized. Node ID: 987654321
359
- Requested sensor data from all nodes
360
- Controller: Received from 123456789: {"type":"sensor",...}
361
- === Collected Sensor Data ===
362
- Node 123456789 (Sensor 1001): T=23.2°C, H=67.4%, Age=5 seconds
363
- ```
364
-
365
- ### Bridge Node Output
366
- ```
367
- === Bridge Node Starting ===
368
- Connecting to WiFi: YourHomeWiFi....
369
- WiFi connected! IP: 192.168.1.100
370
- Bridge Node initialized. Node ID: 555444333
371
- Bridge Status: WiFi=Connected, RSSI=-45, Mesh Nodes=2
372
- ```
373
-
374
- ## Key Features Demonstrated
375
-
376
- - **Automatic Discovery**: Nodes find each other automatically
377
- - **Message Broadcasting**: Sensor data reaches all interested nodes
378
- - **JSON Communication**: Structured data exchange
379
- - **Command System**: Controller can request data from sensors
380
- - **External Connectivity**: Bridge connects mesh to Internet
381
- - **Self-Healing**: Network continues working if nodes disconnect
382
-
383
- ## Extending Your Mesh
384
-
385
- ### Add More Sensors
386
- - Temperature/humidity sensors (DHT22)
387
- - Motion detectors (PIR)
388
- - Light sensors (photoresistor)
389
- - Soil moisture sensors
390
-
391
- ### Add Actuators
392
- - LED strips for notifications
393
- - Servo motors for mechanical control
394
- - Relays for switching devices
395
- - Buzzers for alerts
396
-
397
- ### External Integrations
398
- - MQTT broker connectivity
399
- - HTTP REST API calls
400
- - Home Assistant integration
401
- - Cloud database logging
402
-
403
- ## Next Steps
404
-
405
- - Explore [Custom Packages](../tutorials/custom-packages.md) for type-safe messaging
406
- - Learn about [Alteriom Extensions](../alteriom/overview.md) for pre-built sensor packages
407
- - Dive into [Advanced Topics](../advanced/performance.md) for optimization
408
- - Check out [Troubleshooting](../troubleshooting/common-issues.md) if you encounter issues
409
-
1
+ # Your First Mesh Network
2
+
3
+ This tutorial builds on the [Quick Start Guide](quickstart.md) to create a more comprehensive mesh network with multiple types of nodes and practical functionality.
4
+
5
+ ## Overview
6
+
7
+ We'll build a mesh network with three types of nodes:
8
+ 1. **Sensor Node** - Collects and broadcasts environmental data
9
+ 2. **Controller Node** - Receives sensor data and controls devices
10
+ 3. **Bridge Node** - Connects mesh to external networks (WiFi/Internet)
11
+
12
+ ## Node 1: Sensor Node
13
+
14
+ This node simulates environmental sensors and broadcasts data to the mesh.
15
+
16
+ ```cpp
17
+ #include "painlessMesh.h"
18
+
19
+ #define MESH_PREFIX "MyMeshNetwork"
20
+ #define MESH_PASSWORD "somethingSneaky"
21
+ #define MESH_PORT 5555
22
+
23
+ Scheduler userScheduler;
24
+ painlessMesh mesh;
25
+
26
+ // Sensor simulation
27
+ float temperature = 22.5;
28
+ float humidity = 65.0;
29
+ uint32_t sensorId = 1001;
30
+
31
+ // Task to send sensor data every 30 seconds
32
+ Task taskSendSensor(30000, TASK_FOREVER, [](){
33
+ // Simulate sensor readings with some variation
34
+ temperature += random(-10, 10) / 10.0;
35
+ humidity += random(-50, 50) / 10.0;
36
+
37
+ // Keep values in reasonable ranges
38
+ temperature = constrain(temperature, 15.0, 35.0);
39
+ humidity = constrain(humidity, 30.0, 90.0);
40
+
41
+ // Create JSON message
42
+ String msg = "{";
43
+ msg += "\"type\":\"sensor\",";
44
+ msg += "\"nodeId\":" + String(mesh.getNodeId()) + ",";
45
+ msg += "\"sensorId\":" + String(sensorId) + ",";
46
+ msg += "\"temperature\":" + String(temperature, 1) + ",";
47
+ msg += "\"humidity\":" + String(humidity, 1) + ",";
48
+ msg += "\"timestamp\":" + String(mesh.getNodeTime());
49
+ msg += "}";
50
+
51
+ mesh.sendBroadcast(msg);
52
+ Serial.printf("Sent sensor data: T=%.1f°C, H=%.1f%%\n", temperature, humidity);
53
+ });
54
+
55
+ void receivedCallback(uint32_t from, String &msg) {
56
+ Serial.printf("Sensor Node: Received from %u: %s\n", from, msg.c_str());
57
+
58
+ // Sensor nodes can respond to commands
59
+ if (msg.indexOf("\"command\":\"read_sensor\"") > 0) {
60
+ // Force immediate sensor reading
61
+ taskSendSensor.forceNextIteration();
62
+ Serial.println("Forced sensor reading requested");
63
+ }
64
+ }
65
+
66
+ void newConnectionCallback(uint32_t nodeId) {
67
+ Serial.printf("Sensor Node: New connection to %u\n", nodeId);
68
+ }
69
+
70
+ void changedConnectionCallback() {
71
+ Serial.printf("Sensor Node: Changed connections. Nodes: %s\n",
72
+ mesh.subConnectionJson().c_str());
73
+ }
74
+
75
+ void setup() {
76
+ Serial.begin(115200);
77
+ Serial.println("=== Sensor Node Starting ===");
78
+
79
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
80
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
81
+ mesh.onReceive(&receivedCallback);
82
+ mesh.onNewConnection(&newConnectionCallback);
83
+ mesh.onChangedConnections(&changedConnectionCallback);
84
+
85
+ userScheduler.addTask(taskSendSensor);
86
+ taskSendSensor.enable();
87
+
88
+ Serial.printf("Sensor Node initialized. Node ID: %u\n", mesh.getNodeId());
89
+ }
90
+
91
+ void loop() {
92
+ mesh.update();
93
+ }
94
+ ```
95
+
96
+ ## Node 2: Controller Node
97
+
98
+ This node receives sensor data and can send commands to other nodes.
99
+
100
+ ```cpp
101
+ #include "painlessMesh.h"
102
+
103
+ #define MESH_PREFIX "MyMeshNetwork"
104
+ #define MESH_PASSWORD "somethingSneaky"
105
+ #define MESH_PORT 5555
106
+
107
+ Scheduler userScheduler;
108
+ painlessMesh mesh;
109
+
110
+ // Storage for sensor data
111
+ struct SensorData {
112
+ uint32_t nodeId;
113
+ uint32_t sensorId;
114
+ float temperature;
115
+ float humidity;
116
+ uint32_t timestamp;
117
+ bool valid;
118
+ };
119
+
120
+ SensorData sensors[10]; // Store data from up to 10 sensors
121
+ int sensorCount = 0;
122
+
123
+ // Task to request sensor data every 60 seconds
124
+ Task taskRequestData(60000, TASK_FOREVER, [](){
125
+ String cmd = "{";
126
+ cmd += "\"type\":\"command\",";
127
+ cmd += "\"command\":\"read_sensor\",";
128
+ cmd += "\"from\":" + String(mesh.getNodeId());
129
+ cmd += "}";
130
+
131
+ mesh.sendBroadcast(cmd);
132
+ Serial.println("Requested sensor data from all nodes");
133
+ });
134
+
135
+ // Task to display collected data every 45 seconds
136
+ Task taskDisplayData(45000, TASK_FOREVER, [](){
137
+ Serial.println("=== Collected Sensor Data ===");
138
+ for (int i = 0; i < sensorCount; i++) {
139
+ if (sensors[i].valid) {
140
+ Serial.printf("Node %u (Sensor %u): T=%.1f°C, H=%.1f%%, Age=%u seconds\n",
141
+ sensors[i].nodeId, sensors[i].sensorId,
142
+ sensors[i].temperature, sensors[i].humidity,
143
+ (mesh.getNodeTime() - sensors[i].timestamp) / 1000000);
144
+ }
145
+ }
146
+ Serial.println("============================");
147
+ });
148
+
149
+ void storeSensorData(uint32_t nodeId, uint32_t sensorId, float temp, float hum, uint32_t timestamp) {
150
+ // Find existing entry or create new one
151
+ int index = -1;
152
+ for (int i = 0; i < sensorCount; i++) {
153
+ if (sensors[i].nodeId == nodeId && sensors[i].sensorId == sensorId) {
154
+ index = i;
155
+ break;
156
+ }
157
+ }
158
+
159
+ if (index == -1 && sensorCount < 10) {
160
+ index = sensorCount++;
161
+ }
162
+
163
+ if (index != -1) {
164
+ sensors[index].nodeId = nodeId;
165
+ sensors[index].sensorId = sensorId;
166
+ sensors[index].temperature = temp;
167
+ sensors[index].humidity = hum;
168
+ sensors[index].timestamp = timestamp;
169
+ sensors[index].valid = true;
170
+ }
171
+ }
172
+
173
+ void receivedCallback(uint32_t from, String &msg) {
174
+ Serial.printf("Controller: Received from %u: %s\n", from, msg.c_str());
175
+
176
+ // Parse sensor data
177
+ if (msg.indexOf("\"type\":\"sensor\"") > 0) {
178
+ // Simple JSON parsing (in production, use ArduinoJson library)
179
+ int tempStart = msg.indexOf("\"temperature\":") + 14;
180
+ int tempEnd = msg.indexOf(",", tempStart);
181
+ float temperature = msg.substring(tempStart, tempEnd).toFloat();
182
+
183
+ int humStart = msg.indexOf("\"humidity\":") + 11;
184
+ int humEnd = msg.indexOf(",", humStart);
185
+ float humidity = msg.substring(humStart, humEnd).toFloat();
186
+
187
+ int sensorStart = msg.indexOf("\"sensorId\":") + 11;
188
+ int sensorEnd = msg.indexOf(",", sensorStart);
189
+ uint32_t sensorId = msg.substring(sensorStart, sensorEnd).toInt();
190
+
191
+ int timeStart = msg.indexOf("\"timestamp\":") + 12;
192
+ int timeEnd = msg.indexOf("}", timeStart);
193
+ uint32_t timestamp = msg.substring(timeStart, timeEnd).toInt();
194
+
195
+ storeSensorData(from, sensorId, temperature, humidity, timestamp);
196
+
197
+ // Trigger actions based on sensor data
198
+ if (temperature > 30.0) {
199
+ Serial.println("WARNING: High temperature detected!");
200
+ // Could send cooling command here
201
+ }
202
+ if (humidity > 80.0) {
203
+ Serial.println("WARNING: High humidity detected!");
204
+ // Could trigger ventilation here
205
+ }
206
+ }
207
+ }
208
+
209
+ void newConnectionCallback(uint32_t nodeId) {
210
+ Serial.printf("Controller: New connection to %u\n", nodeId);
211
+ }
212
+
213
+ void changedConnectionCallback() {
214
+ Serial.printf("Controller: Changed connections. Nodes: %s\n",
215
+ mesh.subConnectionJson().c_str());
216
+ }
217
+
218
+ void setup() {
219
+ Serial.begin(115200);
220
+ Serial.println("=== Controller Node Starting ===");
221
+
222
+ // Initialize sensor storage
223
+ for (int i = 0; i < 10; i++) {
224
+ sensors[i].valid = false;
225
+ }
226
+
227
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
228
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
229
+ mesh.onReceive(&receivedCallback);
230
+ mesh.onNewConnection(&newConnectionCallback);
231
+ mesh.onChangedConnections(&changedConnectionCallback);
232
+
233
+ userScheduler.addTask(taskRequestData);
234
+ userScheduler.addTask(taskDisplayData);
235
+ taskRequestData.enable();
236
+ taskDisplayData.enable();
237
+
238
+ Serial.printf("Controller Node initialized. Node ID: %u\n", mesh.getNodeId());
239
+ }
240
+
241
+ void loop() {
242
+ mesh.update();
243
+ }
244
+ ```
245
+
246
+ ## Node 3: Bridge Node
247
+
248
+ This node connects the mesh to WiFi/Internet for external connectivity.
249
+
250
+ ```cpp
251
+ #include "painlessMesh.h"
252
+ #include <WiFi.h> // Use <ESP8266WiFi.h> for ESP8266
253
+
254
+ #define MESH_PREFIX "MyMeshNetwork"
255
+ #define MESH_PASSWORD "somethingSneaky"
256
+ #define MESH_PORT 5555
257
+
258
+ // External WiFi credentials
259
+ #define STATION_SSID "YourHomeWiFi"
260
+ #define STATION_PASSWORD "YourWiFiPassword"
261
+
262
+ Scheduler userScheduler;
263
+ painlessMesh mesh;
264
+
265
+ // Task to report bridge status
266
+ Task taskBridgeStatus(30000, TASK_FOREVER, [](){
267
+ String status = "{";
268
+ status += "\"type\":\"bridge_status\",";
269
+ status += "\"nodeId\":" + String(mesh.getNodeId()) + ",";
270
+ status += "\"wifi_connected\":" + String(WiFi.status() == WL_CONNECTED ? "true" : "false") + ",";
271
+ status += "\"wifi_rssi\":" + String(WiFi.RSSI()) + ",";
272
+ status += "\"mesh_connections\":" + String(mesh.getNodeList().size()) + ",";
273
+ status += "\"timestamp\":" + String(mesh.getNodeTime());
274
+ status += "}";
275
+
276
+ mesh.sendBroadcast(status);
277
+ Serial.printf("Bridge Status: WiFi=%s, RSSI=%d, Mesh Nodes=%d\n",
278
+ WiFi.status() == WL_CONNECTED ? "Connected" : "Disconnected",
279
+ WiFi.RSSI(), mesh.getNodeList().size());
280
+ });
281
+
282
+ void receivedCallback(uint32_t from, String &msg) {
283
+ Serial.printf("Bridge: Received from %u: %s\n", from, msg.c_str());
284
+
285
+ // Forward sensor data to external server (example)
286
+ if (msg.indexOf("\"type\":\"sensor\"") > 0 && WiFi.status() == WL_CONNECTED) {
287
+ // Here you could forward to HTTP/MQTT/etc
288
+ Serial.println("Would forward sensor data to external server");
289
+ }
290
+ }
291
+
292
+ void newConnectionCallback(uint32_t nodeId) {
293
+ Serial.printf("Bridge: New mesh connection to %u\n", nodeId);
294
+ }
295
+
296
+ void changedConnectionCallback() {
297
+ Serial.printf("Bridge: Mesh topology changed. Nodes: %s\n",
298
+ mesh.subConnectionJson().c_str());
299
+ }
300
+
301
+ void setup() {
302
+ Serial.begin(115200);
303
+ Serial.println("=== Bridge Node Starting ===");
304
+
305
+ // Initialize mesh
306
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
307
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
308
+ mesh.onReceive(&receivedCallback);
309
+ mesh.onNewConnection(&newConnectionCallback);
310
+ mesh.onChangedConnections(&changedConnectionCallback);
311
+
312
+ // Connect to external WiFi
313
+ WiFi.begin(STATION_SSID, STATION_PASSWORD);
314
+ Serial.printf("Connecting to WiFi: %s", STATION_SSID);
315
+
316
+ while (WiFi.status() != WL_CONNECTED) {
317
+ delay(500);
318
+ Serial.print(".");
319
+ }
320
+ Serial.println();
321
+ Serial.printf("WiFi connected! IP: %s\n", WiFi.localIP().toString().c_str());
322
+
323
+ userScheduler.addTask(taskBridgeStatus);
324
+ taskBridgeStatus.enable();
325
+
326
+ Serial.printf("Bridge Node initialized. Node ID: %u\n", mesh.getNodeId());
327
+ }
328
+
329
+ void loop() {
330
+ mesh.update();
331
+ }
332
+ ```
333
+
334
+ ## Deployment Steps
335
+
336
+ 1. **Upload Sensor Node code** to your first ESP32/ESP8266
337
+ 2. **Upload Controller Node code** to your second device
338
+ 3. **Upload Bridge Node code** to your third device (update WiFi credentials first!)
339
+ 4. **Power up all devices** and open Serial Monitors to watch them connect
340
+ 5. **Observe the mesh in action**:
341
+ - Sensor nodes broadcast environmental data
342
+ - Controller receives and processes sensor data
343
+ - Bridge provides external connectivity and status updates
344
+
345
+ ## What You'll See
346
+
347
+ ### Sensor Node Output
348
+ ```
349
+ === Sensor Node Starting ===
350
+ Sensor Node initialized. Node ID: 123456789
351
+ Sensor Node: New connection to 987654321
352
+ Sent sensor data: T=23.2°C, H=67.4%
353
+ ```
354
+
355
+ ### Controller Node Output
356
+ ```
357
+ === Controller Node Starting ===
358
+ Controller Node initialized. Node ID: 987654321
359
+ Requested sensor data from all nodes
360
+ Controller: Received from 123456789: {"type":"sensor",...}
361
+ === Collected Sensor Data ===
362
+ Node 123456789 (Sensor 1001): T=23.2°C, H=67.4%, Age=5 seconds
363
+ ```
364
+
365
+ ### Bridge Node Output
366
+ ```
367
+ === Bridge Node Starting ===
368
+ Connecting to WiFi: YourHomeWiFi....
369
+ WiFi connected! IP: 192.168.1.100
370
+ Bridge Node initialized. Node ID: 555444333
371
+ Bridge Status: WiFi=Connected, RSSI=-45, Mesh Nodes=2
372
+ ```
373
+
374
+ ## Key Features Demonstrated
375
+
376
+ - **Automatic Discovery**: Nodes find each other automatically
377
+ - **Message Broadcasting**: Sensor data reaches all interested nodes
378
+ - **JSON Communication**: Structured data exchange
379
+ - **Command System**: Controller can request data from sensors
380
+ - **External Connectivity**: Bridge connects mesh to Internet
381
+ - **Self-Healing**: Network continues working if nodes disconnect
382
+
383
+ ## Extending Your Mesh
384
+
385
+ ### Add More Sensors
386
+ - Temperature/humidity sensors (DHT22)
387
+ - Motion detectors (PIR)
388
+ - Light sensors (photoresistor)
389
+ - Soil moisture sensors
390
+
391
+ ### Add Actuators
392
+ - LED strips for notifications
393
+ - Servo motors for mechanical control
394
+ - Relays for switching devices
395
+ - Buzzers for alerts
396
+
397
+ ### External Integrations
398
+ - MQTT broker connectivity
399
+ - HTTP REST API calls
400
+ - Home Assistant integration
401
+ - Cloud database logging
402
+
403
+ ## Next Steps
404
+
405
+ - Explore [Custom Packages](../tutorials/custom-packages.md) for type-safe messaging
406
+ - Learn about [Alteriom Extensions](../alteriom/overview.md) for pre-built sensor packages
407
+ - Dive into [Advanced Topics](../advanced/performance.md) for optimization
408
+ - Check out [Troubleshooting](../troubleshooting/common-issues.md) if you encounter issues
409
+
410
410
  Congratulations! You now have a working multi-node mesh network with real-world functionality.