gridPowerDelta
This commit is contained in:
parent
c4d30371cf
commit
0eb51d8ad6
@ -85,7 +85,7 @@ public:
|
|||||||
this->onCount = onCount_;
|
this->onCount = onCount_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
virtual void loop() {
|
||||||
const auto status = get();
|
const auto status = get();
|
||||||
const auto ageMillis = millis() - stateMillis;
|
const auto ageMillis = millis() - stateMillis;
|
||||||
if (status) {
|
if (status) {
|
||||||
|
|||||||
115
src/Relay.h
115
src/Relay.h
@ -11,36 +11,55 @@ class Relay final : public Output {
|
|||||||
|
|
||||||
String topicFallback;
|
String topicFallback;
|
||||||
|
|
||||||
|
const uint8_t index;
|
||||||
|
|
||||||
String topic;
|
String topic;
|
||||||
|
|
||||||
const uint8_t index;
|
long gridPowerDeltaOnThreshold = 0;
|
||||||
|
|
||||||
|
long gridPowerDeltaOnDelay = 0;
|
||||||
|
|
||||||
|
long gridPowerDeltaOffThreshold = 0;
|
||||||
|
|
||||||
|
long gridPowerDeltaOffDelay = 0;
|
||||||
|
|
||||||
|
unsigned long gridPowerDeltaMillis = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Relay(const uint8_t index, const String &topic, const char *name, const uint8_t pin, const bool inverted, const bool logState) : Output(name, pin, inverted, logState), nameFallback(name), topicFallback(topic), topic(topic), index(index) {
|
Relay(const uint8_t index, const String &topic, const char *name, const uint8_t pin, const bool inverted, const bool logState) : Output(name, pin, inverted, logState), nameFallback(name), topicFallback(topic), index(index), topic(topic) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() override {
|
void setup() override {
|
||||||
Output::setup();
|
Output::setup();
|
||||||
|
|
||||||
Output::setName(configRead(path("name"), nameFallback));
|
Output::setName(configRead(path("name"), nameFallback));
|
||||||
topic = configRead(path("topic"), topicFallback);
|
|
||||||
Output::setInitial(configRead(path("initial"), INITIAL_OFF));
|
Output::setInitial(configRead(path("initial"), INITIAL_OFF));
|
||||||
Output::setOnMillis(configRead(path("onMillis"), 0L));
|
Output::setOnMillis(configRead(path("onMillis"), 0L));
|
||||||
Output::setOffMillis(configRead(path("offMillis"), 0L));
|
Output::setOffMillis(configRead(path("offMillis"), 0L));
|
||||||
|
|
||||||
|
topic = configRead(path("topic"), topicFallback);
|
||||||
|
|
||||||
|
gridPowerDeltaOnThreshold = configRead(path("autoOnThreshold"), -400L);
|
||||||
|
gridPowerDeltaOnDelay = configRead(path("autoOnDelay"), 30000L);
|
||||||
|
|
||||||
|
gridPowerDeltaOffThreshold = configRead(path("autoOffThreshold"), 100L);
|
||||||
|
gridPowerDeltaOffDelay = configRead(path("autoOffDelay"), 30000L);
|
||||||
|
|
||||||
_applyInitial();
|
_applyInitial();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loop() override {
|
||||||
|
Output::loop();
|
||||||
|
doGridPowerDelta();
|
||||||
|
}
|
||||||
|
|
||||||
void setName(const String &value) override {
|
void setName(const String &value) override {
|
||||||
Output::setName(value);
|
Output::setName(value);
|
||||||
configWrite(path("name"), nameFallback, value);
|
configWrite(path("name"), nameFallback, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTopic(const String &value) {
|
|
||||||
topic = value;
|
|
||||||
configWrite(path("topic"), topicFallback, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInitial(const Initial value) override {
|
void setInitial(const Initial value) override {
|
||||||
Output::setInitial(value);
|
Output::setInitial(value);
|
||||||
configWrite(path("initial"), INITIAL_OFF, value);
|
configWrite(path("initial"), INITIAL_OFF, value);
|
||||||
@ -56,23 +75,46 @@ public:
|
|||||||
configWrite(path("offMillis"), 0L, value);
|
configWrite(path("offMillis"), 0L, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTopic(const String &value) {
|
||||||
|
topic = value;
|
||||||
|
configWrite(path("topic"), topicFallback, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoOnThreshold(const long value) {
|
||||||
|
gridPowerDeltaOnThreshold = value;
|
||||||
|
configWrite(path("autoOnThreshold"), 0L, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoOnDelay(const long value) {
|
||||||
|
gridPowerDeltaOnDelay = value;
|
||||||
|
configWrite(path("autoOnDelay"), 0L, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoOffThreshold(const long value) {
|
||||||
|
gridPowerDeltaOffThreshold = value;
|
||||||
|
configWrite(path("autoOffThreshold"), 0L, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAutoOffDelay(const long value) {
|
||||||
|
gridPowerDeltaOffDelay = value;
|
||||||
|
configWrite(path("autoOffDelay"), 0L, value);
|
||||||
|
}
|
||||||
|
|
||||||
void json(const JsonObject json) const {
|
void json(const JsonObject json) const {
|
||||||
json["name"] = name;
|
json["name"] = name;
|
||||||
json["topic"] = topic;
|
|
||||||
json["state"] = get();
|
json["state"] = get();
|
||||||
json["stateAgeMillis"] = millis() - stateMillis;
|
json["stateAgeMillis"] = millis() - stateMillis;
|
||||||
json["initial"] = initialToString(initial);
|
json["initial"] = initialToString(initial);
|
||||||
json["onCount"] = onCount;
|
json["onCount"] = onCount;
|
||||||
json["onMillis"] = onMillis;
|
json["onMillis"] = onMillis;
|
||||||
json["offMillis"] = offMillis;
|
json["offMillis"] = offMillis;
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
json["topic"] = topic;
|
||||||
|
|
||||||
String path(const char *name) const {
|
json["autoOnThreshold"] = gridPowerDeltaOnThreshold;
|
||||||
char path[64];
|
json["autoOnDelay"] = gridPowerDeltaOnDelay;
|
||||||
snprintf(path, sizeof(path), "/relay%d/%s", index, name);
|
json["autoOffThreshold"] = gridPowerDeltaOffThreshold;
|
||||||
return String(path);
|
json["autoOffDelay"] = gridPowerDeltaOffDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -83,6 +125,49 @@ protected:
|
|||||||
mqttPublish(topic, doc);
|
mqttPublish(topic, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
String path(const char *name) const {
|
||||||
|
char path[64];
|
||||||
|
snprintf(path, sizeof(path), "/relay%d/%s", index, name);
|
||||||
|
return String(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doGridPowerDelta() {
|
||||||
|
const auto age = millis() - gridPowerDeltaMillis;
|
||||||
|
if (get()) {
|
||||||
|
if (gridPowerDelta > gridPowerDeltaOffThreshold) {
|
||||||
|
if (gridPowerDeltaMillis == 0) {
|
||||||
|
Serial.printf("[%s] CONSUMING TOO MUCH: Preparing to power OFF...\n", name.c_str());
|
||||||
|
gridPowerDeltaMillis = max(1UL, millis());
|
||||||
|
} else {
|
||||||
|
if (age > gridPowerDeltaOffDelay) {
|
||||||
|
gridPowerDeltaMillis = 0;
|
||||||
|
set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (gridPowerDeltaMillis > 0) {
|
||||||
|
Serial.printf("[%s] Powering off CANCELED!\n", name.c_str());
|
||||||
|
gridPowerDeltaMillis = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (gridPowerDelta < gridPowerDeltaOnThreshold) {
|
||||||
|
if (gridPowerDeltaMillis == 0) {
|
||||||
|
Serial.printf("[%s] PRODUCING TOO MUCH: Preparing to power ON...\n", name.c_str());
|
||||||
|
gridPowerDeltaMillis = max(1UL, millis());
|
||||||
|
} else {
|
||||||
|
if (age > gridPowerDeltaOnDelay) {
|
||||||
|
gridPowerDeltaMillis = 0;
|
||||||
|
set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (gridPowerDeltaMillis > 0) {
|
||||||
|
Serial.printf("[%s] Powering on CANCELED!\n", name.c_str());
|
||||||
|
gridPowerDeltaMillis = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
36
src/mqtt.cpp
36
src/mqtt.cpp
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "PubSubClient.h"
|
#include "PubSubClient.h"
|
||||||
|
|
||||||
|
const String GRID_POWER_DELTA_TOPIC = "electricity/grid/power/signed/w";
|
||||||
|
|
||||||
WiFiClient wifiClient;
|
WiFiClient wifiClient;
|
||||||
|
|
||||||
PubSubClient client(wifiClient);
|
PubSubClient client(wifiClient);
|
||||||
@ -13,10 +15,32 @@ bool mqttShouldConnect = false;
|
|||||||
|
|
||||||
unsigned long mqttLast = 0;
|
unsigned long mqttLast = 0;
|
||||||
|
|
||||||
|
unsigned long warningLast = 0;
|
||||||
|
|
||||||
void mqttSetup() {
|
void mqttSetup() {
|
||||||
mqttShouldConnect = true;
|
mqttShouldConnect = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double gridPowerDelta = NAN;
|
||||||
|
|
||||||
|
double gridPowerDeltaMillis = 0;
|
||||||
|
|
||||||
|
void mqttReceive(const char *topic, const uint8_t *bytes, const unsigned int length) {
|
||||||
|
if (length >= 100) {
|
||||||
|
Serial.println("[MQTT] Inbound buffer overflow");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char string[100];
|
||||||
|
memcpy(string, bytes, length);
|
||||||
|
const auto payload = String(string);
|
||||||
|
if (GRID_POWER_DELTA_TOPIC == topic) {
|
||||||
|
gridPowerDelta = payload.toDouble();
|
||||||
|
gridPowerDeltaMillis = millis();
|
||||||
|
} else {
|
||||||
|
Serial.printf("[MQTT] Received unexpected topic: %s\n", topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mqttLoop() {
|
void mqttLoop() {
|
||||||
if (client.loop()) {
|
if (client.loop()) {
|
||||||
if (!mqttShouldConnect) {
|
if (!mqttShouldConnect) {
|
||||||
@ -24,20 +48,22 @@ void mqttLoop() {
|
|||||||
Serial.println("[MQTT] Stopped.");
|
Serial.println("[MQTT] Stopped.");
|
||||||
}
|
}
|
||||||
} else if (mqttShouldConnect) {
|
} else if (mqttShouldConnect) {
|
||||||
const auto host = configRead("/mqtt/host", "", false);
|
const auto host = configRead("/mqtt/host", "10.0.0.50", false);
|
||||||
if (host == "") {
|
if (host == "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mqttLast == 0 || millis() - mqttLast >= 3000) {
|
if (mqttLast == 0 || millis() - mqttLast >= 3000) {
|
||||||
const auto id = configRead("/mqtt/id", "test", false);
|
const auto id = configRead("/mqtt/id", "test");
|
||||||
const auto user = configRead("/mqtt/user", "", false);
|
const auto user = configRead("/mqtt/user", "");
|
||||||
const auto pass = configRead("/mqtt/pass", "", false, true);
|
const auto pass = configRead("/mqtt/pass", "", true, true);
|
||||||
const auto port = configRead("/mqtt/port", 1883L, false);
|
const auto port = configRead("/mqtt/port", 1883L);
|
||||||
mqttLast = max(1UL, millis());
|
mqttLast = max(1UL, millis());
|
||||||
client.setServer(host.c_str(), port);
|
client.setServer(host.c_str(), port);
|
||||||
Serial.printf("[MQTT] Connecting: %s:%ld\n", host.c_str(), port);
|
Serial.printf("[MQTT] Connecting: %s:%ld\n", host.c_str(), port);
|
||||||
if (client.connect(id.c_str(), user.c_str(), pass.c_str())) {
|
if (client.connect(id.c_str(), user.c_str(), pass.c_str())) {
|
||||||
Serial.printf("[MQTT] Connected.\n");
|
Serial.printf("[MQTT] Connected.\n");
|
||||||
|
client.subscribe(GRID_POWER_DELTA_TOPIC.c_str());
|
||||||
|
client.setCallback(mqttReceive);
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("[MQTT] Failed to connect.\n");
|
Serial.printf("[MQTT] Failed to connect.\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
extern double gridPowerDelta;
|
||||||
|
|
||||||
|
extern double gridPowerDeltaMillis;
|
||||||
|
|
||||||
void mqttSetup();
|
void mqttSetup();
|
||||||
|
|
||||||
void mqttLoop();
|
void mqttLoop();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user