APsystem - Solar monitoring


Sinds this month I have a APsystems Solar system with an ECU to collect data from the solarpanels.
This ECU sends its data to the apsystems cloud monitoring.
Now I found a script that pulls data from the apsystems cloud api and pushes this to pvoutput.
In homeassistant I configured the pvoutput plugin to combine the solar data from apssystems with my other solarpanels.

I was wondering if it is possible to create a integrations for apsystems so that homeassistant can monitor the cloud system trough the api.

Anyone else using this system?

Hi Frank,

Could you share that script? I would love to also play with it.

thanks in advance.

This is the script I am using now:


import requests
import json
from datetime import date
from datetime import datetime
import os.path

#id's and keys

#enter a path and filename below, a file wil be create to save the last update datetime
LAST_UPDATE_FILE = "E:\pvoutput.txt" #example "text.txt" or "/home/pi/aps/lastupdate"

#usually all below this point should not be modified
APSYSTEMS_URL = 'http://api.apsystemsema.com:8073/apsema/v1/ecu/getPowerInfo'
PVOUTPUT_URL = 'http://pvoutput.org/service/r2/addstatus.jsp'

def readLastUpdate():
    f = open(LAST_UPDATE_FILE,"r")
    datestring = f.read()
    return datetime.strptime(datestring, "%Y%m%d %H:%M")

def writeLastUpdate(timestringminutes):
    f = open(LAST_UPDATE_FILE,"w+")
    f.write(getDateStringOfToday()+ ' ' +timestringminutes)

def getDateStringOfToday():
    return date.today().strftime("%Y%m%d");

def getDataFromAPS():
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',

    data = {
      'ecuId': ECU_ID,
      'filter': 'power',
      'date': getDateStringOfToday()

    response = requests.post(APSYSTEMS_URL, headers=headers, data=data)
    return response.json();

def sendUpdateToPVOutput(timestringminutes, powerstring):
    pvoutputdata = {
      'd': getDateStringOfToday(),
      't': timestringminutes,
      'v2': powerstring

    headerspv = {
        'X-Pvoutput-SystemId': PV_OUTPUT_SYSTEMID,
        'X-Pvoutput-Apikey': PV_OUTPUT_APIKEY

    responsepv = requests.post(PVOUTPUT_URL, headers=headerspv, data=pvoutputdata)

    print ("Response: " + responsepv.text + " updated: " + timestringminutes + " power: " + powerstring)

if not os.path.isfile(LAST_UPDATE_FILE):
    writeLastUpdate('00:00') #create file for the first time

rootdict = getDataFromAPS()
timesstring = rootdict.get("data").get("time")
powersstring = rootdict.get("data").get("power")

timelist = json.loads(timesstring)
powerlist = json.loads(powersstring)
latestUpdate = readLastUpdate()
print("Found latest update: ")

i = len(timelist) - 1
count = 0;
while i >= 0 and count < MAX_NUMBER_HISTORY:
    timestringminutes = timelist[i][:-3] #get time and strip the seconds
    powerstring = powerlist[i] #get power

    currentUpdate = datetime.strptime(getDateStringOfToday()+ ' ' +timestringminutes, "%Y%m%d %H:%M")

    if currentUpdate > latestUpdate:
        sendUpdateToPVOutput(timestringminutes, powerstring)
        print("No update needed for: " + timestringminutes)

    if count == 0:
    i -= 1
    count += 1

I run this script with a scheduled task in Windows

would it also be possible to extract it from the local ECU unit ? this would reduce the need for authorization tokens etc ?

I also have an APSystems monitored solar unit.

During install and configuration the unit broadcasts its own WiFi network and all data can be accessed via the APSystemsECU app to verify connection. Configuration is done through that app, after which it joins the customer’s WiFi network and starts reporting data to the cloud service. After that point the customer is instructed to use the APSystemsEMA app or the website to access the data via the cloud service.

I’ll see if I can locate some way to access the ECU directly on my own network as well; meanwhile I’ll be eagerly watching this thread since I just set up my Home Assistant install yesterday.

I have checked this but on the ip address of the ECU there are no open ports. As far is I can find there was in a early version of the ECU a local webinterface where you can pull info out. But in the new version it is not available. Maybe there is a way to enable it but there is nog much info around on the internet.

you’re right. maybe it needs to be put in some kind of dev/debug mode or something. maybe like pressing the “ap” button but then permanently.

I ran the script, and it doesn’t even need authentication so my concern about hassle was unfounded :wink:

My findings are similar; you can press the button and get it to broadcast its own wireless network that connects with the ECUApp. Once that expires or is configured to connect to an existing Wi-Fi, the ECU starts reporting data to the website and stops being available locally. The website seems to be the only choice for the ECU-R.

I installed appdaemon and the script, which worked out of the box but I made some tweaks, and then created my own module to pull my net metering stats from my power provider (Florida Power and Light) as well.

I’m learning how to write addons directly for HA, and am using the FPL as a sample case, but plan to do the same with the APSystems EMA as well. I’ll contribute the code for both once I have something that works.

This is a side project for me in addition to both work and school, any my first addon code, so I don’t have a timeline for completion.

Sorry, it wasn’t Frank’s script that I installed into appdaemon and ran. It was another script I found in another thread: https://github.com/felipegonzalez/homeassistant-cuau/blob/217ca75e742218df9c8bb24c116f9d28e0f825d0/appdaemon/config/apps/ap_systems.py

I was trying this way, but… I think won’t work ever!!!

I have a hass.io Rpi.
Is there a way to running it in the same Home Assistant hardware?

Did you get some good news on the Integration Implement?

Here is another threat @olivier got it working throught Scraping ECU web interface…
Aparently he got access via his ECU unit…

   platform: scrape
   resource: 1
   select: " tr:nth-child(2) > td"
   name : Lifetime_generation
   value_template: ‘{{ ((value.split(" ")[0]) | replace (“KW”, “”)) }}’
   unit_of_measurement: “kWh”
   scan_interval: 60

I’m building my Solar array this month, and will be using APSystems micro-inverters.

I was wondering if there’s a way to skip their cloud service and log everything locally?

@phrfpeixoto Are you using an ECU as well? I have written a windows program that proves that you can indeed work independently of the cloud. So it’s just a POC not a data logger. The most important thing is to return a correct timestamp to the ECU-R (don’t know if it also applies to the ECU-C). If the returned timestamp does not match the last data sent from the ECU, the ECU will retransmit buffered data frames or go into error modus. It requires some Python knowledge to deploy the four necessary socket channels for this purpose. Also, the DNS query from ECU to apsystemsema must be routed locally to the node that is capturing the data. But that was all under investigation in January of this year. Meanwhile, the necessary firmware versions for the ECU-R have been released and since I now know what is being sent, I don’t feel the urg to work off cloud anymore. Data also does not include temperature and Zigbee signal strenght.

There is an integration for HA available on Github (based on the ECUapp) and there is also a discussion on GitHub to directly read Zigbee from the inverters without ECU.

Note: registration to the EMA cloud is available for DIY installers

Hi @killabee.nl,

Since your post, there have been some changes. There is an integration available on GitHub. It reads the ECU same way the ECUapp without the need of activating the ECU’s own WiFi point. Ports are open (Wifi as well as ethernet).

Amazing work! Congratulations! Is that open source? Any way I can deploy it directly on an RPi running local and push the necessary data through MQTT?

Your screenshot shows the raw socket comms, but we can’t see exactly which parameters are being reported by the ECU, and what sensors we could create from that data.

I’d like to avoid the cloud as much as possible.

The bottom line is that the ECU expects a response to the data sent by the ECU to the EMA cloud.

Every 5 minutes the ECU opens port 8995 or 8996 and sends out the data to EMA. In response the ECU expects a timestamp -5 minutes so that the ECU data buffer is maintained. Port 8995 or 8996 is being closed after a while so response must be given while the port is open. Command and Timestamp format is 10120210328100026. If no response is sent, ECU shuts down after a while, thinking there is no internet connectivity.

I’m now investigating if timestamp responses must be given on these two ports or can also be given on 8899. This is the query port the ECUapp uses. Purpose is to keep the ECU up’n’running.

EDIT: Well this experiment failed :woozy_face:

It would take some programming experience to build this in Python the ECU responses can be what confusing if it empties the data buffer so it is complex. Less parameters are available (no inverter temperature and inverter signal strenght).

Apparently this is not working for me now. Is this still working for you or have they closed up this kind of access?

Due the problem with the old apsystems API that is not working anymore, I create a new HTTP APsystems Sensor. It is in HACS structure. So if you are using HACS, just add this repository:

It uses the https://apsystemsema.com web site to get the information. So it works with any APsystems inverter / ECU model.

Please, help me to test. If you like, just give me a beer :slight_smile:

I got access to an ECU-C for 1hour.
I found out that you can activate Sunspec Modbus on the ECU-C.
Next i have installed the Modbus Doctor Software.

Modbus TCP will work on ECU-C

I have read the holding register 40000-40399 and i got an answer.
may be other registers are also OK
it seems that the registers are the same as solaredge

Next is to find out all the registers that are used.
have a nice day