@alteriom/painlessmesh 1.8.0 → 1.8.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.
- package/CHANGELOG.md +24 -0
- package/README.md +51 -11
- package/examples/multi_bridge/README.md +346 -0
- package/examples/multi_bridge/primary_bridge.ino +96 -0
- package/examples/multi_bridge/regular_node.ino +141 -0
- package/examples/multi_bridge/secondary_bridge.ino +111 -0
- package/examples/queued_alarms/README.md +390 -0
- package/examples/queued_alarms/queued_alarms.ino +265 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/arduino/wifi.hpp +319 -3
- package/src/painlessmesh/mesh.hpp +200 -0
- package/src/painlessmesh/message_queue.hpp +368 -0
- package/src/painlessmesh/plugin.hpp +69 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// Multi-Bridge Example: Secondary Bridge Node
|
|
3
|
+
//
|
|
4
|
+
// This example demonstrates a secondary bridge (priority 5) in a
|
|
5
|
+
// multi-bridge deployment. This provides hot standby redundancy
|
|
6
|
+
// and can handle load if the primary bridge is busy.
|
|
7
|
+
//
|
|
8
|
+
// Features demonstrated:
|
|
9
|
+
// - Secondary bridge with medium priority
|
|
10
|
+
// - Hot standby mode (always ready)
|
|
11
|
+
// - Automatic failover if primary fails
|
|
12
|
+
// - Load balancing support
|
|
13
|
+
//************************************************************
|
|
14
|
+
|
|
15
|
+
#include "painlessMesh.h"
|
|
16
|
+
|
|
17
|
+
#define MESH_PREFIX "MultiBridgeMesh"
|
|
18
|
+
#define MESH_PASSWORD "meshpassword"
|
|
19
|
+
#define MESH_PORT 5555
|
|
20
|
+
|
|
21
|
+
// Secondary router connection (backup Internet or different ISP)
|
|
22
|
+
#define ROUTER_SSID "SecondaryRouter"
|
|
23
|
+
#define ROUTER_PASSWORD "routerpass2"
|
|
24
|
+
|
|
25
|
+
Scheduler userScheduler;
|
|
26
|
+
painlessMesh mesh;
|
|
27
|
+
|
|
28
|
+
// Task to display bridge coordination status
|
|
29
|
+
Task taskBridgeStatus(10000, TASK_FOREVER, [](){
|
|
30
|
+
Serial.println("\n=== Secondary Bridge Status ===");
|
|
31
|
+
Serial.printf("Node ID: %u\n", mesh.getNodeId());
|
|
32
|
+
Serial.printf("Connected Nodes: %d\n", mesh.getNodeList().size());
|
|
33
|
+
|
|
34
|
+
// Show all active bridges in the mesh
|
|
35
|
+
auto activeBridges = mesh.getActiveBridges();
|
|
36
|
+
Serial.printf("Active Bridges: %d\n", activeBridges.size());
|
|
37
|
+
for (auto bridgeId : activeBridges) {
|
|
38
|
+
Serial.printf(" - Bridge: %u%s\n", bridgeId,
|
|
39
|
+
(bridgeId == mesh.getNodeId()) ? " (ME)" : "");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Show recommended bridge for next message
|
|
43
|
+
uint32_t recommended = mesh.getRecommendedBridge();
|
|
44
|
+
Serial.printf("Recommended Bridge: %u\n", recommended);
|
|
45
|
+
|
|
46
|
+
if (recommended == mesh.getNodeId()) {
|
|
47
|
+
Serial.println("⚠️ I AM THE ACTIVE BRIDGE (primary likely failed!)");
|
|
48
|
+
} else {
|
|
49
|
+
Serial.println("✓ Standby mode - primary bridge is active");
|
|
50
|
+
}
|
|
51
|
+
Serial.println("=============================\n");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
55
|
+
Serial.printf("Received from %u: %s\n", from, msg.c_str());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
59
|
+
Serial.printf("New Connection, nodeId = %u\n", nodeId);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void changedConnectionCallback() {
|
|
63
|
+
Serial.printf("Changed connections. Node count: %d\n", mesh.getNodeList().size());
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet) {
|
|
67
|
+
if (hasInternet) {
|
|
68
|
+
Serial.printf("✓ Bridge %u: Internet connected\n", bridgeNodeId);
|
|
69
|
+
} else {
|
|
70
|
+
Serial.printf("⚠️ Bridge %u: Internet OFFLINE\n", bridgeNodeId);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void setup() {
|
|
75
|
+
Serial.begin(115200);
|
|
76
|
+
delay(2000);
|
|
77
|
+
|
|
78
|
+
Serial.println("\n\n=== Multi-Bridge: SECONDARY BRIDGE ===\n");
|
|
79
|
+
|
|
80
|
+
// Initialize mesh as secondary bridge with priority 5
|
|
81
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
82
|
+
|
|
83
|
+
// Enable multi-bridge coordination mode
|
|
84
|
+
mesh.enableMultiBridge(true);
|
|
85
|
+
|
|
86
|
+
// Set bridge selection strategy (PRIORITY_BASED is default)
|
|
87
|
+
mesh.setBridgeSelectionStrategy(painlessMesh::PRIORITY_BASED);
|
|
88
|
+
|
|
89
|
+
// Initialize as bridge with priority 5 (secondary)
|
|
90
|
+
mesh.initAsBridge(MESH_PREFIX, MESH_PASSWORD,
|
|
91
|
+
ROUTER_SSID, ROUTER_PASSWORD,
|
|
92
|
+
&userScheduler, MESH_PORT, 5); // Priority 5 = Secondary
|
|
93
|
+
|
|
94
|
+
mesh.onReceive(&receivedCallback);
|
|
95
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
96
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
97
|
+
mesh.onBridgeStatusChanged(&bridgeStatusCallback);
|
|
98
|
+
|
|
99
|
+
// Add status reporting task
|
|
100
|
+
userScheduler.addTask(taskBridgeStatus);
|
|
101
|
+
taskBridgeStatus.enable();
|
|
102
|
+
|
|
103
|
+
Serial.println("\n=== Secondary Bridge Ready ===");
|
|
104
|
+
Serial.println("This node is the SECONDARY bridge (Priority 5)");
|
|
105
|
+
Serial.println("It operates in hot standby mode");
|
|
106
|
+
Serial.println("Will take over if primary bridge fails\n");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
void loop() {
|
|
110
|
+
mesh.update();
|
|
111
|
+
}
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# Queued Alarms Example
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This example demonstrates **priority-based message queueing** for critical IoT systems that cannot afford to lose data during Internet outages. It's designed for the fish farm dissolved oxygen (O2) monitoring use case described in [Issue #66](https://github.com/Alteriom/painlessMesh/issues/66).
|
|
6
|
+
|
|
7
|
+
## Problem Statement
|
|
8
|
+
|
|
9
|
+
In production IoT systems like fish farm monitoring, **critical alarms must never be lost**. When the bridge node loses Internet connectivity:
|
|
10
|
+
|
|
11
|
+
- ❌ **Without queueing**: Critical O2 alarms are lost → fish die
|
|
12
|
+
- ✅ **With queueing**: Alarms are queued and delivered when connection restored → supervisor notified, fish saved
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
### ✅ Priority-Based Queueing
|
|
17
|
+
|
|
18
|
+
- **CRITICAL** (Priority 0): Life-safety alarms - never dropped
|
|
19
|
+
- **HIGH** (Priority 1): Important warnings - preserved up to 80% capacity
|
|
20
|
+
- **NORMAL** (Priority 2): Regular data - preserved up to 60% capacity
|
|
21
|
+
- **LOW** (Priority 3): Telemetry - dropped first when queue full
|
|
22
|
+
|
|
23
|
+
### ✅ Automatic Queue Management
|
|
24
|
+
|
|
25
|
+
- Queues messages when Internet unavailable
|
|
26
|
+
- Flushes queue when Internet restored
|
|
27
|
+
- Prunes old messages (configurable age)
|
|
28
|
+
- Monitors queue health with callbacks
|
|
29
|
+
|
|
30
|
+
### ✅ Production Ready
|
|
31
|
+
|
|
32
|
+
- Survives Internet outages (queuing)
|
|
33
|
+
- Handles queue overflow intelligently
|
|
34
|
+
- Provides queue statistics
|
|
35
|
+
- Retry logic with attempt tracking
|
|
36
|
+
|
|
37
|
+
## Hardware Requirements
|
|
38
|
+
|
|
39
|
+
- **ESP32** or **ESP8266**
|
|
40
|
+
- At least 2 nodes (1 bridge + 1 sensor node)
|
|
41
|
+
- Bridge node needs WiFi router access
|
|
42
|
+
|
|
43
|
+
## Configuration
|
|
44
|
+
|
|
45
|
+
### 1. Mesh Network Settings
|
|
46
|
+
|
|
47
|
+
```cpp
|
|
48
|
+
#define MESH_PREFIX "FishFarmMesh"
|
|
49
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
50
|
+
#define MESH_PORT 5555
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Router Credentials (Bridge Node)
|
|
54
|
+
|
|
55
|
+
```cpp
|
|
56
|
+
#define ROUTER_SSID "YourWiFiSSID"
|
|
57
|
+
#define ROUTER_PASSWORD "YourWiFiPassword"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Enable in setup for bridge node:
|
|
61
|
+
```cpp
|
|
62
|
+
mesh.stationManual(ROUTER_SSID, ROUTER_PASSWORD);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 3. Sensor Thresholds
|
|
66
|
+
|
|
67
|
+
Adjust for your sensors (dissolved oxygen in mg/L):
|
|
68
|
+
|
|
69
|
+
```cpp
|
|
70
|
+
#define CRITICAL_O2_THRESHOLD 3.0 // Life-critical
|
|
71
|
+
#define WARNING_O2_THRESHOLD 5.0 // Warning level
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. Queue Configuration
|
|
75
|
+
|
|
76
|
+
```cpp
|
|
77
|
+
#define MAX_QUEUE_SIZE 500 // Max messages
|
|
78
|
+
#define QUEUE_PRUNE_AGE (24 * 60 * 60 * 1000) // 24 hours
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## How It Works
|
|
82
|
+
|
|
83
|
+
### Normal Operation (Internet Available)
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Sensor → Mesh → Bridge → Internet → Cloud/MQTT
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Messages sent immediately, no queueing.
|
|
90
|
+
|
|
91
|
+
### Offline Mode (No Internet)
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Sensor → Mesh → Bridge → Queue (Priority-based)
|
|
95
|
+
↓
|
|
96
|
+
[CRITICAL never dropped]
|
|
97
|
+
[LOW dropped first]
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Messages queued with priority, delivered when Internet restored.
|
|
101
|
+
|
|
102
|
+
### Internet Restored
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Queue → Flush → MQTT/HTTP → Cloud
|
|
106
|
+
↓
|
|
107
|
+
Remove on success
|
|
108
|
+
Retry on failure (max 3 attempts)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Usage
|
|
112
|
+
|
|
113
|
+
### 1. Flash Bridge Node
|
|
114
|
+
|
|
115
|
+
1. Uncomment these lines in `setup()`:
|
|
116
|
+
```cpp
|
|
117
|
+
mesh.stationManual(ROUTER_SSID, ROUTER_PASSWORD);
|
|
118
|
+
mesh.setHostname("FishFarmBridge");
|
|
119
|
+
```
|
|
120
|
+
2. Upload to ESP32/ESP8266 with router access
|
|
121
|
+
3. Bridge connects to router and provides Internet to mesh
|
|
122
|
+
|
|
123
|
+
### 2. Flash Sensor Nodes
|
|
124
|
+
|
|
125
|
+
1. Leave router lines commented
|
|
126
|
+
2. Upload to sensor node ESP32/ESP8266
|
|
127
|
+
3. Node joins mesh and monitors sensors
|
|
128
|
+
|
|
129
|
+
### 3. Monitor Serial Output
|
|
130
|
+
|
|
131
|
+
**Normal operation:**
|
|
132
|
+
```
|
|
133
|
+
✅ ONLINE MODE - Internet restored
|
|
134
|
+
📊 Telemetry: 7.32 mg/L
|
|
135
|
+
📊 Telemetry: 6.85 mg/L
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Internet lost:**
|
|
139
|
+
```
|
|
140
|
+
⚠️ OFFLINE MODE ACTIVATED
|
|
141
|
+
Queue size: 0 messages
|
|
142
|
+
📊 Telemetry: 6.42 mg/L - queued #1
|
|
143
|
+
[Queue: 1 messages]
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Critical alarm (offline):**
|
|
147
|
+
```
|
|
148
|
+
🚨 CRITICAL O2 ALARM: 2.87 mg/L - QUEUED #5
|
|
149
|
+
[Queue: 5 messages (1 CRITICAL)]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Internet restored:**
|
|
153
|
+
```
|
|
154
|
+
✅ ONLINE MODE - Internet restored
|
|
155
|
+
Flushing 5 queued messages...
|
|
156
|
+
Sending queued message #1 (priority=3, attempts=0)
|
|
157
|
+
Sending queued message #5 (priority=0, attempts=0)
|
|
158
|
+
✅ Queue flushed (5 messages sent)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Queue States
|
|
162
|
+
|
|
163
|
+
The example monitors queue health:
|
|
164
|
+
|
|
165
|
+
- **EMPTY**: No messages queued
|
|
166
|
+
- **NORMAL**: Queue has space available
|
|
167
|
+
- **75% FULL**: Warning - queue reaching capacity
|
|
168
|
+
- **FULL**: Queue full - dropping LOW priority messages
|
|
169
|
+
|
|
170
|
+
Example output:
|
|
171
|
+
```
|
|
172
|
+
⚠️ Queue 75% full (375 messages)
|
|
173
|
+
🚨 Queue FULL (500 messages) - dropping LOW priority
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Testing Without Hardware
|
|
177
|
+
|
|
178
|
+
### Simulate Internet Loss
|
|
179
|
+
|
|
180
|
+
In real deployment, Internet loss is automatic. For testing, you can:
|
|
181
|
+
|
|
182
|
+
1. **Disconnect router**: Physically disconnect Ethernet/WAN
|
|
183
|
+
2. **Block MAC address**: Router settings → Block bridge MAC
|
|
184
|
+
3. **Power cycle router**: Turn off router
|
|
185
|
+
4. **Modify code**: Add test button to toggle `offlineMode`
|
|
186
|
+
|
|
187
|
+
### Verify Queue Behavior
|
|
188
|
+
|
|
189
|
+
1. Start with Internet connected
|
|
190
|
+
2. Cause Internet loss (any method above)
|
|
191
|
+
3. Wait for critical alarms to queue
|
|
192
|
+
4. Restore Internet
|
|
193
|
+
5. Verify messages are flushed
|
|
194
|
+
|
|
195
|
+
Expected sequence:
|
|
196
|
+
```
|
|
197
|
+
✅ Online → ⚠️ Offline (queueing) → ✅ Online (flush queue)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Integration with Cloud Services
|
|
201
|
+
|
|
202
|
+
### MQTT Example
|
|
203
|
+
|
|
204
|
+
Replace simulated sending with MQTT:
|
|
205
|
+
|
|
206
|
+
```cpp
|
|
207
|
+
#include <PubSubClient.h>
|
|
208
|
+
|
|
209
|
+
WiFiClient wifiClient;
|
|
210
|
+
PubSubClient mqttClient(wifiClient);
|
|
211
|
+
|
|
212
|
+
// In setup()
|
|
213
|
+
mqttClient.setServer("mqtt.example.com", 1883);
|
|
214
|
+
|
|
215
|
+
// In bridgeStatusCallback()
|
|
216
|
+
for (auto& msg : messages) {
|
|
217
|
+
bool sent = mqttClient.publish(
|
|
218
|
+
msg.destination.c_str(), // Topic from queueMessage()
|
|
219
|
+
msg.payload.c_str()
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
if (sent) {
|
|
223
|
+
mesh.removeQueuedMessage(msg.id);
|
|
224
|
+
} else {
|
|
225
|
+
mesh.incrementQueuedMessageAttempts(msg.id);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### HTTP Example
|
|
231
|
+
|
|
232
|
+
Replace simulated sending with HTTP POST:
|
|
233
|
+
|
|
234
|
+
```cpp
|
|
235
|
+
#include <HTTPClient.h>
|
|
236
|
+
|
|
237
|
+
HTTPClient http;
|
|
238
|
+
|
|
239
|
+
for (auto& msg : messages) {
|
|
240
|
+
http.begin(msg.destination); // URL from queueMessage()
|
|
241
|
+
http.addHeader("Content-Type", "application/json");
|
|
242
|
+
|
|
243
|
+
int httpCode = http.POST(msg.payload);
|
|
244
|
+
bool sent = (httpCode == 200 || httpCode == 201);
|
|
245
|
+
|
|
246
|
+
if (sent) {
|
|
247
|
+
mesh.removeQueuedMessage(msg.id);
|
|
248
|
+
} else {
|
|
249
|
+
mesh.incrementQueuedMessageAttempts(msg.id);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
http.end();
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Message Format
|
|
257
|
+
|
|
258
|
+
Example JSON message structure:
|
|
259
|
+
|
|
260
|
+
### Critical Alarm
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"type": "CRITICAL_ALARM",
|
|
264
|
+
"sensor": "O2",
|
|
265
|
+
"value": 2.87,
|
|
266
|
+
"threshold": 3.0,
|
|
267
|
+
"tankId": "TANK_A",
|
|
268
|
+
"nodeId": 123456789,
|
|
269
|
+
"timestamp": 1234567890
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### Warning
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"type": "WARNING",
|
|
277
|
+
"sensor": "O2",
|
|
278
|
+
"value": 4.5,
|
|
279
|
+
"threshold": 5.0,
|
|
280
|
+
"nodeId": 123456789
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Telemetry
|
|
285
|
+
```json
|
|
286
|
+
{
|
|
287
|
+
"sensor": "O2",
|
|
288
|
+
"value": 7.32,
|
|
289
|
+
"nodeId": 123456789
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## API Reference
|
|
294
|
+
|
|
295
|
+
### Enable Queue
|
|
296
|
+
|
|
297
|
+
```cpp
|
|
298
|
+
mesh.enableMessageQueue(true, MAX_QUEUE_SIZE);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Queue Message
|
|
302
|
+
|
|
303
|
+
```cpp
|
|
304
|
+
uint32_t msgId = mesh.queueMessage(
|
|
305
|
+
payload, // Message content
|
|
306
|
+
destination, // Cloud endpoint/topic
|
|
307
|
+
PRIORITY_CRITICAL // Priority level
|
|
308
|
+
);
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Flush Queue
|
|
312
|
+
|
|
313
|
+
```cpp
|
|
314
|
+
auto messages = mesh.flushMessageQueue();
|
|
315
|
+
for (auto& msg : messages) {
|
|
316
|
+
if (sendToCloud(msg)) {
|
|
317
|
+
mesh.removeQueuedMessage(msg.id);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Query Queue
|
|
323
|
+
|
|
324
|
+
```cpp
|
|
325
|
+
uint32_t total = mesh.getQueuedMessageCount();
|
|
326
|
+
uint32_t critical = mesh.getQueuedMessageCount(PRIORITY_CRITICAL);
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### Callbacks
|
|
330
|
+
|
|
331
|
+
```cpp
|
|
332
|
+
mesh.onBridgeStatusChanged([](uint32_t bridgeId, bool hasInternet) {
|
|
333
|
+
// Handle Internet connectivity change
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
mesh.onQueueStateChanged([](QueueState state, uint32_t count) {
|
|
337
|
+
// Handle queue state change (EMPTY, NORMAL, 75%, FULL)
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Troubleshooting
|
|
342
|
+
|
|
343
|
+
### Queue Always Full
|
|
344
|
+
|
|
345
|
+
- Increase `MAX_QUEUE_SIZE`
|
|
346
|
+
- Decrease message frequency
|
|
347
|
+
- Lower message priorities
|
|
348
|
+
- Reduce `QUEUE_PRUNE_AGE`
|
|
349
|
+
|
|
350
|
+
### Messages Not Flushing
|
|
351
|
+
|
|
352
|
+
- Check `bridgeStatusCallback()` is called
|
|
353
|
+
- Verify Internet connectivity with `mesh.hasInternetConnection()`
|
|
354
|
+
- Check MQTT/HTTP sending code
|
|
355
|
+
- Monitor serial for errors
|
|
356
|
+
|
|
357
|
+
### High Memory Usage
|
|
358
|
+
|
|
359
|
+
- Reduce `MAX_QUEUE_SIZE`
|
|
360
|
+
- Enable aggressive pruning
|
|
361
|
+
- Use shorter message payloads
|
|
362
|
+
- Monitor with `ESP.getFreeHeap()`
|
|
363
|
+
|
|
364
|
+
## Performance
|
|
365
|
+
|
|
366
|
+
### Memory Usage
|
|
367
|
+
|
|
368
|
+
| Queue Size | RAM Usage (approx) |
|
|
369
|
+
|------------|-------------------|
|
|
370
|
+
| 100 | ~20 KB |
|
|
371
|
+
| 500 | ~100 KB |
|
|
372
|
+
| 1000 | ~200 KB |
|
|
373
|
+
|
|
374
|
+
**ESP32**: Can handle 1000+ messages
|
|
375
|
+
**ESP8266**: Recommend ≤500 messages
|
|
376
|
+
|
|
377
|
+
### Throughput
|
|
378
|
+
|
|
379
|
+
- **Queue**: ~1000 msg/sec
|
|
380
|
+
- **Flush**: Limited by MQTT/HTTP send rate (~10-50 msg/sec)
|
|
381
|
+
|
|
382
|
+
## Related Documentation
|
|
383
|
+
|
|
384
|
+
- [Issue #66: Message Queueing Feature](https://github.com/Alteriom/painlessMesh/issues/66)
|
|
385
|
+
- [Issue #63: Bridge Status Broadcast](https://github.com/Alteriom/painlessMesh/issues/63)
|
|
386
|
+
- [painlessMesh Documentation](https://gitlab.com/painlessMesh/painlessMesh)
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT License - See repository LICENSE file
|