NEWS
[Skript] Viessmann Eigenverbrauch optimieren
-
Ursprünglich wollte ich nach der Inbetriebnahme unserer PV-Anlage mit Speicher in unserer Viessmann-Anlage die Eigenverbauchsoptimierung aktivieren. Allerdings gab es dabei gleich mehrere Probleme:
- Die Heizung scheint nicht korrekt mit dem verbauten KOSTAL Smart Energy Meter kommunizieren zu können
- Selbst wenn sie es könnte, scheint es so zu sein, dass der Zähler an anderer Position montiert sein müsste (Verbrauchsmessung exkl. Heizung), bei uns wird der gesamte Hausverbrauch gemessen.
Ich hatte keine Lust, noch einen weiteren Zähler von Viessmann installieren zu lassen, daher habe ich mir eine Lösung via Javascript überlegt, die mit dem Modbus-Adapter auf die Werte des KOSTAL Wechselrichters (und darüber auch den Smart Energy Meter) zugreift.
Benötigte Adapter:
- viessmannapi
- modbus
- javascript
if(existsState('javascript.0.heizung.dhw.lastrun') === false) { createState('heizung.dhw.lastrun', 0, {name: 'Letzter gestarteter Aufheizprozess', unit: '', type: 'number', role: 'value'}); } if(existsState('javascript.0.heizung.dhw.pvsince') === false) { createState('heizung.dhw.pvsince', 0, {name: 'Beginn des Überschusszeitraums', unit: '', type: 'number', role: 'value'}); } let low_power = 0; //* subscribe to changes in modbus value of inverter output on({ id: 'modbus.0.holdingRegisters.575_Wechselrichteroutput', change: "ne" }, function (obj) { let dc1 = getState('modbus.0.holdingRegisters.260_PV_Leistung 1').val; let dc2 = getState('modbus.0.holdingRegisters.270_PV_Leistung 2').val; //* calculate current overall PV power let pvpower = dc1 + dc2; //* get current battery power state of charging (+ for discharging, - for charging) let batt_charge = getState('modbus.0.holdingRegisters.582_Batterieladung').val; let batt_charge_signed = batt_charge; if(batt_charge > 0) { batt_charge = 0; } //* current home power consumption let house_usage = getState('modbus.0.holdingRegisters.252_Hausverbrauch').val; //* thereof provided by PV let house_from_pv = getState('modbus.0.holdingRegisters.116_Verbrauch_aus PV').val; //* current battery state of charge in percent let batt_soc = getState('modbus.0.holdingRegisters.514_Battery_SOC').val; let inv_output = obj.state.val; //* power adjusted by battery charge let pvpower_real = inv_output - batt_charge_signed; if(pvpower_real < 0) { pvpower_real = 0; } //* remaining power that possibly would be sent to grid let rest = pvpower + batt_charge - house_from_pv; let rest_real = rest - 40; //* half of battery charging power is ignored for calculation rest_real = rest - (batt_charge / 2); log('PV: ' + pvpower + " (" + pvpower_real + "), WR: " + inv_output + ", Charge: " + batt_charge + " (" + batt_charge_signed + ", " + batt_soc + "), House: " + house_from_pv + " (" + house_usage + "), Überschuss: " + rest + " (" + rest_real + ")", 'debug'); //* since when (timestamp) power is sent to grid let pv_plus_since = getState('javascript.0.heizung.dhw.pvsince').val let pv_plus_for = 0; if(rest_real > 200) { low_power = 0; if(!pv_plus_since) { setState('javascript.0.heizung.dhw.pvsince', (new Date()).getTime()); } else { //* how long (minutes) power is already sent to grid let curtime = (new Date()).getTime(); pv_plus_for = Math.round((curtime - pv_plus_since) / 1000 / 60); } } else if(low_power > 2) { //* low power for more than 2 loops, so reset the "since" timestamp setState('javascript.0.heizung.dhw.pvsince', 0); low_power = 0; } else { // no rest, so reset the timer if more than 2 times lower than needed low_power++; } //* if we have enough power generated for a long enough period if((pv_plus_for >= 5 || (pv_plus_for >= 2 && batt_soc > 85)) && rest_real > 400 && batt_soc > 50 && (batt_charge > -1000 || batt_soc > 66)) { //* check if warm water charging is currently active let dhw_active = getState('viessmannapi.0.heating.dhw.charging.active').val; if(!dhw_active) { //* check current warm water temperature let temp = getState('viessmannapi.0.heating.dhw.sensors.temperature.hotWaterStorage.top.value').val; let targetTemperature = 60; //* if we have enough power but not that much, we lower the warm water temp by 5°C if(rest_real < 1000 && batt_soc < 80) { targetTemperature = 55; } log('WW-Temperatur: ' + temp + '°C', 'debug'); //* if current temperature is less than 6°C below the desired temperature if(temp < targetTemperature - 6) { //* check if last charging was completed more than 10 minutes ago let last = getState('javascript.0.heizung.dhw.lastrun').val; let checkLast = new Date(); checkLast.setMinutes(checkLast.getMinutes() - 10); if(last < checkLast.getTime()) { //* if this is true the request for one time charging was not fulfilled by the heater let started = getState('viessmannapi.0.heating.dhw.oneTimeCharge.active').val; if(started) { log('Stoppe Warmwassergenerierung. Charge ist nicht "true".'); setState('javascript.0.heizung.dhw.lastrun', (new Date()).getTime()); sendTo('viessmannapi.0', 'action', { feature: 'heating.dhw.oneTimeCharge', action: 'deactivate', payload: {} }); } else { //* set new desired temperature and start charging now log('Starte Warmwassergenerierung.'); setState('javascript.0.heizung.dhw.lastrun', (new Date()).getTime()); let curTargetTemp = getState('viessmannapi.0.heating.dhw.temperature.temp2.value').val; if(curTargetTemp != targetTemperature) { sendTo('viessmannapi.0', 'action', { feature: 'heating.dhw.temperature.temp2', action: 'setTargetTemperature', payload: {temperature: targetTemperature} }); } sendTo('viessmannapi.0', 'action', { feature: 'heating.dhw.oneTimeCharge', action: 'activate', payload: {} }); } } else { log('Warmwassergenerierung nicht lang genug her (' + Math.round(((new Date()).getTime() - last) / 1000 / 60) + ').', 'debug'); } } } else { let temp = getState('viessmannapi.0.heating.dhw.sensors.temperature.hotWaterStorage.top.value').val; log('Warmwassergenerierung läuft bereits.', 'debug'); log('WW-Temperatur: ' + temp + '°C', 'debug'); } } else if(rest_real > 100 && pv_plus_for > 0 && pv_plus_for < 5) { log('PV Überschuss erst seit ' + pv_plus_for + ' Minute(n).', 'debug'); } }); //* subscribe on hot water charging state on({id: 'viessmannapi.0.heating.dhw.charging.active', change: 'ne'}, function(obj) { //* set last run marker (timestamp) on each state change if(obj.state.val == true) { log('Warmwassergenerierung gestartet.'); setState('javascript.0.heizung.dhw.lastrun', (new Date()).getTime()); } else { log('Warmwassergenerierung beendet.'); setState('javascript.0.heizung.dhw.lastrun', (new Date()).getTime()); //* reset target hot water temperature for one-time-charging to 55°C let targetTemp = getState('viessmannapi.0.heating.dhw.temperature.temp2.value').val; if(targetTemp > 55) { sendTo('viessmannapi.0', 'action', { feature: 'heating.dhw.temperature.temp2', action: 'setTargetTemperature', payload: {temperature: 55} }); } } });
Bin für Anmerkungen und Verbesserungsvorschläge offen