VOOL EV charger monitor and control over ModBus

How to integrate VOOL EV charger with HomeAssistant over modbus.

Disclaimer: I’m not against the VOOL’s idea/logic how to charge EV - it will suit for majority of people - but I wanted to tinker and have “full control” over how to or when to charge the vehicle.

Prerequisites are that modbus is enabled in VOOL (if needed can be asked trough support or enabled according to manual) and charger firmware is at least 1.9.40!
With lower versions modbus will be available on port 502, but register 100 (Charger State) will return ‘3200’ and not the correct information!

As modbus is confiugurable only trough configuration.yaml it is simple copy and paste

modbus:
  - name: modbus_hub
    type: tcp
    host: <CHARGER IP>
    port: 502
    delay: 1
    message_wait_milliseconds: 100
    timeout: 5

    switches:
      - name: vool_charger_switch_charging
        address: 500
        command_on: 1
        command_off: 2

    sensors:
      - name: vool_charger_charger_state_enum
        address: 100
        data_type: uint16

      - name: vool_charger_ac_current_l1
        address: 102
        scale: 0.01
        unit_of_measurement: A
        precision: 2
      - name: vool_charger_ac_current_l2
        address: 103
        scale: 0.01
        unit_of_measurement: A
        precision: 2
      - name: vool_charger_ac_current_l3
        address: 104
        scale: 0.01
        unit_of_measurement: A
        precision: 2

      - name: vool_charger_voltage_l1
        address: 105
        scale: 0.1
        unit_of_measurement: V
        precision: 1
      - name: vool_charger_voltage_l2
        address: 106
        scale: 0.1
        unit_of_measurement: V
        precision: 1
      - name: vool_charger_voltage_l3
        address: 107
        scale: 0.1
        unit_of_measurement: V
        precision: 1

      - name: vool_charger_active_power
        address: 108
        data_type: int16
        scale: 0.01
        unit_of_measurement: kW
        precision: 2
      - name: vool_charger_active_power_l1
        address: 109
        scale: 0.01
        unit_of_measurement: kW
        precision: 2
      - name: vool_charger_active_power_l2
        address: 110
        scale: 0.01
        unit_of_measurement: kW
        precision: 2
      - name: vool_charger_active_power_l3
        address: 111
        scale: 0.01
        unit_of_measurement: kW
        precision: 2

      - name: vool_charger_energy_imported_msb
        address: 200
        data_type: uint32
        unit_of_measurement: Wh

As charger state returns only number I made a template sensor to make it human readable:

{% set mapper =  {      
      '0' : 'UNDEFINED',
      '1' : 'AVAILABLE',
      '2' : 'PREPARING',
      '3' : 'CHARGING',
      '4' : 'SUSPENDED_EV',
      '5' : 'SUSPENDED_EVSE',
      '6' : 'FINISHING',
      '7' : 'RESERVED',
      '8' : 'UNAVAILABLE',
	  '9' : 'FAULTED',
	  '10' : 'STARTING_CHARGING'
	  } 
	%}
    {% set state =  states.sensor.vool_charger_charger_state_enum.state %}
    {{ mapper[state] if state in mapper else 'Unknown' }}

And for switching on and off another template switch has been made:
That is because modbus register 500 for charging state does not reflect the state (always 0).
From manual “Reaction to the start/stop command can be concluded from the “Charger State” value.”

template:
  - switch:
     - name: vool_charger_switch_template
       unique_id: vool_charger_switch_template
       ## state on: 3 (CHARGING), 4 (SUSPENDED_EV), 5 (SUSPENDED_EVSE)
       ## state off: 1 (AVAILABLE), 2 (PREPARING), 6 (FINISHING)
       state: >
         {% if states("sensor.vool_charger_charger_state_enum") in ["3", "4", "5"] %}
           on
         {% elif states("sensor.vool_charger_charger_state_enum") in ["1", "2", "6"] %}
           off
         {% else %}

         {% endif %}
       turn_on:
         action: switch.turn_on
         target:
           entity_id: switch.vool_charger_switch_charging

       turn_off:
         action: switch.turn_off
         target:
           entity_id: switch.vool_charger_switch_charging
       ## switch available: cable connected, charger state is: 1 (AVAILABLE), 2(PREPARING), 3(CHARGING), 4 (SUSPENDED_EV), 5 (SUSPENDED_EVSE), 6 (FINISHING),
       availability: >
         {% if is_state("binary_sensor.cupra_tavascan_charging_cable_connected", "on") %}
           {% if states("sensor.vool_charger_charger_state_enum") in ["1", "2", "3", "4", "5", "6"] %}
             on
           {% endif %}
         {% else %}
             off
         {% endif %}

NB! This solution does not follow the OCPP v1.6 standard!
According to standard - starting charging again from FINISHING state should not be possible.
And some cars manufacturers even fail when trying to restart charging from FINISHING state - so be warned!

At first modbus seemed complicated … but in the end i’d say the solution suits my needs at the moment :slight_smile:.

Maybe that is not the best solution - but that is how I got it working for now.

And as always - there is room for improvement!

Thanks a lot for putting this together and sharing your config. Appreciate it!

One thing I’m still stuck on is actually enabling Modbus on the VOOL side. The manual provided mentions that it “can be manually enabled using special parameter (522-
Enable Modbus TCP/UDP interface)”, but I can’t find this parameter in mobile app UI nor in Vool Portal.

Could you clarify how you enabled Modbus on your unit?

I did contact trough their chat and they enabled it by themselves.

1 Like

I created a HACS integration for this. Haven’t tested it too much, but basics seemed to work.