@alteriom/painlessmesh 1.10.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/BRIDGE_TO_INTERNET.md +167 -29
  2. package/CHANGELOG.md +483 -0
  3. package/CONTRIBUTING.md +56 -53
  4. package/README.md +100 -95
  5. package/RELEASE_GUIDE.md +81 -780
  6. package/examples/alteriom/README.md +8 -10
  7. package/examples/alteriom/alteriom.ino +2 -2
  8. package/examples/alteriom/alteriom_sensor_package.hpp +17 -11
  9. package/examples/alteriom/mppt_example/alteriom_custom_package_template.hpp +320 -0
  10. package/examples/alteriom/mppt_example/alteriom_sensor_package.hpp +1389 -0
  11. package/examples/alteriom/mppt_example/{alteriom_mppt_example.ino → mppt_example.ino} +4 -0
  12. package/examples/basic/test/simulator/README.md +3 -3
  13. package/examples/bridge_failover/README.md +51 -14
  14. package/examples/commandControl/commandControl.ino +86 -0
  15. package/examples/commandControl/platformio.ini +26 -0
  16. package/examples/mqttBridge/mqttBridge.ino +4 -0
  17. package/examples/mqttBridge/platformio.ini +1 -1
  18. package/examples/otaSender/otaSender.ino +5 -1
  19. package/examples/priority/README.md +1 -1
  20. package/examples/priority/{priority_basic_example.ino → priority_basic_example/priority_basic_example.ino} +4 -4
  21. package/examples/priority/{priority_with_queue.ino → priority_with_queue/priority_with_queue.ino} +20 -2
  22. package/examples/reliableSensorLogging/platformio.ini +26 -0
  23. package/examples/reliableSensorLogging/reliableSensorLogging.ino +151 -0
  24. package/examples/sendToInternet/README.md +12 -5
  25. package/examples/sendToInternet/{CMakeLists.txt → pc_node/CMakeLists.txt} +7 -7
  26. package/examples/sendToInternet/{PC_NODE_README.md → pc_node/PC_NODE_README.md} +15 -15
  27. package/examples/sendToInternet/{build.sh → pc_node/build.sh} +5 -5
  28. package/examples/sendToInternet/{pc_mesh_node.cpp → pc_node/pc_mesh_node.cpp} +12 -1
  29. package/examples/sharedGateway/README.md +1 -2
  30. package/keywords.txt +50 -1
  31. package/library.json +8 -6
  32. package/library.properties +2 -2
  33. package/package.json +3 -3
  34. package/src/AlteriomPainlessMesh.h +3 -3
  35. package/src/arduino/wifi.hpp +556 -126
  36. package/src/painlessMesh.h +2 -2
  37. package/src/painlessMeshSTA.cpp +607 -87
  38. package/src/painlessMeshSTA.h +135 -3
  39. package/src/painlessmesh/ack.hpp +283 -0
  40. package/src/painlessmesh/buffer.hpp +70 -8
  41. package/src/painlessmesh/callback.hpp +38 -5
  42. package/src/painlessmesh/configuration.hpp +69 -1
  43. package/src/painlessmesh/connection.hpp +12 -5
  44. package/src/painlessmesh/gateway.hpp +270 -5
  45. package/src/painlessmesh/layout.hpp +70 -2
  46. package/src/painlessmesh/logger.hpp +15 -0
  47. package/src/painlessmesh/mesh.hpp +552 -48
  48. package/src/painlessmesh/ntp.hpp +2 -4
  49. package/src/painlessmesh/plugin.hpp +30 -6
  50. package/src/painlessmesh/protocol.hpp +55 -2
  51. package/src/painlessmesh/router.hpp +192 -77
  52. package/src/painlessmesh/tcp.hpp +10 -0
  53. package/src/painlessmesh/message_tracker.hpp +0 -311
  54. /package/examples/sendToInternet/{mock_server_test.ino → mock_server_test/mock_server_test.ino} +0 -0
@@ -1,311 +0,0 @@
1
- #ifndef _PAINLESS_MESH_MESSAGE_TRACKER_HPP_
2
- #define _PAINLESS_MESH_MESSAGE_TRACKER_HPP_
3
-
4
- #include <map>
5
- #include <algorithm>
6
- #include "painlessmesh/configuration.hpp"
7
- #include "painlessmesh/logger.hpp"
8
-
9
- // External logger instance
10
- extern painlessmesh::logger::LogClass Log;
11
-
12
- namespace painlessmesh {
13
-
14
- /**
15
- * Key for tracking messages by their unique combination of ID and origin node
16
- */
17
- struct MessageKey {
18
- uint32_t messageId;
19
- uint32_t originNode;
20
-
21
- bool operator<(const MessageKey& other) const {
22
- if (messageId != other.messageId) {
23
- return messageId < other.messageId;
24
- }
25
- return originNode < other.originNode;
26
- }
27
-
28
- bool operator==(const MessageKey& other) const {
29
- return messageId == other.messageId && originNode == other.originNode;
30
- }
31
- };
32
-
33
- /**
34
- * Tracked message entry with timestamp and acknowledgment status
35
- */
36
- struct TrackedMessage {
37
- uint32_t timestamp; // When the message was first processed (millis)
38
- bool acknowledged; // Whether the message has been acknowledged
39
-
40
- TrackedMessage() : timestamp(0), acknowledged(false) {}
41
- TrackedMessage(uint32_t ts) : timestamp(ts), acknowledged(false) {}
42
- };
43
-
44
- /**
45
- * MessageTracker - Prevents duplicate message processing and tracks acknowledgments
46
- *
47
- * This class provides efficient tracking of processed messages to prevent
48
- * duplicate processing in mesh networks. It supports:
49
- * - Configurable maximum tracked messages (memory-efficient for ESP8266)
50
- * - Automatic cleanup of expired entries
51
- * - Acknowledgment tracking for reliable delivery
52
- * - Thread-safe consideration for ESP32
53
- *
54
- * Example usage:
55
- * \code
56
- * MessageTracker tracker(500, 60000); // Max 500 messages, 60s timeout
57
- *
58
- * uint32_t msgId = 12345;
59
- * uint32_t originNode = 67890;
60
- *
61
- * // Check if message was already processed
62
- * if (!tracker.isProcessed(msgId, originNode)) {
63
- * // Process the message
64
- * processMessage(msg);
65
- *
66
- * // Mark as processed
67
- * tracker.markProcessed(msgId, originNode);
68
- * }
69
- *
70
- * // Later, mark as acknowledged
71
- * tracker.markAcknowledged(msgId, originNode);
72
- *
73
- * // Periodically cleanup old entries
74
- * tracker.cleanup();
75
- * \endcode
76
- */
77
- class MessageTracker {
78
- public:
79
- /**
80
- * Constructor
81
- * @param maxMessages Maximum number of messages to track (default: 500)
82
- * @param timeoutMs Timeout in milliseconds for automatic cleanup (default: 60000)
83
- */
84
- MessageTracker(uint16_t maxMessages = 500, uint32_t timeoutMs = 60000)
85
- : maxTrackedMessages(maxMessages), messageTimeoutMs(timeoutMs) {}
86
-
87
- /**
88
- * Check if a message has already been processed
89
- * @param messageId The unique message identifier
90
- * @param originNode The node that originated the message
91
- * @return true if the message was already processed, false otherwise
92
- */
93
- bool isProcessed(uint32_t messageId, uint32_t originNode) {
94
- MessageKey key = {messageId, originNode};
95
- auto it = trackedMessages.find(key);
96
- return it != trackedMessages.end();
97
- }
98
-
99
- /**
100
- * Mark a message as processed
101
- * If the tracker is at capacity, oldest entries will be removed first.
102
- * Note: If maxMessages is 0, this method does nothing and returns false.
103
- * @param messageId The unique message identifier
104
- * @param originNode The node that originated the message
105
- * @return true if message was tracked, false if capacity is 0
106
- */
107
- bool markProcessed(uint32_t messageId, uint32_t originNode) {
108
- MessageKey key = {messageId, originNode};
109
- uint32_t currentTime = millis();
110
-
111
- // Check if already exists
112
- auto it = trackedMessages.find(key);
113
- if (it != trackedMessages.end()) {
114
- // Update timestamp but preserve acknowledged status
115
- it->second.timestamp = currentTime;
116
- Log(logger::GENERAL, "MessageTracker: Updated message %u from node %u\n",
117
- messageId, originNode);
118
- return true;
119
- }
120
-
121
- // Handle capacity 0 case - don't add new entries
122
- if (maxTrackedMessages == 0) {
123
- Log(logger::GENERAL, "MessageTracker: Cannot track message %u (capacity=0)\n",
124
- messageId);
125
- return false;
126
- }
127
-
128
- // Enforce memory limits before adding new entry
129
- if (trackedMessages.size() >= maxTrackedMessages) {
130
- enforceMemoryLimit();
131
- }
132
-
133
- // Add new entry
134
- trackedMessages[key] = TrackedMessage(currentTime);
135
- Log(logger::GENERAL, "MessageTracker: Tracked message %u from node %u (size=%zu)\n",
136
- messageId, originNode, trackedMessages.size());
137
- return true;
138
- }
139
-
140
- /**
141
- * Mark a message as acknowledged
142
- * @param messageId The unique message identifier
143
- * @param originNode The node that originated the message
144
- * @return true if the message was found and marked, false otherwise
145
- */
146
- bool markAcknowledged(uint32_t messageId, uint32_t originNode) {
147
- MessageKey key = {messageId, originNode};
148
- auto it = trackedMessages.find(key);
149
-
150
- if (it != trackedMessages.end()) {
151
- it->second.acknowledged = true;
152
- Log(logger::GENERAL, "MessageTracker: Acknowledged message %u from node %u\n",
153
- messageId, originNode);
154
- return true;
155
- }
156
-
157
- Log(logger::GENERAL, "MessageTracker: Message %u from node %u not found for acknowledgment\n",
158
- messageId, originNode);
159
- return false;
160
- }
161
-
162
- /**
163
- * Check if a message has been acknowledged
164
- * @param messageId The unique message identifier
165
- * @param originNode The node that originated the message
166
- * @return true if acknowledged, false if not found or not acknowledged
167
- */
168
- bool isAcknowledged(uint32_t messageId, uint32_t originNode) {
169
- MessageKey key = {messageId, originNode};
170
- auto it = trackedMessages.find(key);
171
-
172
- if (it != trackedMessages.end()) {
173
- return it->second.acknowledged;
174
- }
175
-
176
- return false;
177
- }
178
-
179
- /**
180
- * Cleanup expired entries based on the configured timeout
181
- * @return Number of entries removed
182
- */
183
- uint32_t cleanup() {
184
- uint32_t currentTime = millis();
185
- uint32_t removedCount = 0;
186
-
187
- auto it = trackedMessages.begin();
188
- while (it != trackedMessages.end()) {
189
- // Handle millis() overflow - if currentTime < timestamp, assume overflow
190
- uint32_t age;
191
- if (currentTime >= it->second.timestamp) {
192
- age = currentTime - it->second.timestamp;
193
- } else {
194
- // Overflow occurred
195
- age = (0xFFFFFFFF - it->second.timestamp) + currentTime + 1;
196
- }
197
-
198
- if (age > messageTimeoutMs) {
199
- it = trackedMessages.erase(it);
200
- removedCount++;
201
- } else {
202
- ++it;
203
- }
204
- }
205
-
206
- if (removedCount > 0) {
207
- Log(logger::GENERAL, "MessageTracker: Cleaned up %u expired entries (size=%zu)\n",
208
- removedCount, trackedMessages.size());
209
- }
210
-
211
- return removedCount;
212
- }
213
-
214
- /**
215
- * Get the current number of tracked messages
216
- * @return Number of entries in the tracker
217
- */
218
- size_t size() const {
219
- return trackedMessages.size();
220
- }
221
-
222
- /**
223
- * Check if the tracker is empty
224
- * @return true if no messages are being tracked
225
- */
226
- bool empty() const {
227
- return trackedMessages.empty();
228
- }
229
-
230
- /**
231
- * Clear all tracked messages
232
- */
233
- void clear() {
234
- trackedMessages.clear();
235
- Log(logger::GENERAL, "MessageTracker: Cleared all entries\n");
236
- }
237
-
238
- /**
239
- * Get the maximum number of tracked messages
240
- * @return Configured maximum
241
- */
242
- uint16_t getMaxMessages() const {
243
- return maxTrackedMessages;
244
- }
245
-
246
- /**
247
- * Get the timeout value in milliseconds
248
- * @return Configured timeout
249
- */
250
- uint32_t getTimeoutMs() const {
251
- return messageTimeoutMs;
252
- }
253
-
254
- /**
255
- * Set a new maximum for tracked messages
256
- * If current size exceeds new max, oldest entries will be removed
257
- * @param maxMessages New maximum
258
- */
259
- void setMaxMessages(uint16_t maxMessages) {
260
- maxTrackedMessages = maxMessages;
261
-
262
- // Enforce new limit if needed
263
- while (trackedMessages.size() > maxTrackedMessages) {
264
- enforceMemoryLimit();
265
- }
266
- }
267
-
268
- /**
269
- * Set a new timeout value
270
- * @param timeoutMs New timeout in milliseconds
271
- */
272
- void setTimeoutMs(uint32_t timeoutMs) {
273
- messageTimeoutMs = timeoutMs;
274
- }
275
-
276
- private:
277
- std::map<MessageKey, TrackedMessage> trackedMessages;
278
- uint16_t maxTrackedMessages;
279
- uint32_t messageTimeoutMs;
280
-
281
- /**
282
- * Enforce memory limit by removing the oldest entry
283
- * @return true if an entry was removed, false if tracker was empty
284
- */
285
- bool enforceMemoryLimit() {
286
- if (trackedMessages.empty()) {
287
- return false;
288
- }
289
-
290
- // Find the oldest entry
291
- auto oldest = trackedMessages.begin();
292
- uint32_t oldestTimestamp = oldest->second.timestamp;
293
-
294
- for (auto it = trackedMessages.begin(); it != trackedMessages.end(); ++it) {
295
- if (it->second.timestamp < oldestTimestamp) {
296
- oldest = it;
297
- oldestTimestamp = it->second.timestamp;
298
- }
299
- }
300
-
301
- Log(logger::GENERAL, "MessageTracker: Evicting oldest entry (msg=%u, node=%u) to enforce limit\n",
302
- oldest->first.messageId, oldest->first.originNode);
303
-
304
- trackedMessages.erase(oldest);
305
- return true;
306
- }
307
- };
308
-
309
- } // namespace painlessmesh
310
-
311
- #endif // _PAINLESS_MESH_MESSAGE_TRACKER_HPP_