This adapter integrates APSystems inverters via APSystems ECU-R/ECU-B communication unit to collect data from solar modules.
The adapter queries the local ECU using the proprietary APSytems ECU to EMAapp protocol. It collects realtime information and history data from the ECU about the configured inverters.
The ECU supports several connections and protocols on its LAN and WLAN interface. This implementation is focused on the services available via WLAN TCP port 8899 and the so called command group 11 of the ECU.
This project was only possible because of the great protocol analysis work of @checking12, @HAEdwin and other people on the home assistant forum.
There exists already a Python implementation for home assistant
ksheumaker/homeassistant-apsystems_ecur which was used to get a better understanding of the ECU behavior.
See also the discussion in APsystems APS ECU R local inverters data pull for more details.
apsystems-ecu is a new development in JavaScript for iobroker.
The ECU has to run in its 'normal mode' and has to be connected to the local network and the internet. A connection to the EMA cloud seems to be needed or the Ecu will not offer the used services (but this was not deeper investigated). In my system only the WLAN interface of the Ecu is used. The usage of the LAN interface was not investigated.
The Ecu uses zigbee to communicate with the configured inverters. The poll time of the Ecu to inverter communication in smaller systems is normally 300sec.
It's reported that the cycle time will increase in bigger systems but I could not investigated.
The adapter connects cyclic to the Ecu via TCP port 8899 (default) (port and IP address can be configured) and collects data. The adapter poll time can be configured. Received data used to update the iobroker database. Objects and states are automatically created if new devices (inverters) are online.
Remark:
Only the following interface and protocol is supported
Implementation of all (known) command group 11 services
Cyclic request of realtime services GetSystemInfo, GetRealTimeData and GetInverterSignalLevel
Calling GetPowerOfDay service by command
Calling GetEnergyOfWeekMonthYear service by command
The adapter computes sunrise and sunset based on the iobroker system settings at midnight.
There are several projects about APsystems Inverters available using different interfaces.
Just an incomplete list of links ...
Request: "APS1100160001END\n"
Response | Start Index | Length | Coding | Name | Remark |
---|---|---|---|---|---|
Header | |||||
0 | 3 | ASCII | SignatureStart | always "APS" | |
3 | 2 | ASCII | CommandGroup | always"11" | |
5 | 4 | ASCII | ResponseLenght | from "APS" to "END" | |
9 | 4 | ASCII | CommandCode | "0001" - GetSystem Info | |
ECU data | |||||
13 | 12 | ASCII | ECU-Id | ||
25 | 2 | ASCII | ECIModel | ||
27 | 4 | HEX | LifeTimeEnergy | /10 kWh | |
31 | 4 | HEX | LastSystemPower | W | |
35 | 4 | HEX | CurrentDayEnergy | /100 - kWh | |
39 | 7 | BCD | LastTimeConnectedEMA | always D0D0D0D0D0D0 | |
46 | 2 | HEX | Inverters | ||
48 | 2 | HEX | InvertersOnline | ||
50 | 2 | ASCII | EcuChannel | always "10" | |
52 | 3 | ASCII | VersionLength (vlen) | e.c. "014" | |
55 | vlen | ASCII | Version | e.c. "ECU_R_1.2.17T4" | |
55+vlen | 3 | ASCII | TimeZoneLen (tzlen) | e.c. "009" | |
58+vlen | tzlen | ASCII | TimeZone | (always?) "Utc/GMT-8" | |
58+vlen+tzlen | 6 | HEX | EthernetMAC | ||
64+vlen+tzlen | 6 | HEX | WirelessMAC | ||
Footer | |||||
70+vlen+tzlen | 3 | ASCII | SignaturStop | always "END" | |
73+vlen+tzlen | 1 | ASCII | always "\n" |
Request: "APS110028000221600xxxxxxxEND\n" where 21600xxxxxx=ECUId
Response | Start Index | Length | Coding | Name | Remark |
---|---|---|---|---|---|
Header | |||||
0 | 3 | ASCII | SignatureStart | always "APS" | |
3 | 2 | ASCII | CommandGroup | always"11" | |
5 | 4 | ASCII | ResponseLenght | from "APS" to "END" | |
9 | 4 | ASCII | CommandCode | "0002" - GetRealTimeData | |
13 | 2 | ASCII | MatchStatus | "00"/"01" - ok/no data | |
Common Data | |||||
15 | 2 | ASCII | EcuModel | ||
17 | 2 | HEX | Inverters | Nuber of inverter entries in RSP | |
19 | 7 | BCD | DateTime | ||
entry for each inverter | |||||
common for all Inverter | |||||
26 | 6 | ASCII | InverterId | "408000xxxxxx" | |
32 | 1 | HEX | State | 0x00/0x01 - offline/online | |
33 | 2 | ASCII | InverterType | "00/"01"/"02"/"03" - unknown/YC600,DS3/YC1000/QS1 | |
common if InverterType == "01"/"02"/"03" | |||||
35 | 2 | HEX | Frequency | 0.1 - Hz | |
37 | 2 | HEX | Temperature | -100 - °C | |
if YC600 or DS3 | |||||
39 | 2 | HEX | Power1 | ||
41 | 2 | HEX | AcVoltage1 | ||
43 | 2 | HEX | Power2 | ||
45 | 2 | HEX | AcVoltage2 | ||
if YC1000 | |||||
39 | 2 | HEX | Power1 | ||
41 | 2 | HEX | AcVoltage1 | ||
43 | 2 | HEX | Power2 | ||
45 | 2 | HEX | AcVoltage2 | ||
47 | 2 | HEX | Power3 | ||
49 | 2 | HEX | AcVoltage3 | ||
51 | 2 | HEX | notclear | ||
if QS1 | |||||
39 | 2 | HEX | Power1 | ||
41 | 2 | HEX | AcVoltage | ||
43 | 2 | HEX | Power2 | ||
45 | 2 | HEX | Power3 | ||
47 | 2 | HEX | Power4 | ||
… | |||||
Footer | |||||
len-4 | 3 | ASCII | SignatureStop | always "END" | |
len-1 | 1 | ASCII | always "\n" |
Inverter Id's
| Type | Id-Prefix
| YC600 | "40xxxxxxxxxxx"
| YC1000 | "50xxxxxxxxxxx"
| DS2 | "70xxxxxxxxxxx"
| QS1 | "80xxxxxxxxxxx"
Request: "APS110039000321600xxxxxxxENDddddddddEND\n" where 21600xxxxxxx=ECUId dddddddd=Date (BCD e.c. 20220209)
Response | Start Index | Length | Coding | Name | Remark |
---|---|---|---|---|---|
Header | |||||
0 | 3 | ASCII | SignatureStart | always "APS" | |
3 | 2 | ASCII | CommandGroup | always"11" | |
5 | 4 | ASCII | ResponseLenght | from "APS" to "END" | |
9 | 4 | ASCII | CommandCode | "0003" - GetEnergyOfWeekMonthYear | |
13 | 2 | ASCII | MatchStatus | "00"/"01" - ok/no data | |
for each power value | |||||
15 | 2 | BCD | Time | ||
17 | 2 | HEX | PowerOfDay | ||
… | |||||
Footer | |||||
len-4 | 3 | ASCII | SignatureStop | always "END" | |
len-1 | 1 | ASCII | always "\n" |
Request: "APS110039000421600xxxxxxxENDppEND\n" where 21600xxxxxxx=ECUId, pp=Period ("00"/"01"/"02" - week/month/year)
Response | Start Index | Length | Coding | Name | |
---|---|---|---|---|---|
Header | |||||
0 | 3 | ASCII | SignatureStart | always "APS" | |
3 | 2 | ASCII | CommandGroup | "11" or "12" | |
5 | 4 | ASCII | ResponseLenght | ||
9 | 4 | ASCII | CommandCode | "0004" - GetEnergyOfWeekMonthYear | |
13 | 2 | ASCII | MatchStatus | "00"/"01" - ok/no data | |
Common Data | |||||
15 | 2 | ASCII | WeekMonthYear | 00=week, 01=month, 02=year | |
for each power value | |||||
17 | 4 | BCD | Date | yyymmdd | |
21 | 2 | HEX | PowerOfDay | if CommandGroup 11 | |
21 | 4 | HEX | PowerOfDay | if CommandGroup 12 | |
… | |||||
Footer | |||||
len-4 | 3 | ASCII | SignatureStop | always "END" | |
len-1 | 1 | ASCII | always "\n" |
Request: "APS110028000421600xxxxxxxEND\n" where 21600xxxxxxx=ECUId
Response | Start Index | Length | Coding | Name | |
---|---|---|---|---|---|
Header | |||||
0 | 3 | ASCII | SignatureStart | always "APS" | |
3 | 2 | ASCII | CommandGroup | always"11" | |
5 | 4 | ASCII | ResponseLenght | from "APS" to "END" | |
9 | 4 | ASCII | CommandCode | "0030" - GetInverterSignal | |
13 | 2 | ASCII | MatchStatus | "00"/"01" - ok/no data | |
for each inverter | |||||
17 | 6 | BCD | InverterId | yyymmdd | |
21 | 1 | HEX | SignalLevel | ||
… | |||||
Footer | |||||
len-4 | 3 | ASCII | SignatureStop | always "END" | |
len-1 | 1 | ASCII | always "\n" |
MIT License - Copyright (c) 2021-2022 npeter peter_n@gmx.de
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.