@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.
- package/CHANGELOG.md +144 -0
- package/LICENSE +674 -0
- package/README.md +434 -0
- package/RELEASE_GUIDE.md +419 -0
- package/docs/DOCUMENTATION_MIGRATION_PLAN.md +176 -0
- package/docs/README.md +71 -0
- package/docs/alteriom/overview.md +508 -0
- package/docs/api/core-api.md +607 -0
- package/docs/architecture/mesh-architecture.md +379 -0
- package/docs/architecture/plugin-system.md +517 -0
- package/docs/getting-started/first-mesh.md +410 -0
- package/docs/getting-started/installation.md +275 -0
- package/docs/getting-started/quickstart.md +158 -0
- package/docs/improvements/README.md +69 -0
- package/docs/troubleshooting/common-issues.md +521 -0
- package/docs/troubleshooting/faq.md +473 -0
- package/docs/tutorials/basic-examples.md +718 -0
- package/docs/wiki/API-Reference.md +246 -0
- package/docs/wiki/Complete-Documentation.md +123 -0
- package/examples/alteriom/README.md +82 -0
- package/examples/alteriom/alteriom.ino +186 -0
- package/examples/alteriom/alteriom_sensor_node.ino +184 -0
- package/examples/alteriom/alteriom_sensor_package.hpp +128 -0
- package/examples/alteriom/improved_sensor_node.ino +246 -0
- package/examples/alteriom/platformio.ini +25 -0
- package/examples/basic/basic.ino +66 -0
- package/examples/basic/platformio.ini +25 -0
- package/examples/bridge/bridge.ino +51 -0
- package/examples/bridge/platformio.ini +25 -0
- package/examples/echoNode/echoNode.ino +33 -0
- package/examples/echoNode/platformio.ini +25 -0
- package/examples/logClient/logClient.ino +109 -0
- package/examples/logClient/platformio.ini +25 -0
- package/examples/logServer/logServer.ino +81 -0
- package/examples/logServer/platformio.ini +25 -0
- package/examples/mqttBridge/mqttBridge.ino +118 -0
- package/examples/mqttBridge/platformio.ini +26 -0
- package/examples/namedMesh/namedMesh.ino +97 -0
- package/examples/namedMesh/platformio.ini +25 -0
- package/examples/otaReceiver/otaReceiver.ino +79 -0
- package/examples/otaReceiver/platformio.ini +25 -0
- package/examples/otaSender/nodemcu32s_connections.JPG +0 -0
- package/examples/otaSender/otaSender.ino +151 -0
- package/examples/otaSender/platformio.ini +25 -0
- package/examples/startHere/platformio.ini +25 -0
- package/examples/startHere/startHere.ino +159 -0
- package/examples/webServer/platformio.ini +27 -0
- package/examples/webServer/webServer.ino +89 -0
- package/keywords.txt +49 -0
- package/library.json +34 -0
- package/library.properties +11 -0
- package/package.json +78 -0
- package/src/AlteriomPainlessMesh.h +98 -0
- package/src/arduino/wifi.hpp +365 -0
- package/src/boost/asynctcp.hpp +279 -0
- package/src/painlessMesh.h +70 -0
- package/src/painlessMeshSTA.cpp +236 -0
- package/src/painlessMeshSTA.h +58 -0
- package/src/painlessTaskOptions.h +4 -0
- package/src/painlessmesh/base64.hpp +111 -0
- package/src/painlessmesh/buffer.hpp +229 -0
- package/src/painlessmesh/callback.hpp +91 -0
- package/src/painlessmesh/configuration.hpp +77 -0
- package/src/painlessmesh/connection.hpp +192 -0
- package/src/painlessmesh/layout.hpp +188 -0
- package/src/painlessmesh/logger.hpp +158 -0
- package/src/painlessmesh/memory.hpp +120 -0
- package/src/painlessmesh/mesh.hpp +560 -0
- package/src/painlessmesh/metrics.hpp +323 -0
- package/src/painlessmesh/ntp.hpp +263 -0
- package/src/painlessmesh/ota.hpp +553 -0
- package/src/painlessmesh/plugin.hpp +188 -0
- package/src/painlessmesh/protocol.hpp +813 -0
- package/src/painlessmesh/router.hpp +322 -0
- package/src/painlessmesh/tcp.hpp +71 -0
- package/src/painlessmesh/validation.hpp +239 -0
- package/src/plugin/performance.hpp +214 -0
- package/src/plugin/remote.hpp +64 -0
- package/src/scheduler.cpp +10 -0
- 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
|