Meine Variante als JavaScript:
- Glättung zur Unterstützung von kurzeitigen Wolkenstand (alpha abhängig von Zykluszeit der Leistungsdaten)
- Mindestlaufzeit der Pumpe
- Reine Überschussregelng für Wärmepumpe
- Notifications bei Zustandsänderung
- Manuelle Steuerung bei Bedarf
Vielleicht hilfts wem, läuft jetzt seit ein paar Wochen sehr gut.
Sonnige Tage:
Viele Wolken:
// Übrige Leistung
const Grid = 'fronius.0.powerflow.P_Grid';
// Wärmepumpe
const WP_SwitchID = 'shelly.0.SHSW-PM#68C63AFAF6BC#1.Relay0.Switch';
const WP_Consumption = 1500;
const WP_Hysteresis = 1000;
// Pumpe
const P_SwitchID = 'shelly.0.SHSW-PM#68C63AFAF893#1.Relay0.Switch';
// Leistung der Pumpe
const P_Consumption = 250;
const P_Hysteresis = 100;
// Minuten am Tag, die sie mindestens laufen muss
const P_MinimumRuntime = 7*60
// Stunde wann sie frühestens starten soll
const P_MinStartTime = 9;
// Betriebsstundenzähler der Pumpe
const P_RuntimeID = 'hm-rpc.1.CUX9001001.1.TIME_ON_SUM';
// Variablen zum Speichern der Infos, dadurch kann man das Skript auch neustarten
const P_RuntimeStartTimeID = 'javascript.0.variables.PumpeStartTime';
const P_StartDayID = 'javascript.0.variables.PumpeStartDay';
// Variable für Glättung der Leistung
const GridEMAID = 'javascript.0.variables.P_Grid_EMA'
// Schalter um in den manuellen Modus zu wechseln
const Override_SwitchID = 'hm-rpc.1.CUX2801005.1.STATE';
// Notifications zum Handy
const PushObject = getIdByName('pocketControlPushMessage', true)[0];
function push(msg) {
log(msg);
setState(PushObject, msg);
}
var ema_grid_init = false;
var ema_grid = 0;
var alpha = 0.05;
function calcExponentialMovingAverage(accumulator, new_value, alpha) {
const new_avg = (alpha * new_value) + (1.0 - alpha) * accumulator;
return Math.round(new_avg * 100)/100;
};
on({id: Grid, change: 'any'}, (obj) => {
// Use last average as starting value if script was restarted
if(!ema_grid_init) {
ema_grid_init = true;
ema_grid = getState(GridEMAID).val;
} else {
ema_grid = calcExponentialMovingAverage(ema_grid, obj.state.val, alpha);
setState(GridEMAID, ema_grid);
}
const grid = ema_grid;
// Check if Manual Mode is enabled
if(getState(Override_SwitchID).val) {
return;
}
// Begin at minimumstarttime
if(new Date().getHours() < P_MinStartTime) {
return;
}
if(grid + P_Consumption + P_Hysteresis < 0) {
if(startPumpe()) {
push("[POOL] Pumpe EIN (" + grid + ")")
}
} else if(grid > 0) {
if(stopPumpe()) {
push("[POOL] Pumpe AUS (" + grid + ")");
}
}
if (grid + WP_Consumption + WP_Hysteresis < 0) {
if(startWP()) {
push("[POOL] Wärmepumpe EIN (" + grid + ")");
}
} else if (grid > 0) {
if(stopWP()) {
push("[POOL] Wärmepumpe AUS (" + grid + ")");
}
}
});
function startWP() {
const wpState = getState(WP_SwitchID).val;
if(wpState) {
// already running
return false;
}
// if Pumpe is stopped, return
const pState = getState(P_SwitchID).val;
if(!pState) {
push("[POOL] Wärmepumpe kann nicht gestartet werden, Pumpe läuft nicht");
return false;
}
setState(WP_SwitchID, true);
return true;
}
function stopWP() {
const wpState = getState(WP_SwitchID).val
if(!wpState) {
return false;
}
setState(WP_SwitchID, false);
return true;
}
function updateStartInfo() {
// check if it is the first time of the day we start the pumpe and store runtime infos
const lastStartDay = getState(P_StartDayID).val;
const currentDay = new Date().getDate();
if(lastStartDay !== currentDay) {
push("[POOL] Speichere Start Info für heute");
setState(P_StartDayID, currentDay);
setState(P_RuntimeStartTimeID, getState(P_RuntimeID).val)
}
}
function startPumpe() {
updateStartInfo();
// already started
const pState = getState(P_SwitchID).val
if(pState) {
return false;
}
// starte Pumpe
setState(P_SwitchID, true);
return true;
}
function stopPumpe() {
// if Pumpe already stopped, return
const pState = getState(P_SwitchID).val
if(!pState) {
return false;
}
// when WP is running, do not stop the pump
const wpStatus = getState(WP_SwitchID).val;
if(wpStatus) {
//push("[POOL] Pumpe kann nicht gestoppt werden, WP läuft noch");
return false;
}
// check if minimum runtime has exceeded
const runtime = getState(P_RuntimeID).val - getState(P_RuntimeStartTimeID).val;
if(runtime < P_MinimumRuntime) {
//push("[POOL] Pumpe hat Mindestlaufzeit noch nicht erreicht:" + runtime + "min/" + P_MinimumRuntime + "min");
return false;
}
// WP not running, but pump is
setState(P_SwitchID, false);
return true;
}