Kostal Plenticore 10 Plus
{{Infobox Hardware |Bild=|200px |Bildbeschreibung=Kostal Plenticore Plus mit BYD und KSEM |HWProtocol=IP |HWType=Hybrid Wechselrichter |HWCategory=Wechselrichter |HWVoltage=400 V |HWPoweredBy=3P AC |HWSize=39x67x45 cm (BxHxT) |HWComm=n/a |HWChannels=n/a |HWPowerConsumption=? |HWDeviceFHEM=[[HTTPMOD],[Modbus]] |HWManufacturer=Kostal GmbH }}
Achtung, diese Wiki Seite ist noch eine totale Baustelle :-) Momentan werden die Informationen noch aus den Threads im Forum hierher übertragen.
Der Kostal Plenticore 10 Plus [1] ist eine Hybrid Wechselrichter mit IP-Konnektivität.
Er verfügt über einen LAN-Anschluss und ist auf die Steuerung via WebGUI des Herstellers ausgelegt. Weiterhin kann eine Abfrage mit Modbus/TCP oder auch über eine undokumentierte API erfolgen. Für die API bietet der Hersteller keinerlei Support!
Voraussetzungen Energietechnik
Der Wechselrichter, der Speicher und der KSEM wurden durch einen Fachbetrieb installiert und konfiguriert. Die gesamte Anlage läuft fehlerfrei und wurde durch den Fachbetrieb abgenommen, sowie beim Netzbetreiber angemeldet.
Geräte-Registrierung
Hierfür ist die Dokumentation des Herstellers heranzuziehen. Für eine Verlängerung der Gewährleistungszeit kann man den Plenticore im Herstellerportal registrieren. Dies ist jedoch für die Anbindung an FHEM nicht notwendig.
Einbindung in das Netzwerk
Als Grundlage ist der Plenticore mit dem LAN zu verbinden, wodurch er eine TCP/IP Adresse per DHCP bekommt. Diese ist dann entweder am Display des Plenticore abzulesen, oder über die Oberfläche des Routers zu ermitteln.
Das gleiche gilt für den BYD Speicher, der jedoch zusätzlich auch über WLAN verfügt. Eine Netzwerkanbindung des Speichers ist beim Plenticore nicht zwingend notwendig, da der Plenticore mit dem Speicher über eine RS-485 Schnittstelle kommuniziert. Bei dieser Anbindung werden jedoch noch nicht alle möglichen Werte aus dem Speicher ausgelesen. Später wird hierzu jedoch noch mehr geschrieben, um alle Möglichkeiten offen zu halten.
Der KSEM kann ebenfalls auch direkt per LAN ausgelesen werden, was jedoch ebenfalls nicht zwingend notwendig ist. Eine Kommunikation des KSEM mit dem Plenticore erfolgt über zwei mögliche Wege. Beim Betrieb mit Speicher ist zwingend die RS485 Schnittstelle erforderlich, über die auch deer Plenticore alle Werte übermittelt bekommt. Auch diese sind dann am Plenticore abfragbar. Der zweite Weg wäre dann über die LAN Verbindung, bei der jedoch kein Speicher am Plenticore konfigurierbar ist.
Voraussetzungen FHEM Umfeld
Alle Geräte müssen mit TCP/IP erreichbar sein
Alle Module sollten auf einem aktuellen stand sein
Python
Ein Python 3 sollte vorhanden sein
Wenn man die erweiterten Funktionalitäten, wie Statistiken, Speicher auslesen und später auch das Setzen von Werten im Plenticore, verwenden möchte.
Es müssen folgende Python Module vorhanden sein
pip3 install pycryptodome pip3 install -U fhem
Eine LogDB/LogDBRep sollte bereits vorhanden sein, was hier nicht weiter erklärt wird.
Verwendete Module
- Modbus - HTTPMOD - expandJSON - LogDb - LogDbRep - dummy - Shelly - HourCounter - readingsGroup
Einbindung in FHEM: Überblick
Hardware Anbindung (alles über LAN)
Kostal Plenticore Plus
Kostal Plenticore Plus die Basis information (Modbus/TCP)
Der Kostal Plenticore wird mittels des Moduls MODBUS eingebunden. Dazu gilt zunächst die folgende Konfiguration als Basis, die am Display des Plenticore oder auch in der Kostal Dokumentation zu entnehmen ist.
Plenticore Modbus Definition
GeräteId : 71 IP-Adresse: <IP-Adresse> Port : 1502
Modbus Timing
Das Gerät aktualisiert sich im Abstand von 60 Sekunden durch den stetigen Modbus/TCP Datenstrom. Der Plenticore ist als Modbus Master implementiert und sendet somit alle Daten permanent ins Netzwerk. Die Zeit kann auch verändert werden, jedoch sollte sie nicht zu kurz gewählt sein.
RAW Definition des Wechselrichters
defmod PV_Anlage_1 ModbusAttr 71 60 192.168.178.18:1502 TCP attr PV_Anlage_1 DbLogExclude .* attr PV_Anlage_1 DbLogInclude Act_state_of_charge,Actual_battery_charge_-minus_or_discharge_-plus_Power,Actual_battery_charge_usable_Power,Battery_temperature,Home_own_consumption_from_PV,Home_own_consumption_from_battery,Home_own_consumption_from_grid,Inverter_state,Power_DC1,Power_DC2,Power_DC_Sum,Total_DC_Power,Total_DC_Power_Max,Total_PV_Power_reserve,Voltage_DC1,Voltage_DC2,.*_yield,Solar_.*,Statistic_.* attr PV_Anlage_1 alias PV_Einspeisung attr PV_Anlage_1 comment Kostal Plenticore 10 Plus mit BYD Speicher attr PV_Anlage_1 dev-h-defFormat %.2f attr PV_Anlage_1 dev-h-defLen 2 attr PV_Anlage_1 dev-h-defPoll 1 attr PV_Anlage_1 dev-h-defRevRegs 1 attr PV_Anlage_1 dev-h-defUnpack f> attr PV_Anlage_1 dev-type-STR-format %s attr PV_Anlage_1 dev-type-STR-len 8 attr PV_Anlage_1 dev-type-STR-revRegs 0 attr PV_Anlage_1 dev-type-STR-unpack a* attr PV_Anlage_1 event-on-change-reading statistics_.*,Statistic_.*,Act_state_of_charge,Actual_battery_charge_.*,Battery_temperature,Home_own_consumption_from_.*,Inverter_state,Power_DC1,Power_DC2,Power_DC_Sum,Total_DC_Power,Total_DC_Power_Max,Total_PV_Power_reserve,Voltage_DC1,Voltage_DC2,.*_yield,Solar_.* attr PV_Anlage_1 group PV Eigenverbrauch attr PV_Anlage_1 icon sani_solar attr PV_Anlage_1 obj-h100-reading Total_DC_Power attr PV_Anlage_1 obj-h104-format %s attr PV_Anlage_1 obj-h104-reading State_of_energy_manager attr PV_Anlage_1 obj-h104-revRegs 0 attr PV_Anlage_1 obj-h104-unpack N attr PV_Anlage_1 obj-h106-reading Home_own_consumption_from_battery attr PV_Anlage_1 obj-h108-reading Home_own_consumption_from_grid attr PV_Anlage_1 obj-h110-reading Total_home_consumption_Battery attr PV_Anlage_1 obj-h112-reading Total_home_consumption_Grid attr PV_Anlage_1 obj-h114-reading Total_home_consumption_PV attr PV_Anlage_1 obj-h116-reading Home_own_consumption_from_PV attr PV_Anlage_1 obj-h118-reading Total_home_consumption attr PV_Anlage_1 obj-h120-reading Isolation_resistance attr PV_Anlage_1 obj-h122-reading Power_limit_from_EVU attr PV_Anlage_1 obj-h124-reading Total_home_consumption_rate attr PV_Anlage_1 obj-h14-reading Inverter_serial_number attr PV_Anlage_1 obj-h14-type STR attr PV_Anlage_1 obj-h144-reading Worktime attr PV_Anlage_1 obj-h150-reading Actual_cos_phi attr PV_Anlage_1 obj-h152-reading Grid_frequency attr PV_Anlage_1 obj-h154-reading Current_Phase_1 attr PV_Anlage_1 obj-h156-reading Active_power_Phase_1 attr PV_Anlage_1 obj-h158-reading Voltage_Phase_1 attr PV_Anlage_1 obj-h160-reading Current_Phase_2 attr PV_Anlage_1 obj-h162-reading Active_power_Phase_2 attr PV_Anlage_1 obj-h164-reading Voltage_Phase_2 attr PV_Anlage_1 obj-h166-reading Current_Phase_3 attr PV_Anlage_1 obj-h168-reading Active_power_Phase_3 attr PV_Anlage_1 obj-h170-reading Voltage_Phase_3 attr PV_Anlage_1 obj-h172-reading Total_AC_active_power attr PV_Anlage_1 obj-h174-reading Total_AC_reactive_power attr PV_Anlage_1 obj-h178-reading Total_AC_apparent_power attr PV_Anlage_1 obj-h190-reading Battery_charge_current attr PV_Anlage_1 obj-h194-format %.0f attr PV_Anlage_1 obj-h194-reading Number_of_battery_cycles attr PV_Anlage_1 obj-h200-reading Actual_battery_charge_-minus_or_discharge_-plus_current attr PV_Anlage_1 obj-h202-reading PSSB_fuse_state attr PV_Anlage_1 obj-h208-format %.0f attr PV_Anlage_1 obj-h208-reading Battery_ready_flag attr PV_Anlage_1 obj-h210-reading Act_state_of_charge attr PV_Anlage_1 obj-h212-reading Battery_state attr PV_Anlage_1 obj-h214-reading Battery_temperature attr PV_Anlage_1 obj-h216-reading Battery_voltage attr PV_Anlage_1 obj-h218-reading Cos_phi_(powermeter) attr PV_Anlage_1 obj-h220-reading Frequency_(powermeter) attr PV_Anlage_1 obj-h222-reading Current_phase_1_(powermeter) attr PV_Anlage_1 obj-h224-reading Active_power_phase_1_(powermeter) attr PV_Anlage_1 obj-h226-reading Reactive_power_phase_1_(powermeter) attr PV_Anlage_1 obj-h228-reading Apparent_power_phase_1_(powermeter) attr PV_Anlage_1 obj-h230-reading Voltage_phase_1_(powermeter) attr PV_Anlage_1 obj-h232-reading Current_phase_2_(powermeter) attr PV_Anlage_1 obj-h234-reading Active_power_phase_2_(powermeter) attr PV_Anlage_1 obj-h236-reading Reactive_power_phase_2_(powermeter) attr PV_Anlage_1 obj-h238-reading Apparent_power_phase_2_(powermeter) attr PV_Anlage_1 obj-h240-reading Voltage_phase_2_(powermeter) attr PV_Anlage_1 obj-h242-reading Current_phase_3_(powermeter) attr PV_Anlage_1 obj-h244-reading Active_power_phase_3_(powermeter) attr PV_Anlage_1 obj-h246-reading Reactive_power_phase_3_(powermeter) attr PV_Anlage_1 obj-h248-reading Apparent_power_phase_3_(powermeter) attr PV_Anlage_1 obj-h250-reading Voltage_phase_3_(powermeter) attr PV_Anlage_1 obj-h252-reading Total_active_power_(powermeter) attr PV_Anlage_1 obj-h254-reading Total_reactive_power_(powermeter) attr PV_Anlage_1 obj-h256-reading Total_apparent_power_(powermeter) attr PV_Anlage_1 obj-h258-reading Current_DC1 attr PV_Anlage_1 obj-h260-reading Power_DC1 attr PV_Anlage_1 obj-h266-reading Voltage_DC1 attr PV_Anlage_1 obj-h268-reading Current_DC2 attr PV_Anlage_1 obj-h270-reading Power_DC2 attr PV_Anlage_1 obj-h276-reading Voltage_DC2 attr PV_Anlage_1 obj-h278-reading Current_DC3 attr PV_Anlage_1 obj-h280-reading Power_DC3 attr PV_Anlage_1 obj-h286-reading Voltage_DC3 attr PV_Anlage_1 obj-h320-reading Total_yield attr PV_Anlage_1 obj-h322-reading Daily_yield attr PV_Anlage_1 obj-h324-reading Yearly_yield attr PV_Anlage_1 obj-h326-reading Monthly_yield attr PV_Anlage_1 obj-h38-reading Software-Version_Maincontroller_(MC) attr PV_Anlage_1 obj-h38-type STR attr PV_Anlage_1 obj-h384-len 16 attr PV_Anlage_1 obj-h384-reading Inverter_network_name attr PV_Anlage_1 obj-h384-type STR attr PV_Anlage_1 obj-h420-reading IP-address attr PV_Anlage_1 obj-h420-type STR attr PV_Anlage_1 obj-h428-reading IP-subnetmask attr PV_Anlage_1 obj-h428-type STR attr PV_Anlage_1 obj-h436-reading IP-gateway attr PV_Anlage_1 obj-h436-type STR attr PV_Anlage_1 obj-h446-reading IP-DNS1 attr PV_Anlage_1 obj-h446-type STR attr PV_Anlage_1 obj-h454-reading IP-DNS2 attr PV_Anlage_1 obj-h454-type STR attr PV_Anlage_1 obj-h46-reading Software-Version_IO-Controller_(IOC) attr PV_Anlage_1 obj-h46-type STR attr PV_Anlage_1 obj-h514-len 1 attr PV_Anlage_1 obj-h514-reading Battery_actual_SOC attr PV_Anlage_1 obj-h517-reading Battery_Manufacturer attr PV_Anlage_1 obj-h517-type STR attr PV_Anlage_1 obj-h525-format %c attr PV_Anlage_1 obj-h525-reading Battery_Model_ID attr PV_Anlage_1 obj-h525-unpack N attr PV_Anlage_1 obj-h527-format %c attr PV_Anlage_1 obj-h527-reading Battery_Serial_Number attr PV_Anlage_1 obj-h529-len 4 attr PV_Anlage_1 obj-h529-reading Work_Capacity attr PV_Anlage_1 obj-h529-unpack N attr PV_Anlage_1 obj-h531-format %.0f attr PV_Anlage_1 obj-h531-reading Inverter_Max_Power attr PV_Anlage_1 obj-h531-unpack N attr PV_Anlage_1 obj-h535-revRegs 0 attr PV_Anlage_1 obj-h535-unpack n attr PV_Anlage_1 obj-h551-revRegs 0 attr PV_Anlage_1 obj-h559-revRegs 0 attr PV_Anlage_1 obj-h56-format %.0f attr PV_Anlage_1 obj-h56-reading Inverter_state attr PV_Anlage_1 obj-h56-unpack N attr PV_Anlage_1 obj-h575-len 1 attr PV_Anlage_1 obj-h575-reading Inverter_Generation_Power_(actual) attr PV_Anlage_1 obj-h577-len 2 attr PV_Anlage_1 obj-h577-reading Generation_Energy attr PV_Anlage_1 obj-h577-unpack N attr PV_Anlage_1 obj-h578-reading Total_energy attr PV_Anlage_1 obj-h582-reading Actual_battery_charge-discharge_power attr PV_Anlage_1 obj-h586-format %s attr PV_Anlage_1 obj-h586-reading Battery_Firmware attr PV_Anlage_1 obj-h586-unpack N attr PV_Anlage_1 obj-h588-format %s attr PV_Anlage_1 obj-h588-len 1 attr PV_Anlage_1 obj-h588-reading Battery_Type attr PV_Anlage_1 obj-h588-unpack N attr PV_Anlage_1 obj-h6-reading Inverter_article_number attr PV_Anlage_1 obj-h6-type STR attr PV_Anlage_1 obj-h768-len 32 attr PV_Anlage_1 obj-h768-reading Productname attr PV_Anlage_1 obj-h768-type STR attr PV_Anlage_1 obj-h800-len 32 attr PV_Anlage_1 obj-h800-reading Power_class attr PV_Anlage_1 obj-h800-type STR attr PV_Anlage_1 room Strom->Photovoltaik attr PV_Anlage_1 sortby 01 attr PV_Anlage_1 stateFormat {sprintf("\ <TABLE>\ \ <TR>\ <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">Batterie %s</TH>\ <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">aktuell</TH>\ <TH ALIGN=\"RIGHT\" WIDTH=\"20\">Hausverbrauch</TH>\ <TH ALIGN=\"MIDDLE\" WIDTH=\"20\">Erträge</TH>\ </TR>\ \ <TR>\ <TD ALIGN=\"MIDDLE\" WIDTH=\"20\">\ Leistung: %04d W<br>\ Temp.: %02.1f °C<br>\ Ladung total: %2d %%<br>\ Ladung Res.: %04d Wh\ </TD>\ \ <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\ DC total: %05d W<br>\ <br>\ <br>\ PV reserve: %05d W\ </TD>\ \ <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\ von PV: %05d W <br>\ von Batterie: %05d W<br>\ vom Netz: %05d W<br>\ ins Haus: %05d W<br>\ Netz: %05d W\ </TD>\ \ <TD ALIGN=\"RIGHT\" WIDTH=\"20\">\ Tag: %05d KWh <br>\ Monat: %05d KWh<br>\ Jahr: %05d KWh<br>\ Total: %05d KWh\ </TD>\ </TR>\ \ </TABLE>\ " , \ (ReadingsVal($name,"Actual_battery_charge_-minus_or_discharge_-plus_Power",0) lt 0) ? "<span style='color:#00FF00'>Laden</span>":"<span style='color:#FF0000'>Entladen</span>" ,\ \ ReadingsVal($name,"Actual_battery_charge_-minus_or_discharge_-plus_Power",0),\ ReadingsVal($name,"Battery_temperature",0) ,\ ReadingsVal($name,"Act_state_of_charge",0) ,\ ReadingsVal($name,"Actual_battery_charge_usable_Power",0) ,\ \ ReadingsVal($name,"Power_DC_Sum","0"),\ ReadingsVal($name,"Total_PV_Power_reserve","0"),\ \ ReadingsVal($name,"Home_own_consumption_from_PV",0) ,\ ReadingsVal($name,"Home_own_consumption_from_battery",0) ,\ ReadingsVal($name,"Home_own_consumption_from_grid",0),\ ReadingsVal($name,"Home_own_consumption_from_PV",0) +ReadingsVal($name,"Home_own_consumption_from_battery",0)+ReadingsVal($name,"Home_own_consumption_from_grid",0),\ ReadingsVal($name,"Total_active_power_(powermeter)",0),\ \ round(ReadingsVal($name,"Daily_yield",0)/1000 ,0),\ round(ReadingsVal($name,"Monthly_yield",0)/1000 ,0) ,\ round(ReadingsVal($name,"Yearly_yield",0)/1000 ,0) ,\ round(ReadingsVal($name,"Total_yield",0)/1000 ,0)\ )} attr PV_Anlage_1 userReadings Power_DC_Sum:Total_DC_Power.* { ReadingsVal($NAME,"Power_DC1","0")+ReadingsVal($NAME,"Power_DC2","0") },\ \ Total_PV_Power_reserve:Total_DC_Power.* {my $reserve = ReadingsVal($NAME,"Power_DC_Sum","0") * 0.90 - ReadingsVal($NAME,"Home_own_consumption_from_PV","0");;;; ($reserve lt 0)?0:round($reserve,3) },\ \ Total_DC_Power_Max:Total_DC_Power.* { my $Bat_out = (ReadingsVal($NAME,"Actual_battery_charge_-minus_or_discharge_-plus_current","0")*ReadingsVal($NAME,"Battery_voltage","0"));;;; ($Bat_out gt 0)?ReadingsVal($NAME,"Power_DC_Sum","0") + $Bat_out :ReadingsVal($NAME,"Power_DC_Sum","0") },\ \ Actual_battery_charge_-minus_or_discharge_-plus_Power:Actual_battery_charge_-minus_or_discharge_-plus_current.* {round((ReadingsVal($NAME,"Actual_battery_charge_-minus_or_discharge_-plus_current","0")*ReadingsVal($NAME,"Battery_voltage","0")),0)},\ \ Actual_battery_charge_usable_Power:Act_state_of_charge.* {my $x = (8960*(ReadingsVal($NAME,"Act_state_of_charge","0")-10)/100);;;; ($x lt 0)?0:round($x,0) },\ \ Solar_SolarRadiation:Total_DC_Power.* { my $x1 = POSIX::strftime("%Y-%m-%d_%H_00_Rad1wh",localtime(time-60*60)) ;;;; my $x2 = POSIX::strftime("%Y-%m-%d_%H_00_Rad1wh",localtime()) ;;;; my $x_avg = round((ReadingsVal("DWD_Prognose",$x1,0)+ReadingsVal("DWD_Prognose",$x2,0))/2 , 0) ;;;; my $time = POSIX::strftime("%M",localtime()) ;;;; ($time < 30)?ReadingsVal("DWD_Prognose",$x1,0):$x_avg },\ \ statistics_clean:statistics_output.* { my $x = ReadingsVal($NAME,"statistics_output",0);;;; $x =~ s/"moduleid": "scb:statistic:EnergyFlow", |, "moduleid": "scb:statistic:EnergyFlow"|"processdata": \[//g;;;; $x =~ s/id": "|, "unit": "", "value"|^\[|\]\}\]$//g;;;; $x =~ s/moduleid/statistics_00_moduleid/g;;;; $x =~ s/processdata/statistics/g;;;; $x =~ s/\}\, \{/\, /g;;;; $x =~ s/\{\{/\{/g;;;; return $x } attr PV_Anlage_1 verbose 0 <pre> ====== Userreadings ====== Um später einige Abfragen und Diagramme einfacher zu erstellen wurden einige userreadings erstellt, die bereits bei der RAW Definition mit vorhanden sind. Während der Integration in FHEM und der Konfiguration kann es hierdurch jedoch noch Fehlermeldungen im FHEM Log geben, da noch nicht alle Werte vorhanden sind. Dies betrifft insbesondere die Statistics_* readings, die durch ein Python Skript später erzeugt werden. Power_DC_Sum Trigger: Total_DC_Power.* Dies berechnet direkt die Summe der DC-Leistung. Wenn der Plenticore einen Speicher hat, wird dieser am String 3 angeschlossen, sollte also kein Speicher vorhanden sein muss man hier den dritten String auch noch addieren. Total_PV_Power_reserve Trigger: Total_DC_Power.* Hier wird ein reading erstellt, dass als Information über die verwendbare Reserve dient. Die Leistung, die in den Speicher geht sollte man nämlich besser sofort verbrauchen, anstatt es erst zu speicher. Die 0.90 ist ein circa Wirkungsgrad, um von DC- auf AC-Leistung zu kommen. Der Total_PV_Power_reserve Wert kann gerne nach eigenen Belangen kalkuliert werden. Total_DC_Power_Max Trigger: Total_DC_Power.* Um die Batterieleistung mit zu berücksichtigen wird dieser Momentan Wert ermittelt. Actual_battery_charge_-minus_or_discharge_-plus_Power Trigger: Actual_battery_charge_-minus_or_discharge_-plus_current.* Berechnung der Batterie Leistung aus Spannung und Strom , der wert kann positiv oder negativ sein, je nach dem ob geladen oder entladen wird. Actual_battery_charge_usable_Power Trigger: Act_state_of_charge.* Dieser Wert gibt an, wieviel Leistung im Speicher vorhanden ist, reduziert um 10% Verluste. An dieser Stelle muss die Nennleistung des Speichers eingetragen werden, da diese noch nicht ausgelesen werden kann. Obwohl es im "Battery_Type 892941625" stecken könnte. 8929 >> 8.93 KW ??? Solar_SolarRadiation Trigger: Total_DC_Power.* Wer noch keine Wetter prognose verwendet kann dieses reading entfernen. Das wird später noch behandelt. statistics_clean Trigger: statistics_output.* Dies ist ein temporäres reading, das nur als zwischen Schritt für die Erstellung der Statistics_* readings verwendet wird. Befüllt wird zuerst das reading statistics_output durch ein regelmäßig laufendes Python Skript. Wer keine Statistiken haben möchte kann das einfach entfernen. statistics_output Trigger: externes Python Skript Das userreading wird über ein Python Skript mit Daten gefüllt und dient als Trigger für statistics_clean
statistics_clean in readings umwandeln
Die Statistiken des Plenticore werden über ein Python Skript in das reading statistics_output geschrieben. Durch ein userreading wird daraus das JSON vereinfacht und in statistics_claen übertragen. Im letzten Schritt wandelt das expandJSON den JSON String in einzelne readings um.
defmod Plenticore_Statistics expandJSON PV_Anlage_1:statistics_clean:.\{.*} attr Plenticore_Statistics DbLogExclude .* attr Plenticore_Statistics alias Plenticore_Statistics attr Plenticore_Statistics comment Das Device wird über ein Python Skript im reading output befüllt.\ attr Plenticore_Statistics disable 0 attr Plenticore_Statistics room Strom->Photovoltaik
Kostal Plenticore Plus die Statistiken (über Python Skript)
Die Statistiken des Plenticore sind noch eine Zusatzinformation, die nicht über Modbus/TCP übermittelt wird. Diese lassen sich nur über die API des Plenticore abfragen.
Plenticore API
http://<IP-Address_Plenticore/api/v1
Dateiverzeichnis
/opt/fhem /opt/fhem/python/pwd_fhem.json /opt/fhem/python/pwd_plenticore.json /opt/fhem/python/bin /opt/fhem/python/bin/plenticore_statistic.py
Python 3
fhem@raspberrypi:~/python/bin$ which python3 /usr/bin/python3 fhem@raspberrypi:~/python/bin$ python3 --version Python 3.7.3
plenticore_statistic.py
fhem@raspberrypi:~/python/bin$ cat plenticore_statistic.py
import random import string import base64 import json import requests import hashlib import os import hmac from Crypto.Cipher import AES import binascii import fhem import asyncio import sys plenticore = sys.argv[1] web = sys.argv[2] request = '/processdata/scb:statistic:EnergyFlow' try: with open('/opt/fhem/python/pwd_plenticore.json', 'r') as f: credentials=json.load(f) except Exception as e: print('Something went wrong: {}'.format(e)) USER_TYPE = credentials["username"] PASSWD = credentials["password"] BASE_URL = "http://" + plenticore + "/api/v1" AUTH_START = "/auth/start" AUTH_FINISH = "/auth/finish" AUTH_CREATE_SESSION = "/auth/create_session" ME = "/auth/me" def randomString(stringLength): letters = string.ascii_letters return ''.join(random.choice(letters) for i in range(stringLength))'' u = randomString(12) u = base64.b64encode(u.encode('utf-8')).decode('utf-8') step1 = { "username": USER_TYPE, "nonce": u } step1 = json.dumps(step1) url = BASE_URL + AUTH_START headers = {'Content-type': 'application/json', 'Accept': 'application/json'} response = requests.post(url, data=step1, headers=headers) response = json.loads(response.text) i = response['nonce'] e = response['transactionId'] o = response['rounds'] a = response['salt'] bitSalt = base64.b64decode(a) def getPBKDF2Hash(password, bytedSalt, rounds): return hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), bytedSalt, rounds) r = getPBKDF2Hash(PASSWD,bitSalt,o) s = hmac.new(r, "Client Key".encode('utf-8'), hashlib.sha256).digest() c = hmac.new(r, "Server Key".encode('utf-8'), hashlib.sha256).digest() _ = hashlib.sha256(s).digest() d = "n=user,r="+u+",r="+i+",s="+a+",i="+str(o)+",c=biws,r="+i g = hmac.new(_, d.encode('utf-8'), hashlib.sha256).digest() p = hmac.new(c, d.encode('utf-8'), hashlib.sha256).digest() f = bytes(a ^ b for (a, b) in zip(s, g)) proof = base64.b64encode(f).decode('utf-8') step2 = { "transactionId": e, "proof": proof } step2 = json.dumps(step2) url = BASE_URL + AUTH_FINISH headers = {'Content-type': 'application/json', 'Accept': 'application/json'} response = requests.post(url, data=step2, headers=headers) response = json.loads(response.text) token = response['token'] signature = response['signature'] y = hmac.new(_, "Session Key".encode('utf-8'), hashlib.sha256) y.update(d.encode('utf-8')) y.update(s) P = y.digest() protocol_key = P t = os.urandom(16) e2 = AES.new(protocol_key,AES.MODE_GCM,t) e2, authtag = e2.encrypt_and_digest(token.encode('utf-8')) step3 = { "transactionId": e, "iv": base64.b64encode(t).decode('utf-8'), "tag": base64.b64encode(authtag).decode("utf-8"), "payload": base64.b64encode(e2).decode('utf-8') } step3 = json.dumps(step3) headers = { 'Content-type': 'application/json', 'Accept': 'application/json' } url = BASE_URL + AUTH_CREATE_SESSION response = requests.post(url, data=step3, headers=headers) response = json.loads(response.text) sessionId = response['sessionId'] #create a new header with the new Session-ID for all further requests headers = { 'Content-type': 'application/json', 'Accept': 'application/json', 'authorization': "Session " + sessionId } url = BASE_URL + ME response = requests.get(url = url, headers = headers) response = json.loads(response.text) authOK = response['authenticated'] if not authOK: print("authorization NOT OK") sys.exit() url = BASE_URL + "/info/version" response = requests.get(url = url, headers = headers) response = json.loads(response.text) swversion = response['sw_version'] apiversion = response['api_version'] hostname = response['hostname'] name = response['name'] print("Connected to the inverter " + name + "/" + hostname + " with SW-Version " + swversion + " and API-Version " + apiversion) # Auth OK, now send your desired requests url = BASE_URL + request response = requests.get(url = url, headers = headers) response = json.loads(response.text) message = json.dumps(response) #print(json.dumps(response, indent=4, sort_keys=True)) #print(message) async def run(): try: with open('/opt/fhem/python/pwd_fhem.json', 'r') as f: credentials=json.load(f) except Exception as e: print('Something went wrong: {}'.format(e)) fh = fhem.Fhem(web, protocol="http", port=8083, username=credentials["username"], password=credentials["password"]) fh.send_cmd("setreading PV_Anlage_1 statistics_output " + message) asyncio.get_event_loop().run_until_complete(run())
Userreadings
Die userreadings gehören zum Gerät PV_Anlage_1 .
statistics_output
Trigger: externes Python Skript Das Python Skript beschreibt im Gerät PV_Anlage_1 das reading statistics_output, das dort dann weiterverarbeitet wird.
Passworte
Die Passworte für den Plenticore und den FHEM Zugang liegen in einzelnen JSON Dateien
fhem@raspberrypi:~/python$ cat pwd_plenticore.json
{ "username": "user", "password": "<Steht auf dem Gehäuse>" }
fhem@raspberrypi:~/python$ cat pwd_fhem.json
{ "username": "<Ein Fhem Telnet User>", "password": "<Das Passwort des Users>" }
Kostal Smart Energy Manager (KSEM) (Modbus/TCP)
Diese Einbindung ist nicht zwingend notwendig, jedoch weil es möglich ist hier beschrieben. Das Gerät ist hier mit "disable 1" konfiguriert, um es zu verwenden muss das Attribut auf 0 gesetzt oder einfach gelöscht werden.
Auch hier ist ein Interval von 60 Sekunden gesetzt worden. Das Logging ist noch komplett deaktiviert, weshalb man seine Werte noch selber definieren muss.
RAW Definition des KSEM
defmod PV_KSEM ModbusAttr 1 60 192.168.178.17:502 TCP attr PV_KSEM DbLogExclude .* attr PV_KSEM alias PV_Energy_Manager attr PV_KSEM comment Der KSEM ermittelt nicht alle Werte, welche in der SunSpec spezifiziert sind.\ Alle nicht unterstützen Werte sind mit 0x8000 gekennzeichnet.\ Für die nicht unterstützten Zählerstände wird die 0x800000000 ausgegeben.\ \ Der Summenstrom M_AC_Current (sum of active phases) kann aber durch den Endanwender selber\ berechnet werden aus der Summe der Einzelwerte (Phase A AC current, Phase B AC current Phase C AC current)\ \ Die einzelnen Spannungen zwischen den Phasen können nicht gemessen werden und werden deshalb nicht ausgegeben. attr PV_KSEM dev-h-defPoll 1 attr PV_KSEM dev-type-INT16-len 1 attr PV_KSEM dev-type-INT16-unpack s> attr PV_KSEM dev-type-INT16_Current-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_Current_SF",0)) attr PV_KSEM dev-type-INT16_Current-format %.2f attr PV_KSEM dev-type-INT16_Current-len 1 attr PV_KSEM dev-type-INT16_Current-unpack s> attr PV_KSEM dev-type-INT16_Freq-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_Freq_SF",0)) attr PV_KSEM dev-type-INT16_Freq-format %.2f attr PV_KSEM dev-type-INT16_Freq-len 1 attr PV_KSEM dev-type-INT16_Freq-unpack s> attr PV_KSEM dev-type-INT16_PF-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_PF_SF",0)) attr PV_KSEM dev-type-INT16_PF-format %.2f attr PV_KSEM dev-type-INT16_PF-len 1 attr PV_KSEM dev-type-INT16_PF-unpack s> attr PV_KSEM dev-type-INT16_Power-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_Power_SF",0)) attr PV_KSEM dev-type-INT16_Power-format %.2f attr PV_KSEM dev-type-INT16_Power-len 1 attr PV_KSEM dev-type-INT16_Power-unpack s> attr PV_KSEM dev-type-INT16_VA-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_VA_SF",0)) attr PV_KSEM dev-type-INT16_VA-format %.2f attr PV_KSEM dev-type-INT16_VA-len 1 attr PV_KSEM dev-type-INT16_VA-unpack s> attr PV_KSEM dev-type-INT16_VAR-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_VAR_SF",0)) attr PV_KSEM dev-type-INT16_VAR-format %.2f attr PV_KSEM dev-type-INT16_VAR-len 1 attr PV_KSEM dev-type-INT16_VAR-unpack s> attr PV_KSEM dev-type-INT16_Voltage-expr $val * (10 ** ReadingsNum("$name" ,"M_AC_Voltage_SF",0)) attr PV_KSEM dev-type-INT16_Voltage-format %.2f attr PV_KSEM dev-type-INT16_Voltage-len 1 attr PV_KSEM dev-type-INT16_Voltage-unpack s> attr PV_KSEM dev-type-STR32-expr $val =~ s/[\00]+//gr attr PV_KSEM dev-type-STR32-format %s attr PV_KSEM dev-type-STR32-len 16 attr PV_KSEM dev-type-STR32-unpack a* attr PV_KSEM dev-type-UINT16-format %s attr PV_KSEM dev-type-UINT16-len 1 attr PV_KSEM dev-type-UINT32-format %s attr PV_KSEM dev-type-UINT32-len 2 attr PV_KSEM dev-type-UINT64-expr $val/10000 attr PV_KSEM dev-type-UINT64-format %s attr PV_KSEM dev-type-UINT64-len 4 attr PV_KSEM dev-type-UINT64-unpack Q> attr PV_KSEM disable 1 attr PV_KSEM group PV Eigenverbrauch attr PV_KSEM icon measure_power attr PV_KSEM obj-h40072-reading M_AC_Current_A attr PV_KSEM obj-h40072-type INT16_Current attr PV_KSEM obj-h40073-reading M_AC_Current_B attr PV_KSEM obj-h40073-type INT16_Current attr PV_KSEM obj-h40074-reading M_AC_Current_C attr PV_KSEM obj-h40074-type INT16_Current attr PV_KSEM obj-h40075-reading M_AC_Current_SF attr PV_KSEM obj-h40075-type INT16 attr PV_KSEM obj-h40077-reading M_AC_Voltage_AN attr PV_KSEM obj-h40077-type INT16_Voltage attr PV_KSEM obj-h40078-reading M_AC_Voltage_BN attr PV_KSEM obj-h40078-type INT16_Voltage attr PV_KSEM obj-h40079-reading M_AC_Voltage_CN attr PV_KSEM obj-h40079-type INT16_Voltage attr PV_KSEM obj-h40084-reading M_AC_Voltage_SF attr PV_KSEM obj-h40084-type INT16 attr PV_KSEM obj-h40085-reading M_AC_Freq attr PV_KSEM obj-h40085-type INT16_Freq attr PV_KSEM obj-h40086-reading M_AC_Freq_SF attr PV_KSEM obj-h40086-type INT16 attr PV_KSEM obj-h40087-reading M_AC_Power attr PV_KSEM obj-h40087-type INT16_Power attr PV_KSEM obj-h40088-reading M_AC_Power_A attr PV_KSEM obj-h40088-type INT16_Power attr PV_KSEM obj-h40089-reading M_AC_Power_B attr PV_KSEM obj-h40089-type INT16_Power attr PV_KSEM obj-h40090-reading M_AC_Power_C attr PV_KSEM obj-h40090-type INT16_Power attr PV_KSEM obj-h40091-reading M_AC_Power_SF attr PV_KSEM obj-h40091-type INT16 attr PV_KSEM obj-h40092-reading M_AC_VA attr PV_KSEM obj-h40092-type INT16_VA attr PV_KSEM obj-h40093-reading M_AC_VA_A attr PV_KSEM obj-h40093-type INT16_VA attr PV_KSEM obj-h40094-reading M_AC_VA_B attr PV_KSEM obj-h40094-type INT16_VA attr PV_KSEM obj-h40095-reading M_AC_VA_C attr PV_KSEM obj-h40095-type INT16_VA attr PV_KSEM obj-h40096-reading M_AC_VA_SF attr PV_KSEM obj-h40096-type INT16 attr PV_KSEM obj-h40097-reading M_AC_VAR attr PV_KSEM obj-h40097-type INT16_VAR attr PV_KSEM obj-h40098-reading M_AC_VAR_A attr PV_KSEM obj-h40098-type INT16_VAR attr PV_KSEM obj-h40099-reading M_AC_VAR_B attr PV_KSEM obj-h40099-type INT16_VAR attr PV_KSEM obj-h40100-reading M_AC_VAR_C attr PV_KSEM obj-h40100-type INT16_VAR attr PV_KSEM obj-h40101-reading M_AC_VAR_SF attr PV_KSEM obj-h40101-type INT16 attr PV_KSEM obj-h40102-reading M_AC_PF attr PV_KSEM obj-h40102-type INT16_PF attr PV_KSEM obj-h40103-reading M_AC_PF_A attr PV_KSEM obj-h40103-type INT16_PF attr PV_KSEM obj-h40104-reading M_AC_PF_B attr PV_KSEM obj-h40104-type INT16_PF attr PV_KSEM obj-h40105-reading M_AC_PF_C attr PV_KSEM obj-h40105-type INT16_PF attr PV_KSEM obj-h40106-reading M_AC_PF_SF attr PV_KSEM obj-h40106-type INT16 attr PV_KSEM obj-h40108-reading M_Exported attr PV_KSEM obj-h40108-type UINT32 attr PV_KSEM obj-h40110-reading M_Exported_A attr PV_KSEM obj-h40110-type UINT32 attr PV_KSEM obj-h40112-reading M_Exported_B attr PV_KSEM obj-h40112-type UINT32 attr PV_KSEM obj-h40114-reading M_Exported_C attr PV_KSEM obj-h40114-type UINT32 attr PV_KSEM obj-h40116-reading M_Imported attr PV_KSEM obj-h40116-type UINT32 attr PV_KSEM obj-h40118-reading M_Imported_A attr PV_KSEM obj-h40118-type UINT32 attr PV_KSEM obj-h40120-reading M_Imported_B attr PV_KSEM obj-h40120-type UINT32 attr PV_KSEM obj-h40122-reading M_Imported_C attr PV_KSEM obj-h40122-type UINT32 attr PV_KSEM obj-h40125-reading M_Exported_VA attr PV_KSEM obj-h40125-type UINT32 attr PV_KSEM obj-h40127-reading M_Exported_VA_A attr PV_KSEM obj-h40127-type UINT32 attr PV_KSEM obj-h40129-reading M_Exported_VA_B attr PV_KSEM obj-h40129-type UINT32 attr PV_KSEM obj-h40131-reading M_Exported_VA_C attr PV_KSEM obj-h40131-type UINT32 attr PV_KSEM obj-h40133-reading M_Imported_VA attr PV_KSEM obj-h40133-type UINT32 attr PV_KSEM obj-h40135-reading M_Imported_VA_A attr PV_KSEM obj-h40135-type UINT32 attr PV_KSEM obj-h40137-reading M_Imported_VA_B attr PV_KSEM obj-h40137-type UINT32 attr PV_KSEM obj-h40139-reading M_Imported_VA_C attr PV_KSEM obj-h40139-type UINT32 attr PV_KSEM obj-h512-reading Active_energy+ attr PV_KSEM obj-h512-type UINT64 attr PV_KSEM obj-h516-reading Active_energy- attr PV_KSEM obj-h516-type UINT64 attr PV_KSEM obj-h8192-reading ManufacturerID attr PV_KSEM obj-h8192-type UINT16 attr PV_KSEM obj-h8193-reading ProductID attr PV_KSEM obj-h8193-type UINT16 attr PV_KSEM obj-h8194-reading ProductVersion attr PV_KSEM obj-h8194-type UINT16 attr PV_KSEM obj-h8195-reading FirmwareVersion attr PV_KSEM obj-h8195-type UINT16 attr PV_KSEM obj-h8196-reading VendorName attr PV_KSEM obj-h8196-type STR32 attr PV_KSEM obj-h8212-reading Productname attr PV_KSEM obj-h8212-type STR32 attr PV_KSEM obj-h8228-reading SerialNumber attr PV_KSEM obj-h8228-type STR32 attr PV_KSEM obj-h8244-reading MeasuringInterval attr PV_KSEM obj-h8244-type UINT16 attr PV_KSEM room Strom->Photovoltaik attr PV_KSEM sortby 03 attr PV_KSEM userReadings M_AC_Current:M_AC_Current_.* { ReadingsVal($NAME,"M_AC_Current_A",0) + ReadingsVal($NAME,"M_AC_Current_B",0) + ReadingsVal($NAME,"M_AC_Current_C",0) } attr PV_KSEM verbose 0
BYD Speicher (über Python Skript)
Diese Einbindung ist nicht zwingend notwendig, jedoch weil es möglich ist hier beschrieben.
PV Eigenverbrauch-Steuerung
- RAW Definition LWP_LuftWärmePumpe LWP_PV LWP_Signale LWP_Counter rg_LWP_Status - RAW Definition Pool_Softube Pool_PV Pool_Signale Pool_Counter rg_Pool_Status - RAW Definition Waschmaschine Waschmaschine_PV Waschmaschine_Signale Waschmaschine_Counter rg_Waschmaschine_Status
Energie Bilanz
- RAW Definition Energiebilanz LogDBRep_PV_total_diff_Week LogDBRep_PV_total_max_Month LogDBRep_PV_used_diff_Week LogDBRep_PV_used_max_Month
Wetter Prognose
Diagramme
- RAW Definition Leistungsuebersicht - SVG_LogDB_Photovoltaik_1 Hauptverbraucher - SVG_LogDB_Photovoltaik_2 Leistungsbezug - SVG_LogDB_Photovoltaik_3 PV_Bilanz - SVG_LogDB_PV_Bilanz Forecast / Calculation - SVG_LogDB_Photovoltaik_4
Statistiken
Der Plenticore erstellt intern noch diverse Statistiken, die auch über das WebGUI angesehen werden können. Diese werden jedoch nicht über MODBUS/TCP ausgegeben, jedoch auch zum Kostal Portal übermittelt, wo man dann bereits in Form von Diagrammen einen schönen Überblick bekommt. Das Ziel ist jedoch die Statistiken lokal im FHEM abzulegen.
PV Eigenverbrauch-Steuerung
Beispiel Luft Wärme Pumpe
RAW Definition LWP_LuftWärmePumpe (dummy Modul)
defmod LWP dummy attr LWP DbLogExclude .* attr LWP DbLogInclude state attr LWP alias LWP_LuftWärmePumpe attr LWP group PV Eigenverbrauch attr LWP icon sani_earth_source_heat_pump attr LWP readingList LWP_Button PowerLevelMinTime PowerLimitOn PowerLimitOff RunTimeMin RunTimePerDay SetCmdOff SetCmdOn TimeStart TimeEnd attr LWP room Strom->Photovoltaik attr LWP setList LWP_Button:uzsuToggle,on,off PowerLevelMinTime:slider,60,30,300 PowerLimitOn:slider,1000,250,4000 PowerLimitOff:slider,1000,250,4000 RunTimeMin:slider,300,300,7200 RunTimePerDay:slider,900,300,28800 SetCmdOff SetCmdOn TimeStart:time TimeEnd:time attr LWP sortby 05 attr LWP stateFormat state attr LWP verbose 0 attr LWP webCmd LWP_Button setstate LWP off setstate LWP 2020-08-05 17:38:03 LWP_Button off setstate LWP 2020-03-02 11:56:45 PowerLevelMinTime 600 setstate LWP 2020-02-05 14:11:42 PowerLimitOff 2250 setstate LWP 2020-03-02 11:56:39 PowerLimitOn 3000 setstate LWP 2019-08-02 10:31:21 RunTimeMin 3600 setstate LWP 2020-02-05 14:13:01 RunTimePerDay 28800 setstate LWP 2019-12-29 10:47:55 SetCmdOff set shelly01 off 0 setstate LWP 2019-07-22 15:35:59 SetCmdOn set shelly01 on 0 setstate LWP 2019-11-09 12:13:04 TimeEnd 16:00 setstate LWP 2020-04-02 13:51:54 TimeStart 12:30 setstate LWP 2020-08-05 17:38:03 state off
RAW Definition LWP_PV (DOIF Modul)
defmod LWP_PV DOIF ################################################################################################################\ ## 1 Eigenverbrauch abschalten: wenn Mindestlaufzeit erreicht wurde und Maximallaufzeit pro Tag erreicht ist\ ##\ ([LWP_Counter:pulseTimePerDay] >= [LWP:RunTimePerDay] and\ [LWP_Counter:pulseTimeIncrement] >= [LWP:RunTimeMin] and\ [LWP:state] ne "off" and [LWP:LWP_Button] eq "off" )\ \ ({Log 3, " LWP_PV cmd_1 PV : LWP off"}\ {fhem("".ReadingsVal("LWP","SetCmdOff",0))}\ {fhem("set LWP off")}\ {fhem("set Heizung hotWaterTemperatureTarget 50.0")}\ )\ ################################################################################################################\ ## 2 Eigenverbrauch abschalten: wenn Mindestlaufzeit erreicht wurde und die PV Produktion unter dem Mindestbedarf ist\ ##\ DOELSEIF\ ( ([PV_Anlage_1:Total_PV_Power_reserve]+[StromZaehler_Heizung:SMAEM1901401955_Bezug_Wirkleistung]) < [LWP:PowerLimitOff] and\ [LWP_Counter:pulseTimeIncrement] >= [LWP:RunTimeMin] and\ [LWP:state] ne "off" and\ [LWP:LWP_Button] ne "on" )\ \ ({Log 3, " LWP_PV cmd_2 PV : LWP off"}\ {fhem("".ReadingsVal("LWP","SetCmdOff",0))}\ {fhem("set LWP off")}\ {fhem("set Heizung hotWaterTemperatureTarget 50.0")}\ )\ ################################################################################################################\ ## 3 Stop, wenn es nur ein kurzer peak ist. Dieser Do Zweig setzt den wait timer vom Einschaltkommando cmd_4 wieder außerkraft,\ ## wenn wärend der Wartezeit die PV Anlage zuwenig liefert.\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [LWP:PowerLimitOff] and\ [LWP_PV:wait_timer] ne "no timer" and\ [LWP_PV:wait_timer] ne "" and\ [LWP:state] eq "off" )\ \ ({Log 3, "LWP_PV cmd_3 PV : Stop wait timer LWP"})\ ################################################################################################################\ ## 4 Eigenverbrauch einschalten: wenn PV Produktion über dem Mindestbedarf ist und die Laufzeit pro Tag noch nicht erreicht ist\ ##\ DOELSEIF\ ([Astro:ObsSeason] ne "Sommer" and [Astro:ObsSeason] ne "Frühling" and\ [PV_Anlage_1:Total_PV_Power_reserve] >= [LWP:PowerLimitOn] and\ [[LWP:TimeStart]-[LWP:TimeEnd]] and\ [LWP:state] eq "off" and\ [LWP_Counter:pulseTimePerDay] < [LWP:RunTimePerDay] and\ [Heizung:hotWaterTemperature] < 60 )\ \ ({Log 3, "LWP_PV cmd_4 : LWP on"}\ {fhem("".ReadingsVal("LWP","SetCmdOn",0))}\ {fhem("set LWP on")}\ {fhem("set Heizung hotWaterTemperatureTarget 60.0")}\ )\ ################################################################################################################\ ## 5 Signal für den PV-Modus der LWP einschalten.\ ##\ DOELSEIF\ ([LWP:LWP_Button] eq "on" )\ \ ({Log 3, "LWP_PV cmd_5 PV : LWP on for manuel PV-Modus"}\ {fhem("".ReadingsVal("LWP","SetCmdOn",0))}\ {fhem("set LWP on")}\ {fhem("set Heizung hotWaterTemperatureTarget 60.0")}\ )\ ################################################################################################################\ ## 6 Signal für den PV-Modus der LWP abschalten.\ ##\ DOELSEIF\ ([LWP:LWP_Button] eq "off" and\ [$SELF:cmd_nr] eq "5" )\ \ ({Log 3, "LWP_PV cmd_6 PV : LWP off after manuel PV-Modus"}\ {fhem("".ReadingsVal("LWP","SetCmdOff",0))}\ {fhem("set LWP off")}\ {fhem("set Heizung hotWaterTemperatureTarget 50.0")}\ )\ ################################################################################################################\ ## 7 Stop wait Timer für das Abschalten, wenn die LWP beim Starten noch anläuft\ ##\ DOELSEIF\ ([StromZaehler_Heizung:SMAEM1901401955_Bezug_Wirkleistung] > 300 and\ [Heizung:opStateHeatPump1] eq "Wärmepumpe kommt" and\ [Heizung:opStateHeatPump3] eq "Pumpenvorlauf" )\ \ ({Log 3, "LWP_PV cmd_7 : Stop wait timer LWP"})\ ################################################################################################################\ ## 8 LWP Ende\ ##\ DOELSEIF\ ([StromZaehler_Heizung:SMAEM1901401955_Bezug_Wirkleistung] < 300 and\ [LWP_Counter:pulseTimeIncrement] >= [LWP:RunTimeMin] and\ ([Heizung:opStateHeatPump1] ne "Wärmepumpe läuft" or [Heizung:opStateHeatPump3] eq "Luftabtauen" ) and\ ([$SELF:cmd_nr] eq "4" or [$SELF:cmd_nr] eq "5" or [$SELF:cmd_nr] eq "10") )\ \ ({Log 3, "LWP_PV cmd_8 : LWP run finished"}\ {fhem("".ReadingsVal("LWP","SetCmdOff",0))}\ {fhem("set LWP off")}\ {fhem("set Heizung hotWaterTemperatureTarget 50.0")}\ {fhem("setreading LWP LWP_Button off")}\ )\ ################################################################################################################\ ## 9 LWP Zwangseinschalten: Sollte das Brauchwasser noch nicht aufgeheizt sein, wird um die Hysterese erhöht.\ ## Dies kann passieren, wenn am Tag vorher der PV-Modus lief und dann das Wasser noch knapp über dem Mindestwert ist.\ ##\ DOELSEIF\ ([Astro:ObsSeason] ne "Sommer" and [Astro:ObsSeason] ne "Frühling" and\ [[LWP:TimeEnd]] and\ [Heizung:hotWaterTemperature] < 47 and\ ([LWP_Counter:pulseTimePerDay] < [Pool:RunTimePerDay] or\ [LWP_Counter:countsPerDay] eq 0) )\ \ ({Log 3, "LWP_PV cmd_9 : LWP on for water heating"}\ \ {fhem("set Heizung hotWaterTemperatureTarget ". (ReadingsVal("Heizung","hotWaterTemperature",46)+4))}\ \ {Log 3, "LWP_PV cmd_9 : LWP hotWaterTemperatureTarget ".ReadingsVal("Heizung","hotWaterTemperatureTarget",0)}\ )\ ################################################################################################################\ ## 10 Hohe Priorität im Winter fuer die LWP\ ## Einschalten, wenn der Pool läuft, der Speicher geladen ist und noch Überschuss da ist.\ ##\ DOELSEIF\ ([Astro:ObsSeason] eq "Winter" and\ [PV_Anlage_1:Total_PV_Power_reserve] >= 2000 and\ [shelly02:power_0] > 800 and\ [PV_Anlage_1:Act_state_of_charge] > 60 and\ [Heizung:hotWaterTemperature] < 60 and \ [$SELF:cmd_nr] ne "10" )\ \ ({Log 3, "LWP_PV cmd_10 : LWP Priorität"}\ {fhem("set LWP_PV cmd_4")}\ )\ attr LWP_PV DbLogExclude .* attr LWP_PV DbLogInclude state,cmd.*,Device,LWP_Status,wait_timer attr LWP_PV alias LWP_PV attr LWP_PV cmdState Maximalzeit pro Tag überschritten|Eigenverbrauch aus|Stop wait timer|Eigenverbrauch ein|LWP ein für manuellen PV-Modus|LWP aus nach manuellem PV-Modus|Stop wait timer fuer aus|LWP aus nach PV-Modus|LWP Brauchwasser nachheizen|LWP Priorität attr LWP_PV do always attr LWP_PV group PV Eigenverbrauch-Steuerung attr LWP_PV icon sani_earth_source_heat_pump attr LWP_PV room Strom->Photovoltaik attr LWP_PV sortby 01 attr LWP_PV stateFormat state : LWP_Status : Brauchwasser e_Heizung_hotWaterTemperature °C attr LWP_PV userReadings LWP_Status { ReadingsVal("Heizung","state","") } attr LWP_PV verbose 5 attr LWP_PV wait 0:10:0:[LWP:PowerLevelMinTime]:0:0:900:0:0
- RAW Definition LWP_Signale (Shelly Modul: shelly1pm)
defmod shelly01 Shelly 192.168.178.55 attr shelly01 DbLogExclude .* attr shelly01 DbLogInclude relay.*,power.*,energy.* attr shelly01 alias LWP_Signale attr shelly01 event-on-change-reading relay.*,power.*,energy.*,state,network attr shelly01 group PV Eigenverbrauch-Steuerung attr shelly01 icon taster_ch_1 attr shelly01 mode relay attr shelly01 model shelly1pm attr shelly01 room Shelly,Heizung->System,Strom->Photovoltaik attr shelly01 sortby 02 attr shelly01 stateFormat {sprintf("\ <TABLE>\ \ <TR>\ <TD VALIGN=\"TOP\" ALIGN=\"LEFT\" WIDTH=\"50\">\ WebLink: %s\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"100\">\ Gesamt 0: %08.2f KWh<br>\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"70\">\ Relais 0: %s %06.1f Watt<br>\ </TD>\ </TR>\ \ </TABLE>\ " ,\ ReadingsVal($name,"WebLink","none") ,\ ReadingsVal($name,"energy_0",0)/1000,\ (ReadingsVal($name,"relay","") eq "off") ? "<span style='color:#FF0000'>off</span>":"<span style='color:#00FF00'>on</span>",\ ReadingsVal($name,"power",0),\ )} attr shelly01 userReadings WebLink:network { my $ip=ReadingsVal($NAME,"network","");; $ip =~ s/connected to //gs;; $ip =~ s/<[^>]*>//gs;; return("<html><a href='http://".$ip."/'>WEB</a></html>") } attr shelly01 webCmd |
RAW Definition LWP_Counter (HourCounter Modul)
defmod LWP_Counter HourCounter LWP:on.* LWP:off attr LWP_Counter DbLogExclude .* attr LWP_Counter alias LWP_Counter attr LWP_Counter event-min-interval .*:600 attr LWP_Counter event-on-change-reading .* attr LWP_Counter group PV Eigenverbrauch-Steuerung attr LWP_Counter icon time_timer attr LWP_Counter interval 5 attr LWP_Counter room Strom->Photovoltaik attr LWP_Counter sortby 03 attr LWP_Counter verbose 0
RAW Definition rg_LWP_Status (readingsGroup Modul)
defmod rg_LWP_Status readingsGroup <Device>,<Information>,<Wert> LWP:<Status>,state LWP:<PowerLevelMinTime>,PowerLevelMinTime LWP:<PowerLimitOn>,PowerLimitOn LWP:<PowerLimitOff>,PowerLimitOff LWP:<TimeStart>,!TimeStart LWP:<TimeEnd>,!TimeEnd LWP:<RunTimeMin>,RunTimeMin LWP_Counter:<RunTimeMin>,pulseTimeIncrement LWP:<RunTimePerDay>,RunTimePerDay LWP_Counter:<RunTimePerDay>,pulseTimePerDay LWP_PV:<wait>,wait_timer LWP_PV:<TimeStart>,timer_01_c04 LWP_PV:<TimeEnd>,timer_02_c04 attr rg_LWP_Status DbLogExclude .* attr rg_LWP_Status alias Status LuftWärmePumpe Eigenverbrauch attr rg_LWP_Status commands {state => 'state:on,off',\ PowerLevelMinTime => 'PowerLevelMinTime:selectnumbers,60,60,600,0,lin',\ PowerLimitOn => 'PowerLimitOn:selectnumbers,1000,250,4000,0,lin',\ PowerLimitOff => 'PowerLimitOff:selectnumbers,1000,250,4000,0,lin',\ RunTimeMin => 'RunTimeMin:selectnumbers,300,300,14400,0,lin',\ RunTimePerDay => 'RunTimePerDay:selectnumbers,300,300,28800,0,lin',\ TimeStart => 'TimeStart:time',\ TimeEnd => 'TimeEnd:time'} attr rg_LWP_Status group PV Status attr rg_LWP_Status nameStyle style="color:grey" attr rg_LWP_Status room Strom->Photovoltaik attr rg_LWP_Status sortby 01 attr rg_LWP_Status style style="font-size:18px"
Beispiel Pool
RAW Definition Pool_Softube (dummy Modul)
defmod Pool dummy attr Pool DbLogExclude .* attr Pool DbLogInclude state attr Pool alias Pool_Softube attr Pool event-on-change-reading .* attr Pool group PV Eigenverbrauch attr Pool icon scene_swimming attr Pool readingList Pool_Button PowerLevelMinTime PowerLimitOn PowerLimitOff RunTimeMin RunTimePerDay RunTimePerDaySummer RunTimePerDayWinter SetCmdOff SetCmdOn TimeStart TimeEnd attr Pool room Strom->Photovoltaik attr Pool setList Pool_Button:uzsuToggle,on,off PowerLevelMinTime:slider,30,30,300 PowerLimitOn:slider,500,100,1500 PowerLimitOff:slider,0,100,1000 RunTimeMin:slider,300,300,7200 RunTimePerDay:slider,900,300,64800 RunTimePerDaySummer:slider,900,300,7200 RunTimePerDayWinter:slider,3600,900,64800 SetCmdOff SetCmdOn TimeStart:time TimeEnd:time attr Pool sortby 06 attr Pool stateFormat state attr Pool verbose 0 attr Pool webCmd Pool_Button setstate Pool off setstate Pool 2020-08-28 13:30:10 Pool_Button off setstate Pool 2019-12-02 10:31:26 PowerLevelMinTime 600 setstate Pool 2019-11-13 10:58:18 PowerLimitOff 800 setstate Pool 2019-11-06 11:49:00 PowerLimitOn 1000 setstate Pool 2020-08-14 16:26:09 RunTimeMin 1800 setstate Pool 2020-08-28 06:15:00 RunTimePerDay 3600 setstate Pool 2020-08-16 13:17:45 RunTimePerDaySummer 3600 setstate Pool 2020-08-25 19:32:33 RunTimePerDayWinter 14400 setstate Pool 2019-08-01 14:18:08 SetCmdOff set shelly02 off 0 setstate Pool 2019-08-02 09:33:06 SetCmdOn set shelly02 on 0 setstate Pool 2019-10-31 21:53:28 TimeEnd 16:00 setstate Pool 2020-04-08 18:19:29 TimeStart 12:30 setstate Pool 2020-08-28 14:13:02 state off
RAW Definition Pool_PV (DOIF Modul)
defmod Pool_PV DOIF ################################################################################################################\ ## 1 Eigenverbrauch abschalten: wenn Mindestlaufzeit erreicht wurde und Maximallaufzeit pro Tag erreicht ist\ ##\ ([Pool_Counter:pulseTimePerDay] >= [Pool:RunTimePerDay] and\ [Pool_Counter:pulseTimeIncrement] >= [Pool:RunTimeMin] and\ [Pool:state] eq "on" and [Pool:Pool_Button] eq "off" )\ \ ({Log 3, "Pool_PV cmd_1 : Pool off"}\ {fhem("".ReadingsVal("Pool","SetCmdOff",0))}\ {fhem("set Pool off")} )\ ################################################################################################################\ ## 2 Eigenverbrauch abschalten: wenn Mindestlaufzeit erreicht wurde und die PV-Produktion unter dem Mindestbedarf ist.\ ## Bei Pool Nutzung und Pflegeprogramm wird nicht abgeschaltet.\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [Pool:PowerLimitOff] and\ [Pool_Counter:pulseTimeIncrement] >= [Pool:RunTimeMin] and\ [Pool:state] eq "on" and \ [$SELF:cmd_nr] ne "5" and [$SELF:cmd_nr] ne "7" and [$SELF:cmd_nr] ne "10" )\ \ ({Log 3, "Pool_PV cmd_2 : Pool off"}\ {fhem("".ReadingsVal("Pool","SetCmdOff",0))}\ {fhem("set Pool off")}\ {fhem("setreading Pool Pool_Button off")} )\ ################################################################################################################\ ## 3 Stop, wenn es nur ein kurzer Peak ist. Dieser Do Zweig setzt den wait timer vom Einschaltkommando cmd_4 wieder außer kraft,\ ## wenn während der Wartezeit die PV-Anlage zuwenig liefert.\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [Pool:PowerLimitOff] and\ [$SELF:wait_timer] ne "no timer" and\ [$SELF:wait_timer] ne "" and\ [Pool:state] eq "off" )\ \ ({Log 3, "Pool_PV cmd_3 : Stop wait timer Pool"})\ ################################################################################################################\ ## 4 Eigenverbrauch einschalten: wenn PV-Produktion über dem Mindestbedarf ist und PV-Strom ins Netz eingespeist wird\ ## und die Laufzeit pro Tag noch nicht erreicht ist;; Bei über 7000 Watt Einspeisung sofort aktivieren\ ##\ DOELSEIF\ (([PV_Anlage_1:Total_PV_Power_reserve] >= [Pool:PowerLimitOn] and\ [[Pool:TimeStart]-[Pool:TimeEnd]] and\ [Pool:state] eq "off" and\ [Pool_Counter:pulseTimePerDay] < [Pool:RunTimePerDay]\ ) or\ [PV_Anlage_1:Total_active_power_(powermeter)] <= -7000\ )\ \ ({Log 3, "Pool_PV cmd_4 : Pool on"}\ {fhem("set Pool_Counter pulseTimeIncrement 0")}\ {fhem("".ReadingsVal("Pool","SetCmdOn",0))}\ {fhem("set Pool on")} )\ ################################################################################################################\ ## 5 Steckdose für die Benutzung des Pools einschalten.\ ##\ DOELSEIF\ ([Pool:Pool_Button] eq "on" )\ \ ({Log 3, "Pool_PV cmd_5 : Pool on for usage"}\ {fhem("".ReadingsVal("Pool","SetCmdOn",0))}\ {fhem("set Pool on")} )\ ################################################################################################################\ ## 6 Steckdose des Pools abschalten.\ ##\ DOELSEIF\ ([Pool:Pool_Button] eq "off" and\ [$SELF:cmd_nr] eq "5" or [$SELF:cmd_nr] eq "7")\ \ ({Log 3, "Pool_PV cmd_6 : Pool off after usage"}\ {fhem("".ReadingsVal("Pool","SetCmdOff",0))}\ {fhem("set Pool off")} )\ ################################################################################################################\ ## 7 Stop wait Timer für das Abschalten, wenn die Pumpe beim Starten noch anläuft\ ##\ DOELSEIF\ ([shelly02:power_0] > 10 and\ ([$SELF:cmd_nr] eq "5" or [$SELF:cmd_nr] eq "7" or [$SELF:cmd_nr] eq "9") and\ [$SELF:wait_timer] ne "no timer" and\ [$SELF:wait_timer] ne "" and\ [Pool:state] eq "on" )\ \ ({Log 3, "Pool_PV cmd_7 : Stop wait timer Pool"})\ ################################################################################################################\ ## 8 Pool Ende\ ##\ DOELSEIF\ ([shelly02:power_0] < 10 and\ ([$SELF:cmd_nr] eq "5" or [$SELF:cmd_nr] eq "7" or [$SELF:cmd_nr] eq "9") )\ \ ({Log 3, "Pool_PV cmd_8 : Pool run finished"}\ {fhem("".ReadingsVal("Pool","SetCmdOff",0))}\ {fhem("set Pool off")}\ {fhem("setreading Pool Pool_Button off")} )\ ################################################################################################################\ ## 9 Pflege Zwangseinschaltung: Es muss mindestens einmal pro Tag eingeschaltet werden, auch wenn kein PV Strom vorhanden war.\ ##\ DOELSEIF\ ([[Pool:TimeEnd]] and\ ([Pool_Counter:pulseTimePerDay] < [Pool:RunTimePerDay] or\ [Pool_Counter:countsPerDay] eq 0)\ )\ \ ({Log 3, "Pool_PV cmd_9 : Pool on for maintanance"}\ {fhem("set Pool_Counter pulseTimeIncrement 0")}\ {fhem("".ReadingsVal("Pool","SetCmdOn",0))}\ {fhem("set Pool on")} )\ ################################################################################################################\ ## 10 Pflege Zwangseinschaltung bei günstigem Strom nachts im Winter\ ##\ DOELSEIF\ ([Astro:ObsSeason] eq "Winter" and\ [Strom_Kosten:aWATTar_Trigger] eq "on" and\ [22:00-05:00]\ )\ \ ({Log 3, "Pool_PV cmd_10 : Pool on for maintanance by aWATTar"}\ {fhem("set Pool_Counter pulseTimeIncrement 0")}\ {fhem("".ReadingsVal("Pool","SetCmdOn",0))}\ {fhem("set Pool on")} )\ ################################################################################################################\ ## 11 Abschaltung bei teurem Strom\ ##\ DOELSEIF\ ([Astro:ObsSeason] eq "Winter" and\ [Strom_Kosten:aWATTar_Trigger] eq "off" and\ [$SELF:cmd_nr] eq "10"\ )\ \ ({Log 3, "Pool_PV cmd_11 : Pool off after maintanance by aWATTar"}\ {fhem("".ReadingsVal("Pool","SetCmdOff",0))}\ {fhem("set Pool off")} )\ ################################################################################################################\ ## 12 Pool durch kürzere Laufzeit abkühlen lassen\ ##\ DOELSEIF\ ([06:15] and [Heizung:averageAmbientTemperature])\ \ (\ { if ( [Heizung:averageAmbientTemperature] >= 18 )\ {fhem("setreading Pool RunTimePerDay ".ReadingsVal("Pool","RunTimePerDaySummer",0) )}\ else \ {fhem("setreading Pool RunTimePerDay ".ReadingsVal("Pool","RunTimePerDayWinter",0) )}\ },\ {Log 3, "Pool_PV cmd_12 : Pool RunTimePerDay switched"}\ )\ \ attr Pool_PV DbLogExclude .* attr Pool_PV DbLogInclude cmd.*,state,cmd.*,Device,Pool_Pumpe_Status,wait_timer attr Pool_PV alias Pool_PV attr Pool_PV cmdState Maximalzeit pro Tag überschritten|Eigenverbrauch aus|Stop wait timer|Eigenverbrauch freigegeben|Pool ein für Benutzung|Pool aus nach Benutzung|Stop wait timer für aus|Pool aus|Pflegemodus ohne PV|Strombörse ein|Strombörse aus|RunTimePerDay switched attr Pool_PV disable 0 attr Pool_PV do always attr Pool_PV event-on-change-reading .* attr Pool_PV group PV Eigenverbrauch-Steuerung attr Pool_PV icon scene_swimming attr Pool_PV room Strom->Photovoltaik attr Pool_PV sortby 11 attr Pool_PV stateFormat state : Pool_Pumpe_Status attr Pool_PV userReadings Pool_Pumpe_Status { ReadingsVal("shelly02","power_0",0)>10 ? "Pool_Pumpe_laeuft" : "Pool_Pumpe_aus"} attr Pool_PV verbose 0 attr Pool_PV wait 0:10:0:[Pool:PowerLevelMinTime]:0:0:0:300:0:300
RAW Definition Pool_Signale (Shelly Modul: shelly1pm)
defmod shelly02 Shelly 192.168.178.52 attr shelly02 DbLogExclude .* attr shelly02 DbLogInclude relay.*,power.*,energy.* attr shelly02 alias Pool_Signale attr shelly02 comment relais_0 => Pool limit 1000 W\ relail_1 => Terrasse Lichterkette limit 100 W attr shelly02 event-on-change-reading relay.*,power.*,energy.*,state,network attr shelly02 group PV Eigenverbrauch-Steuerung attr shelly02 icon taster_ch_1 attr shelly02 mode relay attr shelly02 model shelly2.5 attr shelly02 room Shelly,Strom->Photovoltaik attr shelly02 sortby 12 attr shelly02 stateFormat {sprintf("\ <TABLE>\ \ <TR>\ <TD VALIGN=\"TOP\" ALIGN=\"LEFT\" WIDTH=\"50\">\ Status: %s<br>\ WebLink: %s\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"100\">\ Gesamt 0: %08.2f KWh<br>Gesamt 1: %08.2f KWh\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"70\">\ Relais 0: %s %06.1f Watt<br>\ Relais 1: %s %06.1f Watt<br>\ </TD>\ </TR>\ \ </TABLE>\ " ,\ (ReadingsVal($name,"state","none") eq "OK") ? "<span style='color:#00FF00'>OK</span>":"<span style='color:#FF0000'>Error</span>",\ ReadingsVal($name,"WebLink","none") ,\ ReadingsVal($name,"energy_0",0)/1000,\ ReadingsVal($name,"energy_1",0)/1000,\ (ReadingsVal($name,"relay_0","") eq "off") ? "<span style='color:#FF0000'>off</span>":"<span style='color:#00FF00'>on</span>",\ ReadingsVal($name,"power_0",0),\ (ReadingsVal($name,"relay_1","") eq "off") ? "<span style='color:#FF0000'>off</span>":"<span style='color:#00FF00'>on</span>",\ ReadingsVal($name,"power_1",0)\ )} attr shelly02 userReadings WebLink:network { my $ip=ReadingsVal($name,"network","");; $ip =~ s/connected to //gs;; $ip =~ s/<[^>]*>//gs;; return("<html><a href='http://".$ip."/'>WEB</a></html>") } attr shelly02 verbose 0 attr shelly02 webCmd |
RAW Definition Pool_Counter (HourCounter Modul)
defmod Pool_Counter HourCounter shelly02:power_0:\s[0-9]{2,}(\.[0-9]{1,2})*$ shelly02:power_0:\s[0-9]{1}(\.[0-9]{1,2})*$ attr Pool_Counter DbLogExclude .* attr Pool_Counter alias Pool_Counter attr Pool_Counter comment On und Off des Pools werden direkt über den Shelly Stromverbrauch getriggert. attr Pool_Counter event-on-change-reading .* attr Pool_Counter group PV Eigenverbrauch-Steuerung attr Pool_Counter icon time_timer attr Pool_Counter interval 5 attr Pool_Counter room Strom->Photovoltaik attr Pool_Counter sortby 13 attr Pool_Counter verbose 0
RAW Definition rg_Pool_Status (readingsGroup Modul)
defmod rg_Pool_Status readingsGroup <Device>,<Information>,<Wert> Pool:<Status>,!state Pool:<PowerLevelMinTime>,!PowerLevelMinTime Pool:<PowerLimitOn>,!PowerLimitOn Pool:<PowerLimitOff>,!PowerLimitOff Pool:<TimeStart>,!TimeStart Pool:<TimeEnd>,!TimeEnd Pool:<RunTimeMin>,!RunTimeMin Pool_Counter:<RunTimeMin>,!pulseTimeIncrement Pool:<RunTimePerDay>,!RunTimePerDay Pool:<RunTimePerDaySummer>,!RunTimePerDaySummer Pool:<RunTimePerDayWinter>,!RunTimePerDayWinter Pool_Counter:<RunTimePerDay>,!pulseTimePerDay Pool_PV:<wait>,wait_timer Pool_PV:<TimeStart>,timer_01_c04 Pool_PV:<TimeEnd>,timer_02_c04 attr rg_Pool_Status DbLogExclude .* attr rg_Pool_Status alias Status Softube Pool Eigenverbrauch attr rg_Pool_Status commands {state => 'state:on,off',\ PowerLevelMinTime => 'PowerLevelMinTime:selectnumbers,60,30,600,0,lin',\ PowerLimitOn => 'PowerLimitOn:selectnumbers,500,250,1500,0,lin',\ PowerLimitOff => 'PowerLimitOff:selectnumbers,0,100,1000,0,lin',\ RunTimeMin => 'RunTimeMin:selectnumbers,300,300,14400,0,lin',\ RunTimePerDaySummer => 'RunTimePerDaySummer:selectnumbers,300,300,3600,0,lin',\ RunTimePerDayWinter => 'RunTimePerDayWinter:selectnumbers,3600,900,64800,0,lin',\ TimeStart => 'TimeStart:time',\ TimeEnd => 'TimeEnd:time'} attr rg_Pool_Status group PV Status attr rg_Pool_Status nameStyle style="color:grey" attr rg_Pool_Status room Strom->Photovoltaik attr rg_Pool_Status sortby 02 attr rg_Pool_Status style style="font-size:18px"
Beispiel Waschmaschine (mit Walzenschalter ;-) )
RAW Definition Waschmaschine (dummy Modul)
defmod Waschmaschine dummy attr Waschmaschine DbLogExclude .* attr Waschmaschine DbLogInclude state attr Waschmaschine alias Waschmaschine attr Waschmaschine group PV Eigenverbrauch attr Waschmaschine icon scene_washing_machine attr Waschmaschine readingList Waschmaschine_Button PowerLevelMinTime PowerPhaseUse PowerLimitOn PowerLimitOff RunTimeMin RunTimePerDay SetCmdOff SetCmdOn TimeStart TimeEnd attr Waschmaschine room Strom->Photovoltaik attr Waschmaschine setList Waschmaschine_Button:uzsuToggle,on,off PowerLevelMinTime:slider,30,30,300 PowerLimitOn:slider,250,250,2000 PowerLimitOff:slider,0,250,1000 RunTimeMin:slider,300,300,7200 RunTimePerDay:slider,7200,300,28800 SetCmdOff SetCmdOn TimeStart:time TimeEnd:time attr Waschmaschine sortby 07 attr Waschmaschine stateFormat state attr Waschmaschine verbose 0 attr Waschmaschine webCmd Waschmaschine_Button setstate Waschmaschine off setstate Waschmaschine 2019-12-02 10:29:49 PowerLevelMinTime 300 setstate Waschmaschine 2019-11-06 10:56:22 PowerLimitOff 250 setstate Waschmaschine 2020-04-20 13:06:04 PowerLimitOn 2000 setstate Waschmaschine 2019-12-02 15:01:18 RunTimeMin 5400 setstate Waschmaschine 2020-04-02 13:59:34 RunTimePerDay 19200 setstate Waschmaschine 2020-01-01 16:29:10 SetCmdOff set shelly03 off 0 setstate Waschmaschine 2020-01-01 16:29:24 SetCmdOn set shelly03 on 0 setstate Waschmaschine 2019-08-01 14:25:25 TimeEnd 18:00 setstate Waschmaschine 2019-10-28 09:13:30 TimeStart 09:00 setstate Waschmaschine 2020-08-27 16:17:23 Waschmaschine_Button off setstate Waschmaschine 2020-08-28 16:29:42 state off
RAW Definition Waschmaschine_PV (DOIF Modul)
defmod Waschmaschine_PV DOIF ################################################################################################################\ ## 1 Eigenverbrauch sperren: wenn Mindestlaufzeit erreicht wurde und Maximallaufzeit pro Tag erreicht ist\ ## jedoch nicht wenn manueller Betrieb aktiv ist.\ ##\ ([Waschmaschine_Counter:pulseTimePerDay] >= [Waschmaschine:RunTimePerDay] and\ [Waschmaschine_Counter:pulseTimeIncrement] >= [Waschmaschine:RunTimeMin] and\ [Waschmaschine:state] eq "on" and [Waschmaschine:Waschmaschine_Button] eq "off" )\ \ ({Log 3, "Waschmaschine cmd_1 : Eigenverbrauch sperren"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOff",0))}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist ausgeschaltet")}\ {fhem("set Waschmaschine off")}\ )\ ################################################################################################################\ ## 2 Eigenverbrauch sperren: wenn Mindestlaufzeit erreicht wurde und die PV-Produktion unter dem Mindestbedarf ist\ ## ausser bei manuellem Einschalten und wenn das Waschprogramm bereits läuft\ ##\ ## ([PV_Anlage_1:Total_PV_Power_reserve] < [Waschmaschine:PowerLimitOff] and\ ## [Waschmaschine_Counter:pulseTimeIncrement] >= [Waschmaschine:RunTimeMin] and\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [Waschmaschine:PowerLimitOn] and\ [Waschmaschine:state] eq "on" and\ [$SELF:cmd_nr] ne "5" and [$SELF:cmd_nr] ne "7" )\ \ ({Log 3, "Waschmaschine cmd_2 : Eigenverbrauch sperren"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOff",0))}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist ausgeschaltet")}\ {fhem("set Waschmaschine off")}\ )\ ################################################################################################################\ ## 3 Stop, wenn es nur ein kurzer Peak ist. Dieser Do Zweig setzt den wait timer vom Einschaltkommando cmd_4\ ## wieder außer kraft, wenn während der Wartezeit die PV-Anlage zuwenig liefert.\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [Waschmaschine:PowerLimitOff] and\ [Waschmaschine_PV:wait_timer] ne "no timer" and\ [Waschmaschine_PV:wait_timer] ne "" and\ [Waschmaschine:state] eq "off" )\ \ ({Log 3, "Waschmaschine cmd_3 : Waschmaschine stop wait timer"})\ ################################################################################################################\ ## 4 Eigenverbrauch freigeben: wenn PV-Produktion über dem Mindestbedarf ist und PV-Strom ins Netz eingespeist\ ## wird und die Laufzeit pro Tag noch nicht erreicht ist\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] > [Waschmaschine:PowerLimitOn] and\ [Waschmaschine:state] eq "off" and\ [[Waschmaschine:TimeStart]-[Waschmaschine:TimeEnd]] and\ [Waschmaschine_Counter:pulseTimePerDay] < [Waschmaschine:RunTimePerDay] )\ \ ({Log 3, "Waschmaschine cmd_4 : Waschmaschine freigabe"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOn",0))}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist eingeschaltet")}\ {fhem("set Waschmaschine on")}\ )\ ################################################################################################################\ ## 5 Steckdose manuell für die Benutzung der Waschmaschine einschalten.\ ##\ DOELSEIF\ ([Waschmaschine:Waschmaschine_Button] eq "on" )\ \ ({Log 3, "Waschmaschine cmd_5 : Waschmaschine manuell ein"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOn",0))}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist eingeschaltet")}\ {fhem("set Waschmaschine on")}\ )\ ################################################################################################################\ ## 6 Steckdose der Waschmaschine manuell abschalten.\ ##\ DOELSEIF\ ([Waschmaschine:Waschmaschine_Button] eq "off" and\ ([$SELF:cmd_nr] eq "5" or [$SELF:cmd_nr] eq "7") )\ \ ({Log 3, "Waschmaschine cmd_6 : Waschmaschine manuell aus"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOff",0))}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist ausgeschaltet")}\ {fhem("set Waschmaschine off")}\ )\ ################################################################################################################\ ## 7 Statuswechsel wenn das Waschprogramm gestartet ist\ ##\ DOELSEIF\ ([shelly03:power] > 0 and\ [shelly03:power_Waschmaschine_avg] < 70 and\ [$SELF:cmd_nr] ne "7")\ \ ({Log 3, "Waschmaschine cmd_7 : Waschmaschine Programm gestarted"}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Waschprogramm gestartet")}\ )\ ################################################################################################################\ ## 8 Abschalten der Steckdose beim Waschprogramm Ende\ ##\ DOELSEIF\ ([shelly03:power] == 0 and\ [shelly03:power_Waschmaschine_avg] > 0 and\ [$SELF:cmd_nr] eq "7" )\ \ ({Log 3, "Waschmaschine cmd_8 : Waschmaschine aus"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOff",0))}\ {fhem("set Waschmaschine off")}\ {fhem("setreading Waschmaschine Waschmaschine_Button off")}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Waschprogramm beendet")}\ )\ ################################################################################################################\ ## 9 Abschalten der Steckdose wenn die Waschmaschine nicht gebraucht wurde\ ##\ DOELSEIF\ ([PV_Anlage_1:Total_PV_Power_reserve] < [Waschmaschine:PowerLimitOn] and\ [[Waschmaschine:TimeEnd]-[Waschmaschine:TimeStart]] and\ [Waschmaschine:state] eq "on" and\ [$SELF:cmd_nr] ne "5" and [$SELF:cmd_nr] ne "7" )\ \ ({Log 3, "Waschmaschine cmd_9 : Eigenverbrauch sperren"}\ {fhem("".ReadingsVal("Waschmaschine","SetCmdOff",0))}\ {fhem("set Waschmaschine off")}\ {fhem("setreading Waschmaschine Waschmaschine_Button off")}\ {fhem("setreading Waschmaschine_PV Waschmaschine_Status Steckdose ist ausgeschaltet")}\ ) attr Waschmaschine_PV DbLogExclude .* attr Waschmaschine_PV DbLogInclude state,STATE,cmd.*,Device,Waschmaschine_Status,wait_timer attr Waschmaschine_PV alias Waschmaschine_PV attr Waschmaschine_PV cmdState Maximalzeit pro Tag überschritten|Eigenverbrauch gesperrt|Stop wait timer|Eigenverbrauch freigegeben|Waschmaschine manuell ein|Waschmaschine manuell aus|Waschmaschine laeuft|Waschmaschine aus|Eigenverbrauch gesperrt attr Waschmaschine_PV do always attr Waschmaschine_PV group PV Eigenverbrauch-Steuerung attr Waschmaschine_PV icon scene_washing_machine attr Waschmaschine_PV room Strom->Photovoltaik attr Waschmaschine_PV sortby 21 attr Waschmaschine_PV stateFormat state : Waschmaschine_Status attr Waschmaschine_PV verbose 0 attr Waschmaschine_PV wait 0:0:0:[Waschmaschine:PowerLevelMinTime]:0:30:0:60:30
RAW Definition Waschmaschine_Signale (Shelly Modul: shelly1pm)
defmod shelly03 Shelly 192.168.178.54 attr shelly03 DbLogExclude .* attr shelly03 DbLogInclude relay.*,power.*,energy.* attr shelly03 alias Waschmaschine_Signale attr shelly03 event-on-change-reading relay.*,power.*,energy.*,network attr shelly03 group PV Eigenverbrauch-Steuerung attr shelly03 icon taster_ch_1 attr shelly03 interval 60 attr shelly03 mode relay attr shelly03 model shelly1pm attr shelly03 room Shelly,Strom->Photovoltaik attr shelly03 sortby 22 attr shelly03 stateFormat {sprintf("\ <TABLE>\ \ <TR>\ <TD VALIGN=\"TOP\" ALIGN=\"LEFT\" WIDTH=\"50\">\ WebLink: %s\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"100\">\ Gesamt 0: %08.2f KWh<br>\ </TD>\ \ <TD VALIGN=\"TOP\" ALIGN=\"RIGHT\" WIDTH=\"70\">\ Relais 0: %s %06.1f Watt<br>\ </TD>\ </TR>\ \ </TABLE>\ " ,\ ReadingsVal($name,"WebLink","none") ,\ ReadingsVal($name,"energy",0)/1000,\ (ReadingsVal($name,"relay","") eq "off") ? "<span style='color:#FF0000'>off</span>":"<span style='color:#00FF00'>on</span>",\ ReadingsVal($name,"power",0)\ )} attr shelly03 userReadings WebLink:network { my $ip=ReadingsVal($NAME,"network","");; $ip =~ s/connected to //gs;; $ip =~ s/<[^>]*>//gs;; return("<html><a href='http://".$ip."/'>WEB</a></html>") },\ power_Waschmaschine_avg:power.* { movingAverage($NAME,"power",300) } attr shelly03 webCmd |
RAW Definition Waschmaschine_Counter (HourCounter Modul)
defmod Waschmaschine_Counter HourCounter Waschmaschine_PV:.*laeuft Waschmaschine_PV:Waschmaschine_Status:.*[beendet|ausgeschaltet] attr Waschmaschine_Counter DbLogExclude .* attr Waschmaschine_Counter alias Waschmaschine_Counter attr Waschmaschine_Counter event-on-change-reading .* attr Waschmaschine_Counter group PV Eigenverbrauch-Steuerung attr Waschmaschine_Counter icon time_timer attr Waschmaschine_Counter interval 5 attr Waschmaschine_Counter room Strom->Photovoltaik attr Waschmaschine_Counter sortby 23 attr Waschmaschine_Counter verbose 0
RAW Definition rg_Waschmaschine_Status (readingsGroup Modul)
defmod rg_Waschmaschine_Status readingsGroup <Device>,<Information>,<Wert> Waschmaschine:<Status>,!state Waschmaschine:<PowerLevelMinTime>,!PowerLevelMinTime Waschmaschine:<PowerLimitOn>,!PowerLimitOn Waschmaschine:<PowerLimitOff>,!PowerLimitOff Waschmaschine:<TimeStart>,!TimeStart Waschmaschine:<TimeEnd>,!TimeEnd Waschmaschine:<RunTimeMin>,!RunTimeMin Waschmaschine_Counter:<RunTimeMin>,!pulseTimeIncrement Waschmaschine:<RunTimePerDay>,!RunTimePerDay Waschmaschine_Counter:<RunTimePerDay>,!pulseTimePerDay Waschmaschine_PV:<wait>,wait_timer Waschmaschine_PV:<TimeStart>,timer_01_c04 Waschmaschine_PV:<TimeEnd>,timer_02_c04 attr rg_Waschmaschine_Status DbLogExclude .* attr rg_Waschmaschine_Status alias Status Waschmaschine Eigenverbrauch attr rg_Waschmaschine_Status commands {state => 'state:on,off',\ PowerLevelMinTime => 'PowerLevelMinTime:selectnumbers,30,30,300,0,lin',\ PowerLimitOn => 'PowerLimitOn:selectnumbers,250,250,2000,0,lin',\ PowerLimitOff => 'PowerLimitOff:selectnumbers,0,50,800,0,lin',\ RunTimeMin => 'RunTimeMin:selectnumbers,300,300,7200,0,lin',\ RunTimePerDay => 'RunTimePerDay:selectnumbers,7200,300,28800,0,lin',\ TimeStart => 'TimeStart:time',\ TimeEnd => 'TimeEnd:time'} attr rg_Waschmaschine_Status group PV Status attr rg_Waschmaschine_Status nameStyle style="color:grey" attr rg_Waschmaschine_Status room Strom->Photovoltaik attr rg_Waschmaschine_Status sortby 03 attr rg_Waschmaschine_Status style style="font-size:18px"
3. Energie Bilanz
RAW Definition Energiebilanz
Erstellen von zusätzlichen Werten in der Datenbank
Hier werden Werte konsolidiert, weil z.B. der Wert PV_total_Month stetig steigt. Am Ende des Monats sind die gesamten Zwischenwerte ohne Aussagekraft.
RAW Definition LogDBRep_PV_total_diff_Week
RAW Definition LogDBRep_PV_total_max_Month
RAW Definition LogDBRep_PV_used_diff_Week
RAW Definition LogDBRep_PV_used_max_Month
Löschen von nicht mehr benötigten Werten in der Datenbank
Hier wird endgültig aufgeräumt, alte momentan Werte werden gelöscht, wenn sie nach z.B. drei Monaten keine Relevanz mehr haben. Dafür wurden im vorherigen Abschnitt zusätzliche Werte in der Datenbank erzeugt, die in Diagrammen trotzdem noch einen trend erkennen lassen. Wen eine immer größer werdende Datenbank mit steigenden Antwortzeiten nicht stört, der kann das Aufräumen auch weg lassen. Bei einer späteren Migration führt dies natürlich zu höherem Aufwand und hohen Laufzeiten.
4. Wetter Prognose
5. Diagramme
RAW Definition Leistungsuebersicht
SVG_LogDB_Photovoltaik_1
RAW Definition Hauptverbraucher
SVG_LogDB_Photovoltaik_2
RAW Definition Leistungsbezug
SVG_LogDB_Photovoltaik_3
RAW Definition PV_Bilanz
SVG_LogDB_PV_Bilanz
RAW Definition Forecast / Calculation
SVG_LogDB_Photovoltaik_4
Problemlösung
Projekte der FHEM-Community
- Beitrag - Photovoltaik mit Eigenverbrauch Steuerung (Kostal plenticore; EM410)
- Beitrag - Kostal Plenticore Bilanz
- Beitrag - Kostal Plenticore, EM410 (KSEM), BYD, Solarprognose, Forecast
- Thema - Modul 93_DbRep - Reporting und Management von Datenbankinhalten (DbLog)
- Thema - Neue Version von HTTPMOD mit neuen Features zum Testen