@alteriom/painlessmesh 1.8.2 → 1.8.4

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 (51) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +74 -11
  3. package/RELEASE_GUIDE.md +57 -16
  4. package/docs/ARDUINO_LIBRARY_MANAGER_SUBMISSION.md +331 -0
  5. package/docs/features/DIAGNOSTICS_API.md +534 -0
  6. package/docs/getting-started/arduino-manual-install.md +313 -0
  7. package/docs/implementation/BRIDGE_ARCHITECTURE_IMPLEMENTATION.md +340 -0
  8. package/docs/implementation/BRIDGE_HEALTH_MONITORING_IMPLEMENTATION.md +213 -0
  9. package/docs/implementation/BRIDGE_STATUS_FEATURE.md +635 -0
  10. package/docs/implementation/DIAGNOSTICS_API_IMPLEMENTATION.md +232 -0
  11. package/docs/implementation/IMPLEMENTATION_COMPLETE.md +228 -0
  12. package/docs/implementation/IMPLEMENTATION_NTP_TIME_SYNC.md +325 -0
  13. package/docs/implementation/IMPLEMENTATION_SUMMARY.md +316 -0
  14. package/docs/implementation/MESSAGE_QUEUE_IMPLEMENTATION.md +405 -0
  15. package/docs/implementation/MULTI_BRIDGE_IMPLEMENTATION.md +520 -0
  16. package/docs/implementation/NTP_TIME_SYNC_FEATURE.md +392 -0
  17. package/docs/internal/CUSTOM_AGENT_ANALYSIS.md +391 -0
  18. package/docs/internal/ISSUE_65_VERIFICATION.md +947 -0
  19. package/docs/internal/ISSUE_66_CLOSURE.md +249 -0
  20. package/docs/internal/ISSUE_66_STATUS.md +316 -0
  21. package/docs/internal/PR_SUMMARY.md +315 -0
  22. package/docs/internal/REVIEW_SUMMARY.md +332 -0
  23. package/docs/releases/PUBLISH_v1.8.0_INSTRUCTIONS.md +163 -0
  24. package/docs/releases/QUICK_START_RELEASES.md +113 -0
  25. package/docs/releases/RELEASE_CHECKLIST_v1.8.0.md +331 -0
  26. package/docs/releases/RELEASE_CHECKLIST_v1.8.2.md +309 -0
  27. package/docs/releases/RELEASE_NOTES_v1.8.0.md +685 -0
  28. package/docs/releases/RELEASE_NOTES_v1.8.1.md +221 -0
  29. package/docs/releases/RELEASE_NOTES_v1.8.2.md +421 -0
  30. package/docs/releases/RELEASE_NOTES_v1.8.3.md +292 -0
  31. package/docs/releases/RELEASE_NOTES_v1.8.4.md +277 -0
  32. package/docs/troubleshooting/ARDUINO_IDE_VERSION_FIX_SUMMARY.md +229 -0
  33. package/docs/troubleshooting/ARDUINO_LIBRARY_NAME_FIX.md +197 -0
  34. package/docs/troubleshooting/NPM_PUBLISHING_ISSUE_SUMMARY.md +110 -0
  35. package/docs/troubleshooting/station-reconnection-issues.md +172 -0
  36. package/examples/bridge_failover/README.md +17 -1
  37. package/examples/priority/README.md +274 -0
  38. package/examples/priority/priority_basic_example.ino +115 -0
  39. package/examples/priority/priority_with_queue.ino +249 -0
  40. package/examples/routing_demo/README.md +172 -0
  41. package/examples/routing_demo/routing_demo.ino +102 -0
  42. package/library.json +1 -1
  43. package/library.properties +3 -3
  44. package/package.json +1 -1
  45. package/src/arduino/wifi.hpp +62 -16
  46. package/src/painlessMesh.h +15 -0
  47. package/src/painlessMeshSTA.cpp +7 -1
  48. package/src/painlessmesh/buffer.hpp +218 -37
  49. package/src/painlessmesh/connection.hpp +21 -1
  50. package/src/painlessmesh/mesh.hpp +253 -19
  51. package/src/painlessmesh/router.hpp +31 -0
@@ -0,0 +1,392 @@
1
+ # NTP Time Synchronization Feature
2
+
3
+ ## Overview
4
+
5
+ The NTP Time Synchronization feature enables bridge nodes with Internet connectivity to distribute authoritative NTP time to all nodes in the mesh network. This eliminates the need for each node to query NTP servers individually, saving bandwidth, power, and reducing network congestion.
6
+
7
+ ## Type ID: 614 (TIME_SYNC_NTP)
8
+
9
+ ## Architecture
10
+
11
+ ```
12
+ Internet
13
+ |
14
+ | NTP Query
15
+ v
16
+ Bridge Node ---------> Regular Node 1
17
+ | |
18
+ | Broadcast | Update Time
19
+ | Type 614 | Sync RTC
20
+ | |
21
+ +----------------> Regular Node 2
22
+ | |
23
+ +----------------> Regular Node 3
24
+ |
25
+ v
26
+ Application Code
27
+ ```
28
+
29
+ ## Package Structure
30
+
31
+ ### NTPTimeSyncPackage (Type 614)
32
+
33
+ ```cpp
34
+ class NTPTimeSyncPackage : public painlessmesh::plugin::BroadcastPackage {
35
+ public:
36
+ uint32_t ntpTime = 0; // Unix timestamp from NTP server (seconds)
37
+ uint16_t accuracy = 0; // Milliseconds uncertainty/precision
38
+ TSTRING source = ""; // NTP server source (e.g., "pool.ntp.org")
39
+ uint32_t timestamp = 0; // Collection timestamp (millis())
40
+ uint16_t messageType = 614; // MQTT Schema message_type
41
+ };
42
+ ```
43
+
44
+ ### JSON Format
45
+
46
+ ```json
47
+ {
48
+ "type": 614,
49
+ "from": 123456,
50
+ "routing": 2,
51
+ "ntpTime": 1699564800,
52
+ "accuracy": 50,
53
+ "source": "pool.ntp.org",
54
+ "timestamp": 12345678,
55
+ "message_type": 614
56
+ }
57
+ ```
58
+
59
+ ## Implementation Guide
60
+
61
+ ### Bridge Node (Sender)
62
+
63
+ The bridge node queries NTP and broadcasts time to the mesh:
64
+
65
+ ```cpp
66
+ #include "painlessMesh.h"
67
+ #include "examples/alteriom/alteriom_sensor_package.hpp"
68
+
69
+ using namespace alteriom;
70
+
71
+ painlessMesh mesh;
72
+
73
+ // Periodic task to broadcast NTP time
74
+ Task taskBroadcastNTP(60000, TASK_FOREVER, [](){
75
+ auto pkg = NTPTimeSyncPackage();
76
+ pkg.from = mesh.getNodeId();
77
+ pkg.ntpTime = mesh.getNodeTime() / 1000000; // Convert to seconds
78
+ pkg.accuracy = 50; // 50ms uncertainty
79
+ pkg.source = "pool.ntp.org";
80
+ pkg.timestamp = millis();
81
+
82
+ mesh.sendBroadcast(pkg.toJson());
83
+ });
84
+
85
+ void setup() {
86
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
87
+ mesh.stationManual(ROUTER_SSID, ROUTER_PASSWORD); // Bridge mode
88
+
89
+ userScheduler.addTask(taskBroadcastNTP);
90
+ taskBroadcastNTP.enable();
91
+ }
92
+ ```
93
+
94
+ ### Regular Node (Receiver)
95
+
96
+ Regular nodes receive and apply NTP time:
97
+
98
+ ```cpp
99
+ #include "painlessMesh.h"
100
+ #include "examples/alteriom/alteriom_sensor_package.hpp"
101
+
102
+ using namespace alteriom;
103
+
104
+ void receivedCallback(uint32_t from, String& msg) {
105
+ DynamicJsonDocument doc(1024);
106
+ deserializeJson(doc, msg);
107
+ JsonObject obj = doc.as<JsonObject>();
108
+
109
+ if (obj["type"] == 614) {
110
+ auto pkg = NTPTimeSyncPackage(obj);
111
+
112
+ // Verify sender is a bridge (optional but recommended)
113
+ if (isBridgeNode(from)) {
114
+ // Apply time synchronization
115
+ mesh.setTimeFromNTP(pkg.ntpTime);
116
+
117
+ // Optional: Sync RTC module if available
118
+ #ifdef HAS_RTC
119
+ rtc.setTime(pkg.ntpTime);
120
+ #endif
121
+
122
+ Serial.printf("Time synced from %s (±%ums)\n",
123
+ pkg.source.c_str(), pkg.accuracy);
124
+ }
125
+ }
126
+ }
127
+
128
+ void setup() {
129
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
130
+ mesh.onReceive(&receivedCallback);
131
+ }
132
+ ```
133
+
134
+ ## Field Details
135
+
136
+ ### ntpTime (uint32_t)
137
+ - Unix timestamp in seconds since epoch (1970-01-01 00:00:00 UTC)
138
+ - Range: 0 to 4,294,967,295 (year 2106)
139
+ - Example: 1699564800 = 2023-11-09 20:00:00 UTC
140
+
141
+ ### accuracy (uint16_t)
142
+ - Time uncertainty in milliseconds
143
+ - Range: 0 to 65,535ms (0 to 65.5 seconds)
144
+ - Typical values:
145
+ - 10-50ms: Good NTP connection
146
+ - 50-200ms: Average NTP connection
147
+ - 200-1000ms: Poor/distant NTP server
148
+ - 1000-5000ms: Very poor connection or local time source
149
+
150
+ ### source (TSTRING)
151
+ - NTP server hostname or IP address
152
+ - Examples:
153
+ - "pool.ntp.org"
154
+ - "time.google.com"
155
+ - "time.nist.gov"
156
+ - "192.168.1.1" (local router)
157
+ - Empty string if no NTP available
158
+
159
+ ### timestamp (uint32_t)
160
+ - When the time was collected/broadcast (millis())
161
+ - Used for calculating staleness of time data
162
+ - Wraps around every 49.7 days
163
+
164
+ ## Best Practices
165
+
166
+ ### For Bridge Nodes
167
+
168
+ 1. **Update Frequency**: Broadcast every 30-60 seconds
169
+ - Too frequent: Wastes bandwidth
170
+ - Too infrequent: Nodes may drift
171
+
172
+ 2. **NTP Query Strategy**: Query NTP less frequently than broadcast
173
+ - Query NTP every 5-15 minutes
174
+ - Cache and reuse recent NTP time
175
+ - Update accuracy field based on staleness
176
+
177
+ 3. **Error Handling**: Handle NTP failures gracefully
178
+ - Stop broadcasting if NTP unavailable for >15 minutes
179
+ - Or increase accuracy value to indicate uncertainty
180
+
181
+ ### For Regular Nodes
182
+
183
+ 1. **Validation**: Verify sender is bridge before applying time
184
+ ```cpp
185
+ bool isBridgeNode(uint32_t nodeId) {
186
+ // Check if node is in bridge list
187
+ // Or check if node has Internet connectivity flag
188
+ }
189
+ ```
190
+
191
+ 2. **Staleness Check**: Don't apply very old time data
192
+ ```cpp
193
+ uint32_t age = millis() - pkg.timestamp;
194
+ if (age > 120000) { // Older than 2 minutes
195
+ Serial.println("Time data too old, ignoring");
196
+ return;
197
+ }
198
+ ```
199
+
200
+ 3. **Accuracy Threshold**: Only apply if accuracy is acceptable
201
+ ```cpp
202
+ if (pkg.accuracy > 1000) { // Worse than 1 second
203
+ Serial.println("Time accuracy too poor, ignoring");
204
+ return;
205
+ }
206
+ ```
207
+
208
+ 4. **RTC Integration**: Sync RTC for offline operation
209
+ ```cpp
210
+ if (rtcEnabled && pkg.accuracy < 500) {
211
+ rtc.setTime(pkg.ntpTime);
212
+ Serial.println("RTC synced with NTP time");
213
+ }
214
+ ```
215
+
216
+ ## Benefits
217
+
218
+ ### Network Efficiency
219
+ - **Reduced NTP queries**: Only bridge queries NTP, not every node
220
+ - **Lower bandwidth**: One NTP query serves entire mesh
221
+ - **Less congestion**: Fewer nodes competing for Internet access
222
+
223
+ ### Power Savings
224
+ - **No WiFi switching**: Nodes stay on mesh, don't need router connection
225
+ - **Lower power**: No NTP protocol overhead per node
226
+ - **Longer battery life**: Especially important for sensor nodes
227
+
228
+ ### Improved Accuracy
229
+ - **Authoritative source**: Bridge has better NTP access than distant nodes
230
+ - **Lower latency**: Mesh broadcast faster than Internet NTP
231
+ - **Better synchronization**: All nodes sync to same time source
232
+
233
+ ### Offline Operation
234
+ - **RTC sync**: Nodes can sync RTC modules for offline timekeeping
235
+ - **Time continuity**: Time available even when bridge loses Internet
236
+ - **Graceful degradation**: Mesh continues with cached time
237
+
238
+ ## Security Considerations
239
+
240
+ ### Trust and Validation
241
+
242
+ 1. **Bridge Authentication**: Verify time source is trusted bridge
243
+ - Use bridge node whitelist
244
+ - Check sender's bridge status flag
245
+ - Validate against multiple bridges if available
246
+
247
+ 2. **Replay Attack Prevention**: Check timestamp freshness
248
+ ```cpp
249
+ static uint32_t lastTimestamp = 0;
250
+ if (pkg.timestamp <= lastTimestamp) {
251
+ // Potential replay attack or clock rollback
252
+ return;
253
+ }
254
+ lastTimestamp = pkg.timestamp;
255
+ ```
256
+
257
+ 3. **Sanity Checks**: Validate time is reasonable
258
+ ```cpp
259
+ const uint32_t MIN_TIME = 1609459200; // 2021-01-01
260
+ const uint32_t MAX_TIME = 2147483647; // 2038-01-19
261
+
262
+ if (pkg.ntpTime < MIN_TIME || pkg.ntpTime > MAX_TIME) {
263
+ Serial.println("Time out of valid range");
264
+ return;
265
+ }
266
+ ```
267
+
268
+ 4. **Large Jump Detection**: Reject suspicious time changes
269
+ ```cpp
270
+ uint32_t currentTime = getCurrentTime();
271
+ int32_t timeDelta = pkg.ntpTime - currentTime;
272
+
273
+ if (abs(timeDelta) > 86400) { // More than 1 day
274
+ Serial.println("Time change too large, manual intervention needed");
275
+ return;
276
+ }
277
+ ```
278
+
279
+ ## Example Applications
280
+
281
+ ### Sensor Network
282
+ - All sensors use synchronized timestamps
283
+ - Data correlation across nodes is accurate
284
+ - Event ordering is consistent
285
+
286
+ ### Coordinated Actions
287
+ - Multiple nodes can trigger actions at specific times
288
+ - Light shows with precise timing
289
+ - Scheduled operations across mesh
290
+
291
+ ### Data Logging
292
+ - Consistent timestamps for all log entries
293
+ - Time-series data from multiple sources can be merged
294
+ - Historical analysis is accurate
295
+
296
+ ### Security Systems
297
+ - Event timestamps are reliable for audit logs
298
+ - Video/sensor correlation across devices
299
+ - Alarm scheduling with accurate time
300
+
301
+ ## Testing
302
+
303
+ ### Unit Tests
304
+
305
+ The feature includes comprehensive unit tests in `test/catch/catch_alteriom_packages.cpp`:
306
+
307
+ - Basic serialization/deserialization
308
+ - JSON field validation
309
+ - Different NTP sources
310
+ - Edge cases (0 values, max values)
311
+ - Long source hostnames
312
+ - High accuracy values
313
+
314
+ Run tests:
315
+ ```bash
316
+ cd painlessMesh
317
+ cmake -G Ninja .
318
+ ninja
319
+ ./bin/catch_alteriom_packages
320
+ ```
321
+
322
+ ### Integration Testing
323
+
324
+ Test with example sketches:
325
+
326
+ 1. Upload `ntpTimeSyncBridge.ino` to bridge node with Internet
327
+ 2. Upload `ntpTimeSyncNode.ino` to regular mesh nodes
328
+ 3. Monitor serial output to verify:
329
+ - Bridge broadcasts NTP time
330
+ - Nodes receive and apply time
331
+ - Timestamps are consistent
332
+
333
+ ## Troubleshooting
334
+
335
+ ### Bridge Not Broadcasting
336
+
337
+ **Symptoms**: No NTP broadcasts seen by nodes
338
+
339
+ **Solutions**:
340
+ 1. Check Internet connectivity: `ping 8.8.8.8`
341
+ 2. Verify NTP server is reachable
342
+ 3. Check broadcast task is enabled
343
+ 4. Increase debug level: `mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION)`
344
+
345
+ ### Nodes Not Receiving Time
346
+
347
+ **Symptoms**: Nodes connected but not syncing time
348
+
349
+ **Solutions**:
350
+ 1. Verify receiver callback is registered: `mesh.onReceive(&receivedCallback)`
351
+ 2. Check message type parsing: `obj["type"] == 614`
352
+ 3. Ensure JSON buffer is large enough: `DynamicJsonDocument doc(1024)`
353
+ 4. Monitor for JSON parse errors
354
+
355
+ ### Poor Time Accuracy
356
+
357
+ **Symptoms**: High accuracy values (>500ms)
358
+
359
+ **Solutions**:
360
+ 1. Use closer NTP server (local or regional)
361
+ 2. Check network latency to NTP server
362
+ 3. Reduce NTP query frequency
363
+ 4. Consider using multiple NTP sources and averaging
364
+
365
+ ### Time Drift
366
+
367
+ **Symptoms**: Time gradually becomes inaccurate
368
+
369
+ **Solutions**:
370
+ 1. Increase broadcast frequency (30-60 seconds)
371
+ 2. Verify NTP queries are successful
372
+ 3. Check for mesh network stability issues
373
+ 4. Use RTC module for drift compensation
374
+
375
+ ## Related Features
376
+
377
+ - **Bridge Status (Type 610)**: Indicates bridge connectivity status
378
+ - **RTC Integration**: Offline timekeeping when NTP unavailable
379
+ - **Mesh Time Sync**: Built-in mesh time synchronization protocol
380
+
381
+ ## Version History
382
+
383
+ - **v1.8.1**: Initial implementation of NTP time sync feature
384
+ - Type ID 614 allocated for TIME_SYNC_NTP
385
+ - Examples and documentation added
386
+
387
+ ## References
388
+
389
+ - Issue: Enhancement: Bridge-to-Mesh NTP Time Distribution
390
+ - Examples: `examples/ntpTimeSyncBridge/` and `examples/ntpTimeSyncNode/`
391
+ - Tests: `test/catch/catch_alteriom_packages.cpp`
392
+ - Package: `examples/alteriom/alteriom_sensor_package.hpp`