#ifndef VALUE_H #define VALUE_H #include #include #include 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()); 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