Integration of Ampere.IQ inverter/battery and Kiwigrid Energy Manager

Hi,

I am trying to integrate my new PV inverter and battery, but unfortunately the manufacturer doesn’t provide too much information about his interfaces.

According to the manual it provides Ethernet, WLAN and Modbus - which is not really precise :frowning:

The System consists of a hybrid inverter (with battery) and a smart box. The smart box is a white labeled Entergy Manager RailX from Kiwigrid ( Energy Manager RailX | Produkte | Kiwigrid).

Doing some discovering on the line I found some open ports on the smart box but the inverter seems to be in stealth mode (at least nmap doesn’t come up with usable results).

While listening on the line with Wireshark I found that the smart box and the inverter are heavily talking via Modbus TCP and I discovered the following Regersters which are read all the time:

# Reference 	words
# 16489	        6
# 16493         62
# 16629         114
# 40972         24
# 41023         13

Of course, I don’t know what the data is behind those registers but eventually they help to identify what kind of inverter is behind that system. I just can’t believe that they really built their own inverter and not just white labeled another brand :slight_smile:

I tried to use “Sundspec” Plugin and hoped that it works - unfortunately it doesn’t. Actually, the inverter answers with an error message when asking for the holding register 40000.

Any help in identifying what I got here is highly appreciated.

Currently I am in discussion with the manufacturer to get the description of the Modbus registers - but that currently seems to become a endless story :frowning:

I will also have some kind of Kiwigrid Box in my Inverter and Battery.
In search how to integrate them into Homeassistant i stumbled upon these links:

Here they talk about Cross-Vendor APIs - perhaps we find a way for integration here?

Yep they do talk about those APIs - but they are a closed shop and only vendors gain access to these APIs. I already registered and contacted sales with the idea to integrate that Plattform into HA. No reaction for two weeks so far, but I will follow up on that shortly.

Meanwhile I discovered the Modbus interface of the Ampere StoragePro inverter. After doing some pretesting and identifying all the registers delivering any data, I am reengineering the type of value I am reading from the inverter.

Already found some useful data like string voltage, current and power, battery charging power, battery level, overall PV power, power consumption of my house.

But that’s a really small subset of data I am able to receive. There are some plots which I just don’t have a glue what it is or how they relate to the other data I am seeing.

For example I am seeing four plots which are absolutely similar except that each of these plots delivers a different value. So there is a small distance between the values all the time. I know the inverter is three phased and it could be L1,2,3 and overall values, but assumption is totally wrong as the phases will never ever plot the same line over time. But they are definitely related to power - but from what…

Just found this now. I was able to read most of the paramters via the REST API of the Energy Manager (Called Ampere.IQ). See here what I found.

@rak
Thanks for the hint - haven’t found that SAJ convervter yet.

Unfortunately, either SAJ or EKD are smart enough to turn off the API access as I always get “connection refused” error when trying to connect to the converter via http or https :frowning:

I reached out to them but got also the message I should contact sales…
Perhaps this helps a little:

Here is the answer from them:

Kiwigrid bietet keine APIs für den Endnutzer an, sondern nur für die Integration des Kiwigrid-Systems für unsere B2B Kunden. Aus diesem Grund sind unsere APIs nicht öffentlich.
Wenn Sie als Endnutzer den Wunsch haben, weitere Systeme zu integrieren, dann empfehle ich Ihnen, an Ihren Vertriebspartner (EKD, Zolar, BayWa, …) heranzutreten, der solch eine Integration vornehmen kann.

Viele Grüße, vom Kiwi-Team

means in English:

Kiwigrid does not offer APIs for the end user, but only for the integration of the Kiwigrid system for our B2B customers. For this reason, our APIs are not public.
If you as an end user wish to integrate other systems, I recommend that you contact your sales partner (EKD, Zolar, BayWa, …) who can carry out such an integration.

Best regards, from the Kiwi team

So we could try to let them activate the API for us? Or does Homeassistant need to cooperate with them?

I would also like to integrate the Ampere into HomeAssistant. I’m still missing some data to be completely local.

We can exchange the Modbus data to find out the protocol.

I have already created a ymal file to read the data from the inverter.

Here my current .yaml to read inverter information over modbus.

Note: The AmpereStorage can only handle two Modbus connections simultaneously. If an Ampere.IQ is connected, this must be observed!

modbus:
  - name: ApmerePro
    type: tcp
    host: 192.168.178.xx
    port: 502

    sensors:
      - name: PV1 Voltage
        unique_id: ampere_pv1_voltage
        device_address: 3
        address: 517
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: V
        device_class: Voltage
        state_class: measurement
        scale: 0.1
        scan_interval: 10

      - name: PV1 Current
        unique_id: ampere_pv1_current
        device_address: 3
        address: 518
        input_type: input
        data_type: int16
        precision: 2
        unit_of_measurement: A
        device_class: Current
        state_class: measurement
        scale: 0.01
        scan_interval: 10

      - name: PV1 Power
        unique_id: ampere_pv1_power
        device_address: 3
        address: 519
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: PV2 Voltage
        unique_id: ampere_pv2_voltage
        device_address: 3
        address: 520
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: V
        device_class: Voltage
        state_class: measurement
        scale: 0.1
        scan_interval: 10

      - name: PV2 Current
        unique_id: ampere_pv2_current
        device_address: 3
        address: 521
        input_type: input
        data_type: int16
        precision: 2
        unit_of_measurement: A
        device_class: Current
        state_class: measurement
        scale: 0.01
        scan_interval: 10

      - name: PV2 Power
        unique_id: ampere_pv2_power
        device_address: 3
        address: 522
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: Battery Level
        unique_id: ampere_battery_level
        device_address: 3
        address: 1339
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: "%"
        device_class: battery
        state_class: measurement
        scale: 1
        scan_interval: 60

      - name: Battery Running state
        unique_id: ampere_battery_running_state
        device_address: 3
        address: 1340
        input_type: input
        data_type: uint16
        precision: 0
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: Battery Voltage
        unique_id: ampere_battery_voltage
        device_address: 3
        address: 531
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: V
        device_class: Voltage
        state_class: measurement
        scale: 0.1
        scan_interval: 10

      - name: Battery Current
        unique_id: ampere_battery_current
        device_address: 3
        address: 532
        input_type: input
        data_type: int16
        precision: 2
        unit_of_measurement: A
        state_class: measurement
        device_class: Current
        scale: 0.01
        scan_interval: 10

      - name: Battery Power
        unique_id: ampere_battery_power
        device_address: 3
        address: 535
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: Battery Temperature
        unique_id: ampere_battery_temperature
        device_address: 3
        address: 1344
        input_type: input
        data_type: uint16
        precision: 1
        unit_of_measurement: °C
        device_class: Temperature
        scale: 0.1
        scan_interval: 60

      - name: Total active power
        unique_id: total_active_power
        device_address: 3
        address: 1348
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: L1 active power
        unique_id: l1_active_power
        device_address: 3
        address: 1349
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: L2 active power
        unique_id: l2_active_power
        device_address: 3
        address: 1350
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: L3 active power
        unique_id: l3_active_power
        device_address: 3
        address: 1351
        input_type: input
        data_type: int16
        precision: 0
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        scale: 1
        scan_interval: 10

      - name: Daily PV Generation
        unique_id: ampere_daily_pv_generation
        device_address: 3
        address: 16576
        input_type: input
        data_type: uint16
        precision: 2
        unit_of_measurement: kWh
        device_class: energy
        state_class: total_increasing
        scale: 0.01
        scan_interval: 600

      - name: Monthly PV generation
        unique_id: ampere_monthly_pv_generation
        device_address: 3
        address: 16577
        input_type: input
        data_type: uint32
        precision: 2
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
        scale: 0.01
        scan_interval: 600

      - name: Year PV generation
        unique_id: ampere_year_pv_generation
        device_address: 3
        address: 16579
        input_type: input
        data_type: uint32
        precision: 2
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
        scale: 0.01
        scan_interval: 600

      - name: Total PV generation
        unique_id: ampere_total_pv_generation
        device_address: 3
        address: 16581
        input_type: input
        data_type: uint32
        precision: 2
        unit_of_measurement: kWh
        device_class: energy
        state_class: total
        scale: 0.01
        scan_interval: 600

      - name: BMS Software Version
        unique_id: ampere_bms_software_version
        device_address: 3
        address: 33061
        input_type: input
        data_type: int16
        precision: 0
        scale: 0.01
        scan_interval: 600

      - name: BMS Hardware Version
        unique_id: ampere_bms_hardware_version
        device_address: 3
        address: 33062
        input_type: input
        data_type: int16
        precision: 0
        scale: 0.01
        scan_interval: 600

      - name: Batterycluster
        unique_id: ampere_battery_cluster
        device_address: 3
        address: 33063
        input_type: input
        data_type: string
        count: 6
        scan_interval: 600

      - name: Inverter Modell
        unique_id: ampere_inverter_model
        device_address: 3
        address: 33280
        input_type: input
        data_type: string
        count: 7
        scan_interval: 600

      - name: Inverter SN
        unique_id: ampere_inverter_sn
        device_address: 3
        address: 36611
        input_type: input
        data_type: string
        count: 9
        scan_interval: 600

template:
  - sensor:
      - name: Inverter power
        unique_id: ampere_inverter_power
        unit_of_measurement: W
        device_class: power
        state_class: measurement
        availability: >-
          {{ 
          not is_state('sensor.pv1_power', 'unavailable') 
          and not is_state('sensor.pv2_power', 'unavailable') 
          }}
        state: "{{ (states('sensor.pv1_power') | int + states('sensor.pv2_power') | int ) | int }}"

Thanks for that hint.

I found the modbus data model somewhere on a google drive account and implemented the whole model as input in Telegraf. This streams all data into my InfluxDB and I can visualize everything in Grafana easily :slight_smile:

That actually works fine, as long as I disconnect the Ampere.IQ SmartBox from KiwiGrid. As this box is currently absolutely useless in my setup, I just turned it off :slight_smile:

Probably the box will become important when I connect a Wallbox but as I don’t have any administrative privileges on that box, I believe it’ll stay an energy consuming brick of uselessness.

Actually, there are some measures which seem to be wrong. For example the active power of GRID and Inverter, all three phases follow the same path:

I would presume that, depending on current power requirements, the phases should show different power readings. For exampl when I turn on my hair dryer oder water boiler that should draw 1-2 kW on a single phase - hence that phase should differ in that reading somehow.

What do you mean with “this must be observed”? As in “checking if the ampere.iq loses connection to the inverter when HA is also online”?
Also: if it can handle 2 connections, and one of them is “occupied” by the Ampere.IQ, shouldnt using the second connection via HA be fine? Or does the Kiwi Gateway also directly talk to the inverter, therefore blocking the second connection?

What else I wanted to mention:
I used Modbus via yaml and nodered at the same time in HA. Then later Ampere.IQ was set up and I lost the connection in nodered even though I had set a different ‘device_address’.
Hence the note: If an Ampere.IQ has been installed (default device address: 1), only one other channel can be used for Modbus (device address > 1).

I hope I was able to explain this well

I am not using HA Modbus integration because it never worked reliable with the inverter interface.

In my case I just don’t receive any answer from the inverter even if the Modbus-Query (I checked the query with Wireshark) is correct. I found that this behavior is the only what happens if the access rules of that interface are violated.

Since I am using telegraf to query the inverter (with different device address) and turned off the Ampere.IQ box everything runs perfectly.

Interesting, I’ve had modbus integration running for months.
I’m currently in the process of writing an integration (my first and I have to read Dokumentation and understand it first)

1 Like

if you need a beta tester drop me a message.

This is very interesting for me! I will test your modbus integration in the next days, When you are ready with your integration, I would like to test this as well!

@Dawidh @U.Dicke

Would you please be so kind and let me know what the value of these registers are:


        { measurement = "EKD_Powermeter_Data", name = "Meter_A_status", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41020]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_voltage_1", byte_order = "AB", data_type = "UINT16", scale = 0.1, address = [41021]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_current_1", byte_order = "AB", data_type = "INT16", scale = 0.01, address = [41022]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_real_power_1", byte_order = "AB", data_type = "INT16", scale = 1.0, address = [41023]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_apparent_power_1", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41024]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_power_factor_1", byte_order = "AB", data_type = "INT16", scale = 0.001, address = [41025]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_A_frequency_1", byte_order = "AB", data_type = "UINT16", scale = 0.01, address = [41026]},

        { measurement = "EKD_Powermeter_Data", name = "Meter_B_status", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41043]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_voltage_1", byte_order = "AB", data_type = "UINT16", scale = 0.1, address = [41044]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_current_1", byte_order = "AB", data_type = "INT16", scale = 0.01, address = [41045]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_real_power_1", byte_order = "AB", data_type = "INT16", scale = 1.0, address = [41046]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_apparent_power_1", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41047]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_power_factor_1", byte_order = "AB", data_type = "INT16", scale = 0.001, address = [41048]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_frequency_1", byte_order = "AB", data_type = "UINT16", scale = 0.01, address = [41049]},

        { measurement = "EKD_Powermeter_Data", name = "Meter_B_voltage_2", byte_order = "AB", data_type = "UINT16", scale = 0.1, address = [41050]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_current_2", byte_order = "AB", data_type = "INT16", scale = 0.01, address = [41051]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_real_power_2", byte_order = "AB", data_type = "INT16", scale = 1.0, address = [41052]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_apparent_power_2", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41053]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_power_factor_2", byte_order = "AB", data_type = "INT16", scale = 0.001, address = [41054]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_frequency_2", byte_order = "AB", data_type = "UINT16", scale = 0.01, address = [41055]},

        { measurement = "EKD_Powermeter_Data", name = "Meter_B_voltage_3", byte_order = "AB", data_type = "UINT16", scale = 0.1, address = [41056]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_current_3", byte_order = "AB", data_type = "INT16", scale = 0.01, address = [41057]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_real_power_3", byte_order = "AB", data_type = "INT16", scale = 1.0, address = [41058]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_apparent_power_3", byte_order = "AB", data_type = "UINT16", scale = 1.0, address = [41059]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_power_factor_3", byte_order = "AB", data_type = "INT16", scale = 0.001, address = [41060]},
        { measurement = "EKD_Powermeter_Data", name = "Meter_B_frequency_3", byte_order = "AB", data_type = "UINT16", scale = 0.01, address = [41061]},

According to the documentation this should provide the information from the connected SmartMeter (as far as I understand the documentation).

On my 3-phase Inverter the “Meter_A_status” is 1 and “Meter_B_status” is 0.

Personally I would expect to have Meter_B activated as it is a 3-phase setup. Hence, I am suspecting a wrong configuration of my Inverter. If that’s the case, I would need to ask EKD to change this setting.

On my 3-phase Inverter the “Meter_A_status” is 1 and “Meter_B_status” is 0.

This is the same what I see on my site. Therefore I don’t expect any values from “Meter_B_whatever”. At the end the smartmeter DTSU-666 does measure the 3 phases, but it is only needed to help to regulate a zero feed into the grid and a zero consumption from grid as far as possible. Therefore I believe that handling of the total power ist sufficant for that.

Otherwise we both would have the need to ask EKD to change this setting.
My experience with EKD-Solar is: “Don’t waste your time trying to ask” (as long the system does it’s job) :disappointed_relieved:

to complete the informations data from now:

Thank you @Dawidh,
I copied your code into my configuration.yaml, altered the IP-Adress and :tada: it works as expected. Which source did you use for the register adresses? I have read some other adresses in the modbus documentation of the assumed build in inverter.

Picture:

Please notify me when your integration is ready to test! :grinning:

I read out the data directly as a byte stream and analyzed everything (for weeks, every day).
I wrote it all down in an Excel table and then transferred it to a modbus file.

My current repro:

I hope to have a beta integration ready this week. Otherwise only after Easter. This will then go into a new git repro