105 lines
2.0 KiB
C++
105 lines
2.0 KiB
C++
#ifndef VALUE_H
|
|
#define VALUE_H
|
|
|
|
#include <WiFi.h>
|
|
#include <patrix/log.h>
|
|
#include <patrix/mqtt.h>
|
|
|
|
class Value {
|
|
|
|
const char *parent;
|
|
|
|
const char *name;
|
|
|
|
double threshold;
|
|
|
|
unsigned long maxAgeMillis;
|
|
|
|
unsigned long overdueSeconds;
|
|
|
|
double currentValue = NAN;
|
|
|
|
unsigned long currentMillis = 0;
|
|
|
|
time_t currentEpoch = 0;
|
|
|
|
double sentValue = NAN;
|
|
|
|
time_t sentInterval = 0;
|
|
|
|
public:
|
|
|
|
Value(
|
|
const char *parent,
|
|
const char *name,
|
|
const double threshold,
|
|
const unsigned long maxAgeSeconds,
|
|
const unsigned long overdueSeconds
|
|
) : parent(parent),
|
|
name(name),
|
|
threshold(threshold),
|
|
maxAgeMillis(maxAgeSeconds * 1000),
|
|
overdueSeconds(overdueSeconds) {
|
|
//
|
|
}
|
|
|
|
void update(const double value) {
|
|
currentValue = value;
|
|
currentMillis = millis();
|
|
currentEpoch = time(nullptr);
|
|
}
|
|
|
|
void toJson(const JsonObject& json) const {
|
|
json["value"] = currentValue;
|
|
json["time"] = currentEpoch;
|
|
}
|
|
|
|
void send() {
|
|
mqttPublish(String(parent) + "/" + name + "/plain", currentValue, true);
|
|
|
|
JsonDocument json;
|
|
toJson(json.to<JsonObject>());
|
|
mqttPublish(String(parent) + "/" + name + "/json", json, true, false);
|
|
|
|
markSent();
|
|
}
|
|
|
|
bool loop() {
|
|
if (!isnan(currentValue) && millis() - currentMillis > maxAgeMillis) {
|
|
warn("Value too old: %s/%s", parent, name);
|
|
update(NAN);
|
|
}
|
|
|
|
const auto dueToNAN = isnan(currentValue) != isnan(sentValue);
|
|
const auto dueToThreshold = abs(sentValue - currentValue) >= threshold;
|
|
const auto dueToTime = sentInterval != 0 && sentInterval != time(nullptr) / overdueSeconds;
|
|
const auto changed = dueToNAN || dueToThreshold || dueToTime;
|
|
if (changed) {
|
|
send();
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
const char *getName() const {
|
|
return name;
|
|
}
|
|
|
|
double getCurrentValue() const {
|
|
return currentValue;
|
|
}
|
|
|
|
time_t getCurrentEpoch() const {
|
|
return currentEpoch;
|
|
}
|
|
|
|
private:
|
|
|
|
void markSent() {
|
|
sentValue = currentValue;
|
|
sentInterval = time(nullptr) / overdueSeconds;
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|