@alteriom/painlessmesh 1.8.5 → 1.8.7
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 +47 -0
- package/README.md +2 -0
- package/RELEASE_GUIDE.md +9 -3
- package/docs/FAQ_VERSION_NUMBERS.md +152 -0
- package/docs/QUICK_REFERENCE_VERSIONING.md +127 -0
- package/docs/VERSION_MANAGEMENT.md +213 -0
- package/docs/releases/ANNOUNCEMENT_v1.8.6.md +63 -0
- package/docs/releases/ANNOUNCEMENT_v1.8.7.md +113 -0
- package/docs/releases/GITHUB_RELEASE_v1.8.6.md +71 -0
- package/docs/releases/GITHUB_RELEASE_v1.8.7.md +90 -0
- package/docs/releases/RELEASE_NOTES_v1.8.6.md +205 -0
- package/docs/releases/RELEASE_NOTES_v1.8.7.md +184 -0
- package/examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino +0 -1
- package/examples/bridge_failover/README.md +74 -10
- package/examples/bridge_failover/bridge_failover.ino +16 -4
- package/examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino +6 -1
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/AlteriomPainlessMesh.h +3 -3
- package/src/arduino/wifi.hpp +45 -2
- package/src/painlessMesh.h +1 -1
|
@@ -30,10 +30,20 @@ Regular nodes track these broadcasts and detect failures when:
|
|
|
30
30
|
|
|
31
31
|
### 2. Election Trigger
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
An election is triggered when:
|
|
34
|
+
|
|
35
|
+
**Scenario 1: No Bridge Exists (Auto-Election Mode)**
|
|
36
|
+
- After 60-second startup period
|
|
37
|
+
- Periodic monitoring (every 30s) detects no healthy bridge
|
|
34
38
|
- Nodes with router credentials configured start an election
|
|
35
39
|
- Nodes without credentials remain passive
|
|
36
40
|
|
|
41
|
+
**Scenario 2: Bridge Failure**
|
|
42
|
+
- Primary bridge fails or loses Internet connectivity
|
|
43
|
+
- No status received within 60 seconds (configurable timeout)
|
|
44
|
+
- Bridge reports `internetConnected: false`
|
|
45
|
+
- Nodes detect failure and start election
|
|
46
|
+
|
|
37
47
|
### 3. Election Protocol
|
|
38
48
|
|
|
39
49
|
**Step 1: Candidacy Broadcast (Type 611)**
|
|
@@ -97,34 +107,77 @@ To prevent oscillation:
|
|
|
97
107
|
|
|
98
108
|
## Setup Instructions
|
|
99
109
|
|
|
100
|
-
|
|
110
|
+
You can choose between two deployment modes:
|
|
111
|
+
|
|
112
|
+
### Option A: Auto-Election Mode (Recommended)
|
|
113
|
+
|
|
114
|
+
**Best for**: Equal peers where any node can become the bridge based on signal strength.
|
|
115
|
+
|
|
116
|
+
1. Keep `INITIAL_BRIDGE = false` on **ALL nodes**
|
|
117
|
+
2. Configure mesh credentials (MESH_PREFIX, MESH_PASSWORD)
|
|
118
|
+
3. Configure router credentials (ROUTER_SSID, ROUTER_PASSWORD)
|
|
119
|
+
4. Flash the same sketch to all ESP32/ESP8266 devices
|
|
120
|
+
5. Power on all nodes simultaneously
|
|
121
|
+
|
|
122
|
+
**What happens**:
|
|
123
|
+
- Nodes start as regular mesh nodes
|
|
124
|
+
- After 60-second startup period, automatic monitoring begins
|
|
125
|
+
- If no bridge exists, nodes trigger an election
|
|
126
|
+
- Node with best router RSSI wins and becomes bridge
|
|
127
|
+
- Other nodes remain regular with failover capability
|
|
128
|
+
|
|
129
|
+
**Advantages**:
|
|
130
|
+
- Simpler setup - no need to designate a specific node
|
|
131
|
+
- True dynamic failover - any node can become bridge
|
|
132
|
+
- Best bridge selected based on signal strength
|
|
133
|
+
|
|
134
|
+
### Option B: Pre-Designated Bridge Mode
|
|
135
|
+
|
|
136
|
+
**Best for**: When you want a specific node to start as the bridge.
|
|
137
|
+
|
|
138
|
+
**1. Flash Initial Bridge Node**
|
|
101
139
|
|
|
102
140
|
1. Set `INITIAL_BRIDGE` to `true`
|
|
103
141
|
2. Configure router credentials
|
|
104
142
|
3. Flash to one ESP32/ESP8266
|
|
105
143
|
4. This node will connect to router and start as bridge
|
|
106
144
|
|
|
107
|
-
|
|
145
|
+
**2. Flash Regular Nodes**
|
|
108
146
|
|
|
109
147
|
1. Set `INITIAL_BRIDGE` to `false`
|
|
110
148
|
2. Configure same mesh and router credentials
|
|
111
149
|
3. Flash to other ESP32/ESP8266 devices
|
|
112
150
|
4. These nodes can become bridges via election
|
|
113
151
|
|
|
114
|
-
|
|
152
|
+
**Advantages**:
|
|
153
|
+
- Immediate bridge availability (no 60s wait)
|
|
154
|
+
- Predictable initial bridge selection
|
|
155
|
+
- Good for nodes with fixed locations
|
|
156
|
+
|
|
157
|
+
### Test Failover Scenarios
|
|
115
158
|
|
|
116
|
-
**Scenario 1:
|
|
117
|
-
1.
|
|
159
|
+
**Scenario 1: Auto-Election (No Initial Bridge)**
|
|
160
|
+
1. Flash all nodes with `INITIAL_BRIDGE = false`
|
|
161
|
+
2. Power on all nodes
|
|
162
|
+
3. Wait 60 seconds for startup period
|
|
163
|
+
4. Automatic monitoring detects no bridge
|
|
164
|
+
5. Election starts automatically within 30 seconds
|
|
165
|
+
6. Node with best router signal becomes bridge
|
|
166
|
+
7. Monitor serial output to see election process
|
|
167
|
+
|
|
168
|
+
**Scenario 2: Bridge Goes Offline**
|
|
169
|
+
1. Power off the current bridge node (initial or elected)
|
|
118
170
|
2. After 60 seconds, regular nodes detect failure
|
|
119
171
|
3. Election starts automatically
|
|
120
172
|
4. Node with best router signal becomes new bridge
|
|
121
173
|
5. Monitor serial output to see election process
|
|
122
174
|
|
|
123
|
-
**Scenario
|
|
124
|
-
1. Disconnect router from Internet
|
|
175
|
+
**Scenario 3: Bridge Loses Internet**
|
|
176
|
+
1. Disconnect router from Internet (or block bridge node's Internet)
|
|
125
177
|
2. Bridge reports `internetConnected: false`
|
|
126
|
-
3.
|
|
127
|
-
4.
|
|
178
|
+
3. Nodes detect loss of Internet via status broadcasts
|
|
179
|
+
4. Election starts to find a node with working Internet
|
|
180
|
+
5. New bridge elected if another node has Internet access
|
|
128
181
|
|
|
129
182
|
## Serial Output
|
|
130
183
|
|
|
@@ -287,6 +340,17 @@ bool amBridge = mesh.isBridge();
|
|
|
287
340
|
- Wait a few seconds after startup for initial discovery
|
|
288
341
|
- Bridge now broadcasts immediately on startup and when nodes connect (fixed in v1.8.4+)
|
|
289
342
|
|
|
343
|
+
### Bridge Reports No Internet When Router Has Internet
|
|
344
|
+
|
|
345
|
+
**Symptoms**: Bridge shows "Internet available: NO" or `hasInternet: false` despite router having Internet
|
|
346
|
+
|
|
347
|
+
**Cause**: Fixed in v1.8.5+. Previously only checked WiFi connection status, not actual Internet availability.
|
|
348
|
+
|
|
349
|
+
**Solutions**:
|
|
350
|
+
- Update to painlessMesh v1.8.5 or later
|
|
351
|
+
- Bridge now checks both WiFi connection AND valid gateway IP
|
|
352
|
+
- If still seeing issues, verify router's gateway IP is accessible: check `WiFi.gatewayIP()` returns valid IP (not 0.0.0.0)
|
|
353
|
+
|
|
290
354
|
### Election Doesn't Start
|
|
291
355
|
|
|
292
356
|
**Symptoms**: Bridge fails but no election occurs
|
|
@@ -9,14 +9,26 @@
|
|
|
9
9
|
// - ESP32 or ESP8266
|
|
10
10
|
// - WiFi router with Internet connection
|
|
11
11
|
//
|
|
12
|
-
// Setup:
|
|
12
|
+
// Setup Options:
|
|
13
|
+
//
|
|
14
|
+
// OPTION A - Auto-Election Mode (Recommended):
|
|
15
|
+
// 1. Configure your mesh credentials (MESH_PREFIX, MESH_PASSWORD)
|
|
16
|
+
// 2. Configure your router credentials (ROUTER_SSID, ROUTER_PASSWORD)
|
|
17
|
+
// 3. Keep INITIAL_BRIDGE = false on ALL nodes
|
|
18
|
+
// 4. Flash multiple nodes with this sketch
|
|
19
|
+
// 5. After startup (~60 seconds), nodes will automatically elect a bridge
|
|
20
|
+
// based on best router signal strength (RSSI)
|
|
21
|
+
//
|
|
22
|
+
// OPTION B - Pre-Designated Bridge Mode:
|
|
13
23
|
// 1. Configure your mesh credentials (MESH_PREFIX, MESH_PASSWORD)
|
|
14
24
|
// 2. Configure your router credentials (ROUTER_SSID, ROUTER_PASSWORD)
|
|
15
|
-
// 3.
|
|
16
|
-
// 4.
|
|
17
|
-
// 5.
|
|
25
|
+
// 3. Set INITIAL_BRIDGE = true on ONE node (your designated bridge)
|
|
26
|
+
// 4. Keep INITIAL_BRIDGE = false on all other nodes
|
|
27
|
+
// 5. Flash the nodes - designated bridge starts immediately
|
|
28
|
+
// 6. If designated bridge fails, others will hold election
|
|
18
29
|
//
|
|
19
30
|
// Features Demonstrated:
|
|
31
|
+
// - Automatic bridge election when no bridge exists
|
|
20
32
|
// - Automatic bridge failure detection via heartbeats
|
|
21
33
|
// - RSSI-based election protocol
|
|
22
34
|
// - Deterministic winner selection with tiebreakers
|
|
@@ -46,7 +46,12 @@ Task taskBroadcastNTP(NTP_INTERVAL, TASK_FOREVER, [](){
|
|
|
46
46
|
pkg.timestamp = millis();
|
|
47
47
|
|
|
48
48
|
// Serialize and broadcast to mesh
|
|
49
|
-
|
|
49
|
+
JsonDocument doc;
|
|
50
|
+
JsonObject obj = doc.to<JsonObject>();
|
|
51
|
+
pkg.addTo(std::move(obj));
|
|
52
|
+
|
|
53
|
+
String msg;
|
|
54
|
+
serializeJson(doc, msg);
|
|
50
55
|
mesh.sendBroadcast(msg);
|
|
51
56
|
|
|
52
57
|
Serial.printf("Broadcast NTP time: %u from %s (accuracy: %ums)\n",
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name=Alteriom PainlessMesh
|
|
2
|
-
version=1.8.
|
|
2
|
+
version=1.8.7
|
|
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.
|
|
3
|
+
"version": "1.8.7",
|
|
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",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
/**
|
|
30
30
|
* @brief AlteriomPainlessMesh library version information
|
|
31
31
|
*/
|
|
32
|
-
#define ALTERIOM_PAINLESS_MESH_VERSION "1.
|
|
32
|
+
#define ALTERIOM_PAINLESS_MESH_VERSION "1.8.7"
|
|
33
33
|
#define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 1
|
|
34
|
-
#define ALTERIOM_PAINLESS_MESH_VERSION_MINOR
|
|
35
|
-
#define ALTERIOM_PAINLESS_MESH_VERSION_PATCH
|
|
34
|
+
#define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 8
|
|
35
|
+
#define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 7
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
38
|
* @brief Library description and usage information
|
package/src/arduino/wifi.hpp
CHANGED
|
@@ -155,6 +155,44 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
155
155
|
}
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
+
// Add periodic monitoring task to detect when no bridge exists
|
|
159
|
+
// This handles the case where no node was initially configured as a bridge
|
|
160
|
+
this->addTask(30000, TASK_FOREVER, [this]() {
|
|
161
|
+
// Only check if failover is enabled and we have credentials
|
|
162
|
+
if (!bridgeFailoverEnabled || !routerCredentialsConfigured) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Don't check if we're already a bridge
|
|
167
|
+
if (this->isBridge()) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Skip check during startup period (60 seconds) to allow initial bridge discovery
|
|
172
|
+
if (millis() < 60000) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Check if there are any healthy bridges
|
|
177
|
+
bool hasHealthyBridge = false;
|
|
178
|
+
for (const auto& bridge : this->getBridges()) {
|
|
179
|
+
if (bridge.isHealthy(bridgeTimeoutMs) && bridge.internetConnected) {
|
|
180
|
+
hasHealthyBridge = true;
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// If no healthy bridge exists, trigger an election
|
|
186
|
+
if (!hasHealthyBridge) {
|
|
187
|
+
Log(CONNECTION, "Bridge monitor: No healthy bridge detected, triggering election\n");
|
|
188
|
+
// Small delay to randomize election start across nodes
|
|
189
|
+
uint32_t randomDelay = random(1000, 3000);
|
|
190
|
+
this->addTask(randomDelay, TASK_ONCE, [this]() {
|
|
191
|
+
this->startBridgeElection();
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
|
|
158
196
|
tcpServerInit();
|
|
159
197
|
eventHandleInit();
|
|
160
198
|
|
|
@@ -1147,7 +1185,12 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1147
1185
|
obj["from"] = this->nodeId;
|
|
1148
1186
|
obj["routing"] = 2; // BROADCAST routing
|
|
1149
1187
|
obj["timestamp"] = this->getNodeTime();
|
|
1150
|
-
|
|
1188
|
+
|
|
1189
|
+
// Check Internet connectivity: WiFi connected AND valid gateway IP
|
|
1190
|
+
bool hasInternet = (WiFi.status() == WL_CONNECTED) &&
|
|
1191
|
+
(WiFi.gatewayIP() != IPAddress(0, 0, 0, 0));
|
|
1192
|
+
obj["internetConnected"] = hasInternet;
|
|
1193
|
+
|
|
1151
1194
|
obj["routerRSSI"] = WiFi.RSSI();
|
|
1152
1195
|
obj["routerChannel"] = WiFi.channel();
|
|
1153
1196
|
obj["uptime"] = millis();
|
|
@@ -1158,7 +1201,7 @@ class Mesh : public painlessmesh::Mesh<Connection> {
|
|
|
1158
1201
|
serializeJson(doc, msg);
|
|
1159
1202
|
|
|
1160
1203
|
Log(GENERAL, "sendBridgeStatus(): Broadcasting status (Internet: %s)\n",
|
|
1161
|
-
|
|
1204
|
+
hasInternet ? "Connected" : "Disconnected");
|
|
1162
1205
|
|
|
1163
1206
|
this->sendBroadcast(msg);
|
|
1164
1207
|
}
|
package/src/painlessMesh.h
CHANGED