@alteriom/painlessmesh 1.6.1

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 (80) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/LICENSE +674 -0
  3. package/README.md +434 -0
  4. package/RELEASE_GUIDE.md +419 -0
  5. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +176 -0
  6. package/docs/README.md +71 -0
  7. package/docs/alteriom/overview.md +508 -0
  8. package/docs/api/core-api.md +607 -0
  9. package/docs/architecture/mesh-architecture.md +379 -0
  10. package/docs/architecture/plugin-system.md +517 -0
  11. package/docs/getting-started/first-mesh.md +410 -0
  12. package/docs/getting-started/installation.md +275 -0
  13. package/docs/getting-started/quickstart.md +158 -0
  14. package/docs/improvements/README.md +69 -0
  15. package/docs/troubleshooting/common-issues.md +521 -0
  16. package/docs/troubleshooting/faq.md +473 -0
  17. package/docs/tutorials/basic-examples.md +718 -0
  18. package/docs/wiki/API-Reference.md +246 -0
  19. package/docs/wiki/Complete-Documentation.md +123 -0
  20. package/examples/alteriom/README.md +82 -0
  21. package/examples/alteriom/alteriom.ino +186 -0
  22. package/examples/alteriom/alteriom_sensor_node.ino +184 -0
  23. package/examples/alteriom/alteriom_sensor_package.hpp +128 -0
  24. package/examples/alteriom/improved_sensor_node.ino +246 -0
  25. package/examples/alteriom/platformio.ini +25 -0
  26. package/examples/basic/basic.ino +66 -0
  27. package/examples/basic/platformio.ini +25 -0
  28. package/examples/bridge/bridge.ino +51 -0
  29. package/examples/bridge/platformio.ini +25 -0
  30. package/examples/echoNode/echoNode.ino +33 -0
  31. package/examples/echoNode/platformio.ini +25 -0
  32. package/examples/logClient/logClient.ino +109 -0
  33. package/examples/logClient/platformio.ini +25 -0
  34. package/examples/logServer/logServer.ino +81 -0
  35. package/examples/logServer/platformio.ini +25 -0
  36. package/examples/mqttBridge/mqttBridge.ino +118 -0
  37. package/examples/mqttBridge/platformio.ini +26 -0
  38. package/examples/namedMesh/namedMesh.ino +97 -0
  39. package/examples/namedMesh/platformio.ini +25 -0
  40. package/examples/otaReceiver/otaReceiver.ino +79 -0
  41. package/examples/otaReceiver/platformio.ini +25 -0
  42. package/examples/otaSender/nodemcu32s_connections.JPG +0 -0
  43. package/examples/otaSender/otaSender.ino +151 -0
  44. package/examples/otaSender/platformio.ini +25 -0
  45. package/examples/startHere/platformio.ini +25 -0
  46. package/examples/startHere/startHere.ino +159 -0
  47. package/examples/webServer/platformio.ini +27 -0
  48. package/examples/webServer/webServer.ino +89 -0
  49. package/keywords.txt +49 -0
  50. package/library.json +34 -0
  51. package/library.properties +11 -0
  52. package/package.json +78 -0
  53. package/src/AlteriomPainlessMesh.h +98 -0
  54. package/src/arduino/wifi.hpp +365 -0
  55. package/src/boost/asynctcp.hpp +279 -0
  56. package/src/painlessMesh.h +70 -0
  57. package/src/painlessMeshSTA.cpp +236 -0
  58. package/src/painlessMeshSTA.h +58 -0
  59. package/src/painlessTaskOptions.h +4 -0
  60. package/src/painlessmesh/base64.hpp +111 -0
  61. package/src/painlessmesh/buffer.hpp +229 -0
  62. package/src/painlessmesh/callback.hpp +91 -0
  63. package/src/painlessmesh/configuration.hpp +77 -0
  64. package/src/painlessmesh/connection.hpp +192 -0
  65. package/src/painlessmesh/layout.hpp +188 -0
  66. package/src/painlessmesh/logger.hpp +158 -0
  67. package/src/painlessmesh/memory.hpp +120 -0
  68. package/src/painlessmesh/mesh.hpp +560 -0
  69. package/src/painlessmesh/metrics.hpp +323 -0
  70. package/src/painlessmesh/ntp.hpp +263 -0
  71. package/src/painlessmesh/ota.hpp +553 -0
  72. package/src/painlessmesh/plugin.hpp +188 -0
  73. package/src/painlessmesh/protocol.hpp +813 -0
  74. package/src/painlessmesh/router.hpp +322 -0
  75. package/src/painlessmesh/tcp.hpp +71 -0
  76. package/src/painlessmesh/validation.hpp +239 -0
  77. package/src/plugin/performance.hpp +214 -0
  78. package/src/plugin/remote.hpp +64 -0
  79. package/src/scheduler.cpp +10 -0
  80. package/src/wifi.cpp +2 -0
@@ -0,0 +1,813 @@
1
+ #ifndef _PAINLESS_MESH_PROTOCOL_HPP_
2
+ #define _PAINLESS_MESH_PROTOCOL_HPP_
3
+
4
+ #include <cmath>
5
+ #include <list>
6
+
7
+ #include "Arduino.h"
8
+
9
+ #if ARDUINOJSON_VERSION_MAJOR == 7
10
+ #include "ArduinoJson/Deserialization/DeserializationError.hpp"
11
+ #include "ArduinoJson/Document/JsonDocument.hpp"
12
+ #endif
13
+ #include "painlessmesh/configuration.hpp"
14
+
15
+ namespace painlessmesh {
16
+
17
+ namespace router {
18
+
19
+ /** Different ways to route packages
20
+ *
21
+ * NEIGHBOUR packages are send to the neighbour and will be immediately
22
+ * handled there. The TIME_SYNC and NODE_SYNC packages are NEIGHBOUR. SINGLE
23
+ * messages are meant for a specific node. When another node receives this
24
+ * message, it will look in its routing information and send it on to the
25
+ * correct node, without processing the message in any other way. Only the
26
+ * targetted node will actually parse/handle this message (without sending it
27
+ * on). Finally, BROADCAST message are send to every node and
28
+ * processed/handled by every node.
29
+ * */
30
+ enum Type { ROUTING_ERROR = -1, NEIGHBOUR, SINGLE, BROADCAST };
31
+ } // namespace router
32
+
33
+ namespace protocol {
34
+
35
+ enum Type {
36
+ TIME_DELAY = 3,
37
+ TIME_SYNC = 4,
38
+ NODE_SYNC_REQUEST = 5,
39
+ NODE_SYNC_REPLY = 6,
40
+ CONTROL = 7, // deprecated
41
+ BROADCAST = 8, // application data for everyone
42
+ SINGLE = 9 // application data for a single node
43
+ };
44
+
45
+ enum TimeType {
46
+ TIME_SYNC_ERROR = -1,
47
+ TIME_SYNC_REQUEST,
48
+ TIME_REQUEST,
49
+ TIME_REPLY
50
+ };
51
+
52
+ class PackageInterface {
53
+ public:
54
+ virtual JsonObject addTo(JsonObject&& jsonObj) const = 0;
55
+ #if ARDUINOJSON_VERSION_MAJOR < 7
56
+ virtual size_t jsonObjectSize() const = 0;
57
+ #endif
58
+ };
59
+
60
+ /**
61
+ * Single package
62
+ *
63
+ * Message send to a specific node
64
+ */
65
+ class Single : public PackageInterface {
66
+ public:
67
+ int type = SINGLE;
68
+ uint32_t from;
69
+ uint32_t dest;
70
+ TSTRING msg = "";
71
+
72
+ Single() {}
73
+ Single(uint32_t fromID, uint32_t destID, TSTRING& message) {
74
+ from = fromID;
75
+ dest = destID;
76
+ msg = message;
77
+ }
78
+
79
+ Single(JsonObject jsonObj) {
80
+ dest = jsonObj["dest"].as<uint32_t>();
81
+ from = jsonObj["from"].as<uint32_t>();
82
+ msg = jsonObj["msg"].as<TSTRING>();
83
+ }
84
+
85
+ JsonObject addTo(JsonObject&& jsonObj) const {
86
+ jsonObj["type"] = type;
87
+ jsonObj["dest"] = dest;
88
+ jsonObj["from"] = from;
89
+ jsonObj["msg"] = msg;
90
+ return jsonObj;
91
+ }
92
+
93
+ #if ARDUINOJSON_VERSION_MAJOR < 7
94
+ size_t jsonObjectSize() const {
95
+ return JSON_OBJECT_SIZE(4) + ceil(1.1 * msg.length());
96
+ }
97
+ #endif
98
+ };
99
+
100
+ /**
101
+ * Broadcast package
102
+ */
103
+ class Broadcast : public Single {
104
+ public:
105
+ int type = BROADCAST;
106
+
107
+ using Single::Single;
108
+
109
+ JsonObject addTo(JsonObject&& jsonObj) const {
110
+ jsonObj = Single::addTo(std::move(jsonObj));
111
+ jsonObj["type"] = type;
112
+ return jsonObj;
113
+ }
114
+
115
+ #if ARDUINOJSON_VERSION_MAJOR < 7
116
+ size_t jsonObjectSize() const {
117
+ return JSON_OBJECT_SIZE(4) + ceil(1.1 * msg.length());
118
+ }
119
+ #endif
120
+ };
121
+
122
+ class NodeTree : public PackageInterface {
123
+ public:
124
+ uint32_t nodeId = 0;
125
+ bool root = false;
126
+ std::list<NodeTree> subs;
127
+
128
+ NodeTree() {}
129
+ virtual ~NodeTree() = default; // Add virtual destructor
130
+
131
+ NodeTree(uint32_t nodeID, bool iAmRoot) {
132
+ nodeId = nodeID;
133
+ root = iAmRoot;
134
+ }
135
+
136
+ NodeTree(JsonObject jsonObj) {
137
+ #if ARDUINOJSON_VERSION_MAJOR < 7
138
+ if (jsonObj.containsKey("root")) root = jsonObj["root"].as<bool>();
139
+ if (jsonObj.containsKey("nodeId"))
140
+ #else
141
+
142
+ if (jsonObj["root"].is<bool>()) root = jsonObj["root"].as<bool>();
143
+ if (jsonObj["nodeId"].is<uint32_t>())
144
+ #endif
145
+ nodeId = jsonObj["nodeId"].as<uint32_t>();
146
+ else
147
+ nodeId = jsonObj["from"].as<uint32_t>();
148
+
149
+ #if ARDUINOJSON_VERSION_MAJOR < 7
150
+ if (jsonObj.containsKey("subs")) {
151
+ #else
152
+ if (jsonObj["subs"].is<JsonArray>()) {
153
+ #endif
154
+ auto jsonArr = jsonObj["subs"].as<JsonArray>();
155
+ for (size_t i = 0; i < jsonArr.size(); ++i) {
156
+ subs.push_back(NodeTree(jsonArr[i].as<JsonObject>()));
157
+ }
158
+ }
159
+ }
160
+
161
+ JsonObject addTo(JsonObject&& jsonObj) const {
162
+ jsonObj["nodeId"] = nodeId;
163
+ if (root) jsonObj["root"] = root;
164
+ if (subs.size() > 0) {
165
+ #if ARDUINOJSON_VERSION_MAJOR == 7
166
+ JsonArray subsArr = jsonObj["subs"].to<JsonArray>();
167
+ #else
168
+ JsonArray subsArr = jsonObj.createNestedArray("subs");
169
+ #endif
170
+ for (auto&& s : subs) {
171
+ #if ARDUINOJSON_VERSION_MAJOR == 7
172
+ JsonObject subObj = subsArr.add<JsonObject>();
173
+ #else
174
+ JsonObject subObj = subsArr.createNestedObject();
175
+ #endif
176
+ subObj = s.addTo(std::move(subObj));
177
+ }
178
+ }
179
+ return jsonObj;
180
+ }
181
+
182
+ bool operator==(const NodeTree& b) const {
183
+ if (!(this->nodeId == b.nodeId && this->root == b.root &&
184
+ this->subs.size() == b.subs.size()))
185
+ return false;
186
+ auto itA = this->subs.begin();
187
+ auto itB = b.subs.begin();
188
+ for (size_t i = 0; i < this->subs.size(); ++i) {
189
+ if ((*itA) != (*itB)) {
190
+ return false;
191
+ }
192
+ ++itA;
193
+ ++itB;
194
+ }
195
+ return true;
196
+ }
197
+
198
+ bool operator!=(const NodeTree& b) const { return !this->operator==(b); }
199
+
200
+ TSTRING toString(bool pretty = false);
201
+
202
+ #if ARDUINOJSON_VERSION_MAJOR < 7
203
+ size_t jsonObjectSize() const {
204
+ size_t base = 1;
205
+ if (root) ++base;
206
+ if (subs.size() > 0) ++base;
207
+ size_t size = JSON_OBJECT_SIZE(base);
208
+ if (subs.size() > 0) size += JSON_ARRAY_SIZE(subs.size());
209
+ for (auto&& s : subs) size += s.jsonObjectSize();
210
+ return size;
211
+ }
212
+ #endif
213
+
214
+ void clear() {
215
+ nodeId = 0;
216
+ subs.clear();
217
+ root = false;
218
+ }
219
+ };
220
+
221
+ /**
222
+ * NodeSyncRequest package
223
+ */
224
+ class NodeSyncRequest : public NodeTree {
225
+ public:
226
+ int type = NODE_SYNC_REQUEST;
227
+ uint32_t from;
228
+ uint32_t dest;
229
+
230
+ NodeSyncRequest() {}
231
+ NodeSyncRequest(uint32_t fromID, uint32_t destID, std::list<NodeTree> subTree,
232
+ bool iAmRoot = false) {
233
+ from = fromID;
234
+ dest = destID;
235
+ subs = subTree;
236
+ nodeId = fromID;
237
+ root = iAmRoot;
238
+ }
239
+
240
+ NodeSyncRequest(JsonObject jsonObj) : NodeTree(jsonObj) {
241
+ dest = jsonObj["dest"].as<uint32_t>();
242
+ from = jsonObj["from"].as<uint32_t>();
243
+ }
244
+
245
+ JsonObject addTo(JsonObject&& jsonObj) const {
246
+ jsonObj = NodeTree::addTo(std::move(jsonObj));
247
+ jsonObj["type"] = type;
248
+ jsonObj["dest"] = dest;
249
+ jsonObj["from"] = from;
250
+ return jsonObj;
251
+ }
252
+
253
+ bool operator==(const NodeSyncRequest& b) const {
254
+ if (!(this->from == b.from && this->dest == b.dest)) return false;
255
+ return NodeTree::operator==(b);
256
+ }
257
+
258
+ bool operator!=(const NodeSyncRequest& b) const {
259
+ return !this->operator==(b);
260
+ }
261
+
262
+ #if ARDUINOJSON_VERSION_MAJOR < 7
263
+ size_t jsonObjectSize() const {
264
+ size_t base = 4;
265
+ if (root) ++base;
266
+ if (subs.size() > 0) ++base;
267
+ size_t size = JSON_OBJECT_SIZE(base);
268
+ if (subs.size() > 0) size += JSON_ARRAY_SIZE(subs.size());
269
+ for (auto&& s : subs) size += s.jsonObjectSize();
270
+ return size;
271
+ }
272
+ #endif
273
+ };
274
+
275
+ /**
276
+ * NodeSyncReply package
277
+ */
278
+ class NodeSyncReply : public NodeSyncRequest {
279
+ public:
280
+ int type = NODE_SYNC_REPLY;
281
+
282
+ using NodeSyncRequest::NodeSyncRequest;
283
+
284
+ JsonObject addTo(JsonObject&& jsonObj) const {
285
+ jsonObj = NodeSyncRequest::addTo(std::move(jsonObj));
286
+ jsonObj["type"] = type;
287
+ return jsonObj;
288
+ }
289
+ };
290
+
291
+ struct time_sync_msg_t {
292
+ int type = TIME_SYNC_ERROR;
293
+ uint32_t t0 = 0;
294
+ uint32_t t1 = 0;
295
+ uint32_t t2 = 0;
296
+ };
297
+
298
+ /**
299
+ * TimeSync package
300
+ */
301
+ class TimeSync : public PackageInterface {
302
+ public:
303
+ int type = TIME_SYNC;
304
+ uint32_t dest;
305
+ uint32_t from;
306
+ time_sync_msg_t msg;
307
+
308
+ TimeSync() {}
309
+
310
+ TimeSync(uint32_t fromID, uint32_t destID) {
311
+ from = fromID;
312
+ dest = destID;
313
+ msg.type = TIME_SYNC_REQUEST;
314
+ }
315
+
316
+ TimeSync(uint32_t fromID, uint32_t destID, uint32_t t0) {
317
+ from = fromID;
318
+ dest = destID;
319
+ msg.type = TIME_REQUEST;
320
+ msg.t0 = t0;
321
+ }
322
+
323
+ TimeSync(uint32_t fromID, uint32_t destID, uint32_t t0, uint32_t t1) {
324
+ from = fromID;
325
+ dest = destID;
326
+ msg.type = TIME_REPLY;
327
+ msg.t0 = t0;
328
+ msg.t1 = t1;
329
+ }
330
+
331
+ TimeSync(uint32_t fromID, uint32_t destID, uint32_t t0, uint32_t t1,
332
+ uint32_t t2) {
333
+ from = fromID;
334
+ dest = destID;
335
+ msg.type = TIME_REPLY;
336
+ msg.t0 = t0;
337
+ msg.t1 = t1;
338
+ msg.t2 = t2;
339
+ }
340
+
341
+ TimeSync(JsonObject jsonObj) {
342
+ dest = jsonObj["dest"].as<uint32_t>();
343
+ from = jsonObj["from"].as<uint32_t>();
344
+ msg.type = jsonObj["msg"]["type"].as<int>();
345
+ #if ARDUINOJSON_VERSION_MAJOR < 7
346
+ if (jsonObj["msg"].containsKey("t0"))
347
+ msg.t0 = jsonObj["msg"]["t0"].as<uint32_t>();
348
+ if (jsonObj["msg"].containsKey("t1"))
349
+ msg.t1 = jsonObj["msg"]["t1"].as<uint32_t>();
350
+ if (jsonObj["msg"].containsKey("t2"))
351
+ msg.t2 = jsonObj["msg"]["t2"].as<uint32_t>();
352
+ #else
353
+ if (jsonObj["msg"]["t0"].is<uint32_t>())
354
+ msg.t0 = jsonObj["msg"]["t0"].as<uint32_t>();
355
+ if (jsonObj["msg"]["t1"].is<uint32_t>())
356
+ msg.t1 = jsonObj["msg"]["t1"].as<uint32_t>();
357
+ if (jsonObj["msg"]["t2"].is<uint32_t>())
358
+ msg.t2 = jsonObj["msg"]["t2"].as<uint32_t>();
359
+ #endif
360
+ }
361
+
362
+ JsonObject addTo(JsonObject&& jsonObj) const {
363
+ jsonObj["type"] = type;
364
+ jsonObj["dest"] = dest;
365
+ jsonObj["from"] = from;
366
+ #if ARDUINOJSON_VERSION_MAJOR == 7
367
+ auto msgObj = jsonObj["msg"].to<JsonObject>();
368
+ #else
369
+ auto msgObj = jsonObj.createNestedObject("msg");
370
+ #endif
371
+ msgObj["type"] = msg.type;
372
+ if (msg.type >= 1) msgObj["t0"] = msg.t0;
373
+ if (msg.type >= 2) {
374
+ msgObj["t1"] = msg.t1;
375
+ msgObj["t2"] = msg.t2;
376
+ }
377
+ return jsonObj;
378
+ }
379
+
380
+ /**
381
+ * Create a reply to the current message with the new time set
382
+ */
383
+ void reply(uint newT0) {
384
+ msg.t0 = newT0;
385
+ ++msg.type;
386
+ std::swap(from, dest);
387
+ }
388
+
389
+ /**
390
+ * Create a reply to the current message with the new time set
391
+ */
392
+ void reply(uint32_t newT1, uint32_t newT2) {
393
+ msg.t1 = newT1;
394
+ msg.t2 = newT2;
395
+ ++msg.type;
396
+ std::swap(from, dest);
397
+ }
398
+
399
+ #if ARDUINOJSON_VERSION_MAJOR < 7
400
+ size_t jsonObjectSize() const {
401
+ return JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(4);
402
+ }
403
+ #endif
404
+ };
405
+
406
+ /**
407
+ * TimeDelay package
408
+ */
409
+ class TimeDelay : public TimeSync {
410
+ public:
411
+ int type = TIME_DELAY;
412
+ using TimeSync::TimeSync;
413
+
414
+ JsonObject addTo(JsonObject&& jsonObj) const {
415
+ jsonObj = TimeSync::addTo(std::move(jsonObj));
416
+ jsonObj["type"] = type;
417
+ return jsonObj;
418
+ }
419
+ };
420
+
421
+ /**
422
+ * Can store any package variant
423
+ *
424
+ * Internally stores packages as a JsonObject. Main use case is to convert
425
+ * different packages from and to Json (using ArduinoJson).
426
+ */
427
+ class Variant {
428
+ // Copy operations implemented safely to address issue #521
429
+ // Move semantics preferred for performance
430
+ public:
431
+ // Copy constructor - implemented safely
432
+ Variant(const Variant& other) : error(other.error) {
433
+ // Deep copy the JSON buffer to avoid shared references
434
+ if (error == DeserializationError::Ok) {
435
+ #if ARDUINOJSON_VERSION_MAJOR == 7
436
+ jsonBuffer = JsonDocument();
437
+ #else
438
+ jsonBuffer = DynamicJsonDocument(other.jsonBuffer.capacity());
439
+ #endif
440
+ jsonBuffer.set(other.jsonBuffer);
441
+ jsonObj = jsonBuffer.as<JsonObject>();
442
+ }
443
+ }
444
+
445
+ // Copy assignment operator - implemented safely
446
+ Variant& operator=(const Variant& other) {
447
+ if (this != &other) {
448
+ error = other.error;
449
+ if (error == DeserializationError::Ok) {
450
+ #if ARDUINOJSON_VERSION_MAJOR == 7
451
+ jsonBuffer = JsonDocument();
452
+ #else
453
+ jsonBuffer = DynamicJsonDocument(other.jsonBuffer.capacity());
454
+ #endif
455
+ jsonBuffer.set(other.jsonBuffer);
456
+ jsonObj = jsonBuffer.as<JsonObject>();
457
+ }
458
+ }
459
+ return *this;
460
+ }
461
+
462
+ // Move constructor - preferred for performance
463
+ Variant(Variant&& other) noexcept
464
+ : error(std::move(other.error)),
465
+ jsonBuffer(std::move(other.jsonBuffer)) {
466
+ if (error == DeserializationError::Ok) {
467
+ jsonObj = jsonBuffer.as<JsonObject>();
468
+ }
469
+ other.error = DeserializationError::EmptyInput;
470
+ }
471
+
472
+ // Move assignment operator - preferred for performance
473
+ Variant& operator=(Variant&& other) noexcept {
474
+ if (this != &other) {
475
+ error = std::move(other.error);
476
+ jsonBuffer = std::move(other.jsonBuffer);
477
+ if (error == DeserializationError::Ok) {
478
+ jsonObj = jsonBuffer.as<JsonObject>();
479
+ }
480
+ other.error = DeserializationError::EmptyInput;
481
+ }
482
+ return *this;
483
+ }
484
+ #ifdef ARDUINOJSON_ENABLE_STD_STRING
485
+ /**
486
+ * Create Variant object from a json string
487
+ *
488
+ * @param json The json string containing a package
489
+ */
490
+ Variant(const std::string& json)
491
+ #if ARDUINOJSON_VERSION_MAJOR == 7
492
+ : jsonBuffer() {
493
+ #else
494
+ : jsonBuffer(JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(4) +
495
+ 2 * json.length()) {
496
+ #endif
497
+ error = deserializeJson(jsonBuffer, json,
498
+ DeserializationOption::NestingLimit(255));
499
+ if (error == DeserializationError::Ok)
500
+ jsonObj = jsonBuffer.as<JsonObject>();
501
+ }
502
+
503
+ /**
504
+ * Create Variant object from a json string
505
+ *
506
+ * @param json The json string containing a package
507
+ * @param capacity The capacity to reserve for parsing the string
508
+ */
509
+ Variant(const std::string& json, size_t capacity)
510
+ #if ARDUINOJSON_VERSION_MAJOR == 7
511
+ : jsonBuffer() {
512
+ #else
513
+ : jsonBuffer(capacity) {
514
+ #endif
515
+ error = deserializeJson(jsonBuffer, json,
516
+ DeserializationOption::NestingLimit(255));
517
+ if (error == DeserializationError::Ok)
518
+ jsonObj = jsonBuffer.as<JsonObject>();
519
+ }
520
+ #endif
521
+
522
+ #ifdef ARDUINOJSON_ENABLE_ARDUINO_STRING
523
+ /**
524
+ * Create Variant object from a json string
525
+ *
526
+ * @param json The json string containing a package
527
+ */
528
+ Variant(String json)
529
+ #if ARDUINOJSON_VERSION_MAJOR == 7
530
+ : jsonBuffer() {
531
+ #else
532
+ : jsonBuffer(JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(4) +
533
+ 2 * json.length()) {
534
+ #endif
535
+ error = deserializeJson(jsonBuffer, json,
536
+ DeserializationOption::NestingLimit(255));
537
+
538
+ if (error == DeserializationError::Ok)
539
+ jsonObj = jsonBuffer.as<JsonObject>();
540
+ }
541
+
542
+ /**
543
+ * Create Variant object from a json string
544
+ *
545
+ * @param json The json string containing a package
546
+ * @param capacity The capacity to reserve for parsing the string
547
+ */
548
+ Variant(String json, size_t capacity)
549
+ #if ARDUINOJSON_VERSION_MAJOR == 7
550
+ : jsonBuffer() {
551
+ #else
552
+ : jsonBuffer(capacity) {
553
+ #endif
554
+ error = deserializeJson(jsonBuffer, json,
555
+ DeserializationOption::NestingLimit(255));
556
+ if (!error) jsonObj = jsonBuffer.as<JsonObject>();
557
+ }
558
+ #endif
559
+ /**
560
+ * Create Variant object from any package implementing PackageInterface
561
+ */
562
+ Variant(const PackageInterface* pkg)
563
+ #if ARDUINOJSON_VERSION_MAJOR == 7
564
+ : jsonBuffer() {
565
+ #else
566
+ : jsonBuffer(pkg->jsonObjectSize()) {
567
+ #endif
568
+ jsonObj = jsonBuffer.to<JsonObject>();
569
+ jsonObj = pkg->addTo(std::move(jsonObj));
570
+ }
571
+
572
+ /**
573
+ * Create Variant object from a Single package
574
+ *
575
+ * @param single The single package
576
+ */
577
+ Variant(Single single)
578
+ #if ARDUINOJSON_VERSION_MAJOR == 7
579
+ : jsonBuffer() {
580
+ #else
581
+ : jsonBuffer(single.jsonObjectSize()) {
582
+ #endif
583
+ jsonObj = jsonBuffer.to<JsonObject>();
584
+ jsonObj = single.addTo(std::move(jsonObj));
585
+ }
586
+
587
+ /**
588
+ * Create Variant object from a Broadcast package
589
+ *
590
+ * @param broadcast The broadcast package
591
+ */
592
+ Variant(Broadcast broadcast)
593
+ #if ARDUINOJSON_VERSION_MAJOR == 7
594
+ : jsonBuffer() {
595
+ #else
596
+ : jsonBuffer(broadcast.jsonObjectSize()) {
597
+ #endif
598
+ jsonObj = jsonBuffer.to<JsonObject>();
599
+ jsonObj = broadcast.addTo(std::move(jsonObj));
600
+ }
601
+
602
+ /**
603
+ * Create Variant object from a NodeTree
604
+ *
605
+ * @param nodeTree The NodeTree
606
+ */
607
+ Variant(NodeTree nodeTree)
608
+ #if ARDUINOJSON_VERSION_MAJOR == 7
609
+ : jsonBuffer() {
610
+ #else
611
+ : jsonBuffer(nodeTree.jsonObjectSize()) {
612
+ #endif
613
+ jsonObj = jsonBuffer.to<JsonObject>();
614
+ jsonObj = nodeTree.addTo(std::move(jsonObj));
615
+ }
616
+
617
+ /**
618
+ * Create Variant object from a NodeSyncReply package
619
+ *
620
+ * @param nodeSyncReply The nodeSyncReply package
621
+ */
622
+ Variant(NodeSyncReply nodeSyncReply)
623
+ #if ARDUINOJSON_VERSION_MAJOR == 7
624
+ : jsonBuffer() {
625
+ #else
626
+ : jsonBuffer(nodeSyncReply.jsonObjectSize()) {
627
+ #endif
628
+ jsonObj = jsonBuffer.to<JsonObject>();
629
+ jsonObj = nodeSyncReply.addTo(std::move(jsonObj));
630
+ }
631
+
632
+ /**
633
+ * Create Variant object from a NodeSyncRequest package
634
+ *
635
+ * @param nodeSyncRequest The nodeSyncRequest package
636
+ */
637
+ Variant(NodeSyncRequest nodeSyncRequest)
638
+ #if ARDUINOJSON_VERSION_MAJOR == 7
639
+ : jsonBuffer() {
640
+ #else
641
+ : jsonBuffer(nodeSyncRequest.jsonObjectSize()) {
642
+ #endif
643
+ jsonObj = jsonBuffer.to<JsonObject>();
644
+ jsonObj = nodeSyncRequest.addTo(std::move(jsonObj));
645
+ }
646
+
647
+ /**
648
+ * Create Variant object from a TimeSync package
649
+ *
650
+ * @param timeSync The timeSync package
651
+ */
652
+ Variant(TimeSync timeSync)
653
+ #if ARDUINOJSON_VERSION_MAJOR == 7
654
+ : jsonBuffer() {
655
+ #else
656
+ : jsonBuffer(timeSync.jsonObjectSize()) {
657
+ #endif
658
+ jsonObj = jsonBuffer.to<JsonObject>();
659
+ jsonObj = timeSync.addTo(std::move(jsonObj));
660
+ }
661
+
662
+ /**
663
+ * Create Variant object from a TimeDelay package
664
+ *
665
+ * @param timeDelay The timeDelay package
666
+ */
667
+ Variant(TimeDelay timeDelay)
668
+ #if ARDUINOJSON_VERSION_MAJOR == 7
669
+ : jsonBuffer() {
670
+ #else
671
+ : jsonBuffer(timeDelay.jsonObjectSize()) {
672
+ #endif
673
+ jsonObj = jsonBuffer.to<JsonObject>();
674
+ jsonObj = timeDelay.addTo(std::move(jsonObj));
675
+ }
676
+
677
+ /**
678
+ * Whether this package is of the given type
679
+ */
680
+ template <typename T>
681
+ inline bool is() {
682
+ return false;
683
+ }
684
+
685
+ /**
686
+ * Convert Variant to the given type
687
+ */
688
+ template <typename T>
689
+ inline T to() {
690
+ return T(jsonObj);
691
+ }
692
+
693
+ /**
694
+ * Return package type
695
+ */
696
+ int type() { return jsonObj["type"].as<int>(); }
697
+
698
+ /**
699
+ * Package routing method
700
+ */
701
+ router::Type routing() {
702
+ #if ARDUINOJSON_VERSION_MAJOR < 7
703
+ if (jsonObj.containsKey("routing"))
704
+ #else
705
+ if (jsonObj["routing"].is<int>())
706
+ #endif
707
+ return (router::Type)jsonObj["routing"].as<int>();
708
+
709
+ auto type = this->type();
710
+ if (type == SINGLE || type == TIME_DELAY) return router::SINGLE;
711
+ if (type == BROADCAST) return router::BROADCAST;
712
+ if (type == NODE_SYNC_REQUEST || type == NODE_SYNC_REPLY ||
713
+ type == TIME_SYNC)
714
+ return router::NEIGHBOUR;
715
+ return router::ROUTING_ERROR;
716
+ }
717
+
718
+ /**
719
+ * Destination node of the package
720
+ */
721
+ uint32_t dest() {
722
+ #if ARDUINOJSON_VERSION_MAJOR < 7
723
+ if (jsonObj.containsKey("dest")) return jsonObj["dest"].as<uint32_t>();
724
+ #else
725
+ if (jsonObj["dest"].is<uint32_t>()) return jsonObj["dest"].as<uint32_t>();
726
+ #endif
727
+ return 0;
728
+ }
729
+
730
+ #ifdef ARDUINOJSON_ENABLE_STD_STRING
731
+ /**
732
+ * Print a variant to a string
733
+ *
734
+ * @return A json representation of the string
735
+ */
736
+ void printTo(std::string& str, bool pretty = false) {
737
+ if (pretty)
738
+ serializeJsonPretty(jsonObj, str);
739
+ else
740
+ serializeJson(jsonObj, str);
741
+ }
742
+ #endif
743
+
744
+ #ifdef ARDUINOJSON_ENABLE_ARDUINO_STRING
745
+ /**
746
+ * Print a variant to a string
747
+ *
748
+ * @return A json representation of the string
749
+ */
750
+ void printTo(String& str, bool pretty = false) {
751
+ if (pretty)
752
+ serializeJsonPretty(jsonObj, str);
753
+ else
754
+ serializeJson(jsonObj, str);
755
+ }
756
+ #endif
757
+
758
+ DeserializationError error = DeserializationError::Ok;
759
+
760
+ private:
761
+ #if ARDUINOJSON_VERSION_MAJOR == 7
762
+ JsonDocument jsonBuffer;
763
+ #else
764
+ DynamicJsonDocument jsonBuffer;
765
+ #endif
766
+ JsonObject jsonObj;
767
+ };
768
+
769
+ template <>
770
+ inline bool Variant::is<Single>() {
771
+ return jsonObj["type"].as<int>() == SINGLE;
772
+ }
773
+
774
+ template <>
775
+ inline bool Variant::is<Broadcast>() {
776
+ return jsonObj["type"].as<int>() == BROADCAST;
777
+ }
778
+
779
+ template <>
780
+ inline bool Variant::is<NodeSyncReply>() {
781
+ return jsonObj["type"].as<int>() == NODE_SYNC_REPLY;
782
+ }
783
+
784
+ template <>
785
+ inline bool Variant::is<NodeSyncRequest>() {
786
+ return jsonObj["type"].as<int>() == NODE_SYNC_REQUEST;
787
+ }
788
+
789
+ template <>
790
+ inline bool Variant::is<TimeSync>() {
791
+ return jsonObj["type"].as<int>() == TIME_SYNC;
792
+ }
793
+
794
+ template <>
795
+ inline bool Variant::is<TimeDelay>() {
796
+ return jsonObj["type"].as<int>() == TIME_DELAY;
797
+ }
798
+
799
+ template <>
800
+ inline JsonObject Variant::to<JsonObject>() {
801
+ return jsonObj;
802
+ }
803
+
804
+ inline TSTRING NodeTree::toString(bool pretty) {
805
+ TSTRING str;
806
+ auto variant = Variant(*this);
807
+ variant.printTo(str, pretty);
808
+ return str;
809
+ }
810
+
811
+ } // namespace protocol
812
+ } // namespace painlessmesh
813
+ #endif