@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.
- package/BRIDGE_TO_INTERNET.md +167 -29
- package/CHANGELOG.md +483 -0
- package/CONTRIBUTING.md +56 -53
- package/README.md +100 -95
- package/RELEASE_GUIDE.md +81 -780
- package/examples/alteriom/README.md +8 -10
- package/examples/alteriom/alteriom.ino +2 -2
- package/examples/alteriom/alteriom_sensor_package.hpp +17 -11
- package/examples/alteriom/mppt_example/alteriom_custom_package_template.hpp +320 -0
- package/examples/alteriom/mppt_example/alteriom_sensor_package.hpp +1389 -0
- package/examples/alteriom/mppt_example/{alteriom_mppt_example.ino → mppt_example.ino} +4 -0
- package/examples/basic/test/simulator/README.md +3 -3
- package/examples/bridge_failover/README.md +51 -14
- package/examples/commandControl/commandControl.ino +86 -0
- package/examples/commandControl/platformio.ini +26 -0
- package/examples/mqttBridge/mqttBridge.ino +4 -0
- package/examples/mqttBridge/platformio.ini +1 -1
- package/examples/otaSender/otaSender.ino +5 -1
- package/examples/priority/README.md +1 -1
- package/examples/priority/{priority_basic_example.ino → priority_basic_example/priority_basic_example.ino} +4 -4
- package/examples/priority/{priority_with_queue.ino → priority_with_queue/priority_with_queue.ino} +20 -2
- package/examples/reliableSensorLogging/platformio.ini +26 -0
- package/examples/reliableSensorLogging/reliableSensorLogging.ino +151 -0
- package/examples/sendToInternet/README.md +12 -5
- package/examples/sendToInternet/{CMakeLists.txt → pc_node/CMakeLists.txt} +7 -7
- package/examples/sendToInternet/{PC_NODE_README.md → pc_node/PC_NODE_README.md} +15 -15
- package/examples/sendToInternet/{build.sh → pc_node/build.sh} +5 -5
- package/examples/sendToInternet/{pc_mesh_node.cpp → pc_node/pc_mesh_node.cpp} +12 -1
- package/examples/sharedGateway/README.md +1 -2
- package/keywords.txt +50 -1
- package/library.json +8 -6
- package/library.properties +2 -2
- package/package.json +3 -3
- package/src/AlteriomPainlessMesh.h +3 -3
- package/src/arduino/wifi.hpp +556 -126
- package/src/painlessMesh.h +2 -2
- package/src/painlessMeshSTA.cpp +607 -87
- package/src/painlessMeshSTA.h +135 -3
- package/src/painlessmesh/ack.hpp +283 -0
- package/src/painlessmesh/buffer.hpp +70 -8
- package/src/painlessmesh/callback.hpp +38 -5
- package/src/painlessmesh/configuration.hpp +69 -1
- package/src/painlessmesh/connection.hpp +12 -5
- package/src/painlessmesh/gateway.hpp +270 -5
- package/src/painlessmesh/layout.hpp +70 -2
- package/src/painlessmesh/logger.hpp +15 -0
- package/src/painlessmesh/mesh.hpp +552 -48
- package/src/painlessmesh/ntp.hpp +2 -4
- package/src/painlessmesh/plugin.hpp +30 -6
- package/src/painlessmesh/protocol.hpp +55 -2
- package/src/painlessmesh/router.hpp +192 -77
- package/src/painlessmesh/tcp.hpp +10 -0
- package/src/painlessmesh/message_tracker.hpp +0 -311
- /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_
|
/package/examples/sendToInternet/{mock_server_test.ino → mock_server_test/mock_server_test.ino}
RENAMED
|
File without changes
|