Realtime uitlezen APSystems in Domoticz

Realtime uitlezen APSystems in Domoticz

1 mei 2021 34 Door Björn Meijer

Sinds kort zijn wij trotse bezitters van zonnepanelen. Omdat het energieverbruik reeds werd bijgehouden in Domoticz en geen voorstander ben van verschillende portals/apps om alles in bij te houden wilde ik ook de opbrengst van de zonnepanelen weergegeven hebben in Domoticz.

Nadat de leverancier alle panelen op het dak had gemonteerd en het systeem draaide vroeg ik of de ECU-R ook uit te lezen was via Domoticz. Helaas, dit bleek afgeschermd te zijn. Maar er was wel een app (EMA App) en een webportal waarmee je het verbruik kon uitlezen. Beide opties gaven een vertraging van circa vijf minuten. Er was ook nog de ECUAPP. Door op de zijkant van de router te klikken zend deze een uur lang een WiFi-signaal uit. Door met je telefoon/tablet te verbinden met deze WiFi-hotspot kun je met de ECUAPP de realtime waarden uitlezen.

Op Tweakers.net waren ze hier ook achter gekomen en zijn een aantal slimme koppen bezig geweest om al een groot deel van de data via een Python-script uit te lezen. Hierbij dient te worden opgemerkt dat dit alleen werkt via WiFi.

Een aantal leden van Tweakers maakt gebruik van Home Assistant. De plug-in dient dus (iets) aangepast te worden waardoor het gebruikt kan voor Domoticz.

Plug-in installeren

Naast onderstaande code heb je ook de plug-in nodig welke te downloaden is van Github.

Om de python scripts uit te kunnen voeren dient op de Raspberry Pi Python 3.x te worden geïnstalleerd.

#!/usr/bin/env python3
 
from APSystemsECUR import APSystemsECUR
import time
import asyncio
import urllib.request
import urllib.parse
import urllib
from pprint import pprint
 
 
ecu_ip = "<ECU-R-IP>"
sleep = 300
 
url = '<DomoticzIP>:8080/json.htm?'
puntcomma = '\u003B'
 
loop = asyncio.get_event_loop()
ecu = APSystemsECUR(ecu_ip)
 
while True:
        try:
                data = loop.run_until_complete(ecu.async_query_ecu())
                print(data)
 
                lifetime_energy = str(data.get('lifetime_energy')*1000)
                today_energy_kwh = str(data.get('today_energy')*1000)
                current_power = str(data.get('current_power'))
                print('current_power: ' + current_power)
                generated_energy = (current_power + puntcomma + lifetime_energy)
                print('output: ' + today_energy_kwh + ';' + current_power)
                #pwr = .format(today_energy_kwh, current_power)
                #print('PWR: ' + pwr)
                print('Today energy [kWh]: ' + today_energy_kwh)
                if (float(today_energy_kwh) >= 0 or float(current_power) >= 0):
                    getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1606, 'svalue': (generated_energy)}
                    webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                    print(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1610, 'svalue': data.get('timestamp')}
                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                #print(url + urllib.parse.urlencode(getVars))
        #inverter values
                inverters = data.get('inverters')
        #count number of inverters
                Inverter_qty = len(data.get('inverters'))
                print('Inverter_cnt: ' + str(Inverter_qty))
        # loop trough all inverters and get the data
                for i in range(Inverter_qty):
                    Inverter = list(inverters.keys())[i]
                    print('InverterId: ' + Inverter)
                    InverterOnline = data['inverters'][Inverter]['online']
                    print('Online: ' + str(InverterOnline))
                    InverterTemperature = data['inverters'][Inverter]['temperature']
                    print('Temperature: ' + str(InverterTemperature))
                    nVoltage = len(data['inverters'][Inverter]['voltage'])
                    nPower = len(data['inverters'][Inverter]['power'])
                    for x in range(nPower):
                        voltage = data['inverters'][Inverter]['voltage'][x]
                        power = data['inverters'][Inverter]['power'][x]
                        print('Power inverter ' + str(i + 1) + ' panel ' + str(x + 1) + ': ' + str(power) + ' W')
                    
        #upload values to Domoticz voor inverter 1
                        if (i == 0) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1624, 'svalue': voltage}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1609, 'svalue': InverterTemperature}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            if (InverterOnline == True)  and (voltage != 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1607, 'switchcmd': 'On', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            elif (InverterOnline == True) and (voltage == 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1607, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))

                            else :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1607, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
 
        #upload values to Domoticz voor inverter 2
                        if (i == 1) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1614, 'svalue': InverterTemperature}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            if (InverterOnline == True)  and (voltage != 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1611, 'switchcmd': 'On', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            elif (InverterOnline == True) and (voltage == 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1611, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))

                            else :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1611, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
 
        #upload values to Domoticz voor inverter 3
                        if (i == 2) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1615, 'svalue': InverterTemperature}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            if (InverterOnline == True)  and (voltage != 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1612, 'switchcmd': 'On', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            elif (InverterOnline == True) and (voltage == 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1612, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))

                            else :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1612, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
 
        #upload values to Domoticz voor inverter 4
                        if (i == 3) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1616, 'svalue': InverterTemperature}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            if (InverterOnline == True)  and (voltage != 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1613, 'switchcmd': 'On', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
                            elif (InverterOnline == True) and (voltage == 0) :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1613, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))

                            else :
                                getVars = {'type' : 'command', 'param' : 'switchlight', 'idx': 1613, 'switchcmd': 'Off', 'level': 0, 'passcode': '' }
                                webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars))
 
        #upload power values to Domoticz voor inverter 1
                        if (i == 0) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1608, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 0) and (x == 1) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1617, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 0) and (x == 2) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 198, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 0) and (x == 3) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 199, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
 
        #upload power values to Domoticz voor inverter 2
                        if (i == 1) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1618, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 1) and (x == 1) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1619, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 1) and (x == 2) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 202, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 1) and (x == 3) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 203, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
 
        #upload power values to Domoticz voor inverter 3
                        if (i == 2) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1620, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 2) and (x == 1) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1621, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 2) and (x == 2) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 206, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 2) and (x == 3) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 207, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
 
        #upload power values to Domoticz voor inverter 4
                        if (i == 3) and (x == 0) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1622, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 3) and (x == 1) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 1623, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 3) and (x == 2) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 210, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
                        elif (i == 3) and (x == 3) :
                            getVars = {'type' : 'command', 'param' : 'udevice', 'nvalue' : 0, 'idx': 211, 'svalue': (power)}
                            webUrl = urllib.request.urlopen(url + urllib.parse.urlencode(getVars) + (puntcomma) + '0')
 
 
        except Exception as err:
            print(f"[ERROR]", {err})
 
        #print(f"Sleeping for {sleep} sec")
        time.sleep(sleep)
  • Plaats de plug-in en bovenstaand script in je Domoticz map onder scripts/python/ECU-R.
  • Maak een Dummy sensor aan in Domoticz en noem deze ‘Virtual switches’ of een andere duidelijke naam.

Dummy sensoren toevoegen in Domoticz

Dummy sensor toevoegen in Domoticz
Dummy sensor toevoegen in Domoticz
  • Maak een virtuele sensor aan van het type ‘Elektra (Actueel + teller)’. Geef de sensor de naam ‘Opwekking zonnepanelen’.
Virtuele sensor aanmaken voor opwekking zonnepanelen
Virtuele sensor aanmaken voor opwekking zonnepanelen
  • Maak een virtuele sensor aan van het type ‘Schakelaar’ en noem deze Inverter [nummer inverter].
  • Herhaal deze stap voor het aantal micro-omvormers dat je hebt.
Virtuele sensor aanmaken voor APSystem omvormer
Virtuele sensor aanmaken voor APSystems omvormer
  • Maak een virtuele sensor aan van het type ‘Verbruik (Elektra)’ en noem deze Inverter [nummer inverter] – Power [paneelnummer].
  • Herhaal deze stap voor het aantal panelen per micro-omvormer.
Virtuele sensor t.b.v. opgewekt vermogen omvormer
Virtuele sensor t.b.v. opgewekt vermogen omvormer
  • Maak een virtuele sensor aan van het type ‘Temperatuur’ en noem deze Inverter [nummer inverter] – Temperatuur.
  • Herhaal deze stap voor het aantal micro-omvormers dat je hebt.
Virtuele sensor voor temperatuurweergave omvormer
Virtuele sensor voor temperatuurweergave omvormer
  • Maak een virtuele sensor aan van het type ‘Tekst’ en noem deze Timestamp.
  • Ga naar ‘Apparaten’ en pas in bovenstaand script de idx-en aan naar de idx van de virtuele sensoren welke je net hebt aangemaakt en sla het script op.
  • Start het script op met het commando python3 <Domoticz map>/scripts/python/ECU-R/ECU-R.py.
  • Om het script na elke reboot van de Raspberry Pi automatisch laten opstarten dien je de volgende regel toe te voegen in crontab: @reboot python3 /home/pi/domoticz/scripts/python/ECU-R/ECU-R.py.

Update 25-01-2023

Gebruiker Sebastiaan Terlouw heeft het script iets aangepast waardoor deze nu ook compatible is voor de DS3 regelaar.

Update 15-02-2023

Sebastiaan Terlouw heeft het netvoltage toegevoegd aan het script.