Alfen Eve Pro EV chargepoint interface via TCP modbus

Hello,

I implemented an interface to read out sensors and set the charge current on an Alfen Eve Pro chargepoint for electrical vehicles.

My goal: being able to store locally generated energy in the car battery instead of delivering it back into the grid.

We have a digital electricity meter that has a P1 port. This port tells you every second how much energy is consumed from the net, and -in case of overproduction- how much energy is sent back into the grid.
This port can be interfaced with DSMR reader that will post energy consumption figures via MQTT. Using that information I can figure out if the house is delivering energy back to the grid, and if it is, instruct the chargepoint to charge the car battery instead. At the current electricity prices, this bring me a netto gain of 0.20 :euro: per kWh.

What I implemented results in dynamic control of the charge current for the electric vehicle taking into account the local consumption of the house too. The graph below shows how this looks (static charging from 9:30 … 10:30 and then dynamic charging on a day with fluctuating solar generation).

skitch

The interface to the chargepoint happens via modbus over TCP. You need to enable this setting on your chargepoint via the control software of Alfen, it is not enabled by default.

To read out the sensors, add the following section to your configuration.yaml:

modbus:
  - name: laadpaal
    type: tcp
    host: 192.168.xxx.yyy
    port: 502
    sensors:
      - name: laadpaal_name
        slave: 200
        address: 100
        count: 17
        data_type: string
      - name: laadpaal_temperature
        slave: 200
        address: 1102
        data_type: float32
        unit_of_measurement: °C
      - name: laadpaal_active_max_current
        slave: 200
        address: 1100
        data_type: float32
        unit_of_measurement: A
      - name: laadpaal_real_power_sum
        slave: 1
        address: 344
        data_type: float32
        unit_of_measurement: W
      - name: laadpaal_mode3_state
        slave: 1
        address: 1201
        count: 5
        data_type: string
        scan_interval: 5
      - name: laadpaal_actual_applied_maxcurrent
        slave: 1
        address: 1206
        data_type: float32
        unit_of_measurement: A
      - name: laadpaal_modbus_maxcurrent
        slave: 1
        address: 1210
        data_type: float32
        unit_of_measurement: A
      - name: laadpaal_socket1_current_valid_time
        slave: 1
        address: 1208
        data_type: uint32
        unit_of_measurement: s

Then to convert the chargepoint mode sensor to a human-readable chargepoint status that you can use in automations, add this template:

template:
  - sensor:
      - name: mode3_sanitized
        state: "{{states('sensor.laadpaal_mode3_state').replace('\0','') }}"
      - name: chargepoint_status
        state: >
          {% set m3 = states('sensor.mode3_sanitized') %}
          {% if m3 in ['A', 'E'] %} available
          {% elif m3 in ['B1', 'B2', 'C1', 'D1'] %} connected
          {% elif m3 in ['C2', 'D2'] %} charging
          {% else %} {{ m3 }}
          {% endif %}

With this you can already read the sensors and the current on your chargepoint and make automations to enable your front lights when you plug in the car when you arrive home in the evening :nerd_face:

Now onto the more interesting part: to be able to set the charge current based on the energy produced by your solar installation. For this you need to be able to call the modbus.write_register function with as parameter a 32-bit float that sets the charge current in amps. If you lookup how a float is represented as a 32-bit value (IEEE 754 format), you’ll see that 16 decimal is represented as 0x41800000. Because a single modbus register can only contain 16 bits, the modbus.write_register function needs to be called with two parameters so that the function knows it needs to perform two consecutive writes to the chargepoint at the right target address.
This means to set the charge current to 16A you need to pass to the function the base address of the correct register and then the parameters 0x4180 and the parameter 0x0000.

I do this via a script in Home Assistant that takes as input the two bytes and passed those to the modbus.write_register function. It looks like this:

alias: Set modbus maxcurrent
variables:
  value_msb: 16768
  value_lsb: 0
sequence:
  - service: modbus.write_register
    data:
      address: 1210
      unit: 1
      hub: laadpaal
      value:
        - '{{ value_msb }}'
        - '{{ value_lsb }}'
mode: single

Then you need a way to call the script to pass the parameters. I do this via an automation that takes the input from MQTT and passes it to the script. This automation looks like this:

alias: '[elek] Set the chargepoint current'
description: 'Pass MQTT current to the script'
trigger:
  - platform: mqtt
    topic: chargepoint/maxcurrent
condition: []
action:
  - service: script.set_modbus_maxcurrent
    data_template:
      value_msb: '{{ trigger.payload_json.value_msb | int}}'
      value_lsb: '{{ trigger.payload_json.value_lsb | int}}'
mode: single

We’re almost there :slight_smile:

Now all we need is a script that implements the rules on when to charge with which current.

The rules I have are simple:

  • default to minimum charge current (6A)
  • when we deliver back to the grid, increment the charge current
  • when we start consuming electricity from the grid, decrement the charge current but not lower than minimum
  • allow to set a time for ‘boost charge’ that charges the car at full speed (16A) in case this is required.

Now as I am more of a Perl guy instead of a Python guru I wrote this script in Perl. I could not find an efficient way to implement this in Home Assistant itself. This is due to a lack of knowledge from my side and not a limitation of Home assistant :smiley:

This script is published here.

Actually, the thing I was struggling most with was to convert the integer value of the charge current into the correct 2x16-bit values. In Perl I just do pack/unpack. In Python I don’t know how. :man_shrugging:

# Warning: Perl code ahead ;-)
my $network_long = unpack 'L', pack 'f', $current;`

my $parameters = {
	'value_msb' => $network_long / 2**16,
	'value_lsb' => $network_long % 2**16,
	'current'   => $current
};

Then I send that over MQTT into the Home Assistant automation. My attempts to implement this in Home Assistant with templates were futile. Either way: I am all open for suggestions on this part!

Some important/interesting notes when you would want to duplicate this:

  • it appears that (EU) electric vehicles that use a standard AC charge socket only support charge currents from 6A and upwards. If you set the current lower, the vehicle stops charging. You can use this to halt charging, e.g. until the sun comes back during the day. Simply set the charge current to ‘0’ in that case.
  • the Eve chargepoint only supports a single modbus TCP connection. I first tried to set the current from the Perl script and use Home Assistant to read out the sensors and monitor the status. This led to Home Assistant losing the connection to the chargepoint when it tried to read out sensor values.
  • if you happen to have an Alfen Eve Pro double chargepoint, then you can access the socket-specific settings of the rightmost charge plug by accessing the registers I documented above, but then at slave address 2. Slave address 1 are the settings of the leftmost charge plug, or the only plug in case of the Eve Pro Single chargepoint.

Have fun,
Hollie.

11 Likes

Hey @menloperk,

thanks!

The clarification for the values that you see in my script is very simple and indeed something I did not mention in the original explanation: I am currently charging a plug-in hybrid car that only has a single phase charge current of max 16A. So a single ‘1A’ step account for ±230 W more or less power consumption.
Indeed if you are using 3-phase charging you need to account for the three phases.

Are you already switching between 1-phase and 3-phase charging via Home Assistant? If you do, feel free to add the required address to set that up, I cannot test it currently with my car.

Best regards,
Lieven

Hey Rene,

thank you for the updates on your setup. From my side I am using a separate DSMR reader instance that pushes consumption values to an MQTT server once per second. Then wait for 3 incoming value to calculate an update for the charge point.

I have setup a timeout for the values received over modbus on the chargepoint of 60 seconds. This way, should anything fail in the software that calculates the new charge current so that it stops updating, then the chargepoint will fallback to the safe current after max one minute. This is a inverse compared to what you did with the setting of 16 A. It depends on what you what to obtain I guess

I agree with you that you have some margin on the fuses but I don’t want to experiment too much with that. Basically my method is ‘playing safe’ in a sense that I prefer to have the current lower for longer instead of it being too high for a short time.

So if my quooker kicks in for a couple of seconds it will immediately drive the Alfen down in power as there is a sudden drop in excessive power production.

Yes, this is what I also want to see as behaviour.

Thanks again for sharing and have fun with your setup!

Lieven

Hi @hollie,

When you read the Alfen charging point with modbus over tcp? Will the default load balancing from the charge point itself still working?

I prefer the situation to do the load balancing by the Alfen itself based on P1 connection and read all data (eg kWh data) with modbus/tcp to HA.

Regards,
Pascal

Hey Pascal,

that is a good question actually. I don’t have a P1 connection up to the chargepoint as it is located too far from my meter so this option is not activated on my device.

I do see in the configuration software of Alfen that the active load balancing data source can be either set to ‘Energy management system’ or to ‘Meter’. It is not clear to me if the modbus interface is active on the device if the load balancing is set to ‘Meter’.

I’d say: give it a try. For a minimal test you can add a readout of the chargepoint temperature to Home Assistant like this:

modbus:
  - name: laadpaal
    type: tcp
    host: 192.168.xxx.yyy
    port: 502
    sensors:
      - name: laadpaal_temperature
        slave: 200
        address: 1102
        data_type: float32
        unit_of_measurement: °C

If this works when the chargepoint is connected to the P1 port for load balancing the you can extend the configuration to also readout the other relevant parameters.

Kind regards,
Lieven

Hello Lieven,

How did you phisically connect to your charging station? Did you connect the RJ11 of RJ45?
I would like to have the same setup as you, but do not have any software to control my charging station. I’ve donwloaded the software from Alfen’s website, but cannot sign in because I dont have credentials. How did you get those? Or do you have a other way to get in to the management software?
Thanks in advance!

Jeroen

Hey Jeroen,

my charging station is connected solely over ethernet (RJ45). For de control software: you can simply download it from the site of Alfen as you state and then via their support desk you request an account. With that account you can open the software and configure the charging station as you wish.

The only thing I can add: depending on the ‘feature licenses’ that are already activated on your station it is possible that the feature ‘active load balancing’ is not yet unlocked. In that case you need to buy the additional license for that feature. It is required to be able to activate the modbus interface. That feature was not active on my charging station and I could unlock it via the extra license and the configuration software.

Best regards and success with the experiments!
Lieven

2 Likes

Thanks for your information.
I’ve got an account for the Alfen Service Installer and connected it to the same network as Home Assistant.
It turned out I have the license for Load Balancing and it is set to Modbus now. I filled in the IP address of Home Assistant. Unfortunately it does not work yet.
In Home Assistant I get ‘connection refused’ and the ACE tells me “connection error for Modbus unit 5 (192.168.1.10)”.
could you please share how you have the settings of modbus in ACE?
mine are as follows:
Data source: meter
Protocol: Modbus tcp/ip

and on the TCP/IP meter tab:
IP address 192.168.1.10
Slave address: 5
Mode: Custom Register Mapping/Socomec (both don’t work).

I coppied your HA config so these are the same.
Thanks in advance!

Hey Jeroen,

due to the holidays I don’t have physical access to the device to check the exacte settings, but if my memory serves well there should be an option ‘energy management system’ instead of ‘meter’ as data source. I think that is the reason why it is not working as expected for you right now.

Also: I did not have to make any changes to the TCP/IP tab.

If this does not help you further then let me know and I will provide the full info by the end of the week when I can check the service installer software.

Kind regards,
Lieven

Your the best! It is working now! I am very happy!

Thank you very much and I wish you a happy holiday!

Hey Jeroen,

good to hear and thanks for reporting back.

Happy holidays!
Lieven

Hi Jeroen Leeflang @BevelvoerderNr1 ,

I’ve got stuck at the same as described in your post, could you please provide how you fixed it?

thanks in advance, groet,

Jeroen

Sure!
I connected my charger via RJ45 to my switch.
I have made a account on the Alfen back office and asked for ACE credentials.
After that I logged in on ACE with the delivered credentials I went to General and made sure the Active loadbalancing was unlocked.
Then I went to Load Balancing and set Data Source to ‘Energy Management System’. That did the trick!

3 Likes

Yes, last sentence did the trick.
Great, thanks!

Hi,
i also have an Alfen Wallbox, but no car yet.
I found this video: Wallbox über Modbus in den ioBroker integrieren (inkl. Blockly) | haus-automatisierung.com [4K] - YouTube

I think is very helpful, but is in germen and is for iobroker.
With this video realized to read values from the wallbox.

maybe it is helpful for you too

volti-ba

2 Likes

I like it. I am starting my journey looking for chargepoint and have a proposal of Alfen Eve Pro so looking if I can interface it in a way or another with HA :slight_smile:

Back to basic: you can read its status/variables via MODBUS & can “act” on some settings ? Correct ? Where/How did you find information about registers etc… (I am not a specialist but read already some data via MODBUS from my SMA)

Hey @csacre
your assumption is correct. You can use the MODBUS interface to read device status and to set parameters like e.g. the charge current.

The register map is documented in a PDF from Alfen that you can find here: loxone-library > MODBUS TCP/IP register mapping

Best regards,
Lieven.

@hollie, crystal clear. Thank you for the link!
Great project!

Hi Lieven, I’m pretty new to HA. I followed your guideline and was able to read out the sensors of my Alfen charging station. However, I can’t really follow your explanation how to integrate your perl script in HA. Could you briefly explain how exactly I could integrate your perl code in HA?

Hey @Willli

good to hear you have the modbus interface up and running.

In fact the Perl script is just running in parallel next to HomeAssistant as a separate process.

The reason I wrote it this way is because for me it was easier to write the logic and the formatting of the data that needs to be sent to the chargepoint in Perl than in Python as I am more comfortable with Perl. @menloperk who is more comfortable with Python did provide an example code that you could actually integrate in Home Assistant but for one reason or another he removed his post from this thread.

The communication between the two happens over MQTT.

So you need:

  • an MQTT broker (e.g. mosquitto)
  • Home Assistant running and configured to communicate to the broker
  • the Perl script I wrote that is communicating to the broker
  • a unit that tells what the energy balance of the system is (e.g. an electricity meter with DSMR interface) to the broker

What the script does:

  • it listens to the topics dsmr/reading/electricity_currently_delivered and dsmr/reading/electricity_currently_returned over MQTT
  • based on the information it receives it will try to increase or decrease the current setting in the chargepoint to minimize the energy consumption from the grid by posting to the topic chargepoint/maxcurrent. That value is then consumed by the script in HomeAssistant to push it further to the chargepoint.

To allow easy deployment of the script I have updated the repository with a Dockerfile and an example docker-compose file that creates and runs a docker container with the script so that you don’t have to setup a Perl environment.

Best regards,
Lieven.

1 Like