Victron EV charger integration

Sharing my experience integrating a Victron NS EV charger to Home Assistant using Modbus TCP, without a GX controller.

Credit to Sascha Bajonczak, who posted about integrating charging point metrics in Home Assistant with Modbus, which helped me significantly in drafting this configuration.

Also thanks to VincentVreeburg who posted their config on the Victron Community that helped guide me with this project.

Victron publish the Modbus TCP Register list on their website, which I used to obtain the relevant modbus addresses. They also have a PNG image of the charger unit on their site that with looks great with the charger-card lovelace card available through HACS (sorry for no links - limited as new user!).

It is worth noting that while this is a 3 phase 22kw charger, I am using this in single phase mode. If you are using the full three phases, it’s likely that you will need to use a different modbus address to obtain the power value (likely 5014 - Total power).

So first, the modbus configuration to obtain the values from the EVSE:

modbus:
  - name: VictronEVSE
    type: tcp
    host: 192.168.x.x
    port: 502
    delay: 5
    message_wait_milliseconds: 30
    timeout: 5
    sensors:
      - name: "EVSE_ChargeMode"
        data_type: uint16
        input_type: holding
        address: 5009
        scan_interval: 10
      - name: "EVSE_ChargingActive"
        data_type: uint16
        input_type: holding
        address: 5010
        scan_interval: 10
      - name: "EVSE_L1PowerUsed"
        data_type: uint16
        input_type: holding
        address: 5011
        scan_interval: 10
      - name: "EVSE_ChargerStatus"
        data_type: uint16
        input_type: holding
        address: 5015
        scan_interval: 10
      - name: "EVSE_ChargeCurrentActual"
        data_type: uint16
        input_type: holding
        address: 5018
        scan_interval: 10
      - name: "EVSE_SessionTimeL"
        data_type: uint16
        input_type: holding
        address: 5020
        scan_interval: 10
      - name: "EVSE_SessionEnergy"
        data_type: uint16
        input_type: holding
        address: 5021
        scan_interval: 10

    switches:
      - name: "EVSE_StartStopCharging"
        address: 5010
        command_on: 1
        command_off: 0
        scan_interval: 10
        verify:
            input_type: holding
            address: 5010
            state_on: 1
            state_off: 0

This obtains all the key values that I saw as useful, when compared to the native bluetooth application provided by Victron.

So these were in a more useful format and available via a single helper, I created the following sensor:

sensor:
- platform: template
  sensors:
    evse:
      friendly_name: "Victron EVSE"
      unique_id: EVSE
      value_template: >-
       {{ states("sensor.EVSE_ChargerStatus") }}
      attribute_templates:
        Charge_Mode: >
         {% set status = states("sensor.EVSE_ChargeMode") %}
         {%if status == '0' %}
           Manual
         {% endif%}
         {%if status == '1' %}
           Auto
         {% endif%}
         {%if status == '2' %}
           Scheduled
         {% endif%}
        Charging_Active: >
         {% set status = states("sensor.EVSE_ChargingActive") %}
         {%if status == '0' %}
           Not Charging
         {% endif%}
         {%if status == '1' %}
           Charging
         {% endif%}
        L1_Power_Used: >
         {{(states("sensor.EVSE_L1PowerUsed") | float) *0.001}}
        Charger_Status_Text: >
         {% set status = states("sensor.EVSE_ChargerStatus") %}
         {%if status == '0' %}
           Disconnected
         {% endif%}
         {%if status == '1' %}
           Connected
         {% endif%}
         {%if status == '2' %}
           Charging
         {% endif%}
         {%if status == '3' %}
           Charged
         {% endif%}
         {%if status == '4' %}
           Waiting for sun
         {% endif%}
         {%if status == '5' %}
           Waiting for RFID
         {% endif%}      
         {%if status == '6' %}
           Waiting for start
         {% endif%}
         {%if status == '7' %}
           Low SOC
         {% endif%}
         {%if status == '8' %}
           Ground test error
         {% endif%}
         {%if status == '9' %}
           Welded contacts test error
         {% endif%}
         {%if status == '10' %}
           CP input test error
         {% endif%}
         {%if status == '11' %}
           Residual current detected
         {% endif%}
         {%if status == '12' %}
           Undervoltage detected
         {% endif%}
         {%if status == '13' %}
           Overheating detected
         {% endif%}
         {%if status == '14' %}
           Reserved
         {% endif%}
         {%if status == '15' %}
           Reserved
         {% endif%}
         {%if status == '16' %}
           Reserved
         {% endif%}
         {%if status == '17' %}
           Reserved
         {% endif%}
         {%if status == '18' %}
           Reserved
         {% endif%}      
         {%if status == '19' %}
           Reserved
         {% endif%}
         {%if status == '20' %}
           Charging limit
         {% endif%}
         {%if status == '21' %}
           Start charging
         {% endif%}
         {%if status == '22' %}
           Switching to 3 phase
         {% endif%}
         {%if status == '23' %}
           Switching to 1 phase
         {% endif%}
         {%if status == '24' %}
           Stop charging
         {% endif%}
        Charge_Current_Actual: >
         {{(states("sensor.EVSE_ChargeCurrentActual") | float) *0.1}}
        Session_Time_L: >
         {% set total_seconds =  states("sensor.EVSE_SessionTimeL") %}
         {% set hours = (total_seconds|int // 3600) %}
         {% set minutes = (total_seconds|int % 3600) // 60 %}
         {% set seconds = (total_seconds |int% 60) %}
         {{ '%02d' % hours }}:{{ '%02d' % minutes }}:{{ '%02d' % seconds }}
        Session_Energy: >
         {{(states("sensor.EVSE_SessionEnergy") | float) *0.01}}

I was then able to use these values with the lovelace charger card:

type: custom:charger-card
entity: sensor.evse
brand: template
show_leds: false
details:
  status:
    entity_id: sensor.evse
    attribute: Charger_Status_Text
  substatus:
    entity_id: sensor.evse
    attribute: Charging_Active
  info_right:
    - entity_id: sensor.evse
      attribute: Charge_Current_Actual
      text: Amps
      icon: mdi:current-ac
      unit_show: true
      unit: A
    - entity_id: sensor.evse
      attribute: L1_Power_Used
      text: Power
      icon: mdi:lightning-bolt
      unit_show: true
      unit: kW
  stats:
    default:
      - entity_id: sensor.evse
        attribute: Session_Energy
        text: Session Energy
        unit_show: true
        unit: KwH
      - entity_id: sensor.evse
        attribute: Session_Time_L
        text: Session Time
      - entity_id: sensor.evse
        attribute: Charge_Mode
        text: Charging Mode
customCardTheme: theme_custom
chargerImage: Generic
customImage: \local\VictronNS
show_name: true
show_status: true
show_stats: true
show_toolbar: false
show_collapsibles: false
compact_view: false
grid_options:
  columns: full

I’m pretty happy with the end result. It’s worth noting the switch tile below the charger card can only be used to ā€œstopā€ the charging session when in Scheduled mode. I haven’t tested this in other modes as yet, but assume in Manual mode it will allow starting and stopping of charging.

Hope this helps others with integrating this EV charger into your Home Assistant environment!

2 Likes

Love your work! I’ve been looking at this charger due to its low price in Australia ($550 makes it the cheapest EV charger with Modbus support).

I’m tempted to use EVCC.io as it has everything built in to adjust the charge rate based on the output of my solar panels, but nice to know I can also pop it into my existing HA setup if I wish.

How have you found the reliability of the Modbus comms? No dropouts or timeouts? It responds to commands quickly?

So far, I’ve had zero issues. No errors in HA Core logs, and it updates promptly.

I’ve got the intervals set quite conservative though, and minimised the data being queried to only what I need for the time being.

I don’t have solar yet, but plan to this year and will be giving EVCC a try then.

For anyone following this thread - I’ve had the Victron charger installed for 2 weeks now and it has been excellent with Home Assistant and EVCC. The Modbus commands are documented well and it acts on them instantly. All locally too. No cloud required.

I’ve just installed a Victron EV charger and don’t even know where to start integrating it into home assistant.

I dont have a victron solar system, so no gx device - our solar system is sunsynk.

Off to youtube some more on how to get this to work.

Install the Modbus integration:

That’s how the charger and HA can communicate.

@anthonyw’s first post in this thread is a good starting point for what to do after you’ve installed Modbus in HA. They’ve done all the hard work for us!

Personally, I just used EVCC.io instead and then added it to Home Assistant via their add-on:

As all I needed was something basic in HA, not full control. I prefer to use EVCC for that.

Great write up, I am using this with my own Victron NS.

Are you familiar with how I would create a switch to set charging amps, and what this would look like in the yaml.

The below dosent work FYI. Obviously a switch cant send numbers. Assuming it would need to be a modbus write command. And how could this be incorporated into the charger card.

    switches:
      - name: "EVSE_StartStopCharging"
        address: 5010
        command_on: 1
        command_off: 0
        scan_interval: 10
        verify:
            input_type: holding
            address: 5010
            state_on: 1
            state_off: 0
      - name: "EVSE_SetChargeCurrent"
        address: 5016
        command_6: 6
        command_7: 7
        command_8: 8
        command_9: 9
        command_10: 10
        command_11: 11
        command_12: 12
        command_13: 13
        command_14: 14
        command_15: 15
        command_16: 16
        scan_interval: 10
        verify:
            input_type: holding
            address: 5016
            command_6: 6
            command_7: 7
            command_8: 8
            command_9: 9
            command_10: 10
            command_11: 11
            command_12: 12
            command_13: 13
            command_14: 14
            command_15: 15
            command_16: 16

Anyone figured out how to change the colour of the LEDs in the light ring? Would be handy as a little status indicator for when things happen in EVCC :slight_smile:

I managed to get it working, but a week or so ago, it just stopped working, with nothing having changed. Now to start fault finding :grimacing: