@alteriom/painlessmesh 1.8.0 → 1.8.2

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.
@@ -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
@@ -0,0 +1,265 @@
1
+ //************************************************************
2
+ // Queued Alarms Example - Message Queueing for Offline Mode
3
+ //
4
+ // Demonstrates priority-based message queueing for critical alarms
5
+ // when Internet connection is unavailable. Perfect for IoT systems
6
+ // that cannot afford to lose critical data.
7
+ //
8
+ // Use Case: Fish farm dissolved oxygen monitoring
9
+ // - CRITICAL alarms (low O2) must never be lost
10
+ // - Queue messages during Internet outages
11
+ // - Automatic delivery when connection restored
12
+ //
13
+ // Hardware: ESP32 or ESP8266
14
+ //************************************************************
15
+
16
+ #include "painlessMesh.h"
17
+
18
+ // Mesh configuration
19
+ #define MESH_PREFIX "FishFarmMesh"
20
+ #define MESH_PASSWORD "somethingSneaky"
21
+ #define MESH_PORT 5555
22
+
23
+ // Router credentials for bridge node
24
+ #define ROUTER_SSID "YourWiFiSSID"
25
+ #define ROUTER_PASSWORD "YourWiFiPassword"
26
+
27
+ // Sensor thresholds (mg/L for dissolved oxygen)
28
+ #define CRITICAL_O2_THRESHOLD 3.0
29
+ #define WARNING_O2_THRESHOLD 5.0
30
+
31
+ // Queue configuration
32
+ #define MAX_QUEUE_SIZE 500
33
+ #define QUEUE_PRUNE_AGE (24 * 60 * 60 * 1000) // 24 hours in ms
34
+
35
+ Scheduler userScheduler;
36
+ painlessMesh mesh;
37
+
38
+ bool offlineMode = false;
39
+ uint32_t lastO2Check = 0;
40
+ uint32_t lastQueuePrune = 0;
41
+
42
+ // Simulated sensor reading (replace with actual sensor code)
43
+ float readDissolvedOxygenSensor() {
44
+ // In real application, read from actual sensor
45
+ // For demo, simulate varying O2 levels
46
+ static float o2Level = 7.0;
47
+ o2Level += random(-20, 20) / 10.0; // +/- 2.0 mg/L variation
48
+ o2Level = constrain(o2Level, 2.0, 10.0);
49
+ return o2Level;
50
+ }
51
+
52
+ // Send critical O2 alarm
53
+ void sendCriticalAlarm(float o2Level) {
54
+ // Create alarm message (in real app, use JSON)
55
+ String payload = String("{\"type\":\"CRITICAL_ALARM\",\"sensor\":\"O2\",\"value\":")
56
+ + String(o2Level, 2) + ",\"threshold\":"
57
+ + String(CRITICAL_O2_THRESHOLD, 2) + ",\"tankId\":\"TANK_A\",\"nodeId\":"
58
+ + mesh.getNodeId() + ",\"timestamp\":" + mesh.getNodeTime() + "}";
59
+
60
+ if (offlineMode || !mesh.hasInternetConnection()) {
61
+ // CRITICAL: Queue for guaranteed delivery
62
+ uint32_t msgId = mesh.queueMessage(
63
+ payload,
64
+ "mqtt://cloud.farm.com/alarms/critical",
65
+ PRIORITY_CRITICAL
66
+ );
67
+
68
+ if (msgId) {
69
+ Serial.printf("🚨 CRITICAL O2 ALARM: %.2f mg/L - QUEUED #%u\n", o2Level, msgId);
70
+ } else {
71
+ Serial.printf("🚨 CRITICAL O2 ALARM: %.2f mg/L - QUEUE FAILED!\n", o2Level);
72
+ }
73
+ } else {
74
+ // Send immediately via bridge (in real app, use MQTT client)
75
+ Serial.printf("🚨 CRITICAL O2 ALARM: %.2f mg/L - SENT IMMEDIATELY\n", o2Level);
76
+ // mqttClient.publish("alarms/critical", payload.c_str());
77
+ }
78
+ }
79
+
80
+ // Send warning alarm
81
+ void sendWarningAlarm(float o2Level) {
82
+ String payload = String("{\"type\":\"WARNING\",\"sensor\":\"O2\",\"value\":")
83
+ + String(o2Level, 2) + ",\"threshold\":"
84
+ + String(WARNING_O2_THRESHOLD, 2) + ",\"nodeId\":"
85
+ + mesh.getNodeId() + "}";
86
+
87
+ if (offlineMode) {
88
+ uint32_t msgId = mesh.queueMessage(
89
+ payload,
90
+ "mqtt://cloud.farm.com/alarms/warning",
91
+ PRIORITY_HIGH
92
+ );
93
+
94
+ if (msgId) {
95
+ Serial.printf("⚠️ WARNING O2: %.2f mg/L - QUEUED #%u\n", o2Level, msgId);
96
+ } else {
97
+ Serial.printf("⚠️ WARNING O2: %.2f mg/L - QUEUE FULL\n", o2Level);
98
+ }
99
+ } else {
100
+ Serial.printf("⚠️ WARNING O2: %.2f mg/L - SENT\n", o2Level);
101
+ }
102
+ }
103
+
104
+ // Send normal telemetry
105
+ void sendNormalTelemetry(float o2Level) {
106
+ String payload = String("{\"sensor\":\"O2\",\"value\":") + String(o2Level, 2)
107
+ + ",\"nodeId\":" + mesh.getNodeId() + "}";
108
+
109
+ if (offlineMode) {
110
+ // Low priority - queue only if space available
111
+ uint32_t msgId = mesh.queueMessage(
112
+ payload,
113
+ "mqtt://cloud.farm.com/telemetry",
114
+ PRIORITY_LOW
115
+ );
116
+
117
+ if (msgId) {
118
+ Serial.printf("📊 Telemetry: %.2f mg/L - queued #%u\n", o2Level, msgId);
119
+ } else {
120
+ Serial.printf("📊 Telemetry: %.2f mg/L - dropped (queue full)\n", o2Level);
121
+ }
122
+ } else {
123
+ Serial.printf("📊 Telemetry: %.2f mg/L\n", o2Level);
124
+ }
125
+ }
126
+
127
+ // Check O2 sensor and send appropriate message
128
+ void checkO2Sensor() {
129
+ float o2Level = readDissolvedOxygenSensor();
130
+
131
+ if (o2Level < CRITICAL_O2_THRESHOLD) {
132
+ sendCriticalAlarm(o2Level);
133
+ } else if (o2Level < WARNING_O2_THRESHOLD) {
134
+ sendWarningAlarm(o2Level);
135
+ } else {
136
+ sendNormalTelemetry(o2Level);
137
+ }
138
+ }
139
+
140
+ // Bridge status callback - Internet connectivity changed
141
+ void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet) {
142
+ if (!hasInternet) {
143
+ offlineMode = true;
144
+ Serial.println("\n⚠️ OFFLINE MODE ACTIVATED");
145
+ Serial.printf(" Bridge node %u lost Internet\n", bridgeNodeId);
146
+ Serial.printf(" Queue size: %u messages\n", mesh.getQueuedMessageCount());
147
+
148
+ uint32_t critical = mesh.getQueuedMessageCount(PRIORITY_CRITICAL);
149
+ if (critical > 0) {
150
+ Serial.printf(" ⚠️ %u CRITICAL messages queued!\n", critical);
151
+ }
152
+ } else {
153
+ offlineMode = false;
154
+ Serial.println("\n✅ ONLINE MODE - Internet restored");
155
+ Serial.printf(" Bridge node %u has Internet\n", bridgeNodeId);
156
+
157
+ // Flush queued messages
158
+ uint32_t queuedCount = mesh.getQueuedMessageCount();
159
+ if (queuedCount > 0) {
160
+ Serial.printf(" Flushing %u queued messages...\n", queuedCount);
161
+
162
+ auto messages = mesh.flushMessageQueue();
163
+ for (auto& msg : messages) {
164
+ // In real application, send via MQTT or HTTP
165
+ Serial.printf(" Sending queued message #%u (priority=%d, attempts=%u)\n",
166
+ msg.id, msg.priority, msg.attempts);
167
+
168
+ // Simulate sending (in real app, check if send succeeded)
169
+ bool sent = true; // Replace with: mqttClient.publish(...)
170
+
171
+ if (sent) {
172
+ mesh.removeQueuedMessage(msg.id);
173
+ } else {
174
+ // Increment attempt counter
175
+ mesh.incrementQueuedMessageAttempts(msg.id);
176
+
177
+ // Remove if too many attempts
178
+ if (msg.attempts >= 3) {
179
+ Serial.printf(" ❌ Message #%u failed after 3 attempts, removing\n", msg.id);
180
+ mesh.removeQueuedMessage(msg.id);
181
+ }
182
+ }
183
+ }
184
+
185
+ Serial.printf(" ✅ Queue flushed (%u messages sent)\n", queuedCount);
186
+ }
187
+ }
188
+ }
189
+
190
+ // Queue state callback - Monitor queue health
191
+ void queueStateCallback(QueueState state, uint32_t messageCount) {
192
+ switch (state) {
193
+ case QUEUE_EMPTY:
194
+ Serial.println("ℹ️ Queue empty");
195
+ break;
196
+ case QUEUE_NORMAL:
197
+ Serial.printf("ℹ️ Queue normal (%u messages)\n", messageCount);
198
+ break;
199
+ case QUEUE_75_PERCENT:
200
+ Serial.printf("⚠️ Queue 75%% full (%u messages)\n", messageCount);
201
+ break;
202
+ case QUEUE_FULL:
203
+ Serial.printf("🚨 Queue FULL (%u messages) - dropping LOW priority\n", messageCount);
204
+ break;
205
+ }
206
+ }
207
+
208
+ void setup() {
209
+ Serial.begin(115200);
210
+ Serial.println("\n\n=== Fish Farm O2 Monitoring with Message Queue ===\n");
211
+
212
+ // Initialize mesh
213
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
214
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
215
+
216
+ // For bridge node: set router credentials
217
+ // Uncomment if this is the bridge node
218
+ // mesh.stationManual(ROUTER_SSID, ROUTER_PASSWORD);
219
+ // mesh.setHostname("FishFarmBridge");
220
+
221
+ // Enable message queue
222
+ mesh.enableMessageQueue(true, MAX_QUEUE_SIZE);
223
+ Serial.printf("Message queue enabled (capacity: %u)\n", MAX_QUEUE_SIZE);
224
+
225
+ // Set callbacks
226
+ mesh.onBridgeStatusChanged(&bridgeStatusCallback);
227
+ mesh.onQueueStateChanged(&queueStateCallback);
228
+
229
+ Serial.println("Setup complete. Monitoring O2 levels...\n");
230
+
231
+ // Initialize random for sensor simulation
232
+ randomSeed(analogRead(0));
233
+ }
234
+
235
+ void loop() {
236
+ mesh.update();
237
+
238
+ // Check O2 sensor every 10 seconds
239
+ if (millis() - lastO2Check > 10000) {
240
+ lastO2Check = millis();
241
+ checkO2Sensor();
242
+
243
+ // Print queue status
244
+ uint32_t queueSize = mesh.getQueuedMessageCount();
245
+ if (queueSize > 0) {
246
+ Serial.printf(" [Queue: %u messages", queueSize);
247
+
248
+ uint32_t critical = mesh.getQueuedMessageCount(PRIORITY_CRITICAL);
249
+ if (critical > 0) {
250
+ Serial.printf(" (%u CRITICAL)", critical);
251
+ }
252
+
253
+ Serial.println("]");
254
+ }
255
+ }
256
+
257
+ // Prune old messages every hour
258
+ if (millis() - lastQueuePrune > 3600000) {
259
+ lastQueuePrune = millis();
260
+ uint32_t pruned = mesh.pruneQueue(QUEUE_PRUNE_AGE);
261
+ if (pruned > 0) {
262
+ Serial.printf("ℹ️ Pruned %u old messages from queue\n", pruned);
263
+ }
264
+ }
265
+ }
package/library.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "type": "git",
7
7
  "url": "https://github.com/Alteriom/painlessMesh"
8
8
  },
9
- "version": "1.8.0",
9
+ "version": "1.8.2",
10
10
  "frameworks": [
11
11
  "arduino"
12
12
  ],
@@ -78,17 +78,36 @@
78
78
  ],
79
79
  "examples": [
80
80
  "examples/alteriom/alteriom.ino",
81
- "examples/alteriom/alteriom_sensor_node.ino",
82
- "examples/alteriom/improved_sensor_node.ino",
81
+ "examples/alteriomSensorNode/alteriom_sensor_node.ino",
82
+ "examples/alteriomImproved/improved_sensor_node.ino",
83
+ "examples/alteriomMetricsHealth/metrics_health_node.ino",
84
+ "examples/alteriomPhase1/phase1_features.ino",
85
+ "examples/alteriomPhase2/phase2_features.ino",
83
86
  "examples/basic/basic.ino",
84
87
  "examples/bridge/bridge.ino",
88
+ "examples/bridge/bridge_health_monitoring_example.ino",
89
+ "examples/bridge/enhanced_mqtt_bridge_example.ino",
90
+ "examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino",
91
+ "examples/bridge_failover/bridge_failover.ino",
92
+ "examples/diagnosticsExample/diagnosticsExample.ino",
85
93
  "examples/echoNode/echoNode.ino",
86
94
  "examples/logClient/logClient.ino",
87
95
  "examples/logServer/logServer.ino",
96
+ "examples/meshCommandNode/meshCommandNode.ino",
88
97
  "examples/mqttBridge/mqttBridge.ino",
98
+ "examples/mqttCommandBridge/mqttCommandBridge.ino",
99
+ "examples/mqttStatusBridge/mqttStatusBridge.ino",
100
+ "examples/mqttTopologyTest/mqttTopologyTest.ino",
101
+ "examples/multi_bridge/primary_bridge.ino",
102
+ "examples/multi_bridge/secondary_bridge.ino",
103
+ "examples/multi_bridge/regular_node.ino",
89
104
  "examples/namedMesh/namedMesh.ino",
105
+ "examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino",
106
+ "examples/ntpTimeSyncNode/ntpTimeSyncNode.ino",
90
107
  "examples/otaReceiver/otaReceiver.ino",
91
108
  "examples/otaSender/otaSender.ino",
109
+ "examples/queued_alarms/queued_alarms.ino",
110
+ "examples/rtcIntegration/rtcIntegration.ino",
92
111
  "examples/startHere/startHere.ino",
93
112
  "examples/webServer/webServer.ino"
94
113
  ]
@@ -1,5 +1,5 @@
1
1
  name=AlteriomPainlessMesh
2
- version=1.8.0
2
+ version=1.8.2
3
3
  author=Coopdis,Scotty Franzyshen,Edwin van Leeuwen,Germán Martín,Maximilian Schwarz,Doanh Doanh,Alteriom
4
4
  maintainer=Alteriom
5
5
  sentence=A painless way to setup a mesh with ESP8266 and ESP32 devices with Alteriom extensions