@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
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library to
|
|
3
|
+
// connect to a node on another network. Please see the WIKI on gitlab
|
|
4
|
+
// for more details
|
|
5
|
+
// https://gitlab.com/painlessMesh/painlessMesh/wikis/bridge-between-mesh-and-another-network
|
|
6
|
+
//************************************************************
|
|
7
|
+
#include "painlessMesh.h"
|
|
8
|
+
|
|
9
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
10
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
11
|
+
#define MESH_PORT 5555
|
|
12
|
+
|
|
13
|
+
#define STATION_SSID "MSYSSID"
|
|
14
|
+
#define STATION_PASSWORD "SSIDPASSWORD"
|
|
15
|
+
#define STATION_PORT 5555
|
|
16
|
+
uint8_t station_ip[4] = {192, 168, 1, 3}; // IP of the server
|
|
17
|
+
|
|
18
|
+
// prototypes
|
|
19
|
+
void receivedCallback(uint32_t from, String &msg);
|
|
20
|
+
|
|
21
|
+
painlessMesh mesh;
|
|
22
|
+
|
|
23
|
+
void setup() {
|
|
24
|
+
Serial.begin(115200);
|
|
25
|
+
mesh.setDebugMsgTypes(
|
|
26
|
+
ERROR | STARTUP |
|
|
27
|
+
CONNECTION); // set before init() so that you can see startup messages
|
|
28
|
+
|
|
29
|
+
// Channel set to 6. Make sure to use the same channel for your mesh and for
|
|
30
|
+
// you other network (STATION_SSID)
|
|
31
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 1);
|
|
32
|
+
// Setup over the air update support
|
|
33
|
+
mesh.initOTAReceive("bridge");
|
|
34
|
+
|
|
35
|
+
mesh.stationManual(STATION_SSID, STATION_PASSWORD, STATION_PORT, station_ip);
|
|
36
|
+
// Bridge node, should (in most cases) be a root node. See [the
|
|
37
|
+
// wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation)
|
|
38
|
+
// for some background
|
|
39
|
+
mesh.setRoot(true);
|
|
40
|
+
// This node and all other nodes should ideally know the mesh contains a root,
|
|
41
|
+
// so call this on all nodes
|
|
42
|
+
mesh.setContainsRoot(true);
|
|
43
|
+
|
|
44
|
+
mesh.onReceive(&receivedCallback);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void loop() { mesh.update(); }
|
|
48
|
+
|
|
49
|
+
void receivedCallback(uint32_t from, String &msg) {
|
|
50
|
+
Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
|
|
51
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library and echos any
|
|
3
|
+
// messages it receives
|
|
4
|
+
//
|
|
5
|
+
//************************************************************
|
|
6
|
+
#include "painlessMesh.h"
|
|
7
|
+
|
|
8
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
9
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
10
|
+
#define MESH_PORT 5555
|
|
11
|
+
|
|
12
|
+
// Prototypes
|
|
13
|
+
void receivedCallback( uint32_t from, String &msg );
|
|
14
|
+
|
|
15
|
+
painlessMesh mesh;
|
|
16
|
+
|
|
17
|
+
void setup() {
|
|
18
|
+
Serial.begin(115200);
|
|
19
|
+
|
|
20
|
+
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
|
|
21
|
+
|
|
22
|
+
mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT );
|
|
23
|
+
mesh.onReceive(&receivedCallback);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void loop() {
|
|
27
|
+
mesh.update();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void receivedCallback( uint32_t from, String &msg ) {
|
|
31
|
+
Serial.printf("echoNode: Received from %u msg=%s\n", from, msg.c_str());
|
|
32
|
+
mesh.sendSingle(from, msg);
|
|
33
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library to
|
|
3
|
+
// setup a node that logs to a central logging node
|
|
4
|
+
// The logServer example shows how to configure the central logging nodes
|
|
5
|
+
//************************************************************
|
|
6
|
+
#include "painlessMesh.h"
|
|
7
|
+
|
|
8
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
9
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
10
|
+
#define MESH_PORT 5555
|
|
11
|
+
|
|
12
|
+
Scheduler userScheduler; // to control your personal task
|
|
13
|
+
painlessMesh mesh;
|
|
14
|
+
|
|
15
|
+
// Prototype
|
|
16
|
+
void receivedCallback( uint32_t from, String &msg );
|
|
17
|
+
|
|
18
|
+
size_t logServerId = 0;
|
|
19
|
+
|
|
20
|
+
// Send message to the logServer every 10 seconds
|
|
21
|
+
Task myLoggingTask(10000, TASK_FOREVER, []() {
|
|
22
|
+
#if ARDUINOJSON_VERSION_MAJOR==7
|
|
23
|
+
JsonDocument jsonBuffer;
|
|
24
|
+
JsonObject msg = jsonBuffer.to<JsonObject>();
|
|
25
|
+
#elif ARDUINOJSON_VERSION_MAJOR==6
|
|
26
|
+
DynamicJsonDocument jsonBuffer(1024);
|
|
27
|
+
JsonObject msg = jsonBuffer.to<JsonObject>();
|
|
28
|
+
#else
|
|
29
|
+
DynamicJsonBuffer jsonBuffer;
|
|
30
|
+
JsonObject& msg = jsonBuffer.createObject();
|
|
31
|
+
#endif
|
|
32
|
+
msg["topic"] = "sensor";
|
|
33
|
+
msg["value"] = random(0, 180);
|
|
34
|
+
|
|
35
|
+
String str;
|
|
36
|
+
#if ARDUINOJSON_VERSION_MAJOR>=6
|
|
37
|
+
serializeJson(msg, str);
|
|
38
|
+
#else
|
|
39
|
+
msg.printTo(str);
|
|
40
|
+
#endif
|
|
41
|
+
if (logServerId == 0) // If we don't know the logServer yet
|
|
42
|
+
mesh.sendBroadcast(str);
|
|
43
|
+
else
|
|
44
|
+
mesh.sendSingle(logServerId, str);
|
|
45
|
+
|
|
46
|
+
// log to serial
|
|
47
|
+
#if ARDUINOJSON_VERSION_MAJOR>=6
|
|
48
|
+
serializeJson(msg, Serial);
|
|
49
|
+
#else
|
|
50
|
+
msg.printTo(Serial);
|
|
51
|
+
#endif
|
|
52
|
+
Serial.printf("\n");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
void setup() {
|
|
56
|
+
Serial.begin(115200);
|
|
57
|
+
|
|
58
|
+
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
|
|
59
|
+
|
|
60
|
+
mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT, WIFI_AP_STA, 6 );
|
|
61
|
+
mesh.onReceive(&receivedCallback);
|
|
62
|
+
|
|
63
|
+
// Add the task to the your scheduler
|
|
64
|
+
userScheduler.addTask(myLoggingTask);
|
|
65
|
+
myLoggingTask.enable();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void loop() {
|
|
69
|
+
// it will run the user scheduler as well
|
|
70
|
+
mesh.update();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void receivedCallback( uint32_t from, String &msg ) {
|
|
74
|
+
Serial.printf("logClient: Received from %u msg=%s\n", from, msg.c_str());
|
|
75
|
+
|
|
76
|
+
// Saving logServer
|
|
77
|
+
#if ARDUINOJSON_VERSION_MAJOR==7
|
|
78
|
+
JsonDocument jsonBuffer;
|
|
79
|
+
DeserializationError error = deserializeJson(jsonBuffer, msg);
|
|
80
|
+
if (error) {
|
|
81
|
+
Serial.printf("DeserializationError\n");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
JsonObject root = jsonBuffer.as<JsonObject>();
|
|
85
|
+
#elif ARDUINOJSON_VERSION_MAJOR==6
|
|
86
|
+
DynamicJsonDocument jsonBuffer(1024 + msg.length());
|
|
87
|
+
DeserializationError error = deserializeJson(jsonBuffer, msg);
|
|
88
|
+
if (error) {
|
|
89
|
+
Serial.printf("DeserializationError\n");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
JsonObject root = jsonBuffer.as<JsonObject>();
|
|
93
|
+
#else
|
|
94
|
+
DynamicJsonBuffer jsonBuffer;
|
|
95
|
+
JsonObject& root = jsonBuffer.parseObject(msg);
|
|
96
|
+
#endif
|
|
97
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
98
|
+
if (root.containsKey("topic")) {
|
|
99
|
+
#else
|
|
100
|
+
if (root["topic"].is<String>()) {
|
|
101
|
+
#endif
|
|
102
|
+
if (String("logServer").equals(root["topic"].as<String>())) {
|
|
103
|
+
// check for on: true or false
|
|
104
|
+
logServerId = root["nodeId"];
|
|
105
|
+
Serial.printf("logServer detected!!!\n");
|
|
106
|
+
}
|
|
107
|
+
Serial.printf("Handled from %u msg=%s\n", from, msg.c_str());
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library to
|
|
3
|
+
// setup a single node (this node) as a logging node
|
|
4
|
+
// The logClient example shows how to configure the other nodes
|
|
5
|
+
// to log to this server
|
|
6
|
+
//************************************************************
|
|
7
|
+
#include "painlessMesh.h"
|
|
8
|
+
|
|
9
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
10
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
11
|
+
#define MESH_PORT 5555
|
|
12
|
+
|
|
13
|
+
Scheduler userScheduler; // to control your personal task
|
|
14
|
+
painlessMesh mesh;
|
|
15
|
+
// Prototype
|
|
16
|
+
void receivedCallback( uint32_t from, String &msg );
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
// Send my ID every 10 seconds to inform others
|
|
20
|
+
Task logServerTask(10000, TASK_FOREVER, []() {
|
|
21
|
+
#if ARDUINOJSON_VERSION_MAJOR==7
|
|
22
|
+
JsonDocument jsonBuffer;
|
|
23
|
+
JsonObject msg = jsonBuffer.to<JsonObject>();
|
|
24
|
+
#elif ARDUINOJSON_VERSION_MAJOR==6
|
|
25
|
+
DynamicJsonDocument jsonBuffer(1024);
|
|
26
|
+
JsonObject msg = jsonBuffer.to<JsonObject>();
|
|
27
|
+
#else
|
|
28
|
+
DynamicJsonBuffer jsonBuffer;
|
|
29
|
+
JsonObject& msg = jsonBuffer.createObject();
|
|
30
|
+
#endif
|
|
31
|
+
msg["topic"] = "logServer";
|
|
32
|
+
msg["nodeId"] = mesh.getNodeId();
|
|
33
|
+
|
|
34
|
+
String str;
|
|
35
|
+
#if ARDUINOJSON_VERSION_MAJOR>=6
|
|
36
|
+
serializeJson(msg, str);
|
|
37
|
+
#else
|
|
38
|
+
msg.printTo(str);
|
|
39
|
+
#endif
|
|
40
|
+
mesh.sendBroadcast(str);
|
|
41
|
+
|
|
42
|
+
// log to serial
|
|
43
|
+
#if ARDUINOJSON_VERSION_MAJOR>=6
|
|
44
|
+
serializeJson(msg, Serial);
|
|
45
|
+
#else
|
|
46
|
+
msg.printTo(Serial);
|
|
47
|
+
#endif
|
|
48
|
+
Serial.printf("\n");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
void setup() {
|
|
52
|
+
Serial.begin(115200);
|
|
53
|
+
|
|
54
|
+
//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE | DEBUG ); // all types on
|
|
55
|
+
//mesh.setDebugMsgTypes( ERROR | CONNECTION | SYNC | S_TIME ); // set before init() so that you can see startup messages
|
|
56
|
+
mesh.setDebugMsgTypes( ERROR | CONNECTION | S_TIME ); // set before init() so that you can see startup messages
|
|
57
|
+
|
|
58
|
+
mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT, WIFI_AP_STA, 6 );
|
|
59
|
+
mesh.onReceive(&receivedCallback);
|
|
60
|
+
|
|
61
|
+
mesh.onNewConnection([](size_t nodeId) {
|
|
62
|
+
Serial.printf("New Connection %u\n", nodeId);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
mesh.onDroppedConnection([](size_t nodeId) {
|
|
66
|
+
Serial.printf("Dropped Connection %u\n", nodeId);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Add the task to the your scheduler
|
|
70
|
+
userScheduler.addTask(logServerTask);
|
|
71
|
+
logServerTask.enable();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void loop() {
|
|
75
|
+
// it will run the user scheduler as well
|
|
76
|
+
mesh.update();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void receivedCallback( uint32_t from, String &msg ) {
|
|
80
|
+
Serial.printf("logServer: Received from %u msg=%s\n", from, msg.c_str());
|
|
81
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library to
|
|
3
|
+
// connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
|
|
4
|
+
// To send a message to a mesh node, you can publish it to "painlessMesh/to/12345678" where 12345678 equals the nodeId.
|
|
5
|
+
// To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
|
|
6
|
+
// When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
|
|
7
|
+
// Every message from the mesh which is send to the gateway node will be published to "painlessMesh/from/12345678" where 12345678
|
|
8
|
+
// is the nodeId from which the packet was send.
|
|
9
|
+
//************************************************************
|
|
10
|
+
|
|
11
|
+
#include <Arduino.h>
|
|
12
|
+
#include <painlessMesh.h>
|
|
13
|
+
#include <PubSubClient.h>
|
|
14
|
+
#include <WiFiClient.h>
|
|
15
|
+
|
|
16
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
17
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
18
|
+
#define MESH_PORT 5555
|
|
19
|
+
|
|
20
|
+
#define STATION_SSID "YourAP_SSID"
|
|
21
|
+
#define STATION_PASSWORD "YourAP_PWD"
|
|
22
|
+
|
|
23
|
+
#define HOSTNAME "MQTT_Bridge"
|
|
24
|
+
|
|
25
|
+
// Prototypes
|
|
26
|
+
void receivedCallback( const uint32_t &from, const String &msg );
|
|
27
|
+
void mqttCallback(char* topic, byte* payload, unsigned int length);
|
|
28
|
+
|
|
29
|
+
IPAddress getlocalIP();
|
|
30
|
+
|
|
31
|
+
IPAddress myIP(0,0,0,0);
|
|
32
|
+
IPAddress mqttBroker(192, 168, 1, 1);
|
|
33
|
+
|
|
34
|
+
painlessMesh mesh;
|
|
35
|
+
WiFiClient wifiClient;
|
|
36
|
+
PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient);
|
|
37
|
+
|
|
38
|
+
void setup() {
|
|
39
|
+
Serial.begin(115200);
|
|
40
|
+
|
|
41
|
+
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
|
|
42
|
+
|
|
43
|
+
// Channel set to 6. Make sure to use the same channel for your mesh and for you other
|
|
44
|
+
// network (STATION_SSID)
|
|
45
|
+
mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
|
|
46
|
+
mesh.onReceive(&receivedCallback);
|
|
47
|
+
|
|
48
|
+
mesh.stationManual(STATION_SSID, STATION_PASSWORD);
|
|
49
|
+
mesh.setHostname(HOSTNAME);
|
|
50
|
+
|
|
51
|
+
// Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background
|
|
52
|
+
mesh.setRoot(true);
|
|
53
|
+
// This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
|
|
54
|
+
mesh.setContainsRoot(true);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
void loop() {
|
|
58
|
+
mesh.update();
|
|
59
|
+
mqttClient.loop();
|
|
60
|
+
|
|
61
|
+
if(myIP != getlocalIP()){
|
|
62
|
+
myIP = getlocalIP();
|
|
63
|
+
Serial.println("My IP is " + myIP.toString());
|
|
64
|
+
|
|
65
|
+
if (mqttClient.connect("painlessMeshClient")) {
|
|
66
|
+
mqttClient.publish("painlessMesh/from/gateway","Ready!");
|
|
67
|
+
mqttClient.subscribe("painlessMesh/to/#");
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void receivedCallback( const uint32_t &from, const String &msg ) {
|
|
73
|
+
Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
|
|
74
|
+
String topic = "painlessMesh/from/" + String(from);
|
|
75
|
+
mqttClient.publish(topic.c_str(), msg.c_str());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void mqttCallback(char* topic, uint8_t* payload, unsigned int length) {
|
|
79
|
+
char* cleanPayload = (char*)malloc(length+1);
|
|
80
|
+
memcpy(cleanPayload, payload, length);
|
|
81
|
+
cleanPayload[length] = '\0';
|
|
82
|
+
String msg = String(cleanPayload);
|
|
83
|
+
free(cleanPayload);
|
|
84
|
+
|
|
85
|
+
String targetStr = String(topic).substring(16);
|
|
86
|
+
|
|
87
|
+
if(targetStr == "gateway")
|
|
88
|
+
{
|
|
89
|
+
if(msg == "getNodes")
|
|
90
|
+
{
|
|
91
|
+
auto nodes = mesh.getNodeList(true);
|
|
92
|
+
String str;
|
|
93
|
+
for (auto &&id : nodes)
|
|
94
|
+
str += String(id) + String(" ");
|
|
95
|
+
mqttClient.publish("painlessMesh/from/gateway", str.c_str());
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if(targetStr == "broadcast")
|
|
99
|
+
{
|
|
100
|
+
mesh.sendBroadcast(msg);
|
|
101
|
+
}
|
|
102
|
+
else
|
|
103
|
+
{
|
|
104
|
+
uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
|
|
105
|
+
if(mesh.isConnected(target))
|
|
106
|
+
{
|
|
107
|
+
mesh.sendSingle(target, msg);
|
|
108
|
+
}
|
|
109
|
+
else
|
|
110
|
+
{
|
|
111
|
+
mqttClient.publish("painlessMesh/from/gateway", "Client not connected!");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
IPAddress getlocalIP() {
|
|
117
|
+
return IPAddress(mesh.getStationIP());
|
|
118
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
PubSubClient
|
|
9
|
+
|
|
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,97 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library
|
|
3
|
+
//
|
|
4
|
+
// This example shows how to build a mesh with named nodes using the plugin
|
|
5
|
+
// system
|
|
6
|
+
//
|
|
7
|
+
//
|
|
8
|
+
//************************************************************
|
|
9
|
+
#include <cstdint>
|
|
10
|
+
#include <map>
|
|
11
|
+
#include "Arduino.h"
|
|
12
|
+
#include "painlessMesh.h"
|
|
13
|
+
#include "painlessmesh/plugin.hpp"
|
|
14
|
+
|
|
15
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
16
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
17
|
+
#define MESH_PORT 5555
|
|
18
|
+
|
|
19
|
+
painlessMesh mesh;
|
|
20
|
+
|
|
21
|
+
// NOTE: various ideas for improvement
|
|
22
|
+
// - Send new names regularly and only send all names sometimes
|
|
23
|
+
// - Keep track of the names the neighbour already knows (when we receive them)
|
|
24
|
+
// and only send unknown names/nodes
|
|
25
|
+
// - Use some kind of bidirectoral map, so both get_name_from_id and
|
|
26
|
+
// get_id_from_name are fast
|
|
27
|
+
|
|
28
|
+
// Send the names you know to your neighbours
|
|
29
|
+
class NamePackage : public painlessmesh::plugin::NeighbourPackage {
|
|
30
|
+
public:
|
|
31
|
+
std::map<TSTRING, uint32_t> names;
|
|
32
|
+
|
|
33
|
+
// Set an id for the package. Id can be any unique int not already in use. The
|
|
34
|
+
// mesh uses the numbers 1..12, so using a number larger than that
|
|
35
|
+
NamePackage() : painlessmesh::plugin::NeighbourPackage(21) {}
|
|
36
|
+
|
|
37
|
+
NamePackage(JsonObject jsonObj)
|
|
38
|
+
: painlessmesh::plugin::NeighbourPackage(jsonObj) {
|
|
39
|
+
for (JsonPair kv : jsonObj) {
|
|
40
|
+
names.insert(std::pair<TSTRING, uint32_t>(kv.key().c_str(), kv.value()));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
45
|
+
jsonObj = painlessmesh::plugin::NeighbourPackage::addTo(std::move(jsonObj));
|
|
46
|
+
for (auto&& kv : names) {
|
|
47
|
+
jsonObj[kv.first] = kv.second;
|
|
48
|
+
}
|
|
49
|
+
return jsonObj;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
std::map<TSTRING, uint32_t> known_names;
|
|
54
|
+
TSTRING get_name_from_id(uint32_t id) {
|
|
55
|
+
for (auto&& kv : known_names) {
|
|
56
|
+
if (kv.second == id) {
|
|
57
|
+
return kv.first;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return String(id);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
uint32_t get_id_from_name(TSTRING name) {
|
|
64
|
+
auto it = known_names.find(name);
|
|
65
|
+
return (it != known_names.end()) ? it->second : 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void setup() {
|
|
69
|
+
Serial.begin(115200);
|
|
70
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP);
|
|
71
|
+
|
|
72
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT);
|
|
73
|
+
|
|
74
|
+
auto sendPkg = std::make_shared<NamePackage>();
|
|
75
|
+
sendPkg->names = known_names;
|
|
76
|
+
// Every minute we send the names we know to our neighbours
|
|
77
|
+
mesh.addTask(TASK_MINUTE, TASK_FOREVER, [sendPkg, &mesh]() {
|
|
78
|
+
sendPkg->names = known_names;
|
|
79
|
+
mesh.sendPackage(sendPkg.get());
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// When we receive a message of the correct type, then insert the names they
|
|
83
|
+
// know into our map of names
|
|
84
|
+
mesh.onPackage(sendPkg->type, [](painlessmesh::protocol::Variant& var) {
|
|
85
|
+
const auto& pkg = var.to<NamePackage>();
|
|
86
|
+
for (auto&& kv : pkg.names) {
|
|
87
|
+
known_names.insert(kv);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return false;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void loop() {
|
|
95
|
+
// it will run the user scheduler as well
|
|
96
|
+
mesh.update();
|
|
97
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|