@alteriom/painlessmesh 1.7.8 ā 1.8.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/CHANGELOG.md +139 -3
- package/README.md +114 -4
- package/RELEASE_GUIDE.md +57 -8
- package/docs/BRIDGE_FAILOVER.md +512 -0
- package/docs/BRIDGE_HEALTH_MONITORING.md +293 -0
- package/docs/CREATE_MISSING_RELEASES.md +321 -0
- package/docs/README.md +2 -1
- package/docs/RELEASE_AGENT_SUMMARY.md +386 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.8.md +523 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.9.md +542 -0
- package/docs/troubleshooting/ESP32_C6_COMPATIBILITY.md +157 -0
- package/docs/troubleshooting/common-issues.md +28 -0
- package/examples/alteriom/alteriom_sensor_package.hpp +233 -1
- package/examples/alteriom/platformio.ini +1 -1
- package/examples/alteriomImproved/platformio.ini +1 -1
- package/examples/alteriomMetricsHealth/metrics_health_node.ino +18 -7
- package/examples/alteriomMetricsHealth/platformio.ini +1 -1
- package/examples/alteriomPhase1/platformio.ini +1 -1
- package/examples/alteriomPhase2/platformio.ini +1 -1
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +1014 -11
- package/examples/alteriomSensorNode/platformio.ini +1 -1
- package/examples/basic/basic.ino +6 -2
- package/examples/basic/platformio.ini +1 -1
- package/examples/bridge/alteriom_sensor_package.hpp +1170 -0
- package/examples/bridge/bridge.ino +44 -23
- package/examples/bridge/bridge_health_monitoring_example.ino +188 -0
- package/examples/bridge/enhanced_mqtt_bridge.hpp +1 -1
- package/examples/bridge/mqtt_command_bridge.hpp +2 -2
- package/examples/bridge/platformio.ini +2 -1
- package/examples/bridgeAwareSensorNode/alteriom_sensor_package.hpp +1227 -0
- package/examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino +343 -0
- package/examples/bridgeAwareSensorNode/platformio.ini +26 -0
- package/examples/bridge_failover/README.md +358 -0
- package/examples/bridge_failover/bridge_failover.ino +180 -0
- package/examples/bridge_failover/platformio.ini +27 -0
- package/examples/diagnosticsExample/diagnosticsExample.ino +171 -0
- package/examples/diagnosticsExample/platformio.ini +26 -0
- package/examples/echoNode/platformio.ini +1 -1
- package/examples/logClient/platformio.ini +1 -1
- package/examples/logServer/platformio.ini +1 -1
- package/examples/mqttStatusBridge/platformio.ini +1 -1
- package/examples/namedMesh/platformio.ini +1 -1
- package/examples/ntpTimeSyncBridge/alteriom_sensor_package.hpp +1383 -0
- package/examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino +81 -0
- package/examples/ntpTimeSyncNode/alteriom_sensor_package.hpp +1383 -0
- package/examples/ntpTimeSyncNode/ntpTimeSyncNode.ino +109 -0
- package/examples/otaReceiver/platformio.ini +1 -1
- package/examples/rtcIntegration/README.md +235 -0
- package/examples/rtcIntegration/rtcIntegration.ino +196 -0
- package/examples/startHere/platformio.ini +1 -1
- package/examples/webServer/platformio.ini +1 -1
- package/library.json +93 -53
- package/library.properties +1 -1
- package/package.json +2 -2
- package/src/arduino/wifi.hpp +581 -0
- package/src/painlessMeshSTA.cpp +68 -0
- package/src/painlessMeshSTA.h +3 -0
- package/src/painlessmesh/mesh.hpp +1127 -4
- package/src/painlessmesh/rtc.hpp +203 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// Bridge-Aware Sensor Node Example
|
|
3
|
+
//
|
|
4
|
+
// This example demonstrates how to use the bridge status
|
|
5
|
+
// callback feature to implement intelligent message queueing.
|
|
6
|
+
//
|
|
7
|
+
// Features:
|
|
8
|
+
// - Monitors bridge Internet connectivity status
|
|
9
|
+
// - Queues critical messages when Internet is unavailable
|
|
10
|
+
// - Automatically sends queued messages when Internet returns
|
|
11
|
+
// - Implements failover logic for multiple bridges
|
|
12
|
+
//
|
|
13
|
+
// Use case: Fish farm monitoring system that needs to ensure
|
|
14
|
+
// critical alarms are delivered even during Internet outages
|
|
15
|
+
//************************************************************
|
|
16
|
+
|
|
17
|
+
#include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
|
|
18
|
+
#include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
|
|
19
|
+
#include "alteriom_sensor_package.hpp"
|
|
20
|
+
#include "painlessMesh.h"
|
|
21
|
+
|
|
22
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
23
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
24
|
+
#define MESH_PORT 5555
|
|
25
|
+
|
|
26
|
+
Scheduler userScheduler;
|
|
27
|
+
painlessMesh mesh;
|
|
28
|
+
|
|
29
|
+
// Alteriom package handlers
|
|
30
|
+
using namespace alteriom;
|
|
31
|
+
|
|
32
|
+
// Message queue for offline mode
|
|
33
|
+
struct QueuedMessage {
|
|
34
|
+
uint32_t timestamp;
|
|
35
|
+
bool isCritical;
|
|
36
|
+
SensorPackage data;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
std::vector<QueuedMessage> messageQueue;
|
|
40
|
+
const size_t MAX_QUEUE_SIZE = 100; // Prevent memory overflow
|
|
41
|
+
|
|
42
|
+
// Bridge connectivity tracking
|
|
43
|
+
bool internetAvailable = false;
|
|
44
|
+
uint32_t primaryBridgeId = 0;
|
|
45
|
+
|
|
46
|
+
// Simulation variables
|
|
47
|
+
float currentTemperature = 25.0;
|
|
48
|
+
float currentOxygenLevel = 7.5; // mg/L - critical threshold is 5.0
|
|
49
|
+
|
|
50
|
+
// Function prototypes
|
|
51
|
+
void sendSensorData();
|
|
52
|
+
void handleIncomingPackage(uint32_t from, String& msg);
|
|
53
|
+
void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet);
|
|
54
|
+
void checkCriticalConditions();
|
|
55
|
+
void flushMessageQueue();
|
|
56
|
+
void queueMessage(const SensorPackage& data, bool isCritical);
|
|
57
|
+
|
|
58
|
+
Task taskSendSensorData(30000, TASK_FOREVER, &sendSensorData);
|
|
59
|
+
Task taskCheckCritical(5000, TASK_FOREVER, &checkCriticalConditions);
|
|
60
|
+
|
|
61
|
+
void setup() {
|
|
62
|
+
Serial.begin(115200);
|
|
63
|
+
|
|
64
|
+
// Initialize mesh
|
|
65
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
66
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
67
|
+
|
|
68
|
+
// Setup callbacks
|
|
69
|
+
mesh.onReceive(&handleIncomingPackage);
|
|
70
|
+
mesh.onBridgeStatusChanged(&bridgeStatusCallback);
|
|
71
|
+
|
|
72
|
+
mesh.onNewConnection([](uint32_t nodeId) {
|
|
73
|
+
Serial.printf("ā New connection: %u\n", nodeId);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
mesh.onChangedConnections([]() {
|
|
77
|
+
Serial.println("ā¹ Mesh connections changed");
|
|
78
|
+
|
|
79
|
+
// Check if we have a primary bridge
|
|
80
|
+
auto primaryBridge = mesh.getPrimaryBridge();
|
|
81
|
+
if (primaryBridge) {
|
|
82
|
+
Serial.printf(" Primary bridge: %u (RSSI: %d dBm, Internet: %s)\n",
|
|
83
|
+
primaryBridge->nodeId,
|
|
84
|
+
primaryBridge->routerRSSI,
|
|
85
|
+
primaryBridge->internetConnected ? "Yes" : "No");
|
|
86
|
+
} else {
|
|
87
|
+
Serial.println(" ā No healthy bridges available");
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Add tasks
|
|
92
|
+
userScheduler.addTask(taskSendSensorData);
|
|
93
|
+
taskSendSensorData.enable();
|
|
94
|
+
|
|
95
|
+
userScheduler.addTask(taskCheckCritical);
|
|
96
|
+
taskCheckCritical.enable();
|
|
97
|
+
|
|
98
|
+
Serial.println("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
99
|
+
Serial.println(" Bridge-Aware Sensor Node");
|
|
100
|
+
Serial.println(" Fish Farm Monitoring System");
|
|
101
|
+
Serial.println("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
102
|
+
Serial.printf(" Node ID: %u\n", mesh.getNodeId());
|
|
103
|
+
Serial.println(" Monitoring: Temperature, Dissolved Oxygen");
|
|
104
|
+
Serial.println(" Critical Oā threshold: 5.0 mg/L");
|
|
105
|
+
Serial.println("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void loop() {
|
|
109
|
+
mesh.update();
|
|
110
|
+
|
|
111
|
+
// Simulate sensor drift
|
|
112
|
+
static uint32_t lastSimUpdate = 0;
|
|
113
|
+
if (millis() - lastSimUpdate > 10000) {
|
|
114
|
+
// Randomly vary oxygen level (can go critical)
|
|
115
|
+
currentOxygenLevel += random(-20, 15) / 10.0;
|
|
116
|
+
currentOxygenLevel = constrain(currentOxygenLevel, 3.0, 9.0);
|
|
117
|
+
|
|
118
|
+
currentTemperature += random(-10, 10) / 10.0;
|
|
119
|
+
currentTemperature = constrain(currentTemperature, 20.0, 30.0);
|
|
120
|
+
|
|
121
|
+
lastSimUpdate = millis();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
void sendSensorData() {
|
|
126
|
+
// Create sensor package
|
|
127
|
+
SensorPackage sensorData;
|
|
128
|
+
sensorData.from = mesh.getNodeId();
|
|
129
|
+
sensorData.sensorId = mesh.getNodeId();
|
|
130
|
+
sensorData.timestamp = mesh.getNodeTime();
|
|
131
|
+
sensorData.temperature = currentTemperature;
|
|
132
|
+
sensorData.humidity = 65.0 + random(-50, 50) / 10.0; // Not critical for fish farm
|
|
133
|
+
sensorData.pressure = currentOxygenLevel; // Abuse pressure field for Oā level
|
|
134
|
+
sensorData.batteryLevel = 85 + random(-10, 5);
|
|
135
|
+
|
|
136
|
+
// Determine if this is critical data (low oxygen)
|
|
137
|
+
bool isCritical = (currentOxygenLevel < 5.5); // Early warning threshold
|
|
138
|
+
|
|
139
|
+
if (internetAvailable) {
|
|
140
|
+
// Internet available - send immediately
|
|
141
|
+
JsonDocument doc;
|
|
142
|
+
JsonObject obj = doc.to<JsonObject>();
|
|
143
|
+
sensorData.addTo(std::move(obj));
|
|
144
|
+
|
|
145
|
+
String msg;
|
|
146
|
+
serializeJson(doc, msg);
|
|
147
|
+
mesh.sendBroadcast(msg);
|
|
148
|
+
|
|
149
|
+
Serial.printf("š¤ Sent: T=%.1f°C, Oā=%.1f mg/L, Bat=%d%% %s\n",
|
|
150
|
+
sensorData.temperature,
|
|
151
|
+
currentOxygenLevel,
|
|
152
|
+
sensorData.batteryLevel,
|
|
153
|
+
isCritical ? "ā CRITICAL" : "");
|
|
154
|
+
} else {
|
|
155
|
+
// Internet offline - queue message
|
|
156
|
+
queueMessage(sensorData, isCritical);
|
|
157
|
+
|
|
158
|
+
Serial.printf("š¾ Queued: T=%.1f°C, Oā=%.1f mg/L %s [Queue: %d/%d]\n",
|
|
159
|
+
sensorData.temperature,
|
|
160
|
+
currentOxygenLevel,
|
|
161
|
+
isCritical ? "ā CRITICAL" : "",
|
|
162
|
+
messageQueue.size(),
|
|
163
|
+
MAX_QUEUE_SIZE);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
void checkCriticalConditions() {
|
|
168
|
+
// Check for critical low oxygen
|
|
169
|
+
if (currentOxygenLevel < 5.0) {
|
|
170
|
+
Serial.printf("šØ CRITICAL ALARM: Low Oxygen = %.1f mg/L!\n", currentOxygenLevel);
|
|
171
|
+
|
|
172
|
+
// Create critical alarm package
|
|
173
|
+
SensorPackage alarm;
|
|
174
|
+
alarm.from = mesh.getNodeId();
|
|
175
|
+
alarm.sensorId = mesh.getNodeId();
|
|
176
|
+
alarm.timestamp = mesh.getNodeTime();
|
|
177
|
+
alarm.temperature = currentTemperature;
|
|
178
|
+
alarm.pressure = currentOxygenLevel;
|
|
179
|
+
alarm.deviceStatus = 0xFF; // Critical alarm flag
|
|
180
|
+
alarm.batteryLevel = 85;
|
|
181
|
+
|
|
182
|
+
if (internetAvailable) {
|
|
183
|
+
// Send immediately
|
|
184
|
+
JsonDocument doc;
|
|
185
|
+
JsonObject obj = doc.to<JsonObject>();
|
|
186
|
+
alarm.addTo(std::move(obj));
|
|
187
|
+
|
|
188
|
+
String msg;
|
|
189
|
+
serializeJson(doc, msg);
|
|
190
|
+
mesh.sendBroadcast(msg);
|
|
191
|
+
Serial.println(" āŖ Critical alarm sent immediately");
|
|
192
|
+
} else {
|
|
193
|
+
// Queue with high priority
|
|
194
|
+
queueMessage(alarm, true);
|
|
195
|
+
Serial.printf(" āŖ Critical alarm queued [Queue: %d/%d]\n",
|
|
196
|
+
messageQueue.size(), MAX_QUEUE_SIZE);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
void queueMessage(const SensorPackage& data, bool isCritical) {
|
|
202
|
+
if (messageQueue.size() >= MAX_QUEUE_SIZE) {
|
|
203
|
+
Serial.println("ā Queue full - dropping oldest message");
|
|
204
|
+
messageQueue.erase(messageQueue.begin());
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
QueuedMessage qMsg;
|
|
208
|
+
qMsg.timestamp = millis();
|
|
209
|
+
qMsg.isCritical = isCritical;
|
|
210
|
+
qMsg.data = data;
|
|
211
|
+
|
|
212
|
+
messageQueue.push_back(qMsg);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
void flushMessageQueue() {
|
|
216
|
+
if (messageQueue.empty()) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
Serial.printf("\nš¤ Flushing message queue (%d messages)...\n", messageQueue.size());
|
|
221
|
+
|
|
222
|
+
size_t sentCount = 0;
|
|
223
|
+
size_t criticalCount = 0;
|
|
224
|
+
|
|
225
|
+
for (const auto& qMsg : messageQueue) {
|
|
226
|
+
JsonDocument doc;
|
|
227
|
+
JsonObject obj = doc.to<JsonObject>();
|
|
228
|
+
qMsg.data.addTo(std::move(obj));
|
|
229
|
+
|
|
230
|
+
String msg;
|
|
231
|
+
serializeJson(doc, msg);
|
|
232
|
+
mesh.sendBroadcast(msg);
|
|
233
|
+
|
|
234
|
+
sentCount++;
|
|
235
|
+
if (qMsg.isCritical) criticalCount++;
|
|
236
|
+
|
|
237
|
+
delay(100); // Small delay to avoid flooding
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
messageQueue.clear();
|
|
241
|
+
|
|
242
|
+
Serial.printf("ā Queue flushed: %d messages (%d critical)\n\n",
|
|
243
|
+
sentCount, criticalCount);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet) {
|
|
247
|
+
bool wasAvailable = internetAvailable;
|
|
248
|
+
internetAvailable = hasInternet;
|
|
249
|
+
primaryBridgeId = bridgeNodeId;
|
|
250
|
+
|
|
251
|
+
Serial.println("\nāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā");
|
|
252
|
+
if (hasInternet) {
|
|
253
|
+
Serial.printf("ā Bridge %u: Internet CONNECTED\n", bridgeNodeId);
|
|
254
|
+
|
|
255
|
+
// Get bridge details
|
|
256
|
+
auto bridges = mesh.getBridges();
|
|
257
|
+
for (const auto& bridge : bridges) {
|
|
258
|
+
if (bridge.nodeId == bridgeNodeId) {
|
|
259
|
+
Serial.printf(" Router: %s (RSSI: %d dBm, Ch: %d)\n",
|
|
260
|
+
bridge.gatewayIP.c_str(),
|
|
261
|
+
bridge.routerRSSI,
|
|
262
|
+
bridge.routerChannel);
|
|
263
|
+
Serial.printf(" Bridge uptime: %u seconds\n", bridge.uptime / 1000);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// If Internet was restored, flush queued messages
|
|
268
|
+
if (!wasAvailable) {
|
|
269
|
+
Serial.println(" ā Internet restored - processing queue");
|
|
270
|
+
flushMessageQueue();
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
Serial.printf("ā Bridge %u: Internet OFFLINE\n", bridgeNodeId);
|
|
274
|
+
Serial.println(" ā Entering offline mode");
|
|
275
|
+
Serial.println(" ā Critical alarms will be queued");
|
|
276
|
+
}
|
|
277
|
+
Serial.println("āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā\n");
|
|
278
|
+
|
|
279
|
+
// Show overall mesh status
|
|
280
|
+
if (mesh.hasInternetConnection()) {
|
|
281
|
+
Serial.println("ā Mesh has Internet connectivity");
|
|
282
|
+
} else {
|
|
283
|
+
Serial.println("ā No Internet connectivity in mesh");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Show all known bridges
|
|
287
|
+
auto bridges = mesh.getBridges();
|
|
288
|
+
if (!bridges.empty()) {
|
|
289
|
+
Serial.printf("Known bridges: %d\n", bridges.size());
|
|
290
|
+
for (const auto& bridge : bridges) {
|
|
291
|
+
Serial.printf(" - Bridge %u: %s (RSSI: %d dBm)\n",
|
|
292
|
+
bridge.nodeId,
|
|
293
|
+
bridge.internetConnected ? "Online" : "Offline",
|
|
294
|
+
bridge.routerRSSI);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
Serial.println();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
void handleIncomingPackage(uint32_t from, String& msg) {
|
|
301
|
+
// Parse the JSON message
|
|
302
|
+
JsonDocument doc;
|
|
303
|
+
deserializeJson(doc, msg);
|
|
304
|
+
JsonObject obj = doc.as<JsonObject>();
|
|
305
|
+
|
|
306
|
+
// Check message type
|
|
307
|
+
uint8_t msgType = obj["type"];
|
|
308
|
+
|
|
309
|
+
switch (msgType) {
|
|
310
|
+
case 200: // SensorPackage
|
|
311
|
+
{
|
|
312
|
+
SensorPackage receivedSensor(obj);
|
|
313
|
+
Serial.printf("š„ Sensor from %u: T=%.1f°C, Oā=%.1f mg/L\n",
|
|
314
|
+
receivedSensor.from,
|
|
315
|
+
receivedSensor.temperature,
|
|
316
|
+
receivedSensor.pressure); // Using pressure for Oā
|
|
317
|
+
} break;
|
|
318
|
+
|
|
319
|
+
case 400: // CommandPackage
|
|
320
|
+
{
|
|
321
|
+
CommandPackage receivedCmd(obj);
|
|
322
|
+
if (receivedCmd.dest == mesh.getNodeId()) {
|
|
323
|
+
Serial.printf("š„ Command %d received\n", receivedCmd.command);
|
|
324
|
+
|
|
325
|
+
// Handle commands (e.g., request status, change thresholds)
|
|
326
|
+
if (receivedCmd.command == 3) {
|
|
327
|
+
// Data request - send immediately even if offline
|
|
328
|
+
sendSensorData();
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} break;
|
|
332
|
+
|
|
333
|
+
case 610: // BridgeStatusPackage
|
|
334
|
+
// Handled automatically by mesh's internal callback
|
|
335
|
+
// But we can log that we received it
|
|
336
|
+
Serial.printf("š” Bridge status update from %u\n", from);
|
|
337
|
+
break;
|
|
338
|
+
|
|
339
|
+
default:
|
|
340
|
+
// Unknown message type
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_ldf_mode = deep+
|
|
6
|
+
lib_deps =
|
|
7
|
+
bblanchon/ArduinoJson
|
|
8
|
+
arkhipenko/TaskScheduler
|
|
9
|
+
|
|
10
|
+
[env:esp8266]
|
|
11
|
+
platform = espressif8266
|
|
12
|
+
board = nodemcuv2
|
|
13
|
+
framework = arduino
|
|
14
|
+
lib_extra_dirs = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
15
|
+
lib_deps =
|
|
16
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
17
|
+
esp32async/ESPAsyncTCP@^2.0.0 ; Only for ESP8266
|
|
18
|
+
|
|
19
|
+
[env:esp32]
|
|
20
|
+
platform = espressif32
|
|
21
|
+
board = esp32dev
|
|
22
|
+
framework = arduino
|
|
23
|
+
lib_extra_dirs = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
24
|
+
lib_deps =
|
|
25
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
26
|
+
esp32async/AsyncTCP
|