@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,79 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library
|
|
3
|
+
//
|
|
4
|
+
// 1. sends a silly message to every node on the mesh at a random time between 1
|
|
5
|
+
// and 5 seconds
|
|
6
|
+
// 2. prints anything it receives to Serial.print
|
|
7
|
+
// 3. has OTA support and can be updated remotely
|
|
8
|
+
//
|
|
9
|
+
//************************************************************
|
|
10
|
+
#include "painlessMesh.h"
|
|
11
|
+
|
|
12
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
13
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
14
|
+
#define MESH_PORT 5555
|
|
15
|
+
|
|
16
|
+
Scheduler userScheduler; // to control your personal task
|
|
17
|
+
painlessMesh mesh;
|
|
18
|
+
|
|
19
|
+
// User stub
|
|
20
|
+
void sendMessage(); // Prototype so PlatformIO doesn't complain
|
|
21
|
+
|
|
22
|
+
Task taskSendMessage(TASK_SECOND * 1, TASK_FOREVER, &sendMessage);
|
|
23
|
+
|
|
24
|
+
void sendMessage() {
|
|
25
|
+
String msg = "Hello from node ";
|
|
26
|
+
msg += mesh.getNodeId();
|
|
27
|
+
mesh.sendBroadcast(msg);
|
|
28
|
+
taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Needed for painless library
|
|
32
|
+
void receivedCallback(uint32_t from, String &msg) {
|
|
33
|
+
Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
37
|
+
Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
void changedConnectionCallback() { Serial.printf("Changed connections\n"); }
|
|
41
|
+
|
|
42
|
+
void nodeTimeAdjustedCallback(int32_t offset) {
|
|
43
|
+
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void setup() {
|
|
47
|
+
Serial.begin(115200);
|
|
48
|
+
|
|
49
|
+
// mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC |
|
|
50
|
+
// COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
|
|
51
|
+
mesh.setDebugMsgTypes(
|
|
52
|
+
ERROR | STARTUP |
|
|
53
|
+
DEBUG); // set before init() so that you can see startup messages
|
|
54
|
+
|
|
55
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
56
|
+
mesh.onReceive(&receivedCallback);
|
|
57
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
58
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
59
|
+
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
|
|
60
|
+
|
|
61
|
+
// if you want your node to accept OTA firmware, simply include this line
|
|
62
|
+
// with whatever role you want your hardware to be. For instance, a
|
|
63
|
+
// mesh network may have a thermometer, rain detector, and bridge. Each of
|
|
64
|
+
// those may require different firmware, so different roles are preferrable.
|
|
65
|
+
//
|
|
66
|
+
// MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT OR YOU WILL LOSE
|
|
67
|
+
// THE ABILITY TO UPLOAD MORE FIRMWARE OVER OTA. YOU ALSO WANT TO MAKE SURE
|
|
68
|
+
// THE ROLES ARE CORRECT
|
|
69
|
+
mesh.initOTAReceive("otareceiver");
|
|
70
|
+
mesh.setContainsRoot(true);
|
|
71
|
+
|
|
72
|
+
userScheduler.addTask(taskSendMessage);
|
|
73
|
+
taskSendMessage.enable();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
void loop() {
|
|
77
|
+
// it will run the user scheduler as well
|
|
78
|
+
mesh.update();
|
|
79
|
+
}
|
|
@@ -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
|
|
Binary file
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is an example that uses the painlessmesh library to
|
|
3
|
+
// upload firmware to another node on the network.
|
|
4
|
+
// This will upload to an ESP device running the otaReceiver.ino
|
|
5
|
+
//
|
|
6
|
+
// The naming convetions should be as follows for bin files
|
|
7
|
+
// firmware_<hardware>_<role>.bin
|
|
8
|
+
// To create your own binary files, export them and rename
|
|
9
|
+
// them to follow this format, where hardware will be
|
|
10
|
+
// "ESP8266" or "ESP32" (capitalized.)
|
|
11
|
+
// If sending to the otacreceiver sketch, role should be
|
|
12
|
+
// "otareceiver" (lowercase)
|
|
13
|
+
//
|
|
14
|
+
// This sketch assumes a Nodemcu-32s with an SD card
|
|
15
|
+
// connected as shown in the jpg included in the sketch folder
|
|
16
|
+
// This code may have to be reworked/hardware adjusted for
|
|
17
|
+
// other boards or ESP8266. The core code works well though
|
|
18
|
+
//
|
|
19
|
+
// MAKE SURE YOUR UPLOADED OTA FIRMWARE INCLUDES OTA SUPPORT
|
|
20
|
+
// OR YOU WILL LOSE THE ABILITY TO UPLOAD MORE FIRMWARE.
|
|
21
|
+
// THE INCLUDED .bin DOES NOT HAVE OTA SUPPORT SO THIS MUST BE
|
|
22
|
+
// REFLASHED
|
|
23
|
+
//************************************************************
|
|
24
|
+
|
|
25
|
+
#ifdef ESP32
|
|
26
|
+
#else
|
|
27
|
+
#define CS_PIN D8
|
|
28
|
+
#endif
|
|
29
|
+
|
|
30
|
+
#include "painlessMesh.h"
|
|
31
|
+
|
|
32
|
+
#include <FS.h>
|
|
33
|
+
#include "SD.h"
|
|
34
|
+
#include "SPI.h"
|
|
35
|
+
|
|
36
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
37
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
38
|
+
#define MESH_PORT 5555
|
|
39
|
+
|
|
40
|
+
#define OTA_PART_SIZE 1024 //How many bytes to send per OTA data packet
|
|
41
|
+
|
|
42
|
+
painlessMesh mesh;
|
|
43
|
+
|
|
44
|
+
void setup() {
|
|
45
|
+
Serial.begin(115200);
|
|
46
|
+
delay(1000);
|
|
47
|
+
mesh.setDebugMsgTypes(
|
|
48
|
+
ERROR | STARTUP | CONNECTION |
|
|
49
|
+
DEBUG); // set before init() so that you can see startup messages
|
|
50
|
+
|
|
51
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, MESH_PORT);
|
|
52
|
+
|
|
53
|
+
// Bridge node, should (in most cases) be a root node. See [the
|
|
54
|
+
// wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation)
|
|
55
|
+
// for some background
|
|
56
|
+
mesh.setRoot(true);
|
|
57
|
+
// This node and all other nodes should ideally know the mesh contains a root,
|
|
58
|
+
// so call this on all nodes
|
|
59
|
+
mesh.setContainsRoot(true);
|
|
60
|
+
|
|
61
|
+
delay(1000);
|
|
62
|
+
#ifdef ESP32
|
|
63
|
+
if (!SD.begin()) {
|
|
64
|
+
#else
|
|
65
|
+
if (!SD.begin(CS_PIN)) {
|
|
66
|
+
#endif
|
|
67
|
+
rebootEspWithReason("Could not mount SD card, restarting");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
File dir = SD.open("/");
|
|
71
|
+
while (true) {
|
|
72
|
+
File entry = dir.openNextFile();
|
|
73
|
+
if (!entry) { //End of files
|
|
74
|
+
rebootEspWithReason("Could not find valid firmware, please validate");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
//This block of code parses the file name to make sure it is valid.
|
|
78
|
+
//It will also get the role and hardware the firmware is targeted at.
|
|
79
|
+
if (!entry.isDirectory()) {
|
|
80
|
+
TSTRING name = entry.name();
|
|
81
|
+
if (name.length() > 1 && name.indexOf('_') != -1 &&
|
|
82
|
+
name.indexOf('_') != name.lastIndexOf('_') &&
|
|
83
|
+
name.indexOf('.') != -1) {
|
|
84
|
+
TSTRING firmware = name.substring(1, name.indexOf('_'));
|
|
85
|
+
TSTRING hardware =
|
|
86
|
+
name.substring(name.indexOf('_') + 1, name.lastIndexOf('_'));
|
|
87
|
+
TSTRING role =
|
|
88
|
+
name.substring(name.lastIndexOf('_') + 1, name.indexOf('.'));
|
|
89
|
+
TSTRING extension =
|
|
90
|
+
name.substring(name.indexOf('.') + 1, name.length());
|
|
91
|
+
if (firmware.equals("firmware") &&
|
|
92
|
+
(hardware.equals("ESP8266") || hardware.equals("ESP32")) &&
|
|
93
|
+
extension.equals("bin")) {
|
|
94
|
+
|
|
95
|
+
Serial.println("OTA FIRMWARE FOUND, NOW BROADCASTING");
|
|
96
|
+
|
|
97
|
+
//This is the important bit for OTA, up to now was just getting the file.
|
|
98
|
+
//If you are using some other way to upload firmware, possibly from
|
|
99
|
+
//mqtt or something, this is what needs to be changed.
|
|
100
|
+
//This function could also be changed to support OTA of multiple files
|
|
101
|
+
//at the same time, potentially through using the pkg.md5 as a key in
|
|
102
|
+
//a map to determine which to send
|
|
103
|
+
mesh.initOTASend(
|
|
104
|
+
[&entry](painlessmesh::plugin::ota::DataRequest pkg,
|
|
105
|
+
char* buffer) {
|
|
106
|
+
|
|
107
|
+
//fill the buffer with the requested data packet from the node.
|
|
108
|
+
entry.seek(OTA_PART_SIZE * pkg.partNo);
|
|
109
|
+
entry.readBytes(buffer, OTA_PART_SIZE);
|
|
110
|
+
|
|
111
|
+
//The buffer can hold OTA_PART_SIZE bytes, but the last packet may
|
|
112
|
+
//not be that long. Return the actual size of the packet.
|
|
113
|
+
return min((unsigned)OTA_PART_SIZE,
|
|
114
|
+
entry.size() - (OTA_PART_SIZE * pkg.partNo));
|
|
115
|
+
},
|
|
116
|
+
OTA_PART_SIZE);
|
|
117
|
+
|
|
118
|
+
//Calculate the MD5 hash of the firmware we are trying to send. This will be used
|
|
119
|
+
//to validate the firmware as well as tell if a node needs this firmware.
|
|
120
|
+
MD5Builder md5;
|
|
121
|
+
md5.begin();
|
|
122
|
+
md5.addStream(entry, entry.size());
|
|
123
|
+
md5.calculate();
|
|
124
|
+
|
|
125
|
+
//Make it known to the network that there is OTA firmware available.
|
|
126
|
+
//This will send a message every minute for an hour letting nodes know
|
|
127
|
+
//that firmware is available.
|
|
128
|
+
//This returns a task that allows you to do things on disable or more,
|
|
129
|
+
//like closing your files or whatever.
|
|
130
|
+
mesh.offerOTA(role, hardware, md5.toString(),
|
|
131
|
+
ceil(((float)entry.size()) / OTA_PART_SIZE), false);
|
|
132
|
+
|
|
133
|
+
while (true) {
|
|
134
|
+
//This program will not reach loop() so we dont have to worry about
|
|
135
|
+
//file scope.
|
|
136
|
+
mesh.update();
|
|
137
|
+
delay(1000);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void rebootEspWithReason(String reason) {
|
|
146
|
+
Serial.println(reason);
|
|
147
|
+
delay(1000);
|
|
148
|
+
ESP.restart();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
void loop(){};
|
|
@@ -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@^2.0.0 ; 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,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 = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
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 = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the easyMesh library
|
|
3
|
+
//
|
|
4
|
+
// 1. blinks led once for every node on the mesh
|
|
5
|
+
// 2. blink cycle repeats every BLINK_PERIOD
|
|
6
|
+
// 3. sends a silly message to every node on the mesh at a random time between 1 and 5 seconds
|
|
7
|
+
// 4. prints anything it receives to Serial.print
|
|
8
|
+
//
|
|
9
|
+
//
|
|
10
|
+
//************************************************************
|
|
11
|
+
#include <painlessMesh.h>
|
|
12
|
+
|
|
13
|
+
// some gpio pin that is connected to an LED...
|
|
14
|
+
// on my rig, this is 2, change to the right number of your LED.
|
|
15
|
+
#ifndef LED
|
|
16
|
+
#ifdef LED_BUILTIN
|
|
17
|
+
#define LED LED_BUILTIN
|
|
18
|
+
#else
|
|
19
|
+
#define LED 2
|
|
20
|
+
#endif
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
#define BLINK_PERIOD 3000 // milliseconds until cycle repeat
|
|
24
|
+
#define BLINK_DURATION 100 // milliseconds LED is on for
|
|
25
|
+
|
|
26
|
+
#define MESH_SSID "whateverYouLike"
|
|
27
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
28
|
+
#define MESH_PORT 5555
|
|
29
|
+
|
|
30
|
+
// Prototypes
|
|
31
|
+
void sendMessage();
|
|
32
|
+
void receivedCallback(uint32_t from, String & msg);
|
|
33
|
+
void newConnectionCallback(uint32_t nodeId);
|
|
34
|
+
void changedConnectionCallback();
|
|
35
|
+
void nodeTimeAdjustedCallback(int32_t offset);
|
|
36
|
+
void delayReceivedCallback(uint32_t from, int32_t delay);
|
|
37
|
+
|
|
38
|
+
Scheduler userScheduler; // to control your personal task
|
|
39
|
+
painlessMesh mesh;
|
|
40
|
+
|
|
41
|
+
bool calc_delay = false;
|
|
42
|
+
SimpleList<uint32_t> nodes;
|
|
43
|
+
|
|
44
|
+
void sendMessage() ; // Prototype
|
|
45
|
+
Task taskSendMessage( TASK_SECOND * 1, TASK_FOREVER, &sendMessage ); // start with a one second interval
|
|
46
|
+
|
|
47
|
+
// Task to blink the number of nodes
|
|
48
|
+
Task blinkNoNodes;
|
|
49
|
+
bool onFlag = false;
|
|
50
|
+
|
|
51
|
+
void setup() {
|
|
52
|
+
Serial.begin(115200);
|
|
53
|
+
|
|
54
|
+
pinMode(LED, OUTPUT);
|
|
55
|
+
|
|
56
|
+
mesh.setDebugMsgTypes(ERROR | DEBUG); // set before init() so that you can see error messages
|
|
57
|
+
|
|
58
|
+
mesh.init(MESH_SSID, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
59
|
+
mesh.onReceive(&receivedCallback);
|
|
60
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
61
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
62
|
+
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);
|
|
63
|
+
mesh.onNodeDelayReceived(&delayReceivedCallback);
|
|
64
|
+
|
|
65
|
+
userScheduler.addTask( taskSendMessage );
|
|
66
|
+
taskSendMessage.enable();
|
|
67
|
+
|
|
68
|
+
blinkNoNodes.set(BLINK_PERIOD, (mesh.getNodeList().size() + 1) * 2, []() {
|
|
69
|
+
// If on, switch off, else switch on
|
|
70
|
+
if (onFlag)
|
|
71
|
+
onFlag = false;
|
|
72
|
+
else
|
|
73
|
+
onFlag = true;
|
|
74
|
+
blinkNoNodes.delay(BLINK_DURATION);
|
|
75
|
+
|
|
76
|
+
if (blinkNoNodes.isLastIteration()) {
|
|
77
|
+
// Finished blinking. Reset task for next run
|
|
78
|
+
// blink number of nodes (including this node) times
|
|
79
|
+
blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
|
|
80
|
+
// Calculate delay based on current mesh time and BLINK_PERIOD
|
|
81
|
+
// This results in blinks between nodes being synced
|
|
82
|
+
blinkNoNodes.enableDelayed(BLINK_PERIOD -
|
|
83
|
+
(mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
userScheduler.addTask(blinkNoNodes);
|
|
87
|
+
blinkNoNodes.enable();
|
|
88
|
+
|
|
89
|
+
randomSeed(analogRead(A0));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void loop() {
|
|
93
|
+
mesh.update();
|
|
94
|
+
digitalWrite(LED, !onFlag);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
void sendMessage() {
|
|
98
|
+
String msg = "Hello from node ";
|
|
99
|
+
msg += mesh.getNodeId();
|
|
100
|
+
msg += " myFreeMemory: " + String(ESP.getFreeHeap());
|
|
101
|
+
mesh.sendBroadcast(msg);
|
|
102
|
+
|
|
103
|
+
if (calc_delay) {
|
|
104
|
+
SimpleList<uint32_t>::iterator node = nodes.begin();
|
|
105
|
+
while (node != nodes.end()) {
|
|
106
|
+
mesh.startDelayMeas(*node);
|
|
107
|
+
node++;
|
|
108
|
+
}
|
|
109
|
+
calc_delay = false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
Serial.printf("Sending message: %s\n", msg.c_str());
|
|
113
|
+
|
|
114
|
+
taskSendMessage.setInterval( random(TASK_SECOND * 1, TASK_SECOND * 5)); // between 1 and 5 seconds
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
void receivedCallback(uint32_t from, String & msg) {
|
|
119
|
+
Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
123
|
+
// Reset blink task
|
|
124
|
+
onFlag = false;
|
|
125
|
+
blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
|
|
126
|
+
blinkNoNodes.enableDelayed(BLINK_PERIOD - (mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
|
|
127
|
+
|
|
128
|
+
Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
|
|
129
|
+
Serial.printf("--> startHere: New Connection, %s\n", mesh.subConnectionJson(true).c_str());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
void changedConnectionCallback() {
|
|
133
|
+
Serial.printf("Changed connections\n");
|
|
134
|
+
// Reset blink task
|
|
135
|
+
onFlag = false;
|
|
136
|
+
blinkNoNodes.setIterations((mesh.getNodeList().size() + 1) * 2);
|
|
137
|
+
blinkNoNodes.enableDelayed(BLINK_PERIOD - (mesh.getNodeTime() % (BLINK_PERIOD*1000))/1000);
|
|
138
|
+
|
|
139
|
+
nodes = mesh.getNodeList();
|
|
140
|
+
|
|
141
|
+
Serial.printf("Num nodes: %d\n", nodes.size());
|
|
142
|
+
Serial.printf("Connection list:");
|
|
143
|
+
|
|
144
|
+
SimpleList<uint32_t>::iterator node = nodes.begin();
|
|
145
|
+
while (node != nodes.end()) {
|
|
146
|
+
Serial.printf(" %u", *node);
|
|
147
|
+
node++;
|
|
148
|
+
}
|
|
149
|
+
Serial.println();
|
|
150
|
+
calc_delay = true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
void nodeTimeAdjustedCallback(int32_t offset) {
|
|
154
|
+
Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(), offset);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
void delayReceivedCallback(uint32_t from, int32_t delay) {
|
|
158
|
+
Serial.printf("Delay to node %u is %d us\n", from, delay);
|
|
159
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
esp32async/ESPAsyncWebServer
|
|
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 ; 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
|
|
27
|
+
AsyncWebServer
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// this is a simple example that uses the painlessMesh library to
|
|
3
|
+
// connect to a another network and broadcast message from a webpage to the edges of the mesh network.
|
|
4
|
+
// This sketch can be extended further using all the abilities of the AsyncWebserver library (WS, events, ...)
|
|
5
|
+
// for more details
|
|
6
|
+
// https://gitlab.com/painlessMesh/painlessMesh/wikis/bridge-between-mesh-and-another-network
|
|
7
|
+
// for more details about my version
|
|
8
|
+
// https://gitlab.com/Assassynv__V/painlessMesh
|
|
9
|
+
// and for more details about the AsyncWebserver library
|
|
10
|
+
// https://github.com/me-no-dev/ESPAsyncWebServer
|
|
11
|
+
//************************************************************
|
|
12
|
+
|
|
13
|
+
#include "IPAddress.h"
|
|
14
|
+
#include "painlessMesh.h"
|
|
15
|
+
|
|
16
|
+
#ifdef ESP8266
|
|
17
|
+
#include "Hash.h"
|
|
18
|
+
#include <ESPAsyncTCP.h>
|
|
19
|
+
#else
|
|
20
|
+
#include <AsyncTCP.h>
|
|
21
|
+
#endif
|
|
22
|
+
#include <ESPAsyncWebServer.h>
|
|
23
|
+
|
|
24
|
+
#define MESH_PREFIX "whateverYouLike"
|
|
25
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
26
|
+
#define MESH_PORT 5555
|
|
27
|
+
|
|
28
|
+
#define STATION_SSID "mySSID"
|
|
29
|
+
#define STATION_PASSWORD "myPASSWORD"
|
|
30
|
+
|
|
31
|
+
#define HOSTNAME "HTTP_BRIDGE"
|
|
32
|
+
|
|
33
|
+
// Prototype
|
|
34
|
+
void receivedCallback( const uint32_t &from, const String &msg );
|
|
35
|
+
IPAddress getlocalIP();
|
|
36
|
+
|
|
37
|
+
painlessMesh mesh;
|
|
38
|
+
AsyncWebServer server(80);
|
|
39
|
+
IPAddress myIP(0,0,0,0);
|
|
40
|
+
IPAddress myAPIP(0,0,0,0);
|
|
41
|
+
|
|
42
|
+
void setup() {
|
|
43
|
+
Serial.begin(115200);
|
|
44
|
+
|
|
45
|
+
mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
|
|
46
|
+
|
|
47
|
+
// Channel set to 6. Make sure to use the same channel for your mesh and for you other
|
|
48
|
+
// network (STATION_SSID)
|
|
49
|
+
mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
|
|
50
|
+
mesh.onReceive(&receivedCallback);
|
|
51
|
+
|
|
52
|
+
mesh.stationManual(STATION_SSID, STATION_PASSWORD);
|
|
53
|
+
mesh.setHostname(HOSTNAME);
|
|
54
|
+
|
|
55
|
+
// 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
|
|
56
|
+
mesh.setRoot(true);
|
|
57
|
+
// This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
|
|
58
|
+
mesh.setContainsRoot(true);
|
|
59
|
+
|
|
60
|
+
myAPIP = IPAddress(mesh.getAPIP());
|
|
61
|
+
Serial.println("My AP IP is " + myAPIP.toString());
|
|
62
|
+
|
|
63
|
+
//Async webserver
|
|
64
|
+
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
|
|
65
|
+
request->send(200, "text/html", "<form>Text to Broadcast<br><input type='text' name='BROADCAST'><br><br><input type='submit' value='Submit'></form>");
|
|
66
|
+
if (request->hasArg("BROADCAST")){
|
|
67
|
+
String msg = request->arg("BROADCAST");
|
|
68
|
+
mesh.sendBroadcast(msg);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
server.begin();
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void loop() {
|
|
76
|
+
mesh.update();
|
|
77
|
+
if(myIP != getlocalIP()){
|
|
78
|
+
myIP = getlocalIP();
|
|
79
|
+
Serial.println("My IP is " + myIP.toString());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
void receivedCallback( const uint32_t &from, const String &msg ) {
|
|
84
|
+
Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
IPAddress getlocalIP() {
|
|
88
|
+
return IPAddress(mesh.getStationIP());
|
|
89
|
+
}
|
package/keywords.txt
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# painlessMesh library keywords
|
|
2
|
+
|
|
3
|
+
# Classes (KEYWORD1)
|
|
4
|
+
painlessMesh KEYWORD1
|
|
5
|
+
Scheduler KEYWORD1
|
|
6
|
+
Task KEYWORD1
|
|
7
|
+
|
|
8
|
+
# Methods and Functions (KEYWORD2)
|
|
9
|
+
init KEYWORD2
|
|
10
|
+
update KEYWORD2
|
|
11
|
+
sendBroadcast KEYWORD2
|
|
12
|
+
sendSingle KEYWORD2
|
|
13
|
+
onReceive KEYWORD2
|
|
14
|
+
onNewConnection KEYWORD2
|
|
15
|
+
onChangedConnections KEYWORD2
|
|
16
|
+
onNodeTimeAdjusted KEYWORD2
|
|
17
|
+
getNodeList KEYWORD2
|
|
18
|
+
getNodeId KEYWORD2
|
|
19
|
+
getNodeTime KEYWORD2
|
|
20
|
+
setDebugMsgTypes KEYWORD2
|
|
21
|
+
subConnectionJson KEYWORD2
|
|
22
|
+
asNodeTree KEYWORD2
|
|
23
|
+
|
|
24
|
+
# Alteriom Extensions (KEYWORD1)
|
|
25
|
+
SensorPackage KEYWORD1
|
|
26
|
+
CommandPackage KEYWORD1
|
|
27
|
+
StatusPackage KEYWORD1
|
|
28
|
+
|
|
29
|
+
# Alteriom Methods (KEYWORD2)
|
|
30
|
+
addTo KEYWORD2
|
|
31
|
+
jsonObjectSize KEYWORD2
|
|
32
|
+
|
|
33
|
+
# Constants (LITERAL1)
|
|
34
|
+
MESH_PREFIX LITERAL1
|
|
35
|
+
MESH_PASSWORD LITERAL1
|
|
36
|
+
MESH_PORT LITERAL1
|
|
37
|
+
TASK_SECOND LITERAL1
|
|
38
|
+
TASK_MINUTE LITERAL1
|
|
39
|
+
TASK_HOUR LITERAL1
|
|
40
|
+
TASK_FOREVER LITERAL1
|
|
41
|
+
ERROR LITERAL1
|
|
42
|
+
STARTUP LITERAL1
|
|
43
|
+
CONNECTION LITERAL1
|
|
44
|
+
SYNC LITERAL1
|
|
45
|
+
COMMUNICATION LITERAL1
|
|
46
|
+
GENERAL LITERAL1
|
|
47
|
+
MSG_TYPES LITERAL1
|
|
48
|
+
REMOTE LITERAL1
|
|
49
|
+
DEBUG LITERAL1
|
package/library.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "painlessMesh",
|
|
3
|
+
"keywords": "ethernet, m2m, iot, mesh, alteriom, sensor",
|
|
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
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Alteriom/painlessMesh"
|
|
8
|
+
},
|
|
9
|
+
"version": "1.6.1",
|
|
10
|
+
"frameworks": "arduino",
|
|
11
|
+
"platforms": "espressif8266, espressif32",
|
|
12
|
+
"dependencies": [
|
|
13
|
+
{ "owner": "esp32async", "name": "AsyncTCP", "version": "^3.4.7", "platforms" : ["espressif32"] },
|
|
14
|
+
{ "owner": "esp32async", "name": "ESPAsyncTCP", "version": "^2.0.0", "platforms" : ["espressif8266"] },
|
|
15
|
+
{ "owner": "bblanchon", "name": "ArduinoJson", "version": "^7.4.2" },
|
|
16
|
+
{ "owner": "arkhipenko", "name": "TaskScheduler", "version": "^3.8.5" }
|
|
17
|
+
],
|
|
18
|
+
"authors": [
|
|
19
|
+
{ "name": "Scotty Franzyshen" },
|
|
20
|
+
{
|
|
21
|
+
"name": "Coopdis",
|
|
22
|
+
"url": "https://github.com/Coopdis"
|
|
23
|
+
},
|
|
24
|
+
{ "name": "Edwin van Leeuwen" },
|
|
25
|
+
{ "name": "Germán Martín" },
|
|
26
|
+
{ "name": "Maximilian Schwarz" },
|
|
27
|
+
{ "name": "Doanh Doanh" },
|
|
28
|
+
{
|
|
29
|
+
"name": "Alteriom",
|
|
30
|
+
"url": "https://github.com/Alteriom"
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"headers": "painlessMesh.h"
|
|
34
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
name=AlteriomPainlessMesh
|
|
2
|
+
version=1.6.1
|
|
3
|
+
author=Coopdis,Scotty Franzyshen,Edwin van Leeuwen,Germán Martín,Maximilian Schwarz,Doanh Doanh,Alteriom
|
|
4
|
+
maintainer=Alteriom
|
|
5
|
+
sentence=A painless way to setup a mesh with ESP8266 and ESP32 devices with Alteriom extensions
|
|
6
|
+
paragraph=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.
|
|
7
|
+
category=Communication
|
|
8
|
+
url=https://github.com/Alteriom/painlessMesh
|
|
9
|
+
architectures=esp8266,esp32
|
|
10
|
+
includes=AlteriomPainlessMesh.h
|
|
11
|
+
depends=ArduinoJson, TaskScheduler
|