feat: 全量同步 254 个常用的 Arduino 扩展库文件

This commit is contained in:
yczpf2019
2026-01-24 16:05:38 +08:00
parent c665ba662b
commit 397b9a23a3
6878 changed files with 2732224 additions and 1 deletions

View File

@@ -0,0 +1,202 @@
#ifndef _PAINLESS_MESH_PLUGIN_PERFORMANCE_HPP_
#define _PAINLESS_MESH_PLUGIN_PERFORMANCE_HPP_
#include "painlessmesh/configuration.hpp"
#include "painlessmesh/logger.hpp"
#include "painlessmesh/plugin.hpp"
namespace painlessmesh {
namespace plugin {
/** Add performance tracking to the mesh
*
* Nodes will send out special packages to each other, allowing each node to
* keep track of different performance measures
*/
namespace performance {
/** Track mean and variance of the given value
*
* Older values are discounted, so that you keep a rolling average
*/
class Stats {
public:
void update(double v, double alpha = 0.1) {
if (!init) {
mu = v;
init = true;
return;
}
auto d = v - mu;
mu = mu + alpha * d;
var = (1 - alpha) * (var + alpha * pow(d, 2));
}
// Returns the mean and 95% interval based on 1.96*sd? or 2.96*sd
TSTRING toString() const {
#ifdef PAINLESSMESH_ENABLE_STD_STRING
std::stringstream ss;
ss << mu << "[" << mu - 1.96 * sqrt(var) << "," << mu + 1.96 * sqrt(var)
<< "]";
return ss.str();
#else
return TSTRING(mu) + TSTRING("[") + TSTRING(mu - 1.96 * sqrt(var)) +
TSTRING(",") + TSTRING(mu + 1.96 * sqrt(var)) + TSTRING("]");
#endif
}
protected:
double mu = 0;
double var = 0;
bool init = false;
};
class PerformancePackage : public plugin::BroadcastPackage {
public:
int id = 0; // Can see if we missed values
int time; // Get an idea of the delay, by comparing it with nodetime
int stability; // stability of the sending node
int freeMemory; // memory of the sending node
#ifdef ESP32
TSTRING hardware = "ESP32";
#else
TSTRING hardware = "ESP8266";
#endif
PerformancePackage() : plugin::BroadcastPackage(13) {}
PerformancePackage(JsonObject jsonObj) : plugin::BroadcastPackage(jsonObj) {
id = jsonObj["id"];
time = jsonObj["time"];
stability = jsonObj["stability"];
freeMemory = jsonObj["freeMemory"];
hardware = jsonObj["hardware"].as<TSTRING>();
}
JsonObject addTo(JsonObject&& jsonObj) const {
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
jsonObj["type"] = type;
jsonObj["id"] = id;
jsonObj["time"] = time;
jsonObj["stability"] = stability;
jsonObj["freeMemory"] = freeMemory;
jsonObj["hardware"] = hardware;
return jsonObj;
}
size_t jsonObjectSize() const {
return JSON_OBJECT_SIZE(4 + 5) + round(2 * (hardware.length()));
}
};
/// Numbers to track for each node we receive PerformancePackages from
class Track {
public:
uint32_t nodeId;
TSTRING hardware;
uint32_t hits = 0;
uint32_t misses = 0;
int lastId = 0;
Stats delay;
Stats stability;
Stats freeMemory;
uint32_t present = 0; // Every so often check if each node is absent or
// present in the layout
uint32_t absent = 0;
Track() {}
void addTo(JsonObject& jsonObj) const {
jsonObj["nodeId"] = nodeId;
jsonObj["hardware"] = hardware;
jsonObj["hits"] = hits;
jsonObj["misses"] = misses;
jsonObj["delay"] = delay.toString();
jsonObj["stability"] = stability.toString();
jsonObj["freeMemory"] = freeMemory.toString();
jsonObj["present"] = present;
jsonObj["absent"] = absent;
}
};
/// Holds resulst from all the nodes
class TrackMap : public protocol::PackageInterface,
public std::map<uint32_t, Track> {
public:
JsonObject addTo(JsonObject&& jsonObj) const {
jsonObj["event"] = "performance";
// Start array
auto jsonArr = jsonObj.createNestedArray("nodes");
// for each in map do
for (auto&& pair : (*this)) {
auto obj = jsonArr.createNestedObject();
pair.second.addTo(obj);
}
return jsonObj;
} // namespace performance
size_t jsonObjectSize() const {
return JSON_OBJECT_SIZE(2 + 15) + JSON_ARRAY_SIZE(this->size()) +
this->size()*(JSON_OBJECT_SIZE(9) + 4 * 100);
}
}; // namespace plugin
template <class T>
void begin(T& mesh, double frequency = 2) {
auto tracker = std::make_shared<TrackMap>();
auto sendPkg = std::make_shared<PerformancePackage>();
mesh.onPackage(sendPkg->type, [&mesh, tracker](protocol::Variant var) {
auto pkg = var.to<PerformancePackage>();
// if not in tracker, add it
if (!tracker->count(pkg.from)) {
tracker->operator[](pkg.from) = Track();
if (pkg.id > 0) tracker->operator[](pkg.from).lastId = pkg.id - 1;
}
// update all the values in the trackmap
tracker->operator[](pkg.from).nodeId = pkg.from;
tracker->operator[](pkg.from).hardware = pkg.hardware;
++tracker->operator[](pkg.from).hits;
if (pkg.id < tracker->operator[](pkg.from).lastId) // Node was reset?
tracker->operator[](pkg.from).lastId = pkg.id;
else {
tracker->operator[](pkg.from).misses +=
(pkg.id - tracker->operator[](pkg.from).lastId) - 1;
}
tracker->operator[](pkg.from).lastId = pkg.id;
tracker->operator[](pkg.from).delay.update(
((int)mesh.getNodeTime() - pkg.time) / 1000);
tracker->operator[](pkg.from).stability.update(pkg.stability);
tracker->operator[](pkg.from).freeMemory.update(pkg.freeMemory);
return false;
});
sendPkg->from = mesh.getNodeId();
mesh.addTask(frequency*TASK_SECOND, TASK_FOREVER, [sendPkg, &mesh]() {
++sendPkg->id;
sendPkg->time = mesh.getNodeTime();
sendPkg->stability = mesh.stability;
sendPkg->freeMemory = ESP.getFreeHeap();
mesh.sendPackage(sendPkg.get());
});
mesh.addTask(TASK_MINUTE, TASK_FOREVER, [tracker, &mesh]() {
for (auto&& pair : (*tracker)) {
if (mesh.isConnected(pair.first))
++pair.second.present;
else
++pair.second.absent;
}
protocol::Variant var(tracker.get());
TSTRING str;
var.printTo(str);
#ifdef PAINLESSMESH_ENABLE_STD_STRING
std::cout << str << std::endl;
#else
Serial.println(str);
#endif
});
}
} // namespace performance
} // namespace plugin
} // namespace painlessmesh
#endif