@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,188 @@
1
+ #ifndef _PAINLESS_MESH_LAYOUT_HPP_
2
+ #define _PAINLESS_MESH_LAYOUT_HPP_
3
+
4
+ #include <list>
5
+ #include <memory>
6
+
7
+ #include "painlessmesh/protocol.hpp"
8
+
9
+ namespace painlessmesh {
10
+ namespace layout {
11
+
12
+ #include <memory>
13
+ /**
14
+ * Whether the tree contains the given nodeId
15
+ */
16
+ inline bool contains(protocol::NodeTree nodeTree, uint32_t nodeId) {
17
+ if (nodeTree.nodeId == nodeId) {
18
+ return true;
19
+ }
20
+ for (auto&& s : nodeTree.subs) {
21
+ if (contains(s, nodeId)) return true;
22
+ }
23
+ return false;
24
+ }
25
+
26
+ inline protocol::NodeTree excludeRoute(protocol::NodeTree&& tree,
27
+ uint32_t exclude) {
28
+ // Make sure to exclude any subs with nodeId == 0,
29
+ // even if exlude is not set to zero
30
+ tree.subs.remove_if([exclude](protocol::NodeTree s) {
31
+ return s.nodeId == 0 || s.nodeId == exclude;
32
+ });
33
+ return tree;
34
+ }
35
+
36
+ template <class T>
37
+ class Layout {
38
+ public:
39
+ size_t stability = 0;
40
+ std::list<std::shared_ptr<T> > subs;
41
+
42
+ /** Return the nodeId of the node that we are running on.
43
+ *
44
+ * On the ESP hardware nodeId is uniquely calculated from the MAC address of
45
+ * the node.
46
+ */
47
+ uint32_t getNodeId() { return nodeId; }
48
+
49
+ /**
50
+ * Check whether this node is a root node.
51
+ */
52
+ bool isRoot() { return root; }
53
+
54
+ protocol::NodeTree asNodeTree() {
55
+ auto nt = protocol::NodeTree(nodeId, root);
56
+ for (auto&& s : subs) {
57
+ if (s->nodeId == 0) continue;
58
+ nt.subs.push_back(protocol::NodeTree(*s));
59
+ }
60
+ return nt;
61
+ }
62
+
63
+ protected:
64
+ uint32_t nodeId = 0;
65
+ bool root = false;
66
+ };
67
+
68
+ template <class T>
69
+ void syncLayout(Layout<T>& layout, uint32_t changedId) {
70
+ // TODO: this should be called from changed connections and dropped
71
+ // connections events
72
+ for (auto&& sub : layout.subs) {
73
+ if (sub->connected() && !sub->newConnection && sub->nodeId != 0 &&
74
+ sub->nodeId != changedId) { // Exclude current
75
+ sub->nodeSyncTask.forceNextIteration();
76
+ }
77
+ }
78
+ layout.stability /= 2;
79
+ }
80
+
81
+ class Neighbour : public protocol::NodeTree {
82
+ public:
83
+ // Inherit constructors
84
+ using protocol::NodeTree::NodeTree;
85
+
86
+ /**
87
+ * Is the passed nodesync valid
88
+ *
89
+ * If not then the caller of this function should probably disconnect
90
+ * this neighbour.
91
+ */
92
+ bool validSubs(protocol::NodeTree tree) {
93
+ if (nodeId == 0) // Cant really know, so valid as far as we know
94
+ return true;
95
+ if (nodeId != tree.nodeId) return false;
96
+ for (auto&& s : tree.subs) {
97
+ if (layout::contains(s, nodeId)) return false;
98
+ }
99
+ return true;
100
+ }
101
+
102
+ /**
103
+ * Update subs with the new subs
104
+ *
105
+ * \param tree The possible new tree with this node as base
106
+ *
107
+ * Generally one probably wants to call validSubs before calling this
108
+ * function.
109
+ *
110
+ * \return Whether we adopted the new tree
111
+ */
112
+ bool updateSubs(protocol::NodeTree tree) {
113
+ if (nodeId == 0 || tree != (*this)) {
114
+ nodeId = tree.nodeId;
115
+ subs = tree.subs;
116
+ root = tree.root;
117
+ return true;
118
+ }
119
+ return false;
120
+ }
121
+
122
+ /**
123
+ * Create a request
124
+ */
125
+ protocol::NodeSyncRequest request(NodeTree&& layout) {
126
+ auto subTree = excludeRoute(std::move(layout), nodeId);
127
+ return protocol::NodeSyncRequest(subTree.nodeId, nodeId, subTree.subs,
128
+ subTree.root);
129
+ }
130
+
131
+ /**
132
+ * Create a reply
133
+ */
134
+ protocol::NodeSyncReply reply(NodeTree&& layout) {
135
+ auto subTree = excludeRoute(std::move(layout), nodeId);
136
+ return protocol::NodeSyncReply(subTree.nodeId, nodeId, subTree.subs,
137
+ subTree.root);
138
+ }
139
+ };
140
+
141
+ /**
142
+ * The size of the mesh (the number of nodes)
143
+ */
144
+ inline uint32_t size(protocol::NodeTree nodeTree) {
145
+ auto no = 1;
146
+ for (auto&& s : nodeTree.subs) {
147
+ no += size(s);
148
+ }
149
+ return no;
150
+ }
151
+
152
+ /**
153
+ * Whether the top node in the tree is also the root of the mesh
154
+ */
155
+ inline bool isRoot(protocol::NodeTree nodeTree) {
156
+ if (nodeTree.root) return true;
157
+ return false;
158
+ }
159
+
160
+ /**
161
+ * Whether any node in the tree is also root of the mesh
162
+ */
163
+ inline bool isRooted(protocol::NodeTree nodeTree) {
164
+ if (isRoot(nodeTree)) return true;
165
+ for (auto&& s : nodeTree.subs) {
166
+ if (isRooted(s)) return true;
167
+ }
168
+ return false;
169
+ }
170
+
171
+ /**
172
+ * Return all nodes in a list container
173
+ */
174
+ inline std::list<uint32_t> asList(protocol::NodeTree nodeTree,
175
+ bool includeSelf = true) {
176
+ std::list<uint32_t> lst;
177
+ if (includeSelf) lst.push_back(nodeTree.nodeId);
178
+ for (auto&& s : nodeTree.subs) {
179
+ lst.splice(lst.end(), asList(s));
180
+ }
181
+ return lst;
182
+ }
183
+
184
+ } // namespace layout
185
+ } // namespace painlessmesh
186
+
187
+ #endif
188
+
@@ -0,0 +1,158 @@
1
+ #ifndef _PAINLESS_MESH_LOGGER_HPP_
2
+ #define _PAINLESS_MESH_LOGGER_HPP_
3
+
4
+ #include <list>
5
+
6
+ namespace painlessmesh {
7
+ namespace logger {
8
+ #include <stdarg.h>
9
+ #include "Arduino.h"
10
+
11
+ #define REMOTE_QUEUE_SIZE 10
12
+
13
+ typedef enum {
14
+ ERROR = 1 << 0,
15
+ STARTUP = 1 << 1,
16
+ MESH_STATUS = 1 << 2,
17
+ CONNECTION = 1 << 3,
18
+ SYNC = 1 << 4,
19
+ S_TIME = 1 << 5,
20
+ COMMUNICATION = 1 << 6,
21
+ GENERAL = 1 << 7,
22
+ MSG_TYPES = 1 << 8,
23
+ REMOTE = 1 << 9, // not yet implemented
24
+ APPLICATION = 1 << 10,
25
+ DEBUG = 1 << 11
26
+ } LogLevel;
27
+
28
+ class LogClass {
29
+ public:
30
+ void setLogLevel(uint16_t newTypes) {
31
+ // set the different kinds of debug messages you want to generate.
32
+ types = newTypes;
33
+ Serial.print(F("\nsetLogLevel:"));
34
+ if (types & ERROR) {
35
+ Serial.print(F(" ERROR |"));
36
+ }
37
+ if (types & STARTUP) {
38
+ Serial.print(F(" STARTUP |"));
39
+ }
40
+ if (types & MESH_STATUS) {
41
+ Serial.print(F(" MESH_STATUS |"));
42
+ }
43
+ if (types & CONNECTION) {
44
+ Serial.print(F(" CONNECTION |"));
45
+ }
46
+ if (types & SYNC) {
47
+ Serial.print(F(" SYNC |"));
48
+ }
49
+ if (types & S_TIME) {
50
+ Serial.print(F(" S_TIME |"));
51
+ }
52
+ if (types & COMMUNICATION) {
53
+ Serial.print(F(" COMMUNICATION |"));
54
+ }
55
+ if (types & GENERAL) {
56
+ Serial.print(F(" GENERAL |"));
57
+ }
58
+ if (types & MSG_TYPES) {
59
+ Serial.print(F(" MSG_TYPES |"));
60
+ }
61
+ if (types & REMOTE) {
62
+ Serial.print(F(" REMOTE |"));
63
+ }
64
+ if (types & APPLICATION) {
65
+ Serial.print(F(" APPLICATION |"));
66
+ }
67
+ if (types & DEBUG) {
68
+ Serial.print(F(" DEBUG |"));
69
+ }
70
+ Serial.println();
71
+ return;
72
+ }
73
+ void operator()(LogLevel type, const char *format...) {
74
+ if (type & types) { // Print only the message types set for output
75
+ va_list args;
76
+ va_start(args, format);
77
+
78
+ vsnprintf(str, 200, format, args);
79
+
80
+ if (types) {
81
+ switch (type) {
82
+ case ERROR:
83
+ Serial.print(F("ERROR: "));
84
+ break;
85
+ case STARTUP:
86
+ Serial.print(F("STARTUP: "));
87
+ break;
88
+ case MESH_STATUS:
89
+ Serial.print(F("MESH_STATUS: "));
90
+ break;
91
+ case CONNECTION:
92
+ Serial.print(F("CONNECTION: "));
93
+ break;
94
+ case SYNC:
95
+ Serial.print(F("SYNC: "));
96
+ break;
97
+ case S_TIME:
98
+ Serial.print(F("S_TIME: "));
99
+ break;
100
+ case COMMUNICATION:
101
+ Serial.print(F("COMMUNICATION: "));
102
+ break;
103
+ case GENERAL:
104
+ Serial.print(F("GENERAL: "));
105
+ break;
106
+ case MSG_TYPES:
107
+ Serial.print(F("MSG_TYPES: "));
108
+ break;
109
+ case REMOTE:
110
+ this->remote(format);
111
+ Serial.print(F("REMOTE: "));
112
+ break;
113
+ case APPLICATION:
114
+ Serial.print(F("APPLICATION: "));
115
+ break;
116
+ case DEBUG:
117
+ Serial.print(F("DEBUG: "));
118
+ break;
119
+ }
120
+ }
121
+
122
+ Serial.print(str);
123
+
124
+ va_end(args);
125
+ }
126
+ }
127
+
128
+ void remote(const char *format...) {
129
+ if (REMOTE & types) { // Store only the message if REMOTE set
130
+ va_list args;
131
+ va_start(args, format);
132
+
133
+ vsnprintf(str, 200, format, args);
134
+
135
+ remote_queue.push_back(std::pair<uint, TSTRING>(remote_uuid, str));
136
+ ++remote_uuid;
137
+ if (remote_queue.size() > REMOTE_QUEUE_SIZE) {
138
+ // No place to store the reason, but do signify the queue is full,
139
+ // discard any follow up
140
+ remote_queue.pop_front();
141
+ }
142
+ }
143
+ }
144
+
145
+ std::list<std::pair<uint, TSTRING>> &get_remote_queue() {
146
+ return remote_queue;
147
+ }
148
+
149
+ private:
150
+ uint16_t types = 0;
151
+ char str[200];
152
+ std::list<std::pair<uint, TSTRING>> remote_queue;
153
+ uint remote_uuid;
154
+ };
155
+
156
+ } // namespace logger
157
+ } // namespace painlessmesh
158
+ #endif
@@ -0,0 +1,120 @@
1
+ #ifndef _PAINLESS_MESH_MEMORY_HPP_
2
+ #define _PAINLESS_MESH_MEMORY_HPP_
3
+
4
+ /**
5
+ * Memory management utilities for painlessMesh
6
+ *
7
+ * This module provides optimized memory management utilities to reduce
8
+ * allocations and improve performance in memory-constrained environments.
9
+ */
10
+
11
+ #include "painlessmesh/configuration.hpp"
12
+ #include <memory>
13
+ #include <vector>
14
+
15
+ namespace painlessmesh {
16
+ namespace memory {
17
+
18
+ /**
19
+ * Object pool for frequently allocated types
20
+ * Reduces allocation overhead for commonly used objects
21
+ */
22
+ template<typename T>
23
+ class ObjectPool {
24
+ public:
25
+ ObjectPool(size_t initial_size = 10) {
26
+ pool_.reserve(initial_size);
27
+ for (size_t i = 0; i < initial_size; ++i) {
28
+ pool_.emplace_back(std::make_unique<T>());
29
+ }
30
+ }
31
+
32
+ std::unique_ptr<T> acquire() {
33
+ if (!pool_.empty()) {
34
+ auto obj = std::move(pool_.back());
35
+ pool_.pop_back();
36
+ return obj;
37
+ }
38
+ return std::make_unique<T>();
39
+ }
40
+
41
+ void release(std::unique_ptr<T> obj) {
42
+ if (pool_.size() < max_pool_size_) {
43
+ // Reset object to default state before returning to pool
44
+ *obj = T{};
45
+ pool_.push_back(std::move(obj));
46
+ }
47
+ // If pool is full, let unique_ptr destroy the object automatically
48
+ }
49
+
50
+ size_t size() const { return pool_.size(); }
51
+
52
+ private:
53
+ std::vector<std::unique_ptr<T>> pool_;
54
+ static constexpr size_t max_pool_size_ = 20; // Prevent unlimited growth
55
+ };
56
+
57
+ /**
58
+ * Pre-sized string buffer to avoid frequent reallocations
59
+ */
60
+ class StringBuffer {
61
+ public:
62
+ explicit StringBuffer(size_t initial_capacity = 512) {
63
+ buffer_.reserve(initial_capacity);
64
+ }
65
+
66
+ void clear() { buffer_.clear(); }
67
+
68
+ void append(const TSTRING& str) {
69
+ if (buffer_.capacity() < buffer_.size() + str.length()) {
70
+ buffer_.reserve(std::max(buffer_.capacity() * 2, buffer_.size() + str.length()));
71
+ }
72
+ buffer_ += str;
73
+ }
74
+
75
+ const TSTRING& str() const { return buffer_; }
76
+ TSTRING& str() { return buffer_; }
77
+
78
+ size_t capacity() const { return buffer_.capacity(); }
79
+ size_t size() const { return buffer_.size(); }
80
+
81
+ private:
82
+ TSTRING buffer_;
83
+ };
84
+
85
+ /**
86
+ * Memory usage statistics for monitoring
87
+ */
88
+ struct MemoryStats {
89
+ size_t total_allocated = 0;
90
+ size_t total_freed = 0;
91
+ size_t current_usage = 0;
92
+ size_t peak_usage = 0;
93
+ size_t allocation_count = 0;
94
+
95
+ void record_allocation(size_t size) {
96
+ total_allocated += size;
97
+ current_usage += size;
98
+ peak_usage = std::max(peak_usage, current_usage);
99
+ ++allocation_count;
100
+ }
101
+
102
+ void record_deallocation(size_t size) {
103
+ total_freed += size;
104
+ current_usage = (current_usage >= size) ? current_usage - size : 0;
105
+ }
106
+
107
+ void reset() {
108
+ *this = MemoryStats{};
109
+ }
110
+ };
111
+
112
+ // Global memory statistics (optional, can be disabled for production)
113
+ #ifdef PAINLESS_MESH_ENABLE_MEMORY_STATS
114
+ extern MemoryStats global_memory_stats;
115
+ #endif
116
+
117
+ } // namespace memory
118
+ } // namespace painlessmesh
119
+
120
+ #endif // _PAINLESS_MESH_MEMORY_HPP_