@alteriom/painlessmesh 1.8.12 → 1.8.14

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 CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.8.14] - 2025-11-21
11
+
12
+ ### Fixed
13
+
14
+ - **Bridge Internet Detection** - Fixed `hasInternetConnection()` returning false on bridge nodes immediately after initialization
15
+ - **Root Cause**: Base `hasInternetConnection()` only checked `knownBridges` list; bridge self-registration happens asynchronously
16
+ - Added override in Arduino `wifi::Mesh` to check local WiFi status before checking remote bridges
17
+ - Bridge nodes now immediately report correct internet status via `WiFi.status()` check
18
+ - Fixes issue where internet-dependent features (like WhatsApp messaging) failed on bridge nodes
19
+ - **Impact**: Bridge nodes correctly report internet connectivity immediately after initialization
20
+ - **Affected Components**: Bridge_fallover example, any code using `mesh.hasInternetConnection()` on bridge nodes
21
+ - Core fix in `src/arduino/wifi.hpp` - added WiFi status check override
22
+ - Resolves GitHub issue #159
23
+ - Merged via PR #160
24
+
10
25
  ## [1.8.12] - 2025-11-19
11
26
 
12
27
  ### Changed
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.12",
9
+ "version": "1.8.14",
10
10
  "frameworks": [
11
11
  "arduino"
12
12
  ],
@@ -1,5 +1,5 @@
1
1
  name=Alteriom PainlessMesh
2
- version=1.8.12
2
+ version=1.8.14
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alteriom/painlessmesh",
3
- "version": "1.8.12",
3
+ "version": "1.8.14",
4
4
  "description": "painlessMesh is a user-friendly library for creating mesh networks with ESP8266 and ESP32 devices. This Alteriom fork includes additional packages for sensor data (SensorPackage), device commands (CommandPackage), and status monitoring (StatusPackage). It handles routing and network management automatically, so you can focus on your application. The library uses JSON-based messaging and syncs time across all nodes, making it ideal for coordinated behaviour like synchronized light displays or sensor networks reporting to a central node.",
5
5
  "keywords": [
6
6
  "arduino",
@@ -85,6 +85,6 @@
85
85
  "CHANGELOG.md",
86
86
  "RELEASE_GUIDE.md",
87
87
  "DOCUMENTATION_INDEX.md",
88
- "RELEASE_NOTES_1.8.12.md"
88
+ "RELEASE_NOTES_1.8.13.md"
89
89
  ]
90
90
  }
@@ -29,10 +29,10 @@
29
29
  /**
30
30
  * @brief AlteriomPainlessMesh library version information
31
31
  */
32
- #define ALTERIOM_PAINLESS_MESH_VERSION "1.8.12"
32
+ #define ALTERIOM_PAINLESS_MESH_VERSION "1.8.13"
33
33
  #define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 1
34
34
  #define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 8
35
- #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 12
35
+ #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 13
36
36
 
37
37
  /**
38
38
  * @brief Library description and usage information
@@ -89,9 +89,9 @@ class Mesh : public painlessmesh::Mesh<Connection> {
89
89
 
90
90
  this->init(nodeId);
91
91
 
92
- // Add bridge election package handler (Type 611)
92
+ // Add bridge election package handler (Type BRIDGE_ELECTION)
93
93
  this->callbackList.onPackage(
94
- 611, // BRIDGE_ELECTION type
94
+ protocol::BRIDGE_ELECTION,
95
95
  [this](protocol::Variant& variant, std::shared_ptr<Connection>, uint32_t) {
96
96
  JsonDocument doc;
97
97
  TSTRING str;
@@ -113,9 +113,9 @@ class Mesh : public painlessmesh::Mesh<Connection> {
113
113
  return false; // Don't consume the package
114
114
  });
115
115
 
116
- // Add bridge takeover package handler (Type 612)
116
+ // Add bridge takeover package handler (Type BRIDGE_TAKEOVER)
117
117
  this->callbackList.onPackage(
118
- 612, // BRIDGE_TAKEOVER type
118
+ protocol::BRIDGE_TAKEOVER,
119
119
  [this](protocol::Variant& variant, std::shared_ptr<Connection>, uint32_t) {
120
120
  JsonDocument doc;
121
121
  TSTRING str;
@@ -618,6 +618,28 @@ class Mesh : public painlessmesh::Mesh<Connection> {
618
618
  return activeBridges;
619
619
  }
620
620
 
621
+ /**
622
+ * Check if any bridge in the mesh has Internet connectivity
623
+ *
624
+ * Override of base class method to also check if THIS node is a bridge
625
+ * with Internet connectivity, not just other bridges in the mesh.
626
+ *
627
+ * @return true if at least one bridge (including this node) has Internet
628
+ */
629
+ bool hasInternetConnection() {
630
+ // First check if THIS node is a bridge with Internet
631
+ if (this->isBridge()) {
632
+ // Check Internet connectivity: WiFi connected AND valid IP address
633
+ bool hasInternet = (WiFi.status() == WL_CONNECTED) && (WiFi.localIP() != IPAddress(0, 0, 0, 0));
634
+ if (hasInternet) {
635
+ return true;
636
+ }
637
+ }
638
+
639
+ // Then check other bridges in the mesh (call parent implementation)
640
+ return painlessmesh::Mesh<Connection>::hasInternetConnection();
641
+ }
642
+
621
643
  /**
622
644
  * Get recommended bridge for message transmission
623
645
  *
@@ -817,7 +839,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
817
839
  JsonDocument doc;
818
840
  JsonObject obj = doc.to<JsonObject>();
819
841
 
820
- obj["type"] = 610; // BRIDGE_STATUS type
842
+ obj["type"] = protocol::BRIDGE_STATUS;
821
843
  obj["from"] = this->nodeId;
822
844
  obj["routing"] = 1; // SINGLE routing (direct to node)
823
845
  obj["dest"] = nodeId;
@@ -830,7 +852,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
830
852
  obj["routerChannel"] = WiFi.channel();
831
853
  obj["uptime"] = millis();
832
854
  obj["gatewayIP"] = WiFi.gatewayIP().toString();
833
- obj["message_type"] = 610;
855
+ obj["message_type"] = protocol::BRIDGE_STATUS;
834
856
 
835
857
  String msg;
836
858
  serializeJson(doc, msg);
@@ -838,8 +860,10 @@ class Mesh : public painlessmesh::Mesh<Connection> {
838
860
  Log(CONNECTION, "Sending bridge status directly to node %u (Internet: %s)\n",
839
861
  nodeId, hasInternet ? "YES" : "NO");
840
862
 
841
- // Send directly to the new node using routing table (which is now ready)
842
- this->sendSingle(nodeId, msg);
863
+ // Send directly to the new node using raw message to preserve type BRIDGE_STATUS
864
+ // Using sendSingle() would wrap it in type 1 (SINGLE) and hide type BRIDGE_STATUS
865
+ protocol::Variant variant(msg);
866
+ router::send<Connection>(variant, (*this));
843
867
  });
844
868
  });
845
869
 
@@ -1072,7 +1096,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1072
1096
  // Broadcast candidacy using JSON directly (avoiding dependency on alteriom package)
1073
1097
  JsonDocument doc;
1074
1098
  JsonObject obj = doc.to<JsonObject>();
1075
- obj["type"] = 611; // BRIDGE_ELECTION
1099
+ obj["type"] = protocol::BRIDGE_ELECTION;
1076
1100
  obj["from"] = this->nodeId;
1077
1101
  obj["routing"] = 2; // BROADCAST
1078
1102
  obj["routerRSSI"] = routerRSSI;
@@ -1080,11 +1104,14 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1080
1104
  obj["freeMemory"] = ESP.getFreeHeap();
1081
1105
  obj["timestamp"] = this->getNodeTime();
1082
1106
  obj["routerSSID"] = routerSSID;
1083
- obj["message_type"] = 611;
1107
+ obj["message_type"] = protocol::BRIDGE_ELECTION;
1084
1108
 
1085
1109
  String msg;
1086
1110
  serializeJson(doc, msg);
1087
- this->sendBroadcast(msg);
1111
+
1112
+ // Send election message using raw broadcast to preserve type BRIDGE_ELECTION
1113
+ protocol::Variant variant(msg);
1114
+ router::broadcast<protocol::Variant, Connection>(variant, (*this), 0);
1088
1115
 
1089
1116
  Log(CONNECTION, "startBridgeElection(): Candidacy broadcast sent\n");
1090
1117
 
@@ -1223,18 +1250,21 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1223
1250
  Log(STARTUP, "Sending takeover announcement on current channel before switching...\n");
1224
1251
  JsonDocument doc;
1225
1252
  JsonObject obj = doc.to<JsonObject>();
1226
- obj["type"] = 612; // BRIDGE_TAKEOVER
1253
+ obj["type"] = protocol::BRIDGE_TAKEOVER;
1227
1254
  obj["from"] = this->nodeId;
1228
1255
  obj["routing"] = 2; // BROADCAST
1229
1256
  obj["previousBridge"] = previousBridgeId;
1230
1257
  obj["reason"] = "Election winner - best router signal";
1231
1258
  obj["routerRSSI"] = 0; // Not yet connected to router
1232
1259
  obj["timestamp"] = this->getNodeTime();
1233
- obj["message_type"] = 612;
1260
+ obj["message_type"] = protocol::BRIDGE_TAKEOVER;
1234
1261
 
1235
1262
  String msg;
1236
1263
  serializeJson(doc, msg);
1237
- this->sendBroadcast(msg);
1264
+
1265
+ // Send takeover message using raw broadcast to preserve type BRIDGE_TAKEOVER
1266
+ protocol::Variant variant(msg);
1267
+ router::broadcast<protocol::Variant, Connection>(variant, (*this), 0);
1238
1268
 
1239
1269
  // Give time for announcement to propagate before channel switch
1240
1270
  delay(1000);
@@ -1263,18 +1293,22 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1263
1293
  Log(STARTUP, "Sending follow-up takeover announcement on new channel %d\n", _meshChannel);
1264
1294
  JsonDocument doc2;
1265
1295
  JsonObject obj2 = doc2.to<JsonObject>();
1266
- obj2["type"] = 612; // BRIDGE_TAKEOVER
1296
+ obj2["type"] = protocol::BRIDGE_TAKEOVER;
1267
1297
  obj2["from"] = this->nodeId;
1268
1298
  obj2["routing"] = 2; // BROADCAST
1269
1299
  obj2["previousBridge"] = previousBridgeId;
1270
1300
  obj2["reason"] = "Election winner - best router signal";
1271
1301
  obj2["routerRSSI"] = WiFi.RSSI();
1272
1302
  obj2["timestamp"] = this->getNodeTime();
1273
- obj2["message_type"] = 612;
1303
+ obj2["message_type"] = protocol::BRIDGE_TAKEOVER;
1274
1304
 
1275
1305
  String msg2;
1276
1306
  serializeJson(doc2, msg2);
1277
- this->sendBroadcast(msg2);
1307
+
1308
+ // Send follow-up takeover using raw broadcast to preserve type BRIDGE_TAKEOVER
1309
+ protocol::Variant variant2(msg2);
1310
+ router::broadcast<protocol::Variant, Connection>(variant2, (*this), 0);
1311
+
1278
1312
  Log(STARTUP, "✓ Follow-up takeover announcement sent\n");
1279
1313
  });
1280
1314
  }
@@ -1329,7 +1363,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1329
1363
  JsonDocument doc;
1330
1364
  JsonObject obj = doc.to<JsonObject>();
1331
1365
 
1332
- obj["type"] = 610; // BRIDGE_STATUS type
1366
+ obj["type"] = protocol::BRIDGE_STATUS;
1333
1367
  obj["from"] = this->nodeId;
1334
1368
  obj["routing"] = 2; // BROADCAST routing
1335
1369
  obj["timestamp"] = this->getNodeTime();
@@ -1352,7 +1386,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1352
1386
  obj["routerChannel"] = channel;
1353
1387
  obj["uptime"] = uptime;
1354
1388
  obj["gatewayIP"] = gatewayIP;
1355
- obj["message_type"] = 610;
1389
+ obj["message_type"] = protocol::BRIDGE_STATUS;
1356
1390
 
1357
1391
  String msg;
1358
1392
  serializeJson(doc, msg);
@@ -1367,7 +1401,10 @@ class Mesh : public painlessmesh::Mesh<Connection> {
1367
1401
  this->updateBridgeStatus(this->nodeId, hasInternet, rssi, channel,
1368
1402
  uptime, gatewayIP, this->getNodeTime());
1369
1403
 
1370
- this->sendBroadcast(msg);
1404
+ // Send bridge status using raw broadcast to preserve type BRIDGE_STATUS
1405
+ // Using sendBroadcast(msg) would wrap it in type 8 (BROADCAST) and hide type BRIDGE_STATUS
1406
+ protocol::Variant variant(msg);
1407
+ router::broadcast<protocol::Variant, Connection>(variant, (*this), 0);
1371
1408
  }
1372
1409
  void eventHandleInit() {
1373
1410
  using namespace logger;
@@ -5,8 +5,8 @@
5
5
  * @file painlessMesh.h
6
6
  * @brief Main header file for Alteriom painlessMesh library
7
7
  *
8
- * @version 1.8.12
9
- * @date 2025-11-19
8
+ * @version 1.8.13
9
+ * @date 2025-11-20
10
10
  *
11
11
  * painlessMesh is a user-friendly library for creating mesh networks with
12
12
  * ESP8266 and ESP32 devices. This Alteriom fork includes additional packages
@@ -167,10 +167,10 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
167
167
  this->callbackList = painlessmesh::router::addPackageCallback(
168
168
  std::move(this->callbackList), (*this));
169
169
 
170
- // Add bridge status package handler (Type 610)
170
+ // Add bridge status package handler (Type BRIDGE_STATUS)
171
171
  // This will be called when any node receives a bridge status broadcast
172
172
  this->callbackList.onPackage(
173
- 610, // BRIDGE_STATUS type
173
+ protocol::BRIDGE_STATUS,
174
174
  [this](protocol::Variant& variant, std::shared_ptr<T>, uint32_t) {
175
175
  // We need to manually parse the JSON since BridgeStatusPackage is in alteriom namespace
176
176
  // and may not be available in all contexts. We'll parse the critical fields directly.
@@ -49,6 +49,13 @@ enum TimeType {
49
49
  TIME_REPLY
50
50
  };
51
51
 
52
+ // Bridge protocol package types
53
+ // These are used for bridge discovery, election, and coordination
54
+ constexpr int BRIDGE_STATUS = 610; // Bridge status broadcast (internet, RSSI, etc.)
55
+ constexpr int BRIDGE_ELECTION = 611; // Bridge election candidacy announcement
56
+ constexpr int BRIDGE_TAKEOVER = 612; // Bridge takeover notification
57
+ constexpr int BRIDGE_COORDINATION = 613; // Multi-bridge coordination (defined in plugin.hpp)
58
+
52
59
  class PackageInterface {
53
60
  public:
54
61
  virtual JsonObject addTo(JsonObject&& jsonObj) const = 0;
@@ -1,96 +0,0 @@
1
- # Release Notes - Version 1.8.12
2
-
3
- **Release Date:** 2025-11-19
4
-
5
- ## Overview
6
-
7
- Version 1.8.12 is a maintenance release focused on documentation improvements and code quality enhancements. This release includes changes from PRs #152 and #153, ensuring comprehensive documentation coverage and adherence to code formatting standards.
8
-
9
- ## What's New
10
-
11
- ### Documentation Enhancements
12
-
13
- - **Comprehensive Documentation Review** - All documentation has been reviewed and updated to reflect the current state of the library
14
- - **API Reference Updates** - Improved clarity and completeness in API documentation
15
- - **Example Code Documentation** - Enhanced inline documentation for example projects
16
- - **Package Documentation** - Updated documentation for all Alteriom custom packages
17
-
18
- ### Code Quality Improvements
19
-
20
- - **Prettier Configuration** - Added prettier configuration for consistent JSON and Markdown formatting
21
- - New `.prettierrc` configuration file
22
- - New `.prettierignore` file to exclude build artifacts and dependencies
23
- - Added `npm run format` and `npm run format:check` scripts
24
- - **Clang-Format Compliance** - Ensured all C++ code follows established formatting standards
25
- - **Code Organization** - Improved code structure and maintainability
26
-
27
- ### Version Updates
28
-
29
- - Updated all version references across:
30
- - `package.json` - NPM package version
31
- - `library.json` - PlatformIO library version
32
- - `library.properties` - Arduino library version
33
- - `src/painlessMesh.h` - Header file version comments
34
- - `src/AlteriomPainlessMesh.h` - Version defines and comments
35
-
36
- ## Installation
37
-
38
- ### Arduino Library Manager
39
- ```
40
- Sketch → Include Library → Manage Libraries → Search "AlteriomPainlessMesh" → Install
41
- ```
42
-
43
- ### PlatformIO
44
- ```ini
45
- [env:myenv]
46
- lib_deps =
47
- alteriom/AlteriomPainlessMesh @ ^1.8.12
48
- ```
49
-
50
- ### NPM
51
- ```bash
52
- npm install @alteriom/painlessmesh@1.8.12
53
- ```
54
-
55
- ## Compatibility
56
-
57
- - **ESP32** - All variants supported
58
- - **ESP8266** - All variants supported
59
- - **Arduino IDE** - Version 1.8.0 or higher
60
- - **PlatformIO** - Latest version
61
- - **ArduinoJson** - Version 7.4.2 or higher
62
- - **TaskScheduler** - Version 4.0.0 or higher
63
-
64
- ## Migration Guide
65
-
66
- This is a patch release with no breaking changes. Users can upgrade from any 1.8.x version without code modifications.
67
-
68
- ## Known Issues
69
-
70
- None identified in this release.
71
-
72
- ## Pull Requests Included
73
-
74
- - PR #152 - Documentation improvements
75
- - PR #153 - Code quality enhancements
76
-
77
- ## Contributors
78
-
79
- Special thanks to all contributors who helped make this release possible!
80
-
81
- ## Documentation
82
-
83
- - **Main Documentation**: https://alteriom.github.io/painlessMesh/
84
- - **API Reference**: https://alteriom.github.io/painlessMesh/#/api/doxygen
85
- - **Examples**: https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples
86
- - **GitHub Repository**: https://github.com/Alteriom/painlessMesh
87
-
88
- ## Support
89
-
90
- For questions, issues, or feature requests:
91
- - **GitHub Issues**: https://github.com/Alteriom/painlessMesh/issues
92
- - **Documentation**: https://alteriom.github.io/painlessMesh/
93
-
94
- ## License
95
-
96
- This project is licensed under LGPL-3.0. See the LICENSE file for details.