@alteriom/painlessmesh 1.6.1

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 (80) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/LICENSE +674 -0
  3. package/README.md +434 -0
  4. package/RELEASE_GUIDE.md +419 -0
  5. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +176 -0
  6. package/docs/README.md +71 -0
  7. package/docs/alteriom/overview.md +508 -0
  8. package/docs/api/core-api.md +607 -0
  9. package/docs/architecture/mesh-architecture.md +379 -0
  10. package/docs/architecture/plugin-system.md +517 -0
  11. package/docs/getting-started/first-mesh.md +410 -0
  12. package/docs/getting-started/installation.md +275 -0
  13. package/docs/getting-started/quickstart.md +158 -0
  14. package/docs/improvements/README.md +69 -0
  15. package/docs/troubleshooting/common-issues.md +521 -0
  16. package/docs/troubleshooting/faq.md +473 -0
  17. package/docs/tutorials/basic-examples.md +718 -0
  18. package/docs/wiki/API-Reference.md +246 -0
  19. package/docs/wiki/Complete-Documentation.md +123 -0
  20. package/examples/alteriom/README.md +82 -0
  21. package/examples/alteriom/alteriom.ino +186 -0
  22. package/examples/alteriom/alteriom_sensor_node.ino +184 -0
  23. package/examples/alteriom/alteriom_sensor_package.hpp +128 -0
  24. package/examples/alteriom/improved_sensor_node.ino +246 -0
  25. package/examples/alteriom/platformio.ini +25 -0
  26. package/examples/basic/basic.ino +66 -0
  27. package/examples/basic/platformio.ini +25 -0
  28. package/examples/bridge/bridge.ino +51 -0
  29. package/examples/bridge/platformio.ini +25 -0
  30. package/examples/echoNode/echoNode.ino +33 -0
  31. package/examples/echoNode/platformio.ini +25 -0
  32. package/examples/logClient/logClient.ino +109 -0
  33. package/examples/logClient/platformio.ini +25 -0
  34. package/examples/logServer/logServer.ino +81 -0
  35. package/examples/logServer/platformio.ini +25 -0
  36. package/examples/mqttBridge/mqttBridge.ino +118 -0
  37. package/examples/mqttBridge/platformio.ini +26 -0
  38. package/examples/namedMesh/namedMesh.ino +97 -0
  39. package/examples/namedMesh/platformio.ini +25 -0
  40. package/examples/otaReceiver/otaReceiver.ino +79 -0
  41. package/examples/otaReceiver/platformio.ini +25 -0
  42. package/examples/otaSender/nodemcu32s_connections.JPG +0 -0
  43. package/examples/otaSender/otaSender.ino +151 -0
  44. package/examples/otaSender/platformio.ini +25 -0
  45. package/examples/startHere/platformio.ini +25 -0
  46. package/examples/startHere/startHere.ino +159 -0
  47. package/examples/webServer/platformio.ini +27 -0
  48. package/examples/webServer/webServer.ino +89 -0
  49. package/keywords.txt +49 -0
  50. package/library.json +34 -0
  51. package/library.properties +11 -0
  52. package/package.json +78 -0
  53. package/src/AlteriomPainlessMesh.h +98 -0
  54. package/src/arduino/wifi.hpp +365 -0
  55. package/src/boost/asynctcp.hpp +279 -0
  56. package/src/painlessMesh.h +70 -0
  57. package/src/painlessMeshSTA.cpp +236 -0
  58. package/src/painlessMeshSTA.h +58 -0
  59. package/src/painlessTaskOptions.h +4 -0
  60. package/src/painlessmesh/base64.hpp +111 -0
  61. package/src/painlessmesh/buffer.hpp +229 -0
  62. package/src/painlessmesh/callback.hpp +91 -0
  63. package/src/painlessmesh/configuration.hpp +77 -0
  64. package/src/painlessmesh/connection.hpp +192 -0
  65. package/src/painlessmesh/layout.hpp +188 -0
  66. package/src/painlessmesh/logger.hpp +158 -0
  67. package/src/painlessmesh/memory.hpp +120 -0
  68. package/src/painlessmesh/mesh.hpp +560 -0
  69. package/src/painlessmesh/metrics.hpp +323 -0
  70. package/src/painlessmesh/ntp.hpp +263 -0
  71. package/src/painlessmesh/ota.hpp +553 -0
  72. package/src/painlessmesh/plugin.hpp +188 -0
  73. package/src/painlessmesh/protocol.hpp +813 -0
  74. package/src/painlessmesh/router.hpp +322 -0
  75. package/src/painlessmesh/tcp.hpp +71 -0
  76. package/src/painlessmesh/validation.hpp +239 -0
  77. package/src/plugin/performance.hpp +214 -0
  78. package/src/plugin/remote.hpp +64 -0
  79. package/src/scheduler.cpp +10 -0
  80. package/src/wifi.cpp +2 -0
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@alteriom/painlessmesh",
3
+ "version": "1.6.1",
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
+ "keywords": [
6
+ "arduino",
7
+ "mesh",
8
+ "esp32",
9
+ "esp8266",
10
+ "embedded",
11
+ "iot",
12
+ "wireless",
13
+ "alteriom",
14
+ "sensor",
15
+ "painlessmesh",
16
+ "mcp-server",
17
+ "github-copilot",
18
+ "json",
19
+ "time-sync",
20
+ "mesh-networking"
21
+ ],
22
+ "author": {
23
+ "name": "Coopdis",
24
+ "url": "https://github.com/Coopdis"
25
+ },
26
+ "maintainers": [
27
+ {
28
+ "name": "Alteriom",
29
+ "url": "https://github.com/Alteriom"
30
+ }
31
+ ],
32
+ "license": "LGPL-3.0",
33
+ "homepage": "https://github.com/Alteriom/painlessMesh",
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/Alteriom/painlessMesh.git"
37
+ },
38
+ "bugs": {
39
+ "url": "https://github.com/Alteriom/painlessMesh/issues"
40
+ },
41
+ "devDependencies": {
42
+ "@eslint/js": "^9.0.0",
43
+ "prettier": "^3.0.0"
44
+ },
45
+ "scripts": {
46
+ "test": "run-parts --regex catch_ bin/ || echo 'Tests completed'",
47
+ "build": "cmake -G Ninja . && ninja",
48
+ "validate-library": "./scripts/validate-release.sh",
49
+ "postpublish": "echo 'Package published successfully to NPM!'",
50
+ "prebuild": "git submodule update --init"
51
+ },
52
+ "engines": {
53
+ "node": ">=14.0.0"
54
+ },
55
+ "config": {
56
+ "arduino": {
57
+ "library": true,
58
+ "platforms": ["arduino", "esp32", "esp8266"]
59
+ }
60
+ },
61
+ "directories": {
62
+ "example": "examples",
63
+ "test": "test",
64
+ "doc": "docs"
65
+ },
66
+ "files": [
67
+ "src/",
68
+ "examples/",
69
+ "docs/",
70
+ "library.properties",
71
+ "library.json",
72
+ "keywords.txt",
73
+ "README.md",
74
+ "LICENSE",
75
+ "CHANGELOG.md",
76
+ "RELEASE_GUIDE.md"
77
+ ]
78
+ }
@@ -0,0 +1,98 @@
1
+ #ifndef ALTERIOM_PAINLESS_MESH_H
2
+ #define ALTERIOM_PAINLESS_MESH_H
3
+
4
+ /**
5
+ * @file AlteriomPainlessMesh.h
6
+ * @brief Main header file for AlteriomPainlessMesh library
7
+ *
8
+ * This is the primary header file that includes all necessary components
9
+ * for the AlteriomPainlessMesh library, including the core painlessMesh
10
+ * functionality and Alteriom-specific extensions.
11
+ */
12
+
13
+ // Include the core painlessMesh library
14
+ #include "painlessMesh.h"
15
+
16
+ // Include Alteriom extensions
17
+ #include "examples/alteriom/alteriom_sensor_package.hpp"
18
+
19
+ /**
20
+ * @namespace alteriom
21
+ * @brief Namespace containing Alteriom-specific extensions for painlessMesh
22
+ *
23
+ * This namespace includes production-ready packages for common IoT scenarios:
24
+ * - SensorPackage: Environmental sensor data broadcasting
25
+ * - CommandPackage: Device control and configuration
26
+ * - StatusPackage: Device health and operational status
27
+ */
28
+
29
+ /**
30
+ * @brief AlteriomPainlessMesh library version information
31
+ */
32
+ #define ALTERIOM_PAINLESS_MESH_VERSION "1.6.1"
33
+ #define ALTERIOM_PAINLESS_MESH_VERSION_MAJOR 1
34
+ #define ALTERIOM_PAINLESS_MESH_VERSION_MINOR 6
35
+ #define ALTERIOM_PAINLESS_MESH_VERSION_PATCH 1
36
+
37
+ /**
38
+ * @brief Library description and usage information
39
+ *
40
+ * AlteriomPainlessMesh is an enhanced fork of the popular painlessMesh library
41
+ * that adds production-ready, type-safe packages for common IoT communication
42
+ * patterns. It provides:
43
+ *
44
+ * - Automatic mesh network formation and management
45
+ * - Type-safe messaging with compile-time validation
46
+ * - Pre-built packages for sensors, commands, and status reporting
47
+ * - Cross-platform compatibility (ESP32, ESP8266, desktop)
48
+ * - Time synchronization across all mesh nodes
49
+ *
50
+ * @section quick_start Quick Start
51
+ *
52
+ * @code{.cpp}
53
+ * #include "AlteriomPainlessMesh.h"
54
+ *
55
+ * #define MESH_PREFIX "MyMesh"
56
+ * #define MESH_PASSWORD "MyPassword"
57
+ * #define MESH_PORT 5555
58
+ *
59
+ * Scheduler userScheduler;
60
+ * painlessMesh mesh;
61
+ *
62
+ * void setup() {
63
+ * Serial.begin(115200);
64
+ *
65
+ * mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
66
+ * mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
67
+ *
68
+ * mesh.onReceive([](uint32_t from, String& msg) {
69
+ * Serial.printf("Received: %s\n", msg.c_str());
70
+ * });
71
+ * }
72
+ *
73
+ * void loop() {
74
+ * mesh.update();
75
+ * }
76
+ * @endcode
77
+ *
78
+ * @section alteriom_packages Alteriom Packages
79
+ *
80
+ * @code{.cpp}
81
+ * using namespace alteriom;
82
+ *
83
+ * // Send sensor data
84
+ * SensorPackage sensor;
85
+ * sensor.temperature = 25.5;
86
+ * sensor.humidity = 60.0;
87
+ * mesh.sendPackage(&sensor);
88
+ *
89
+ * // Handle received sensor data
90
+ * mesh.onPackage(200, [](protocol::Variant& variant) {
91
+ * SensorPackage data = variant.to<SensorPackage>();
92
+ * Serial.printf("Temperature: %.1f°C\n", data.temperature);
93
+ * return true;
94
+ * });
95
+ * @endcode
96
+ */
97
+
98
+ #endif // ALTERIOM_PAINLESS_MESH_H
@@ -0,0 +1,365 @@
1
+ #ifndef _PAINLESS_MESH_ARDUINO_WIFI_HPP_
2
+ #define _PAINLESS_MESH_ARDUINO_WIFI_HPP_
3
+
4
+ #include "painlessmesh/configuration.hpp"
5
+
6
+ #include "painlessmesh/logger.hpp"
7
+ #ifdef PAINLESSMESH_ENABLE_ARDUINO_WIFI
8
+ #include "painlessMeshSTA.h"
9
+
10
+ #include "painlessmesh/callback.hpp"
11
+ #include "painlessmesh/mesh.hpp"
12
+ #include "painlessmesh/router.hpp"
13
+ #include "painlessmesh/tcp.hpp"
14
+
15
+ extern painlessmesh::logger::LogClass Log;
16
+
17
+ namespace painlessmesh {
18
+ namespace wifi {
19
+ class Mesh : public painlessmesh::Mesh<Connection> {
20
+ public:
21
+ /** Initialize the mesh network
22
+ *
23
+ * Add this to your setup() function. This routine does the following things:
24
+ *
25
+ * - Starts a wifi network
26
+ * - Begins searching for other wifi networks that are part of the mesh
27
+ * - Logs on to the best mesh network node it finds… if it doesn’t find
28
+ * anything, it starts a new search in 5 seconds.
29
+ *
30
+ * @param ssid The name of your mesh. All nodes share same AP ssid. They are
31
+ * distinguished by BSSID.
32
+ * @param password Wifi password to your mesh.
33
+ * @param port the TCP port that you want the mesh server to run on. Defaults
34
+ * to 5555 if not specified.
35
+ * @param connectMode Switch between WIFI_AP, WIFI_STA and WIFI_AP_STA
36
+ * (default) mode
37
+ */
38
+ void init(TSTRING ssid, TSTRING password, uint16_t port = 5555,
39
+ WiFiMode_t connectMode = WIFI_AP_STA, uint8_t channel = 1,
40
+ uint8_t hidden = 0, uint8_t maxconn = MAX_CONN) {
41
+ using namespace logger;
42
+ // Init random generator seed to generate delay variance
43
+ randomSeed(millis());
44
+
45
+ // Shut Wifi down and start with a blank slage
46
+ if (WiFi.status() != WL_DISCONNECTED) WiFi.disconnect();
47
+
48
+ Log(STARTUP, "init(): %d\n",
49
+ #if ESP_ARDUINO_VERSION_MAJOR >= 3
50
+ // Disable autoconnect
51
+ WiFi.setAutoReconnect(false));
52
+ #else
53
+ // Disable autoconnect
54
+ WiFi.setAutoConnect(false));
55
+ #endif
56
+ WiFi.persistent(false);
57
+
58
+ // start configuration
59
+ if (!WiFi.mode(connectMode)) {
60
+ Log(GENERAL, "WiFi.mode() false");
61
+ }
62
+
63
+ _meshSSID = ssid;
64
+ _meshPassword = password;
65
+ _meshChannel = channel;
66
+ _meshHidden = hidden;
67
+ _meshMaxConn = maxconn;
68
+ _meshPort = port;
69
+
70
+ uint8_t MAC[] = {0, 0, 0, 0, 0, 0};
71
+ #if ESP_ARDUINO_VERSION_MAJOR >= 3
72
+ esp_read_mac(MAC, ESP_MAC_WIFI_SOFTAP);
73
+ #else
74
+ if (WiFi.softAPmacAddress(MAC) == 0) {
75
+ Log(ERROR, "init(): WiFi.softAPmacAddress(MAC) failed.\n");
76
+ }
77
+ #endif
78
+ uint32_t nodeId = tcp::encodeNodeId(MAC);
79
+ if (nodeId == 0) Log(ERROR, "NodeId set to 0\n");
80
+
81
+ this->init(nodeId);
82
+
83
+ tcpServerInit();
84
+ eventHandleInit();
85
+
86
+ _apIp = IPAddress(0, 0, 0, 0);
87
+
88
+ if (connectMode & WIFI_AP) {
89
+ apInit(nodeId); // setup AP
90
+ }
91
+ if (connectMode & WIFI_STA) {
92
+ this->initStation();
93
+ }
94
+ }
95
+
96
+ /** Initialize the mesh network
97
+ *
98
+ * Add this to your setup() function. This routine does the following things:
99
+ *
100
+ * - Starts a wifi network
101
+ * - Begins searching for other wifi networks that are part of the mesh
102
+ * - Logs on to the best mesh network node it finds… if it doesn’t find
103
+ * anything, it starts a new search in 5 seconds.
104
+ *
105
+ * @param ssid The name of your mesh. All nodes share same AP ssid. They are
106
+ * distinguished by BSSID.
107
+ * @param password Wifi password to your mesh.
108
+ * @param port the TCP port that you want the mesh server to run on. Defaults
109
+ * to 5555 if not specified.
110
+ * @param connectMode Switch between WIFI_AP, WIFI_STA and WIFI_AP_STA
111
+ * (default) mode
112
+ */
113
+ void init(TSTRING ssid, TSTRING password, Scheduler *baseScheduler,
114
+ uint16_t port = 5555, WiFiMode_t connectMode = WIFI_AP_STA,
115
+ uint8_t channel = 1, uint8_t hidden = 0,
116
+ uint8_t maxconn = MAX_CONN) {
117
+ this->setScheduler(baseScheduler);
118
+ init(ssid, password, port, connectMode, channel, hidden, maxconn);
119
+ }
120
+
121
+ /**
122
+ * Connect (as a station) to a specified network and ip
123
+ *
124
+ * You can pass {0,0,0,0} as IP to have it connect to the gateway
125
+ *
126
+ * This stops the node from scanning for other (non specified) nodes
127
+ * and you should probably also use this node as an anchor: `setAnchor(true)`
128
+ */
129
+ void stationManual(TSTRING ssid, TSTRING password, uint16_t port = 0,
130
+ IPAddress remote_ip = IPAddress(0, 0, 0, 0)) {
131
+ // Set station config
132
+ stationScan.manualIP = remote_ip;
133
+
134
+ // Start scan
135
+ stationScan.init(this, ssid, password, port, _meshChannel,
136
+ static_cast<bool>(_meshHidden));
137
+ stationScan.manual = true;
138
+ }
139
+
140
+ void initStation() {
141
+ stationScan.init(this, _meshSSID, _meshPassword, _meshPort, _meshChannel,
142
+ static_cast<bool>(_meshHidden));
143
+ mScheduler->addTask(stationScan.task);
144
+ stationScan.task.enable();
145
+
146
+ this->droppedConnectionCallbacks.push_back(
147
+ [this](uint32_t nodeId, bool station) {
148
+ if (station) {
149
+ if (WiFi.status() == WL_CONNECTED) WiFi.disconnect();
150
+ // TODO: Can we do this when we get signalled that wifi disconnect
151
+ // is complete
152
+ this->stationScan.yieldConnectToAP();
153
+ // Re-enable it if it was disabled
154
+ this->stationScan.task.enableIfNot();
155
+ }
156
+ });
157
+ }
158
+
159
+ void tcpServerInit() {
160
+ using namespace logger;
161
+ Log(GENERAL, "tcpServerInit():\n");
162
+ _tcpListener = new AsyncServer(_meshPort);
163
+ painlessmesh::tcp::initServer<Connection, painlessmesh::Mesh<Connection>>(
164
+ (*_tcpListener), (*this));
165
+ Log(STARTUP, "AP tcp server established on port %d\n", _meshPort);
166
+ return;
167
+ }
168
+
169
+ void tcpConnect() {
170
+ using namespace logger;
171
+ // TODO: move to Connection or StationConnection?
172
+ Log(GENERAL, "tcpConnect():\n");
173
+ if (stationScan.manual && stationScan.port == 0)
174
+ return; // We have been configured not to connect to the mesh
175
+
176
+ // TODO: We could pass this to tcpConnect instead of loading it here
177
+ if (WiFi.status() == WL_CONNECTED && WiFi.localIP()) {
178
+ AsyncClient *pConn = new AsyncClient();
179
+
180
+ IPAddress ip = WiFi.gatewayIP();
181
+ if (stationScan.manualIP) {
182
+ ip = stationScan.manualIP;
183
+ }
184
+
185
+ painlessmesh::tcp::connect<Connection, painlessmesh::Mesh<Connection>>(
186
+ (*pConn), ip, stationScan.port, (*this));
187
+ } else {
188
+ Log(ERROR, "tcpConnect(): err Something un expected in tcpConnect()\n");
189
+ }
190
+ }
191
+
192
+ bool setHostname(const char *hostname) {
193
+ #ifdef ESP8266
194
+ return WiFi.hostname(hostname);
195
+ #elif defined(ESP32)
196
+ if (strlen(hostname) > 32) {
197
+ return false;
198
+ }
199
+ return WiFi.setHostname(hostname);
200
+ #endif // ESP8266
201
+ }
202
+
203
+ IPAddress getStationIP() { return WiFi.localIP(); }
204
+ IPAddress getAPIP() { return _apIp; }
205
+
206
+ void stop() {
207
+ // remove all WiFi events
208
+ #ifdef ESP32
209
+ WiFi.removeEvent(eventScanDoneHandler);
210
+ WiFi.removeEvent(eventSTAStartHandler);
211
+ WiFi.removeEvent(eventSTADisconnectedHandler);
212
+ WiFi.removeEvent(eventSTAGotIPHandler);
213
+ #elif defined(ESP8266)
214
+ eventSTAConnectedHandler = WiFiEventHandler();
215
+ eventSTADisconnectedHandler = WiFiEventHandler();
216
+ eventSTAGotIPHandler = WiFiEventHandler();
217
+
218
+ stationScan.asyncTask.setCallback(NULL);
219
+ mScheduler->deleteTask(stationScan.asyncTask);
220
+ #endif // ESP32
221
+ // Stop scanning task
222
+ stationScan.task.setCallback(NULL);
223
+ mScheduler->deleteTask(stationScan.task);
224
+ painlessmesh::Mesh<Connection>::stop();
225
+
226
+ // Shutdown wifi hardware
227
+ if (WiFi.status() != WL_DISCONNECTED) WiFi.disconnect();
228
+
229
+ // Delete the tcp server
230
+ delete _tcpListener;
231
+ }
232
+
233
+ protected:
234
+ friend class ::StationScan;
235
+ TSTRING _meshSSID;
236
+ TSTRING _meshPassword;
237
+ uint8_t _meshChannel;
238
+ uint8_t _meshHidden;
239
+ uint8_t _meshMaxConn;
240
+ uint16_t _meshPort;
241
+
242
+ IPAddress _apIp;
243
+ StationScan stationScan;
244
+
245
+ void init(Scheduler *scheduler, uint32_t id) {
246
+ painlessmesh::Mesh<Connection>::init(scheduler, id);
247
+ }
248
+
249
+ void init(uint32_t id) { painlessmesh::Mesh<Connection>::init(id); }
250
+
251
+ void apInit(uint32_t nodeId) {
252
+ _apIp = IPAddress(10, (nodeId & 0xFF00) >> 8, (nodeId & 0xFF), 1);
253
+ IPAddress netmask(255, 255, 255, 0);
254
+
255
+ WiFi.softAPConfig(_apIp, _apIp, netmask);
256
+ WiFi.softAP(_meshSSID.c_str(), _meshPassword.c_str(), _meshChannel,
257
+ _meshHidden, _meshMaxConn);
258
+ }
259
+ void eventHandleInit() {
260
+ using namespace logger;
261
+ #ifdef ESP32
262
+ eventScanDoneHandler = WiFi.onEvent(
263
+ [this](WiFiEvent_t event, WiFiEventInfo_t info) {
264
+ if (this->semaphoreTake()) {
265
+ Log(CONNECTION,
266
+ "eventScanDoneHandler: ARDUINO_EVENT_WIFI_SCAN_DONE\n");
267
+ this->stationScan.scanComplete();
268
+ this->semaphoreGive();
269
+ }
270
+ },
271
+ #if ESP_ARDUINO_VERSION_MAJOR >= 2
272
+ WiFiEvent_t::ARDUINO_EVENT_WIFI_SCAN_DONE);
273
+ #else
274
+ WiFiEvent_t::SYSTEM_EVENT_SCAN_DONE);
275
+ #endif
276
+
277
+ eventSTAStartHandler = WiFi.onEvent(
278
+ [this](WiFiEvent_t event, WiFiEventInfo_t info) {
279
+ if (this->semaphoreTake()) {
280
+ Log(CONNECTION,
281
+ "eventSTAStartHandler: ARDUINO_EVENT_WIFI_STA_START\n");
282
+ this->semaphoreGive();
283
+ }
284
+ },
285
+ #if ESP_ARDUINO_VERSION_MAJOR >= 2
286
+ WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_START);
287
+ #else
288
+ WiFiEvent_t::SYSTEM_EVENT_STA_START);
289
+ #endif
290
+
291
+ eventSTADisconnectedHandler = WiFi.onEvent(
292
+ [this](WiFiEvent_t event, WiFiEventInfo_t info) {
293
+ if (this->semaphoreTake()) {
294
+ Log(CONNECTION,
295
+ "eventSTADisconnectedHandler: "
296
+ "ARDUINO_EVENT_WIFI_STA_DISCONNECTED\n");
297
+ this->droppedConnectionCallbacks.execute(0, true);
298
+ this->semaphoreGive();
299
+ }
300
+ },
301
+ #if ESP_ARDUINO_VERSION_MAJOR >= 2
302
+ WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
303
+ #else
304
+ WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
305
+ #endif
306
+
307
+ eventSTAGotIPHandler = WiFi.onEvent(
308
+ [this](WiFiEvent_t event, WiFiEventInfo_t info) {
309
+ if (this->semaphoreTake()) {
310
+ Log(CONNECTION,
311
+ "eventSTAGotIPHandler: ARDUINO_EVENT_WIFI_STA_GOT_IP\n");
312
+ this->tcpConnect(); // Connect to TCP port
313
+ this->semaphoreGive();
314
+ }
315
+ },
316
+ #if ESP_ARDUINO_VERSION_MAJOR >= 2
317
+ WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);
318
+ #else
319
+ WiFiEvent_t::SYSTEM_EVENT_STA_GOT_IP);
320
+ #endif
321
+
322
+ #elif defined(ESP8266)
323
+ eventSTAConnectedHandler = WiFi.onStationModeConnected(
324
+ [&](const WiFiEventStationModeConnected &event) {
325
+ // Log(CONNECTION, "Event: Station Mode Connected to \"%s\"\n",
326
+ // event.ssid.c_str());
327
+ Log(CONNECTION, "Event: Station Mode Connected\n");
328
+ });
329
+
330
+ eventSTADisconnectedHandler = WiFi.onStationModeDisconnected(
331
+ [&](const WiFiEventStationModeDisconnected &event) {
332
+ Log(CONNECTION, "Event: Station Mode Disconnected\n");
333
+ this->droppedConnectionCallbacks.execute(0, true);
334
+ });
335
+
336
+ eventSTAGotIPHandler =
337
+ WiFi.onStationModeGotIP([&](const WiFiEventStationModeGotIP &event) {
338
+ Log(CONNECTION,
339
+ "Event: Station Mode Got IP (IP: %s Mask: %s Gateway: %s)\n",
340
+ event.ip.toString().c_str(), event.mask.toString().c_str(),
341
+ event.gw.toString().c_str());
342
+ this->tcpConnect(); // Connect to TCP port
343
+ });
344
+ #endif // ESP32
345
+ return;
346
+ }
347
+
348
+ #ifdef ESP32
349
+ WiFiEventId_t eventScanDoneHandler;
350
+ WiFiEventId_t eventSTAStartHandler;
351
+ WiFiEventId_t eventSTADisconnectedHandler;
352
+ WiFiEventId_t eventSTAGotIPHandler;
353
+ #elif defined(ESP8266)
354
+ WiFiEventHandler eventSTAConnectedHandler;
355
+ WiFiEventHandler eventSTADisconnectedHandler;
356
+ WiFiEventHandler eventSTAGotIPHandler;
357
+ #endif // ESP8266
358
+ AsyncServer *_tcpListener;
359
+ };
360
+ } // namespace wifi
361
+ }; // namespace painlessmesh
362
+
363
+ #endif
364
+
365
+ #endif