@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,214 @@
|
|
|
1
|
+
#ifndef _PAINLESS_MESH_PLUGIN_PERFORMANCE_HPP_
|
|
2
|
+
#define _PAINLESS_MESH_PLUGIN_PERFORMANCE_HPP_
|
|
3
|
+
|
|
4
|
+
#include "painlessmesh/configuration.hpp"
|
|
5
|
+
|
|
6
|
+
#include "painlessmesh/logger.hpp"
|
|
7
|
+
#include "painlessmesh/plugin.hpp"
|
|
8
|
+
|
|
9
|
+
namespace painlessmesh {
|
|
10
|
+
namespace plugin {
|
|
11
|
+
/** Add performance tracking to the mesh
|
|
12
|
+
*
|
|
13
|
+
* Nodes will send out special packages to each other, allowing each node to
|
|
14
|
+
* keep track of different performance measures
|
|
15
|
+
*/
|
|
16
|
+
namespace performance {
|
|
17
|
+
|
|
18
|
+
/** Track mean and variance of the given value
|
|
19
|
+
*
|
|
20
|
+
* Older values are discounted, so that you keep a rolling average
|
|
21
|
+
*/
|
|
22
|
+
class Stats {
|
|
23
|
+
public:
|
|
24
|
+
void update(double v, double alpha = 0.1) {
|
|
25
|
+
if (!init) {
|
|
26
|
+
mu = v;
|
|
27
|
+
init = true;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
auto d = v - mu;
|
|
31
|
+
mu = mu + alpha * d;
|
|
32
|
+
var = (1 - alpha) * (var + alpha * pow(d, 2));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Returns the mean and 95% interval based on 1.96*sd? or 2.96*sd
|
|
36
|
+
TSTRING toString() const {
|
|
37
|
+
#ifdef PAINLESSMESH_ENABLE_STD_STRING
|
|
38
|
+
std::stringstream ss;
|
|
39
|
+
ss << mu << "[" << mu - 1.96 * sqrt(var) << "," << mu + 1.96 * sqrt(var)
|
|
40
|
+
<< "]";
|
|
41
|
+
return ss.str();
|
|
42
|
+
#else
|
|
43
|
+
return TSTRING(mu) + TSTRING("[") + TSTRING(mu - 1.96 * sqrt(var)) +
|
|
44
|
+
TSTRING(",") + TSTRING(mu + 1.96 * sqrt(var)) + TSTRING("]");
|
|
45
|
+
#endif
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected:
|
|
49
|
+
double mu = 0;
|
|
50
|
+
double var = 0;
|
|
51
|
+
bool init = false;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
class PerformancePackage : public plugin::BroadcastPackage {
|
|
55
|
+
public:
|
|
56
|
+
int id = 0; // Can see if we missed values
|
|
57
|
+
int time; // Get an idea of the delay, by comparing it with nodetime
|
|
58
|
+
int stability; // stability of the sending node
|
|
59
|
+
int freeMemory; // memory of the sending node
|
|
60
|
+
#ifdef ESP32
|
|
61
|
+
TSTRING hardware = "ESP32";
|
|
62
|
+
#else
|
|
63
|
+
TSTRING hardware = "ESP8266";
|
|
64
|
+
#endif
|
|
65
|
+
PerformancePackage() : plugin::BroadcastPackage(13) {}
|
|
66
|
+
|
|
67
|
+
PerformancePackage(JsonObject jsonObj) : plugin::BroadcastPackage(jsonObj) {
|
|
68
|
+
id = jsonObj["id"];
|
|
69
|
+
time = jsonObj["time"];
|
|
70
|
+
stability = jsonObj["stability"];
|
|
71
|
+
freeMemory = jsonObj["freeMemory"];
|
|
72
|
+
hardware = jsonObj["hardware"].as<TSTRING>();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
76
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
77
|
+
jsonObj["type"] = type;
|
|
78
|
+
jsonObj["id"] = id;
|
|
79
|
+
jsonObj["time"] = time;
|
|
80
|
+
jsonObj["stability"] = stability;
|
|
81
|
+
jsonObj["freeMemory"] = freeMemory;
|
|
82
|
+
jsonObj["hardware"] = hardware;
|
|
83
|
+
return jsonObj;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
87
|
+
size_t jsonObjectSize() const {
|
|
88
|
+
return JSON_OBJECT_SIZE(4 + 5) + round(2 * (hardware.length()));
|
|
89
|
+
}
|
|
90
|
+
#endif
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/// Numbers to track for each node we receive PerformancePackages from
|
|
94
|
+
class Track {
|
|
95
|
+
public:
|
|
96
|
+
uint32_t nodeId;
|
|
97
|
+
TSTRING hardware;
|
|
98
|
+
uint32_t hits = 0;
|
|
99
|
+
uint32_t misses = 0;
|
|
100
|
+
int lastId = 0;
|
|
101
|
+
Stats delay;
|
|
102
|
+
Stats stability;
|
|
103
|
+
Stats freeMemory;
|
|
104
|
+
uint32_t present = 0; // Every so often check if each node is absent or
|
|
105
|
+
// present in the layout
|
|
106
|
+
uint32_t absent = 0;
|
|
107
|
+
Track() {}
|
|
108
|
+
|
|
109
|
+
void addTo(JsonObject& jsonObj) const {
|
|
110
|
+
jsonObj["nodeId"] = nodeId;
|
|
111
|
+
jsonObj["hardware"] = hardware;
|
|
112
|
+
jsonObj["hits"] = hits;
|
|
113
|
+
jsonObj["misses"] = misses;
|
|
114
|
+
jsonObj["delay"] = delay.toString();
|
|
115
|
+
jsonObj["stability"] = stability.toString();
|
|
116
|
+
jsonObj["freeMemory"] = freeMemory.toString();
|
|
117
|
+
jsonObj["present"] = present;
|
|
118
|
+
jsonObj["absent"] = absent;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/// Holds resulst from all the nodes
|
|
123
|
+
class TrackMap : public protocol::PackageInterface,
|
|
124
|
+
public std::map<uint32_t, Track> {
|
|
125
|
+
public:
|
|
126
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
127
|
+
jsonObj["event"] = "performance";
|
|
128
|
+
// Start array
|
|
129
|
+
#if ARDUINOJSON_VERSION_MAJOR == 7
|
|
130
|
+
auto jsonArr = jsonObj["nodes"].to<JsonArray>();
|
|
131
|
+
#else
|
|
132
|
+
auto jsonArr = jsonObj.createNestedArray("nodes");
|
|
133
|
+
#endif
|
|
134
|
+
// for each in map do
|
|
135
|
+
for (auto&& pair : (*this)) {
|
|
136
|
+
#if ARDUINOJSON_VERSION_MAJOR == 7
|
|
137
|
+
JsonObject obj = jsonArr.add<JsonObject>();
|
|
138
|
+
#else
|
|
139
|
+
auto obj = jsonArr.createNestedObject();
|
|
140
|
+
#endif
|
|
141
|
+
pair.second.addTo(obj);
|
|
142
|
+
}
|
|
143
|
+
return jsonObj;
|
|
144
|
+
} // namespace performance
|
|
145
|
+
|
|
146
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
147
|
+
size_t jsonObjectSize() const {
|
|
148
|
+
return JSON_OBJECT_SIZE(2 + 15) + JSON_ARRAY_SIZE(this->size()) +
|
|
149
|
+
this->size() * (JSON_OBJECT_SIZE(9) + 4 * 100);
|
|
150
|
+
}
|
|
151
|
+
#endif
|
|
152
|
+
}; // namespace plugin
|
|
153
|
+
|
|
154
|
+
template <class T>
|
|
155
|
+
void begin(T& mesh, double frequency = 2) {
|
|
156
|
+
auto tracker = std::make_shared<TrackMap>();
|
|
157
|
+
auto sendPkg = std::make_shared<PerformancePackage>();
|
|
158
|
+
|
|
159
|
+
mesh.onPackage(sendPkg->type, [&mesh, tracker](protocol::Variant& var) {
|
|
160
|
+
auto pkg = var.to<PerformancePackage>();
|
|
161
|
+
// if not in tracker, add it
|
|
162
|
+
if (!tracker->count(pkg.from)) {
|
|
163
|
+
tracker->operator[](pkg.from) = Track();
|
|
164
|
+
if (pkg.id > 0) tracker->operator[](pkg.from).lastId = pkg.id - 1;
|
|
165
|
+
}
|
|
166
|
+
// update all the values in the trackmap
|
|
167
|
+
tracker->operator[](pkg.from).nodeId = pkg.from;
|
|
168
|
+
tracker->operator[](pkg.from).hardware = pkg.hardware;
|
|
169
|
+
++tracker->operator[](pkg.from).hits;
|
|
170
|
+
if (pkg.id < tracker->operator[](pkg.from).lastId) // Node was reset?
|
|
171
|
+
tracker->operator[](pkg.from).lastId = pkg.id;
|
|
172
|
+
else {
|
|
173
|
+
tracker->operator[](pkg.from).misses +=
|
|
174
|
+
(pkg.id - tracker->operator[](pkg.from).lastId) - 1;
|
|
175
|
+
}
|
|
176
|
+
tracker->operator[](pkg.from).lastId = pkg.id;
|
|
177
|
+
tracker->operator[](pkg.from).delay.update(
|
|
178
|
+
((int)mesh.getNodeTime() - pkg.time) / 1000);
|
|
179
|
+
tracker->operator[](pkg.from).stability.update(pkg.stability);
|
|
180
|
+
tracker->operator[](pkg.from).freeMemory.update(pkg.freeMemory);
|
|
181
|
+
return false;
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
sendPkg->from = mesh.getNodeId();
|
|
185
|
+
mesh.addTask(frequency * TASK_SECOND, TASK_FOREVER, [sendPkg, &mesh]() {
|
|
186
|
+
++sendPkg->id;
|
|
187
|
+
sendPkg->time = mesh.getNodeTime();
|
|
188
|
+
sendPkg->stability = mesh.stability;
|
|
189
|
+
sendPkg->freeMemory = ESP.getFreeHeap();
|
|
190
|
+
mesh.sendPackage(sendPkg.get());
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
mesh.addTask(TASK_MINUTE, TASK_FOREVER, [tracker, &mesh]() {
|
|
194
|
+
for (auto&& pair : (*tracker)) {
|
|
195
|
+
if (mesh.isConnected(pair.first))
|
|
196
|
+
++pair.second.present;
|
|
197
|
+
else
|
|
198
|
+
++pair.second.absent;
|
|
199
|
+
}
|
|
200
|
+
protocol::Variant var(tracker.get());
|
|
201
|
+
TSTRING str;
|
|
202
|
+
var.printTo(str);
|
|
203
|
+
#ifdef PAINLESSMESH_ENABLE_STD_STRING
|
|
204
|
+
std::cout << str << std::endl;
|
|
205
|
+
#else
|
|
206
|
+
Serial.println(str);
|
|
207
|
+
#endif
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
} // namespace performance
|
|
212
|
+
} // namespace plugin
|
|
213
|
+
} // namespace painlessmesh
|
|
214
|
+
#endif
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "painlessmesh/configuration.hpp"
|
|
4
|
+
|
|
5
|
+
#include "painlessmesh/logger.hpp"
|
|
6
|
+
#include "painlessmesh/plugin.hpp"
|
|
7
|
+
|
|
8
|
+
extern painlessmesh::logger::LogClass Log;
|
|
9
|
+
|
|
10
|
+
namespace painlessmesh {
|
|
11
|
+
namespace plugin {
|
|
12
|
+
/** Add remote logger to the mesh
|
|
13
|
+
*
|
|
14
|
+
* Call remote::begin(nodeId, millis) to start it
|
|
15
|
+
*/
|
|
16
|
+
namespace remote {
|
|
17
|
+
class RemotePackage : public plugin::SinglePackage {
|
|
18
|
+
public:
|
|
19
|
+
std::list<std::pair<uint, TSTRING>> log;
|
|
20
|
+
RemotePackage() : plugin::SinglePackage(14) {}
|
|
21
|
+
RemotePackage(JsonObject jsonObj) : plugin::SinglePackage(jsonObj) {
|
|
22
|
+
for (JsonObject doc : jsonObj["log"].as<JsonArray>()) {
|
|
23
|
+
std::pair<uint, TSTRING> pr(doc["first"], doc["second"]);
|
|
24
|
+
log.push_back(pr);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
29
|
+
jsonObj = SinglePackage::addTo(std::move(jsonObj));
|
|
30
|
+
JsonArray arr = jsonObj["log"].to<JsonArray>();
|
|
31
|
+
for (auto&& pr : log) {
|
|
32
|
+
JsonDocument obj;
|
|
33
|
+
obj["first"] = pr.first;
|
|
34
|
+
obj["second"] = pr.second;
|
|
35
|
+
arr.add(obj);
|
|
36
|
+
}
|
|
37
|
+
return jsonObj;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
template <class T>
|
|
42
|
+
void begin(T& mesh, uint32_t destination, double frequency = 120,
|
|
43
|
+
std::function<bool(protocol::Variant&)> callback = nullptr) {
|
|
44
|
+
auto sendPkg = std::make_shared<RemotePackage>();
|
|
45
|
+
sendPkg->from = mesh.getNodeId();
|
|
46
|
+
sendPkg->dest = destination;
|
|
47
|
+
mesh.addTask(frequency * TASK_SECOND, TASK_FOREVER, [sendPkg, &mesh]() {
|
|
48
|
+
Log.remote("Memory %u and stability %u\n", ESP.getFreeHeap(),
|
|
49
|
+
mesh.stability);
|
|
50
|
+
// Note that we could clear the queue afterwards, but we
|
|
51
|
+
// actually want to keep resending it in case something just
|
|
52
|
+
// went wrong and we lost connection
|
|
53
|
+
sendPkg->log = Log.get_remote_queue();
|
|
54
|
+
if (!sendPkg->log.empty()) mesh.sendPackage(sendPkg.get());
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (callback) {
|
|
58
|
+
mesh.onPackage(sendPkg->type, callback);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
} // namespace remote
|
|
63
|
+
} // namespace plugin
|
|
64
|
+
} // namespace painlessmesh
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* https://github.com/arkhipenko/TaskScheduler/tree/master/examples/Scheduler_example16_Multitab
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
#include "painlessTaskOptions.h"
|
|
6
|
+
|
|
7
|
+
#pragma GCC diagnostic push
|
|
8
|
+
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
9
|
+
#include <TaskScheduler.h>
|
|
10
|
+
#pragma GCC diagnostic pop
|
package/src/wifi.cpp
ADDED