@alteriom/painlessmesh 1.9.20 → 2.0.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.
Files changed (61) hide show
  1. package/BRIDGE_TO_INTERNET.md +167 -29
  2. package/CHANGELOG.md +604 -0
  3. package/CONTRIBUTING.md +56 -53
  4. package/README.md +100 -75
  5. package/RELEASE_GUIDE.md +81 -641
  6. package/examples/alteriom/README.md +8 -10
  7. package/examples/alteriom/alteriom.ino +2 -2
  8. package/examples/alteriom/alteriom_custom_package_template.hpp +11 -11
  9. package/examples/alteriom/alteriom_sensor_package.hpp +17 -11
  10. package/examples/alteriom/mppt_example/alteriom_custom_package_template.hpp +320 -0
  11. package/examples/alteriom/mppt_example/alteriom_sensor_package.hpp +1389 -0
  12. package/examples/alteriom/mppt_example/{alteriom_mppt_example.ino → mppt_example.ino} +5 -1
  13. package/examples/basic/test/simulator/README.md +3 -3
  14. package/examples/bridge_failover/README.md +51 -14
  15. package/examples/bridge_failover/bridge_failover.ino +2 -2
  16. package/examples/commandControl/commandControl.ino +86 -0
  17. package/examples/commandControl/platformio.ini +26 -0
  18. package/examples/mqttBridge/mqttBridge.ino +4 -0
  19. package/examples/mqttBridge/platformio.ini +1 -1
  20. package/examples/otaSender/otaSender.ino +5 -1
  21. package/examples/priority/README.md +1 -1
  22. package/examples/priority/{priority_basic_example.ino → priority_basic_example/priority_basic_example.ino} +4 -4
  23. package/examples/priority/{priority_with_queue.ino → priority_with_queue/priority_with_queue.ino} +20 -2
  24. package/examples/reliableSensorLogging/platformio.ini +26 -0
  25. package/examples/reliableSensorLogging/reliableSensorLogging.ino +151 -0
  26. package/examples/sendToInternet/README.md +12 -5
  27. package/examples/sendToInternet/{CMakeLists.txt → pc_node/CMakeLists.txt} +7 -7
  28. package/examples/sendToInternet/{PC_NODE_README.md → pc_node/PC_NODE_README.md} +15 -15
  29. package/examples/sendToInternet/{build.sh → pc_node/build.sh} +5 -5
  30. package/examples/sendToInternet/{pc_mesh_node.cpp → pc_node/pc_mesh_node.cpp} +12 -1
  31. package/examples/sharedGateway/README.md +1 -2
  32. package/examples/tcpRetryConfig/README.md +110 -0
  33. package/examples/tcpRetryConfig/platformio.ini +26 -0
  34. package/examples/tcpRetryConfig/tcpRetryConfig.ino +154 -0
  35. package/keywords.txt +53 -1
  36. package/library.json +8 -6
  37. package/library.properties +2 -2
  38. package/package.json +3 -3
  39. package/src/AlteriomPainlessMesh.h +4 -4
  40. package/src/arduino/wifi.hpp +605 -143
  41. package/src/painlessMesh.h +2 -2
  42. package/src/painlessMeshSTA.cpp +607 -87
  43. package/src/painlessMeshSTA.h +135 -3
  44. package/src/painlessTaskOptions.h +9 -0
  45. package/src/painlessmesh/ack.hpp +283 -0
  46. package/src/painlessmesh/buffer.hpp +74 -9
  47. package/src/painlessmesh/callback.hpp +38 -5
  48. package/src/painlessmesh/configuration.hpp +82 -3
  49. package/src/painlessmesh/connection.hpp +43 -16
  50. package/src/painlessmesh/gateway.hpp +270 -5
  51. package/src/painlessmesh/layout.hpp +70 -2
  52. package/src/painlessmesh/logger.hpp +15 -0
  53. package/src/painlessmesh/mesh.hpp +625 -70
  54. package/src/painlessmesh/message_queue.hpp +24 -13
  55. package/src/painlessmesh/ntp.hpp +2 -4
  56. package/src/painlessmesh/plugin.hpp +52 -6
  57. package/src/painlessmesh/protocol.hpp +55 -2
  58. package/src/painlessmesh/router.hpp +192 -77
  59. package/src/painlessmesh/tcp.hpp +168 -29
  60. package/src/painlessmesh/message_tracker.hpp +0 -311
  61. /package/examples/sendToInternet/{mock_server_test.ino → mock_server_test/mock_server_test.ino} +0 -0
@@ -6,7 +6,7 @@ This example provides a **PC-based mesh node** that can join a painlessMesh netw
6
6
 
7
7
  ### The Problem This Solves
8
8
 
9
- Previous examples (`mock_server_test.ino`) tested the bridge making HTTP requests directly, but did **NOT** test the complete flow:
9
+ Previous examples (`../mock_server_test/mock_server_test.ino`) tested the bridge making HTTP requests directly, but did **NOT** test the complete flow:
10
10
 
11
11
  ```
12
12
  Regular Node → Mesh Network → Bridge → Internet → Bridge → Mesh Network → Regular Node
@@ -90,7 +90,7 @@ brew install cmake boost
90
90
  For testing, start the mock HTTP server:
91
91
 
92
92
  ```bash
93
- cd ../../test/mock-http-server
93
+ cd ../../../test/mock-http-server
94
94
  python3 server.py
95
95
  ```
96
96
 
@@ -101,13 +101,13 @@ The server will run on `http://localhost:8080` by default.
101
101
  ### Quick Build (Using make)
102
102
 
103
103
  ```bash
104
- cd examples/sendToInternet
104
+ cd examples/sendToInternet/pc_node
105
105
 
106
106
  # Initialize dependencies (if not already done)
107
- cd ../../test
107
+ cd ../../../test
108
108
  git clone https://github.com/bblanchon/ArduinoJson.git
109
109
  git clone https://github.com/arkhipenko/TaskScheduler
110
- cd ../examples/sendToInternet
110
+ cd ../examples/sendToInternet/pc_node
111
111
 
112
112
  # Build
113
113
  cmake .
@@ -131,9 +131,9 @@ make
131
131
 
132
132
  ```bash
133
133
  g++ -std=c++14 -o pc_mesh_node pc_mesh_node.cpp \
134
- -I../../src -I../../test/include -I../../test/ArduinoJson/src \
135
- -I../../test/TaskScheduler/src -I../../test/boost \
136
- ../../test/catch/fake_serial.cpp ../../src/scheduler.cpp \
134
+ -I../../../src -I../../../test/include -I../../../test/ArduinoJson/src \
135
+ -I../../../test/TaskScheduler/src -I../../../test/boost \
136
+ ../../../test/catch/fake_serial.cpp ../../../src/scheduler.cpp \
137
137
  -lboost_system -pthread
138
138
  ```
139
139
 
@@ -371,14 +371,14 @@ brew install boost
371
371
  #### "ArduinoJson not found"
372
372
 
373
373
  ```bash
374
- cd ../../test
374
+ cd ../../../test
375
375
  git clone https://github.com/bblanchon/ArduinoJson.git
376
376
  ```
377
377
 
378
378
  #### "TaskScheduler not found"
379
379
 
380
380
  ```bash
381
- cd ../../test
381
+ cd ../../../test
382
382
  git clone https://github.com/arkhipenko/TaskScheduler
383
383
  ```
384
384
 
@@ -476,7 +476,7 @@ python3 test/mock-http-server/server.py &
476
476
  SERVER_PID=$!
477
477
 
478
478
  # Build PC node
479
- cd examples/sendToInternet
479
+ cd examples/sendToInternet/pc_node
480
480
  cmake . && make
481
481
 
482
482
  # Run test (assuming bridge is running at known IP)
@@ -501,10 +501,10 @@ kill $SERVER_PID
501
501
 
502
502
  ## Related Documentation
503
503
 
504
- - [sendToInternet Example](sendToInternet.ino) - ESP32/ESP8266 example
505
- - [Mock HTTP Server](../../test/mock-http-server/README.md) - Testing endpoint
506
- - [Bridge Documentation](../../BRIDGE_TO_INTERNET.md) - Bridge setup guide
507
- - [Testing Guide](../../test/mock-http-server/TESTING_GUIDE.md) - Complete testing workflow
504
+ - [sendToInternet Example](../sendToInternet.ino) - ESP32/ESP8266 example
505
+ - [Mock HTTP Server](../../../test/mock-http-server/README.md) - Testing endpoint
506
+ - [Bridge Documentation](../../../BRIDGE_TO_INTERNET.md) - Bridge setup guide
507
+ - [Testing Guide](../../../test/mock-http-server/TESTING_GUIDE.md) - Complete testing workflow
508
508
 
509
509
  ## Credits
510
510
 
@@ -73,10 +73,10 @@ echo " - Windows: See https://www.boost.org/"
73
73
  echo ""
74
74
  echo "Checking test dependencies..."
75
75
 
76
- if [ ! -d "../../test/ArduinoJson/src" ]; then
76
+ if [ ! -d "../../../test/ArduinoJson/src" ]; then
77
77
  echo "⚠️ ArduinoJson not found"
78
78
  echo " Cloning ArduinoJson..."
79
- cd ../../test
79
+ cd ../../../test
80
80
  if [ -d "ArduinoJson" ]; then
81
81
  rm -rf ArduinoJson
82
82
  fi
@@ -86,10 +86,10 @@ else
86
86
  echo "✓ ArduinoJson found"
87
87
  fi
88
88
 
89
- if [ ! -d "../../test/TaskScheduler/src" ]; then
89
+ if [ ! -d "../../../test/TaskScheduler/src" ]; then
90
90
  echo "⚠️ TaskScheduler not found"
91
91
  echo " Cloning TaskScheduler..."
92
- cd ../../test
92
+ cd ../../../test
93
93
  if [ -d "TaskScheduler" ]; then
94
94
  rm -rf TaskScheduler
95
95
  fi
@@ -135,7 +135,7 @@ if make 2>&1; then
135
135
  echo ""
136
136
  echo "Next steps:"
137
137
  echo " 1. Start mock HTTP server:"
138
- echo " cd ../../test/mock-http-server && python3 server.py"
138
+ echo " cd ../../../test/mock-http-server && python3 server.py"
139
139
  echo ""
140
140
  echo " 2. Configure and upload bridge to ESP32/ESP8266"
141
141
  echo " (see sendToInternet.ino with IS_BRIDGE_NODE=true)"
@@ -38,6 +38,15 @@
38
38
  * - 5555 is the TCP port the bridge is listening on (MESH_PORT)
39
39
  **/
40
40
 
41
+ // This is a PC-side (desktop) program: it needs Boost and the Arduino
42
+ // emulation layer under test/, neither of which exists for an embedded
43
+ // target. Both the Arduino IDE and arduino-cli compile *every* .cpp in a
44
+ // sketch folder, so without this guard they try to build this file for the
45
+ // ESP and fail on <boost/asio/ip/address.hpp>. ARDUINO is defined by every
46
+ // Arduino toolchain, so the whole file collapses to an empty translation
47
+ // unit there and is left to the CMake/g++ build described above.
48
+ #ifndef ARDUINO
49
+
41
50
  #include <iostream>
42
51
  #include <string>
43
52
  #include <memory>
@@ -356,6 +365,8 @@ int main(int argc, char* argv[]) {
356
365
  node.runUpdateLoop(10);
357
366
 
358
367
  std::cout << "\n✓ PC Mesh Node shutting down..." << std::endl;
359
-
368
+
360
369
  return 0;
361
370
  }
371
+
372
+ #endif // !ARDUINO
@@ -225,8 +225,7 @@ WiFi.channel()
225
225
 
226
226
  ## Related Documentation
227
227
 
228
- - [Shared Gateway Design Document](../../docs/design/SHARED_GATEWAY_DESIGN.md)
229
- - [Bridge Mode Example](../bridge/README.md)
228
+ - [Bridge Mode Example](../bridge/bridge.ino)
230
229
  - [Bridge Failover Example](../bridge_failover/README.md)
231
230
  - [painlessMesh Documentation](https://gitlab.com/painlessMesh/painlessMesh/-/wikis/home)
232
231
 
@@ -0,0 +1,110 @@
1
+ # tcpRetryConfig
2
+
3
+ Tuning painlessMesh's TCP connection retry behaviour with
4
+ `setTcpRetryConfig()` (issue
5
+ [#378](https://github.com/Alteriom/painlessMesh/issues/378)).
6
+
7
+ ## What this controls
8
+
9
+ When a node acquires an IP and tries to open its TCP connection to the mesh,
10
+ that connection can fail — the parent's TCP server may not be ready yet, the
11
+ network stack may still be settling, or several nodes may be connecting at
12
+ once. painlessMesh retries with exponential backoff before giving up and
13
+ falling back to a full WiFi reconnect.
14
+
15
+ Five parameters describe that behaviour:
16
+
17
+ | Field | Default | Meaning |
18
+ |---|---|---|
19
+ | `maxRetries` | 5 | TCP connect attempts after the first before giving up |
20
+ | `retryDelayMs` | 1000 | Base delay between retries; scaled 1x, 2x, 4x, 8x, 8x |
21
+ | `stabilizationDelayMs` | 500 | Wait after IP acquisition before the first attempt |
22
+ | `exhaustionReconnectDelayMs` | 10000 | Wait before the WiFi reconnect that follows exhaustion |
23
+ | `failureBlockDurationMs` | 60000 | How long a failed peer is skipped during AP selection |
24
+
25
+ With the defaults, a node that cannot reach its parent spends
26
+ 1 + 2 + 4 + 8 + 8 = **23 s** retrying, then waits another **10 s** before
27
+ reconnecting WiFi, and will not re-select that same peer for **60 s**.
28
+
29
+ ## Profiles in this sketch
30
+
31
+ Switch with `#define ACTIVE_PROFILE`.
32
+
33
+ | | `PROFILE_REALTIME` | default | `PROFILE_RELIABLE` | `PROFILE_BATTERY` |
34
+ |---|---|---|---|---|
35
+ | `maxRetries` | 1 | 5 | 10 | 2 |
36
+ | `retryDelayMs` | 200 | 1000 | 2000 | 3000 |
37
+ | `stabilizationDelayMs` | 100 | 500 | 1000 | 500 |
38
+ | `exhaustionReconnectDelayMs` | 1000 | 10000 | 30000 | 60000 |
39
+ | `failureBlockDurationMs` | 5000 | 60000 | 180000 | 300000 |
40
+ | worst-case retry time | 0.2 s | 23 s | 126 s | 9 s |
41
+ | full failure cycle | 1.2 s | 33 s | 156 s | 69 s |
42
+
43
+ - **`PROFILE_REALTIME`** — real-time sensor and LED meshes, the use case from
44
+ [discussion #368](https://github.com/Alteriom/painlessMesh/discussions/368).
45
+ A node stuck in a 23 s backoff is worse than one that drops and re-scans, so
46
+ fail fast and move on.
47
+ - **`PROFILE_RELIABLE`** — industrial meshes where getting connected matters
48
+ more than how long it takes. `maxRetries = 10` is the maximum the library
49
+ accepts.
50
+ - **`PROFILE_BATTERY`** — every retry is radio-on time. Few attempts, spaced
51
+ widely, and a long blocklist so the node stops waking up for a peer that is
52
+ known to be down.
53
+
54
+ ## Clamping
55
+
56
+ `setTcpRetryConfig()` coerces the two values that can render a node unusable:
57
+
58
+ - `maxRetries` is capped at **10**. Each retry allocates an `AsyncClient` and
59
+ schedules a task, so an unbounded value is a heap and recursion-depth hazard
60
+ on ESP8266.
61
+ - `retryDelayMs` is held between **50 ms** and **60000 ms**. A zero delay would
62
+ schedule retries with no spacing — a hot loop allocating an `AsyncClient`
63
+ every scheduler tick. The ceiling keeps `retryDelayMs * 8` clear of `uint32_t`
64
+ overflow.
65
+
66
+ Everything else passes through untouched, including zeros, which are
67
+ meaningful:
68
+
69
+ - `maxRetries = 0` — do not retry at all; fall straight back to a WiFi
70
+ reconnect on the first TCP error.
71
+ - `stabilizationDelayMs = 0` — attempt the TCP connection immediately on IP
72
+ acquisition.
73
+ - `exhaustionReconnectDelayMs = 0` — reconnect WiFi immediately after
74
+ exhaustion.
75
+ - `failureBlockDurationMs = 0` — never blocklist a failed peer.
76
+
77
+ Call `getTcpRetryConfig()` after setting to see what actually took effect; the
78
+ sketch prints this at startup.
79
+
80
+ ## The defaults exist for a reason
81
+
82
+ painlessMesh 1.9.x deliberately *raised* these values (retries 3 → 5, base
83
+ delay 500 ms → 1000 ms) to fix real-world mesh instability. Tuning them back
84
+ down reintroduces the problems that change fixed. Symptoms of an over-aggressive
85
+ profile:
86
+
87
+ - **Connection churn** — nodes repeatedly connect and drop. `maxRetries` is too
88
+ low for how long your parent actually takes to be ready; raise it or raise
89
+ `stabilizationDelayMs`.
90
+ - **Rapid reconnect loops / network congestion** — a node hammers a parent whose
91
+ TCP server is down. `exhaustionReconnectDelayMs` is too short.
92
+ - **The same dead peer is picked over and over** — `failureBlockDurationMs` is
93
+ shorter than one full retry-plus-reconnect cycle, so the peer comes off the
94
+ blocklist before the node has finished failing over. Keep
95
+ `failureBlockDurationMs` greater than
96
+ `(sum of retry backoffs) + exhaustionReconnectDelayMs`. All three profiles
97
+ above satisfy this; `catch_tcp_blocklist.cpp` pins it as a test.
98
+
99
+ Change one parameter at a time and watch the serial log with
100
+ `mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION)`.
101
+
102
+ ## Building
103
+
104
+ ```bash
105
+ # PlatformIO
106
+ pio run -e esp32 # or -e esp8266
107
+
108
+ # Arduino CLI
109
+ arduino-cli compile --fqbn esp32:esp32:esp32 examples/tcpRetryConfig/tcpRetryConfig.ino
110
+ ```
@@ -0,0 +1,26 @@
1
+ [platformio]
2
+ src_dir = .
3
+
4
+ [env]
5
+ lib_deps =
6
+ bblanchon/ArduinoJson
7
+ arkhipenko/TaskScheduler
8
+
9
+ lib_ldf_mode = deep+
10
+ [env:esp8266]
11
+ platform = espressif8266
12
+ board = nodemcuv2
13
+ framework = arduino
14
+ lib_extra_dirs = ../../
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 = ../../
24
+ lib_deps =
25
+ ${env.lib_deps} ; Inherit common dependencies
26
+ esp32async/AsyncTCP
@@ -0,0 +1,154 @@
1
+ //************************************************************
2
+ // Tuning the TCP connection retry behaviour (issue #378)
3
+ //
4
+ // painlessMesh retries a failed TCP connection with exponential backoff
5
+ // before giving up and falling back to a full WiFi reconnect. The defaults
6
+ // (5 retries, 1s base delay -> 1s, 2s, 4s, 8s, 8s) are tuned for general
7
+ // purpose meshes and deliberately favour reliability over speed.
8
+ //
9
+ // setTcpRetryConfig() lets you pick a different trade-off. Three ready-made
10
+ // profiles are shown below; switch between them with ACTIVE_PROFILE.
11
+ //
12
+ // Read examples/tcpRetryConfig/README.md before changing these values - the
13
+ // defaults exist because 1.9.x raised them to fix real mesh instability.
14
+ //************************************************************
15
+ #include <painlessMesh.h>
16
+
17
+ #define MESH_SSID "whateverYouLike"
18
+ #define MESH_PASSWORD "somethingSneaky"
19
+ #define MESH_PORT 5555
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Profiles
23
+ // ---------------------------------------------------------------------------
24
+ #define PROFILE_REALTIME 1 // low latency: fail fast, reconnect fast
25
+ #define PROFILE_RELIABLE 2 // industrial: many retries, long backoff
26
+ #define PROFILE_BATTERY 3 // conserve power: few retries, long block
27
+
28
+ // >>> Change this line to try a different profile <<<
29
+ #define ACTIVE_PROFILE PROFILE_REALTIME
30
+
31
+ // Prototypes
32
+ void sendMessage();
33
+ void receivedCallback(uint32_t from, String &msg);
34
+ void newConnectionCallback(uint32_t nodeId);
35
+ void droppedConnectionCallback(uint32_t nodeId);
36
+
37
+ Scheduler userScheduler;
38
+ painlessMesh mesh;
39
+
40
+ Task taskSendMessage(TASK_SECOND * 5, TASK_FOREVER, &sendMessage);
41
+
42
+ // Build the retry configuration for the selected profile.
43
+ painlessmesh::tcp::TcpRetryConfig buildRetryConfig() {
44
+ painlessmesh::tcp::TcpRetryConfig cfg; // starts at the library defaults
45
+
46
+ #if ACTIVE_PROFILE == PROFILE_REALTIME
47
+ // Real-time sensor / LED meshes: a stalled node is worse than a dropped
48
+ // one. Give up on the TCP handshake almost immediately and go straight
49
+ // back to scanning for another parent.
50
+ cfg.maxRetries = 1; // default 5
51
+ cfg.retryDelayMs = 200; // default 1000
52
+ cfg.stabilizationDelayMs = 100; // default 500
53
+ cfg.exhaustionReconnectDelayMs = 1000; // default 10000
54
+ cfg.failureBlockDurationMs = 5000; // default 60000
55
+
56
+ #elif ACTIVE_PROFILE == PROFILE_RELIABLE
57
+ // Industrial / high-reliability meshes: connectivity matters more than
58
+ // how long it takes to get there. Retry patiently and keep a failed peer
59
+ // out of the running for a good while.
60
+ cfg.maxRetries = 10; // default 5 (this is the maximum)
61
+ cfg.retryDelayMs = 2000; // default 1000
62
+ cfg.stabilizationDelayMs = 1000; // default 500
63
+ cfg.exhaustionReconnectDelayMs = 30000; // default 10000
64
+ // Must exceed one full failure cycle (126s of retries + 30s reconnect),
65
+ // otherwise a dead peer leaves the blocklist before we finished failing
66
+ // over and gets re-selected immediately.
67
+ cfg.failureBlockDurationMs = 180000; // default 60000
68
+
69
+ #elif ACTIVE_PROFILE == PROFILE_BATTERY
70
+ // Battery-powered nodes: every retry is radio time. Few attempts, spaced
71
+ // widely, and a long blocklist so we do not keep waking up for a peer
72
+ // that is known to be down.
73
+ cfg.maxRetries = 2; // default 5
74
+ cfg.retryDelayMs = 3000; // default 1000
75
+ cfg.stabilizationDelayMs = 500; // default 500
76
+ cfg.exhaustionReconnectDelayMs = 60000; // default 10000
77
+ cfg.failureBlockDurationMs = 300000; // default 60000
78
+
79
+ #else
80
+ #error "ACTIVE_PROFILE must be one of PROFILE_REALTIME, PROFILE_RELIABLE, PROFILE_BATTERY"
81
+ #endif
82
+
83
+ return cfg;
84
+ }
85
+
86
+ void setup() {
87
+ Serial.begin(115200);
88
+
89
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
90
+
91
+ // Apply the retry configuration BEFORE init() so the very first connection
92
+ // attempt already uses it.
93
+ mesh.setTcpRetryConfig(buildRetryConfig());
94
+
95
+ mesh.init(MESH_SSID, MESH_PASSWORD, &userScheduler, MESH_PORT);
96
+
97
+ // Read the configuration back. Values outside safe operating bounds are
98
+ // clamped by the setter, so this prints what is actually in effect - not
99
+ // necessarily what was requested.
100
+ painlessmesh::tcp::TcpRetryConfig active = mesh.getTcpRetryConfig();
101
+ Serial.println();
102
+ Serial.println(F("Effective TCP retry configuration:"));
103
+ Serial.printf(" maxRetries = %u\n",
104
+ (unsigned)active.maxRetries);
105
+ Serial.printf(" retryDelayMs = %u\n",
106
+ (unsigned)active.retryDelayMs);
107
+ Serial.printf(" stabilizationDelayMs = %u\n",
108
+ (unsigned)active.stabilizationDelayMs);
109
+ Serial.printf(" exhaustionReconnectDelayMs = %u\n",
110
+ (unsigned)active.exhaustionReconnectDelayMs);
111
+ Serial.printf(" failureBlockDurationMs = %u\n",
112
+ (unsigned)active.failureBlockDurationMs);
113
+
114
+ // Worst-case time spent retrying before falling back to a WiFi reconnect.
115
+ uint32_t worstCase = 0;
116
+ for (uint8_t i = 0; i < active.maxRetries; ++i) {
117
+ worstCase += painlessmesh::tcp::retryBackoffDelay(active, i);
118
+ }
119
+ Serial.printf(" -> worst-case retry time = %u ms\n", (unsigned)worstCase);
120
+ Serial.printf(" -> plus reconnect delay = %u ms\n",
121
+ (unsigned)(worstCase + active.exhaustionReconnectDelayMs));
122
+ Serial.println();
123
+
124
+ mesh.onReceive(&receivedCallback);
125
+ mesh.onNewConnection(&newConnectionCallback);
126
+ mesh.onDroppedConnection(&droppedConnectionCallback);
127
+
128
+ userScheduler.addTask(taskSendMessage);
129
+ taskSendMessage.enable();
130
+ }
131
+
132
+ void loop() {
133
+ mesh.update();
134
+ }
135
+
136
+ void sendMessage() {
137
+ String msg = "Hello from node ";
138
+ msg += mesh.getNodeId();
139
+ mesh.sendBroadcast(msg);
140
+ }
141
+
142
+ void receivedCallback(uint32_t from, String &msg) {
143
+ Serial.printf("tcpRetryConfig: Received from %u msg=%s\n", from, msg.c_str());
144
+ }
145
+
146
+ void newConnectionCallback(uint32_t nodeId) {
147
+ Serial.printf("--> Connected to node %u\n", nodeId);
148
+ }
149
+
150
+ void droppedConnectionCallback(uint32_t nodeId) {
151
+ // With an aggressive profile you should expect to see this more often -
152
+ // and to see the reconnect that follows it happen much sooner.
153
+ Serial.printf("--> Dropped connection to node %u\n", nodeId);
154
+ }
package/keywords.txt CHANGED
@@ -4,6 +4,8 @@
4
4
  painlessMesh KEYWORD1
5
5
  Scheduler KEYWORD1
6
6
  Task KEYWORD1
7
+ TcpRetryConfig KEYWORD1
8
+ SendOptions KEYWORD1
7
9
 
8
10
  # Methods and Functions (KEYWORD2)
9
11
  init KEYWORD2
@@ -18,11 +20,57 @@ getNodeList KEYWORD2
18
20
  getNodeId KEYWORD2
19
21
  getNodeTime KEYWORD2
20
22
  setDebugMsgTypes KEYWORD2
23
+ checkAcks KEYWORD2
24
+ pendingAcks KEYWORD2
25
+ setTcpRetryConfig KEYWORD2
26
+ getTcpRetryConfig KEYWORD2
27
+ stop KEYWORD2
28
+ isConnected KEYWORD2
29
+ subConnectionJson KEYWORD2
30
+ startDelayMeas KEYWORD2
31
+ onNodeDelayReceived KEYWORD2
32
+ setRoot KEYWORD2
33
+ setContainsRoot KEYWORD2
34
+ isRoot KEYWORD2
35
+ stationManual KEYWORD2
36
+ setHostname KEYWORD2
37
+ initAsBridge KEYWORD2
38
+ initAsSharedGateway KEYWORD2
39
+ isBridge KEYWORD2
40
+ setRouterCredentials KEYWORD2
41
+ enableBridgeFailover KEYWORD2
42
+ onBridgeRoleChanged KEYWORD2
43
+ onBridgeStatusChanged KEYWORD2
44
+ onGatewayChanged KEYWORD2
45
+ setElectionStartupDelay KEYWORD2
46
+ setElectionRandomDelay KEYWORD2
47
+ setElectionTimeout KEYWORD2
48
+ setMinimumBridgeRSSI KEYWORD2
49
+ setBridgeStatusInterval KEYWORD2
50
+ setBridgeTimeout KEYWORD2
51
+ hasInternetConnection KEYWORD2
52
+ hasLocalInternet KEYWORD2
53
+ getBridges KEYWORD2
54
+ getPrimaryBridge KEYWORD2
55
+ getPrimaryGateway KEYWORD2
56
+ enableSendToInternet KEYWORD2
57
+ sendToInternet KEYWORD2
58
+ enableMessageQueue KEYWORD2
59
+ queueMessage KEYWORD2
60
+ flushMessageQueue KEYWORD2
61
+ getQueueStats KEYWORD2
62
+ initOTASend KEYWORD2
63
+ initOTAReceive KEYWORD2
64
+ overCapacity KEYWORD2
65
+ apChildren KEYWORD2
66
+ getTcpRetryConfig KEYWORD2
21
67
  subConnectionJson KEYWORD2
22
68
  asNodeTree KEYWORD2
23
69
 
24
70
  # Alteriom Extensions (KEYWORD1)
25
71
  SensorPackage KEYWORD1
72
+ MessageAckPackage KEYWORD1
73
+ deliveryCallback_t KEYWORD1
26
74
  CommandPackage KEYWORD1
27
75
  StatusPackage KEYWORD1
28
76
 
@@ -46,4 +94,8 @@ COMMUNICATION LITERAL1
46
94
  GENERAL LITERAL1
47
95
  MSG_TYPES LITERAL1
48
96
  REMOTE LITERAL1
49
- DEBUG LITERAL1
97
+ DEBUG LITERAL1
98
+ PRIORITY_CRITICAL LITERAL1
99
+ PRIORITY_HIGH LITERAL1
100
+ PRIORITY_NORMAL LITERAL1
101
+ PRIORITY_LOW LITERAL1
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.20",
9
+ "version": "2.0.0",
10
10
  "frameworks": [
11
11
  "arduino"
12
12
  ],
@@ -87,13 +87,15 @@
87
87
  "examples/namedMesh/namedMesh.ino",
88
88
  "examples/otaReceiver/otaReceiver.ino",
89
89
  "examples/otaSender/otaSender.ino",
90
- "examples/alteriom/mppt_example/alteriom_mppt_example.ino",
91
- "examples/priority/priority_basic_example.ino",
92
- "examples/priority/priority_with_queue.ino",
93
- "examples/sendToInternet/mock_server_test.ino",
90
+ "examples/alteriom/mppt_example/mppt_example.ino",
91
+ "examples/priority/priority_basic_example/priority_basic_example.ino",
92
+ "examples/priority/priority_with_queue/priority_with_queue.ino",
93
+ "examples/sendToInternet/mock_server_test/mock_server_test.ino",
94
94
  "examples/sendToInternet/sendToInternet.ino",
95
95
  "examples/sharedGateway/sharedGateway.ino",
96
96
  "examples/startHere/startHere.ino",
97
- "examples/webServer/webServer.ino"
97
+ "examples/webServer/webServer.ino",
98
+ "examples/commandControl/commandControl.ino",
99
+ "examples/reliableSensorLogging/reliableSensorLogging.ino"
98
100
  ]
99
101
  }
@@ -1,5 +1,5 @@
1
1
  name=Alteriom PainlessMesh
2
- version=1.9.20
2
+ version=2.0.0
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
@@ -8,4 +8,4 @@ category=Communication
8
8
  url=https://github.com/Alteriom/painlessMesh
9
9
  architectures=esp8266,esp32
10
10
  includes=painlessMesh.h,AlteriomPainlessMesh.h
11
- depends=ArduinoJson, TaskScheduler
11
+ depends=ArduinoJson, TaskScheduler, PubSubClient
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alteriom/painlessmesh",
3
- "version": "1.9.20",
3
+ "version": "2.0.0",
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",
@@ -41,9 +41,9 @@
41
41
  "devDependencies": {
42
42
  "@alteriom/mqtt-schema": "^0.8.0",
43
43
  "@eslint/js": "^10.0.1",
44
- "ajv": "^8.17.1",
44
+ "ajv": "^8.20.0",
45
45
  "ajv-formats": "^3.0.1",
46
- "prettier": "^3.8.1"
46
+ "prettier": "^3.9.6"
47
47
  },
48
48
  "scripts": {
49
49
  "test": "run-parts --regex catch_ bin/ || echo 'Tests completed'",
@@ -29,10 +29,10 @@
29
29
  /**
30
30
  * @brief AlteriomPainlessMesh library version information
31
31
  */
32
- #define ALTERIOM_PAINLESS_MESH_VERSION "1.9.20"
33
- #define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 1
34
- #define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 9
35
- #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 20
32
+ #define ALTERIOM_PAINLESS_MESH_VERSION "2.0.0"
33
+ #define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 2
34
+ #define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 0
35
+ #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 0
36
36
 
37
37
  /**
38
38
  * @brief Library description and usage information