@alteriom/painlessmesh 1.7.9 → 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 +94 -2
- package/README.md +108 -1
- 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/releases/RELEASE_SUMMARY_v1.7.8.md +523 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.9.md +542 -0
- package/examples/alteriom/alteriom_sensor_package.hpp +213 -0
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +1014 -11
- package/examples/basic/basic.ino +6 -2
- package/examples/bridge/bridge.ino +44 -23
- package/examples/bridge/bridge_health_monitoring_example.ino +188 -0
- 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/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/rtcIntegration/README.md +235 -0
- package/examples/rtcIntegration/rtcIntegration.ino +196 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/arduino/wifi.hpp +572 -0
- package/src/painlessMeshSTA.cpp +63 -0
- package/src/painlessMeshSTA.h +3 -0
- package/src/painlessmesh/mesh.hpp +1127 -4
- package/src/painlessmesh/rtc.hpp +203 -0
|
@@ -1165,6 +1165,219 @@ class MeshBridgePackage : public painlessmesh::plugin::BroadcastPackage {
|
|
|
1165
1165
|
#endif
|
|
1166
1166
|
};
|
|
1167
1167
|
|
|
1168
|
+
/**
|
|
1169
|
+
* @brief Bridge status package for monitoring Internet connectivity (Type 610
|
|
1170
|
+
* - BRIDGE_STATUS)
|
|
1171
|
+
*
|
|
1172
|
+
* This package is broadcast by bridge nodes to inform the mesh about their
|
|
1173
|
+
* Internet connectivity status. Regular nodes can use this information to
|
|
1174
|
+
* decide whether to send data, queue messages, or failover to backup bridges.
|
|
1175
|
+
*
|
|
1176
|
+
* Broadcast interval: Configurable, default 30 seconds
|
|
1177
|
+
* Timeout threshold: 60 seconds (nodes consider bridge offline if no heartbeat)
|
|
1178
|
+
*
|
|
1179
|
+
* Type ID 610 for BRIDGE_STATUS per mqtt-schema v0.7.3+.
|
|
1180
|
+
*/
|
|
1181
|
+
class BridgeStatusPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
1182
|
+
public:
|
|
1183
|
+
// Bridge connectivity status
|
|
1184
|
+
bool internetConnected = false; // Is the bridge connected to Internet?
|
|
1185
|
+
int8_t routerRSSI = 0; // Router WiFi signal strength in dBm
|
|
1186
|
+
uint8_t routerChannel = 0; // Router WiFi channel
|
|
1187
|
+
uint32_t uptime = 0; // Bridge uptime in milliseconds
|
|
1188
|
+
TSTRING gatewayIP = ""; // Router gateway IP address
|
|
1189
|
+
uint32_t timestamp = 0; // Timestamp of status check
|
|
1190
|
+
|
|
1191
|
+
// MQTT Schema v0.7.3+ message_type
|
|
1192
|
+
uint16_t messageType = 610; // BRIDGE_STATUS
|
|
1193
|
+
|
|
1194
|
+
BridgeStatusPackage() : BroadcastPackage(610) {}
|
|
1195
|
+
|
|
1196
|
+
BridgeStatusPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
1197
|
+
internetConnected = jsonObj["internetConnected"] | false;
|
|
1198
|
+
routerRSSI = jsonObj["routerRSSI"] | 0;
|
|
1199
|
+
routerChannel = jsonObj["routerChannel"] | 0;
|
|
1200
|
+
uptime = jsonObj["uptime"] | 0;
|
|
1201
|
+
gatewayIP = jsonObj["gatewayIP"].as<TSTRING>();
|
|
1202
|
+
timestamp = jsonObj["timestamp"] | 0;
|
|
1203
|
+
messageType = jsonObj["message_type"] | 610;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
1207
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
1208
|
+
jsonObj["internetConnected"] = internetConnected;
|
|
1209
|
+
jsonObj["routerRSSI"] = routerRSSI;
|
|
1210
|
+
jsonObj["routerChannel"] = routerChannel;
|
|
1211
|
+
jsonObj["uptime"] = uptime;
|
|
1212
|
+
jsonObj["gatewayIP"] = gatewayIP;
|
|
1213
|
+
jsonObj["timestamp"] = timestamp;
|
|
1214
|
+
jsonObj["message_type"] = messageType;
|
|
1215
|
+
return jsonObj;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
1219
|
+
size_t jsonObjectSize() const {
|
|
1220
|
+
return JSON_OBJECT_SIZE(noJsonFields + 7) + gatewayIP.length();
|
|
1221
|
+
}
|
|
1222
|
+
#endif
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
/**
|
|
1226
|
+
* @brief Bridge election package for automatic failover (Type 611 -
|
|
1227
|
+
* BRIDGE_ELECTION)
|
|
1228
|
+
*
|
|
1229
|
+
* When a bridge node goes offline, regular nodes with router credentials can
|
|
1230
|
+
* participate in an election to become the new bridge. Each candidate
|
|
1231
|
+
* broadcasts its RSSI to the router, uptime, and available memory. The node
|
|
1232
|
+
* with the best RSSI wins the election.
|
|
1233
|
+
*
|
|
1234
|
+
* Election process:
|
|
1235
|
+
* 1. Bridge failure detected (no heartbeat for 60+ seconds)
|
|
1236
|
+
* 2. Nodes broadcast BridgeElectionPackage with their router RSSI
|
|
1237
|
+
* 3. 5-second collection window for all candidates
|
|
1238
|
+
* 4. Each node evaluates all candidates locally (deterministic)
|
|
1239
|
+
* 5. Winner promotes itself to bridge, others remain as regular nodes
|
|
1240
|
+
*
|
|
1241
|
+
* Type ID 611 for BRIDGE_ELECTION per mqtt-schema v0.7.3+.
|
|
1242
|
+
*/
|
|
1243
|
+
class BridgeElectionPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
1244
|
+
public:
|
|
1245
|
+
int8_t routerRSSI = 0; // Router WiFi signal strength in dBm (-127 to 0)
|
|
1246
|
+
uint32_t uptime = 0; // Node uptime in milliseconds
|
|
1247
|
+
uint32_t freeMemory = 0; // Free memory in bytes
|
|
1248
|
+
uint32_t timestamp = 0; // Election timestamp
|
|
1249
|
+
TSTRING routerSSID = ""; // Router SSID (for verification)
|
|
1250
|
+
|
|
1251
|
+
// MQTT Schema v0.7.3+ message_type
|
|
1252
|
+
uint16_t messageType = 611; // BRIDGE_ELECTION
|
|
1253
|
+
|
|
1254
|
+
BridgeElectionPackage() : BroadcastPackage(611) {}
|
|
1255
|
+
|
|
1256
|
+
BridgeElectionPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
1257
|
+
routerRSSI = jsonObj["routerRSSI"] | 0;
|
|
1258
|
+
uptime = jsonObj["uptime"] | 0;
|
|
1259
|
+
freeMemory = jsonObj["freeMemory"] | 0;
|
|
1260
|
+
timestamp = jsonObj["timestamp"] | 0;
|
|
1261
|
+
routerSSID = jsonObj["routerSSID"].as<TSTRING>();
|
|
1262
|
+
messageType = jsonObj["message_type"] | 611;
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
1266
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
1267
|
+
jsonObj["routerRSSI"] = routerRSSI;
|
|
1268
|
+
jsonObj["uptime"] = uptime;
|
|
1269
|
+
jsonObj["freeMemory"] = freeMemory;
|
|
1270
|
+
jsonObj["timestamp"] = timestamp;
|
|
1271
|
+
jsonObj["routerSSID"] = routerSSID;
|
|
1272
|
+
jsonObj["message_type"] = messageType;
|
|
1273
|
+
return jsonObj;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
1277
|
+
size_t jsonObjectSize() const {
|
|
1278
|
+
return JSON_OBJECT_SIZE(noJsonFields + 6) + routerSSID.length();
|
|
1279
|
+
}
|
|
1280
|
+
#endif
|
|
1281
|
+
};
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* @brief Bridge takeover announcement package (Type 612 - BRIDGE_TAKEOVER)
|
|
1285
|
+
*
|
|
1286
|
+
* After winning the bridge election, the new bridge node broadcasts this
|
|
1287
|
+
* package to inform all mesh nodes that it is now the primary bridge.
|
|
1288
|
+
* This allows nodes to update their bridge tracking and routing tables.
|
|
1289
|
+
*
|
|
1290
|
+
* Type ID 612 for BRIDGE_TAKEOVER per mqtt-schema v0.7.3+.
|
|
1291
|
+
*/
|
|
1292
|
+
class BridgeTakeoverPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
1293
|
+
public:
|
|
1294
|
+
uint32_t previousBridge = 0; // Previous bridge node ID (0 if none)
|
|
1295
|
+
TSTRING reason =
|
|
1296
|
+
""; // Reason for takeover (e.g., "Election winner - best router signal")
|
|
1297
|
+
int8_t routerRSSI = 0; // New bridge's router signal strength
|
|
1298
|
+
uint32_t timestamp = 0; // Takeover timestamp
|
|
1299
|
+
|
|
1300
|
+
// MQTT Schema v0.7.3+ message_type
|
|
1301
|
+
uint16_t messageType = 612; // BRIDGE_TAKEOVER
|
|
1302
|
+
|
|
1303
|
+
BridgeTakeoverPackage() : BroadcastPackage(612) {}
|
|
1304
|
+
|
|
1305
|
+
BridgeTakeoverPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
1306
|
+
previousBridge = jsonObj["previousBridge"] | 0;
|
|
1307
|
+
reason = jsonObj["reason"].as<TSTRING>();
|
|
1308
|
+
routerRSSI = jsonObj["routerRSSI"] | 0;
|
|
1309
|
+
timestamp = jsonObj["timestamp"] | 0;
|
|
1310
|
+
messageType = jsonObj["message_type"] | 612;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
1314
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
1315
|
+
jsonObj["previousBridge"] = previousBridge;
|
|
1316
|
+
jsonObj["reason"] = reason;
|
|
1317
|
+
jsonObj["routerRSSI"] = routerRSSI;
|
|
1318
|
+
jsonObj["timestamp"] = timestamp;
|
|
1319
|
+
jsonObj["message_type"] = messageType;
|
|
1320
|
+
return jsonObj;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
1324
|
+
size_t jsonObjectSize() const {
|
|
1325
|
+
return JSON_OBJECT_SIZE(noJsonFields + 5) + reason.length();
|
|
1326
|
+
}
|
|
1327
|
+
#endif
|
|
1328
|
+
};
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* @brief NTP time synchronization package (Type 614 - TIME_SYNC_NTP)
|
|
1332
|
+
*
|
|
1333
|
+
* Broadcast by bridge nodes to distribute authoritative NTP time to the mesh.
|
|
1334
|
+
* When a bridge has Internet connectivity, it can provide NTP time to improve
|
|
1335
|
+
* accuracy across the entire mesh network.
|
|
1336
|
+
*
|
|
1337
|
+
* Regular nodes should:
|
|
1338
|
+
* 1. Accept time from bridge nodes (verify sender is bridge)
|
|
1339
|
+
* 2. Update local time with mesh.setTimeFromNTP(ntpTime)
|
|
1340
|
+
* 3. Optionally sync RTC modules if available
|
|
1341
|
+
*
|
|
1342
|
+
* Type ID 614 for TIME_SYNC_NTP.
|
|
1343
|
+
*/
|
|
1344
|
+
class NTPTimeSyncPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
1345
|
+
public:
|
|
1346
|
+
uint32_t ntpTime = 0; // Unix timestamp from NTP server
|
|
1347
|
+
uint16_t accuracy = 0; // Milliseconds uncertainty/precision
|
|
1348
|
+
TSTRING source = ""; // NTP server source (e.g., "pool.ntp.org")
|
|
1349
|
+
uint32_t timestamp = 0; // Collection timestamp
|
|
1350
|
+
|
|
1351
|
+
// MQTT Schema message_type
|
|
1352
|
+
uint16_t messageType = 614; // TIME_SYNC_NTP
|
|
1353
|
+
|
|
1354
|
+
NTPTimeSyncPackage() : BroadcastPackage(614) {}
|
|
1355
|
+
|
|
1356
|
+
NTPTimeSyncPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
1357
|
+
ntpTime = jsonObj["ntpTime"];
|
|
1358
|
+
accuracy = jsonObj["accuracy"];
|
|
1359
|
+
source = jsonObj["source"].as<TSTRING>();
|
|
1360
|
+
timestamp = jsonObj["timestamp"];
|
|
1361
|
+
messageType = jsonObj["message_type"] | 614;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
1365
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
1366
|
+
jsonObj["ntpTime"] = ntpTime;
|
|
1367
|
+
jsonObj["accuracy"] = accuracy;
|
|
1368
|
+
jsonObj["source"] = source;
|
|
1369
|
+
jsonObj["timestamp"] = timestamp;
|
|
1370
|
+
jsonObj["message_type"] = messageType;
|
|
1371
|
+
return jsonObj;
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
1375
|
+
size_t jsonObjectSize() const {
|
|
1376
|
+
return JSON_OBJECT_SIZE(noJsonFields + 5) + source.length();
|
|
1377
|
+
}
|
|
1378
|
+
#endif
|
|
1379
|
+
};
|
|
1380
|
+
|
|
1168
1381
|
} // namespace alteriom
|
|
1169
1382
|
|
|
1170
1383
|
#endif // ALTERIOM_SENSOR_PACKAGE_HPP
|