@alteriom/painlessmesh 1.9.17 → 1.9.19

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
@@ -13,6 +13,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
13
 
14
14
  ### Fixed
15
15
 
16
+ ## [1.9.19] - 2025-12-21
17
+
18
+ ### Fixed
19
+
20
+ - **Gateway Connectivity Error Non-Retryable Fix** - Infrastructure errors no longer waste time with futile retries
21
+ - Gateway connectivity errors ("Router has no internet", "Gateway WiFi not connected") are now non-retryable
22
+ - Distinguishes between infrastructure issues (need user fix) and transient errors (can retry)
23
+ - Provides immediate failure feedback instead of retrying for ~14+ seconds
24
+ - Saves battery and network resources by avoiding retries that can't succeed
25
+ - Clear error messages help users identify and fix infrastructure problems quickly
26
+ - Transient errors (HTTP 203, 5xx, 429, timeouts) still retry with exponential backoff
27
+ - New comprehensive test suite with 25 assertions covering retry logic
28
+ - Documentation: ISSUE_GATEWAY_CONNECTIVITY_NON_RETRYABLE_FIX.md
29
+ - Fully backward compatible: No API changes required
30
+
31
+ ## [1.9.18] - 2025-12-21
32
+
33
+ ### Added
34
+
35
+ - **Internet Connectivity Check Enhancement** - Bridge nodes now verify actual internet access before processing HTTP requests
36
+ - Added `hasActualInternetAccess()` function that performs DNS resolution to detect router internet issues
37
+ - Gateway checks both WiFi association AND DNS resolution before attempting HTTP requests
38
+ - Provides early failure detection when router has no WAN connection
39
+ - Clear, actionable error messages help users troubleshoot connectivity problems:
40
+ - "Gateway WiFi not connected" - ESP not associated with WiFi network
41
+ - "Router has no internet access - check WAN connection" - WiFi OK but router offline
42
+ - Minimal performance impact: ~100ms DNS check vs 30+ second HTTP timeout
43
+ - New test suite with 22 assertions covering connectivity scenarios
44
+ - Documentation: ISSUE_INTERNET_CONNECTIVITY_CHECK.md
45
+ - Backward compatible: No API changes required
46
+
16
47
  ## [1.9.17] - 2025-12-21
17
48
 
18
49
  ### Changed
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  <div align="center">
6
6
 
7
- **Version 1.9.17** - Documentation enhancement with production-level quality and improved package organization
7
+ **Version 1.9.19** - Gateway connectivity error non-retryable fix for infrastructure issues
8
8
 
9
9
  [![CI/CD Pipeline](https://github.com/Alteriom/painlessMesh/actions/workflows/ci.yml/badge.svg)](https://github.com/Alteriom/painlessMesh/actions/workflows/ci.yml)
10
10
  [![Documentation](https://github.com/Alteriom/painlessMesh/actions/workflows/docs.yml/badge.svg)](https://github.com/Alteriom/painlessMesh/actions/workflows/docs.yml)
@@ -146,6 +146,35 @@ mesh.sendToInternet("https://api.callmebot.com/...", "", callback);
146
146
  3. Check HTTP status code in callback (200 = success)
147
147
  4. URL-encode special characters in the message
148
148
 
149
+ ### Gateway shows "no internet access" but WiFi is connected
150
+
151
+ **Symptom:** Error message "Router has no internet access - check WAN connection"
152
+
153
+ **Cause:** The gateway node is connected to WiFi but the router itself has no internet connectivity. This is detected through DNS resolution testing.
154
+
155
+ **Solutions:**
156
+ 1. **Check router WAN connection:**
157
+ - Verify router's internet LED indicator
158
+ - Check router's WAN port cable connection
159
+ - Ensure modem is powered and connected
160
+
161
+ 2. **Check ISP service:**
162
+ - Verify your internet service is active
163
+ - Test internet on other devices connected to same router
164
+ - Contact ISP if service is down
165
+
166
+ 3. **Router configuration:**
167
+ - Verify router has obtained WAN IP address
168
+ - Check router's internet connection status page
169
+ - Restart router if necessary
170
+
171
+ **Technical Details:**
172
+ The gateway performs two connectivity checks:
173
+ 1. `WiFi.status() == WL_CONNECTED` - Verifies WiFi association
174
+ 2. DNS resolution test - Verifies actual internet routing
175
+
176
+ If WiFi is connected but DNS fails, it indicates the router has no upstream internet connection. This prevents unnecessary HTTP request timeouts and provides early error detection.
177
+
149
178
  ### Understanding HTTP Status Codes
150
179
 
151
180
  The callback provides `httpStatus` to indicate the result:
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.9.17",
9
+ "version": "1.9.19",
10
10
  "frameworks": [
11
11
  "arduino"
12
12
  ],
@@ -1,5 +1,5 @@
1
1
  name=Alteriom PainlessMesh
2
- version=1.9.17
2
+ version=1.9.19
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.9.17",
3
+ "version": "1.9.19",
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.9.17"
32
+ #define ALTERIOM_PAINLESS_MESH_VERSION "1.9.19"
33
33
  #define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 1
34
34
  #define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 9
35
- #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 17
35
+ #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 19
36
36
 
37
37
  /**
38
38
  * @brief Library description and usage information
@@ -2120,6 +2120,61 @@ class Mesh : public painlessmesh::Mesh<Connection> {
2120
2120
  router::broadcast<protocol::Variant, Connection>(variant, (*this), 0);
2121
2121
  }
2122
2122
 
2123
+ /**
2124
+ * Check if gateway has actual internet connectivity
2125
+ *
2126
+ * Tests DNS resolution to detect scenarios where WiFi is connected
2127
+ * but the router has no internet access. This provides early detection
2128
+ * before attempting HTTP requests that would timeout or fail.
2129
+ *
2130
+ * @return true if internet is accessible, false otherwise
2131
+ */
2132
+ bool hasActualInternetAccess() {
2133
+ using namespace logger;
2134
+
2135
+ // First check WiFi connection
2136
+ if (WiFi.status() != WL_CONNECTED) {
2137
+ return false;
2138
+ }
2139
+
2140
+ // Check if we have a valid local IP
2141
+ if (WiFi.localIP() == IPAddress(0, 0, 0, 0)) {
2142
+ return false;
2143
+ }
2144
+
2145
+ // Try to resolve a well-known DNS name
2146
+ // Using Google's servers as they have high availability globally
2147
+ IPAddress result;
2148
+
2149
+ #if defined(ESP32) || defined(ESP8266)
2150
+ // Both ESP32 and ESP8266 support WiFi.hostByName()
2151
+ int dnsResult = WiFi.hostByName("www.google.com", result);
2152
+
2153
+ // Check if DNS resolution succeeded
2154
+ if (dnsResult != 1) {
2155
+ Log(COMMUNICATION, "hasActualInternetAccess(): DNS resolution failed (code=%d)\n", dnsResult);
2156
+ return false;
2157
+ }
2158
+
2159
+ // Additional validation: Check if resolved IP is valid
2160
+ // Some ESP8266 versions may return success but set IP to 255.255.255.255 on error
2161
+ if (result == IPAddress(0, 0, 0, 0) || result == IPAddress(255, 255, 255, 255)) {
2162
+ TSTRING resultStr = result.toString();
2163
+ Log(COMMUNICATION, "hasActualInternetAccess(): Invalid DNS result IP: %s\n", resultStr.c_str());
2164
+ return false;
2165
+ }
2166
+ #else
2167
+ // Other platforms: assume internet is available if WiFi connected
2168
+ // (no reliable way to test without platform-specific APIs)
2169
+ return true;
2170
+ #endif
2171
+
2172
+ TSTRING resultStr = result.toString();
2173
+ Log(COMMUNICATION, "hasActualInternetAccess(): Internet connectivity verified (resolved to %s)\n",
2174
+ resultStr.c_str());
2175
+ return true;
2176
+ }
2177
+
2123
2178
  /**
2124
2179
  * Helper method to send gateway acknowledgment
2125
2180
  */
@@ -2196,8 +2251,16 @@ class Mesh : public painlessmesh::Mesh<Connection> {
2196
2251
  }
2197
2252
 
2198
2253
  // Check Internet connectivity
2254
+ // First check WiFi status for quick fail
2199
2255
  if (WiFi.status() != WL_CONNECTED) {
2200
- sendGatewayAck(pkg, false, 0, "Gateway not connected to Internet");
2256
+ sendGatewayAck(pkg, false, 0, "Gateway WiFi not connected");
2257
+ return true; // Consume package - we handled it (with error)
2258
+ }
2259
+
2260
+ // Then check actual internet access (DNS resolution)
2261
+ // This detects when WiFi is connected but router has no internet
2262
+ if (!hasActualInternetAccess()) {
2263
+ sendGatewayAck(pkg, false, 0, "Router has no internet access - check WAN connection");
2201
2264
  return true; // Consume package - we handled it (with error)
2202
2265
  }
2203
2266
 
@@ -5,7 +5,7 @@
5
5
  * @file painlessMesh.h
6
6
  * @brief Main header file for Alteriom painlessMesh library
7
7
  *
8
- * @version 1.9.17
8
+ * @version 1.9.19
9
9
  * @date 2025-12-21
10
10
  *
11
11
  * painlessMesh is a user-friendly library for creating mesh networks with
@@ -1532,10 +1532,38 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
1532
1532
  isRetryable = true;
1533
1533
  Log(COMMUNICATION, "handleGatewayAck(): HTTP 429 rate limit, marking as retryable\n");
1534
1534
  }
1535
- // Network errors (httpStatus == 0) are retryable
1535
+ // Network errors (httpStatus == 0) EXCEPT gateway connectivity errors
1536
+ // Gateway connectivity errors are infrastructure issues (not transient)
1536
1537
  else if (ack.httpStatus == 0) {
1537
- isRetryable = true;
1538
- Log(COMMUNICATION, "handleGatewayAck(): Network error, marking as retryable\n");
1538
+ // Check if this is a gateway-level connectivity error (non-retryable)
1539
+ bool isGatewayConnectivityError = false;
1540
+
1541
+ // These errors indicate infrastructure issues that won't be fixed by retrying:
1542
+ // - "Router has no internet access" - WAN connection down
1543
+ // - "Gateway WiFi not connected" - ESP not associated with WiFi
1544
+ // Use find() for std::string (test env) or indexOf() for Arduino String
1545
+ bool routerError = false, wifiError = false;
1546
+ #if defined(PAINLESSMESH_BOOST)
1547
+ // Test environment: TSTRING is std::string, use find()
1548
+ routerError = (ack.error.find("Router has no internet") != std::string::npos);
1549
+ wifiError = (ack.error.find("Gateway WiFi not connected") != std::string::npos);
1550
+ #else
1551
+ // Arduino environment: TSTRING is String, use indexOf()
1552
+ routerError = (ack.error.indexOf("Router has no internet") >= 0);
1553
+ wifiError = (ack.error.indexOf("Gateway WiFi not connected") >= 0);
1554
+ #endif
1555
+
1556
+ if (routerError || wifiError) {
1557
+ isGatewayConnectivityError = true;
1558
+ Log(COMMUNICATION, "handleGatewayAck(): Gateway connectivity error detected (non-retryable): %s\n",
1559
+ ack.error.c_str());
1560
+ }
1561
+
1562
+ // Only mark as retryable if it's NOT a gateway connectivity error
1563
+ if (!isGatewayConnectivityError) {
1564
+ isRetryable = true;
1565
+ Log(COMMUNICATION, "handleGatewayAck(): Network error, marking as retryable\n");
1566
+ }
1539
1567
  }
1540
1568
  // HTTP 4xx client errors (except 429) are NOT retryable
1541
1569
  // HTTP 3xx redirects are NOT retryable (should be followed by HTTPClient)