Sensor4/src/patrix/sensor/Value.h

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