Alfen Eve Pro EV chargepoint interface via TCP modbus

I’m using this HACS integration as well. I noticed that the device keeps rebooting 3-4 times per day. Has anyone noticed similar behaviour?
Not sure if this integration is causing it… according to the log there’s an out of memory exception.

image

2023-01-29T23:44:20.960Z:RESET:application.c:353:=========================================
2023-01-29T23:44:20.972Z:INFO:application.c:361:build: Aug 15 2022 12:20:52
2023-01-29T23:44:20.980Z:INFO:application.c:362:version: 5.8.1-4123
2023-01-29T23:44:20.988Z:INFO:application.c:363:compiler: gcc 4.8.3
2023-01-29T23:44:20.996Z:INFO:application.c:216:fwu state inactive
2023-01-29T23:44:21.003Z:INFO:application.c:236:Bootloader version 0.1.6
2023-01-29T23:44:21.234Z:USER:taskCANopen.c:224:Persistent configuration retrieved, 243 items
2023-01-29T23:44:21.246Z:INFO:application.c:269:FLASH read protection 0xcc level 2 (permanent)
2023-01-29T23:44:21.269Z:WARNING:bspI2c.c:670:I2C slave not responding #-3 AUXBOARD@0x0028, attempting bus recovery
2023-01-29T23:44:21.285Z:WARNING:bspI2c.c:689:Device AUXBOARD@0x0028 not available
2023-01-29T23:44:21.292Z:USER:application.c:412:Using P1 port
2023-01-29T23:44:21.300Z:INFO:application.c:305:System boot #69, cause Watchdog reset
2023-01-29T23:44:21.308Z:ERROR:bspCrashDump.c:173: -- Crash details recovered. 
2023-01-29T23:44:21.316Z:ERROR:bspCrashDump.c:192:Out of memory
2023-01-29T23:44:21.324Z:ERROR:bspCrashDump.c:192:free 3968 bytes,  lowest ever free 3352 bytes
2023-01-29T23:44:21.335Z:ERROR:bspCrashDump.c:192:fragmentation: 108240048.0%
2023-01-29T23:44:21.343Z:ERROR:bspCrashDump.c:192:fragmentation: 4K blocks -3.2%
2023-01-29T23:44:21.351Z:ERROR:bspCrashDump.c:192:# free blocks: 64
2023-01-29T23:44:21.359Z:ERROR:bspCrashDump.c:192:largest free: 6312 bytes
2023-01-29T23:44:21.367Z:ERROR:bspCrashDump.c:192: 2023-01-29T23:44:17.757Z SW Watchdog (fffe7e4e) triggered.
2023-01-29T23:44:21.378Z:ERROR:bspCrashDump.c:192:Missing: Modbus NFC 
2023-01-29T23:44:21.382Z:ERROR:bspCrashDump.c:192:determining cpu hog...
2023-01-29T23:44:21.390Z:ERROR:bspCrashDump.c:192:Tmr Svc                  1    <1% 
2023-01-29T23:44:21.402Z:ERROR:bspCrashDump.c:192:display              25155    97% 
2023-01-29T23:44:21.410Z:ERROR:bspCrashDump.c:192:lwip                     0    <1% 
2023-01-29T23:44:21.417Z:ERROR:bspCrashDump.c:192:WebClients               0    <1% 
2023-01-29T23:44:21.425Z:ERROR:bspCrashDump.c:192:NFC                      0    <1% 
2023-01-29T23:44:21.433Z:ERROR:bspCrashDump.c:192:Modbus                   0    <1% 
2023-01-29T23:44:21.445Z:ERROR:bspCrashDump.c:192:PPP                      0    <1% 
2023-01-29T23:44:21.453Z:ERROR:bspCrashDump.c:192:OCPP                     0    <1% 
2023-01-29T23:44:21.460Z:ERROR:bspCrashDump.c:192:WebServer                0    <1% 
2023-01-29T23:44:21.468Z:ERROR:bspCrashDump.c:192:CommandLine              0    <1% 
2023-01-29T23:44:21.476Z:ERROR:bspCrashDump.c:192:IDLE                     0    <1% 
2023-01-29T23:44:21.484Z:ERROR:bspCrashDump.c:192:Eth_if                   5    <1% 
2023-01-29T23:44:21.496Z:ERROR:bspCrashDump.c:192:Modem                    2    <1% 
2023-01-29T23:44:21.503Z:ERROR:bspCrashDump.c:192:ModbusTCPIPSlav          0    <1% 
2023-01-29T23:44:21.511Z:ERROR:bspCrashDump.c:192:P1Meter                  2    <1% 
2023-01-29T23:44:21.519Z:ERROR:bspCrashDump.c:192:CANopen                427    1% 
2023-01-29T23:44:21.527Z:ERROR:bspCrashDump.c:192:ModbusTCPIPMast          0    <1% 
2023-01-29T23:44:21.539Z:ERROR:bspCrashDump.c:192:Main                     0    <1% 
2023-01-29T23:44:21.546Z:ERROR:bspCrashDump.c:192:TCP/IP                   0    <1% 
2023-01-29T23:44:21.554Z:ERROR:bspCrashDump.c:192:Master                   0    <1% 
2023-01-29T23:44:21.562Z:ERROR:bspCrashDump.c:197: -- End of crash details
2023-01-29T23:44:21.570Z:INFO:board_ng9xx.c:1475:Registered timeout getHardware
2023-01-29T23:44:21.593Z:WARNING:bspI2c.c:670:I2C slave not responding #-3 MMA8451@0x000d, attempting bus recovery
2023-01-29T23:44:21.609Z:WARNING:bspI2c.c:689:Device MMA8451@0x000d not available
2023-01-29T23:44:21.628Z:WARNING:bspI2c.c:670:I2C slave not responding #-3 BMA456Q@0x0000, attempting bus recovery
2023-01-29T23:44:21.644Z:WARNING:bspI2c.c:689:Device BMA456Q@0x0000 not available

I can see an important indication.

“2023-01-29T23:44:21.316Z:ERROR:bspCrashDump.c:192:Out of memory”
Could be a memory leak with the integration causing the component to crash.

That’s exactly my suspicion. But maybe the device is giving this error anyway and rebooting every day… I just wouldn’t know about it if I didn’t have this integration… :wink:
Found 1 person on another forum now who is experiencing the same issue.

I have 1 Alfen configured a couple of weeks ago. I now try to add a second Alfen and when filling in all parameters, I get “an unknown error occured”.

The logs give

 Logger: py.warnings
Source: custom_components/alfen_wallbox/alfen.py:70
Integration: Alfen Wallbox (documentation)
First occurred: 11:59:52 (5 occurrences)
Last logged: 12:48:28
/config/custom_components/alfen_wallbox/alfen.py:70: RuntimeWarning: coroutine 'ClientSession._request' was never awaited self._session.request(ssl=self.ssl, method='POST', headers = HEADER_JSON, url=self.__get_url('logout')) 

and

Deze fout is ontstaan door een aangepaste integratie.

Logger: aiohttp.server
Source: custom_components/alfen_wallbox/config_flow.py:29
Integration: Alfen Wallbox (documentation)
First occurred: 12:05:25 (3 occurrences)
Last logged: 12:49:06

Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_protocol.py", line 435, in _handle_request
    resp = await request_handler(request)
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_app.py", line 504, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 80, in ban_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 236, in auth_middleware
    return await handler(request)
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 145, in handle
    result = await result
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 180, in post
    return await super().post(request, flow_id)
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 72, in wrapper
    result = await method(view, request, data, *args, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 110, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 253, in async_configure
    result = await self._async_handle_step(
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 335, in _async_handle_step
    result: FlowResult = await getattr(flow, method)(user_input)
  File "/config/custom_components/alfen_wallbox/config_flow.py", line 65, in async_step_user
    return await self._create_device(user_input[CONF_HOST], user_input[CONF_NAME], user_input[CONF_USERNAME], user_input[CONF_PASSWORD])
  File "/config/custom_components/alfen_wallbox/config_flow.py", line 52, in _create_device
    return await self._create_entry(host, name, username, password)
  File "/config/custom_components/alfen_wallbox/config_flow.py", line 29, in _create_entry
    if entry.data[KEY_IP] == host:
KeyError: 'ip'

Try also to install this integration, however i get the following error:

Unexpected error creating device.

Someone an idea of where the problem came from?

1 Like

In order to set the correct values for modbus using py, I figured out a quite straightforward solution.

  • Installed HACS
  • Installed pyscript from HACS

Created the following script in the /pyscript directory and call it alfen.py (name doesn’t matter as long as it has extension .py)

import struct

@service
def set_ev_power(power):
    """Set the EV POWER (watt)"""
    log.info(f"Set EV power to {power} watt")
    voltage = 235 #average voltage in Belgium, but you should probably best take value from metered sensor
    evCurrent = to_hex(power/voltage)
    modbus.write_register(address=1210, slave=1,hub="alfenpro", value=evCurrent )

def to_bytes(f):
    return struct.pack('!f', f)

def to_hex(f):
    hexString = to_bytes(f).hex()
    first = int(hexString[0:4],16) 
    second = int(hexString[4:8],16) 
    return  [first, second]

Then you can call it as a service

Alternatively you can add function decorators so that in case of change in PV power it changes the EV power settings. Then it looks something like this

@state_trigger("sensor.solis_inverter_dc_power")
def set_ev_power():
       """Set the EV POWER (watt)"""
    power =  state.get('sensor.solis_inverter_dc_power')
    voltage = 235
    log.info("Power: %s", power)
    evPower = to_hex(float(power)/voltage)
    modbus.write_register(address=1210, slave=1,hub="alfenpro", value=evPower)

Enough for you guys to experiment with :slight_smile:

4 Likes

Hi peebee01,

Do you got it working?
I have the same problem as you.

for the people who also get an error on alfen.py line 180, in the file const.py you type (in my case)" ‘NG910-60583’: 'Eve Single S-line, 3 phase, LED, type 2 socket ', " do a restart and you can add the box.

1 Like

New Alfen firmware released:
Firmware Release 6.0 for our NG9xx charging platform

Nice new feature:
The charging station can now read DSMR P1 smart meter data from a P1-to-network converter
using the telnet protocol. Configuration items are added to select the P1 interface (serial or telnet)
and set the telnet server properties (IP address and port)

2 Likes

Thanks McDobber! That solved my problem.

Beste Heren,

Na het lezen van jullie mooie oplossing, ben ik aan de slag gegaan met een oude gebruikte ICU EVE met smartcard en zonder display. Ik heb hem aangesloten, maar ik kom er niet in met de software van Alfen. Ik krijg ook geen ARP van de kast via een standaard UTP kabel en Wireshark. Wat doe ik eventueel fout of is het een instelling van de kast?

Alvast bedankt,

Edouard

Lieven,

With high interest I read what you did and I would like to implement the same for me too, but I don’t know how to start.

I have an Alfen Eve Pro Single and a digital energy meter, I also use a Youless adapter to be able to read the energy usage.

I would like to plug in my hybrid car always when I’m home. As soon as there is solar energy available, which should normally be injected to the grid, I would like to upload it to my car. I would also like to have the possibilitty to put the system to “manual” so my car starts loading at maximum speed, which is 3.7 kw in my case.

Where do I start, do I need some extra hardware or do I have everything and is it only configuration I need to do. Can you help me to realise this?

regards,

Dries

Hey Dries,

to implement what you want to do you need the following:

  • information of the P1 port from your digital meter to be able to determine if there is injection into the net. This info you need to know when to start charging the car. This info needs to be available in home assistant.
  • the possibility to tell the Alfen how much current the car can pull (which you can do via the modbus over TCP interface from home assistant).
  • to be able to ‘pauze’ the charging of the car completely it depends which car you have. Mine (Volvo) goes into fault mode if I set the current on the Alfen to ‘0 A’. Other cars do support this to pauze the charge process, see the post from @bartland higher in this thread.
    To pauze the charging I am using the API to the car to stop the charge process. I have documented this here.

Basically all information you need to implement what you have in mind is available in this thread.
It will take some experimenting to get everything up and running, but that is part of the learning processfun :wink:

Best regards,
Lieven

Hi @bartland
I just have an Alfen Eve installed at home and got started adding the scripts. But I was wondering the following: is it possible to know how many fases is currently configured on the charger? If I look at the ACE service installer I see no change when running the script. So I’m wondering if this is intended or there is another way to know the current configuration of the fases.

EDIT:
I figured out what the problem was: In the ACE installer I had to enable Allow 1- and 3-phased charging in the Load balancing section.2023-03-18 08_54_05-ACE Service Installer 3.6.6-163 - Settings_ 2.3.0-1162 -  (Extern_ICU)

Doing so I can now see in the logs the trigger when running the script to run the phase. So I know now it’s working.

Is there a sensor we can create to monitor the current setting on the fases?

Thanks!

1 Like

Hi all,

based on this topic I got the balancing working.
Got 2 questions:

  1. 3 phase loading at 6A is 4100 W, but if I single phase load i’m not pushing back solar on 2 phases and using the net on 1 phase.

I’d like to put load balancing per phase, having different Ampere per phase.
I see modbus adresses per phase, but I’m not sure if this is possible / good for the car or not:
example:

  • Phase 1: 6A
  • Phase 2: 9A
  • Phase 3: 5A (not used as below 6A)
  1. I have an alfen station with removable cable, but i mostly leave it plug in. To start a new sessions, the alfen pole required the cable to be removed from the pole, as it’s in status “B1”. Through backoffice you can do a soft status reset, does anyone know if/how we can do a CS reboot (or status reset) through either Modbus or Homeassistant?

Thanks, and great topic!

Yes, you can create a sensor via modbus to READ the current phases.
This part in the code below creates the sensor sensor.charger_use_1_or_3_phases

      - name: charger_use_1_or_3_phases
        slave: 1
        address: 1215
        data_type: uint16

full code

modbus:
  - name: car_charger
    type: tcp
    host: 192.168.1.2
    port: 502
    sensors:
      - name: charger_use_1_or_3_phases
        slave: 1
        address: 1215
        data_type: uint16
      - name: car_charger_name
        unique_id: 'd7494313-3ce8-4871-9c8b-546fa826d45f'
        slave: 200
        address: 100
        count: 17
        data_type: string
      - name: charger_temperature
        slave: 200
        address: 1102
        data_type: float32
        unit_of_measurement: °C
      - name: charger_active_max_current
        slave: 200
        address: 1100
        data_type: float32
        unit_of_measurement: A
      - name: charger_real_power
        unique_id: '5d2cee9c-2485-4af4-a9a2-a901321924c0'
        slave: 1
        address: 344
        data_type: float32
        unit_of_measurement: W
      - name: charger_mode3_state
        slave: 1
        address: 1201
        count: 5
        data_type: string
        scan_interval: 5
      - name: charger_actual_applied_maxcurrent
        slave: 1
        address: 1206
        data_type: float32
        unit_of_measurement: A
      - name: charger_modbus_maxcurrent
        slave: 1
        address: 1210
        data_type: float32
        unit_of_measurement: A
      - name: charger_socket1_current_valid_time
        slave: 1
        address: 1208
        data_type: uint32
        unit_of_measurement: s
      - name: charger_energy_delivered
        slave: 1
        address: 374
        count: 4
        data_type: float64
        unit_of_measurement: Wh
        device_class: energy
        state_class: total_increasing
1 Like

Do you have any info on how the P1 load balancing works?
In general, it will of course charge the car with the “excess/injection”, but how does it react in the following situations?

  1. Not enough injection continuously
    The minimum required charge for my car is 1300 W. In winter, when I do not have a continuous minimum of 1300 W injection, it would nearly never start charging my car or continuously start/stop. Therefore, I created a script that always charges at min. 1300 W and it increases when (occasionally) I have some more injection. But, it will never stop charging, only when the target SOC is reached.
    I call this the “start now mode” (min. 1300 W + solar excess)

  2. Enough injection
    When I have enough injection (1300 W) during 5 minutes, I start charging the car. The 5 minutes is to avoid that it starts charging just the first moment that it reaches this 1300 W (maybe followed by a drop). Then, every minute, I check if there is still enough injection. If not enough injection, it will stop charging the car. If there is more injection than before, it even increases the power of the car charger.
    To avoid that it stops when it does not have 1300 W, I added a “buffer” of 300 W, meaning that it will not stop charging if there is only 1000 W injection; it can consume max. 300 W from the grid. The reasoning is that it is economically more interesting to put your own solar energy in your car (1000 W) than to sell this 1000 W to the grid for only a few €. The cost of (temporarily) using 300 W from the grid is just a small cost that allows you to continue to charge the car with solar. In addition, this makes that the car does not stop charging that often. It only stop charging when there is less than 1000 W injection. Of course, you can change the buffer to your preferences.
    I call this the “solar charging mode” (sun + max. 300 W grid consumption)

As you see, when you manage the power of your car charger by yourself instead of the P1, you can manage all the situations to your own preference.

I really wonder how the Alphen reacts to the P1 active load balancing.

Hi Bart,

Thank you very much for sharing the code for the sensor reading out the current phases!

I’m looking to create an automation doing the same as your point 2: Start charging at 1300W and increase if needed and decrease when needed.

Would you mind sharing how you have it set up so I have a starting point to build on?

Much appreciated!

This is part of the solution. I won’t post the complete configuration in this thread, because this topic is about the Alfen charger and TCP modbus. There are other threads on charging on solar excess power.

These are 2 automations. The first to start the “sun only charging”.
The second to adjust every minute when the sun only charging is busy.
The scripts define the wattage for the car charger and then send it via scripts to the charger.
I also send a notification to my phone when it starts and stops charging. It helps me to debug also.
I can probably simplify the automations (eg. leave some conditions out).

I also use quite a lot of helpers:
input_number.car_charge_sun_start_wattage: the -1300 W required to start charging the car
input_boolean.car_charge_mode_sun: toggle to choose the sun only mode
input_boolean.car_charge_sun_busy: toggle to keep track if the sun charging mode is on or not

and some sensors:
sensor.net_power: gives the grid consumption or injection in Watt
sensor.charger_real_power: the current wattage of the car charger

- alias: "🚗 car 1 // 🔋 charge // mode sun // start - als er voldoende injectie is"
  id: 'fff013ea-12e1-427f-8283-617a0f2e94ad'
  description: ''
  # start when the wattmater is below the number defined in input_number.car_charge_sun_start_wattage
  trigger:
  - platform: time_pattern
    minutes: /1
  - platform: numeric_state
    entity_id: sensor.net_power
    below: input_number.car_charge_sun_start_wattage
    for: "00:05:00"
  condition:
  - condition: numeric_state
    entity_id: sensor.net_power
    below: input_number.car_charge_sun_start_wattage
  - condition: or
    conditions:
    - condition: state
      entity_id: sensor.charger_status
      state: 'connected'            
    - condition: state
      entity_id: sensor.charger_status
      state: 'charging'
  - condition: state
    entity_id: input_boolean.car_charge_mode_sun
    state: 'on'
  - condition: state
    entity_id: input_boolean.car_charge_sun_busy
    state: 'off'
  action:
  # toggle the switches to keep track of the status
  - service: input_boolean.turn_on
    data: {}
    target:
      entity_id:
        - input_boolean.car_charge_sun_busy
        - input_boolean.car_charge_busy
  # define charger Watt based on injection
  - service: input_number.set_value
    target:
      entity_id: input_number.car_charger_watt
    data:
      value: >-
          {% set charger = states('sensor.charger_real_power') | float(default=0) / 1000 %}        
          {% set maxpower = states('input_number.car_charge_minimum_wattage') | float(default=0) %}
          {% set net = states('sensor.net_power') | float(default=0) %}
          {% if net + charger < maxpower %}
          {{ [(-net + charger) / 1000, maxpower] | max }}
          {% elif net + charger > maxpower %}
          {{ maxpower }}
          {% endif %}
  - wait_template: ''
    timeout: '00:00:05'
  - service: script.charger_define_phase_1_or_3_based_on_watt
  - service: script.charger_define_ampere_based_on_watt     
  - service: script.charger_define_and_write_register_based_on_ampere
  - service: notify.bart_phone
    data:
      title: Auto is gestart met laden op zonne-energie
      message: >
        Zon nu {{ states('sensor.solar_power')}} W | Net: {{ states('sensor.net_power')}} W | Auto laadt nu aan {{states('input_number.car_charger_watt') | round(1)}} kW<br>
        Auto: {{states('sensor.car_1_soc') | round()}}%. Doel: {{ states('input_number.car_charge_target_percentage') | round(0)}}%
      data:
        tag: car_charging_sun
        color: green
        notification_icon: "mdi:car-electric"
        actions:
        - action: URI
          title: meer info
          uri: /dashboard-car/car-charging
  mode: single   

- alias: "🚗 car 1 // 🔋 charge // mode sun //  bezig - check elke minuut tijdens zonneladen"
  id: '258101bc-919c-4944-96e4-bb290cbe8922'
  trigger:
  - platform: time_pattern
    minutes: /1    
  condition:
  - condition: state
    entity_id: input_boolean.car_charge_mode_sun
    state: 'on'  
  # only if charger cable is connected to home charger or already charging
  - condition: or
    conditions:    
    - condition: state
      entity_id: sensor.charger_status
      state: 'connected'            
    - condition: state
      entity_id: sensor.charger_status
      state: 'charging'
  # only when sun is up
  - condition: state
    entity_id: sun.sun
    state: above_horizon
  # only if charging is busy in sun mode 
  - condition: state
    entity_id: input_boolean.car_charge_sun_busy
    state: 'on'
  action:
    - if:
        - condition: template
          value_template: "{{ wattage > 1300 }}"
      then:
        - service: input_number.set_value
          target:
            entity_id: input_number.car_charger_watt
          data:
            value: >-
              {% set charger = states('sensor.charger_real_power') | float(default=0) / 1000 %}        
              {% set net = states('sensor.net_power') | float(default=0) %}
              {{ wattage / 1000 }}
        - wait_template: ''
          timeout: '00:00:05'
        - service: script.charger_define_phase_1_or_3_based_on_watt
        - service: script.charger_define_ampere_based_on_watt
        - service: script.charger_define_and_write_register_based_on_ampere
      else:
        - service: script.stop_charger
          data: {}
        # wait 5 minutes to avoid too frequent start/stop = result in charging faillure
        - service: notify.bart_phone
          data:
            title: Zonneladen gestopt
            message: >
              Zon: {{ states('sensor.solar_power')}} W | Net: {{ states('sensor.net_power')}} W | Auto: {{states('input_number.car_charger_watt') | round(1)}} kW<br>
              Nu: {{states('sensor.car_1_soc') | round()}}%.        
        - wait_template: ''
          timeout: '00:05:00'          
  variables:
      wattage: >
        {% set charger = states('sensor.charger_real_power') | float(default=0) %}        
        {% set maxpower = states('input_number.car_charge_sun_max_netwattage') | float(default=0) %}
        {% set net = states('sensor.net_power') | float(default=0) %}
        {{ - (net - maxpower - charger) }}
  mode: single
2 Likes

Hi, just bumped into your message, I have the exact same issue. Have you been able to solve this issue?