Skip to content

Instantly share code, notes, and snippets.

@KidA001
Last active May 1, 2024 07:11
Show Gist options
  • Save KidA001/dc5584db340cf3ad513f9415b20ed5fa to your computer and use it in GitHub Desktop.
Save KidA001/dc5584db340cf3ad513f9415b20ed5fa to your computer and use it in GitHub Desktop.

Victron Data in HomeAssistant

I love HomeAssistant and I also love my Victron Equipment. I knew they provided data over ModBus and MQTT and a while back I was determined to pull the data into HomeAssistant. I live fully off-grid and it's extremely helpful to know what the state of my system is whereever I am. I also built many automations that help me optimize my available power. Below is a walk through on pulling in Victron data to HomeAssistant over MQTT.

Pre-reqs

These are needed before proceeding:

  • HomeAssistant (Duh!)
  • Some type of VenusOS Device, you'll need the IP and it should be set to a static IP
  • SSH & Web Terminal HomeAssistant Add-On (Used for editing a mosquitto conf file)
  • FileEditor Add-On (Used to edit HomeAssistant config files and sensors)
  • A MQTT GUI, I use MQTT Explorer (Not needed, but helpful to ensure things are working)

Note: I use HomeAssistant & HA interchangibly.

Enable MQTT On your VenusOS Device

Go to the IP address of your Venus device in your web browser. From there go to Settings > Services and enable Modbus, MQTT (SSL) and MQTT (Plaintext)

image

Setup Mosquitto MQTT Broker

From your HomeAssistant instance go to Settings > Add-Ons and click the AddOn Store button and search for Mosquitto broker. Select it and install.

In the Configuration tab of Mosquitto go to the Customize section and ensure active: true and folder: mosquitto are set:

image

Setup a bridge between your Victron MQTT and HomeAssistant/Mosquitto

This allows all data from Victron to be mirrored on your HomeAssistant's Mosquitto Broker. This is the corret way to setup MQTT from Venus on HA instead of using the VenusOS device as a MQTT server.

Open the Teriminal Web View in HomeAssistant, there should be a button in your Nav menu on the left if you already installed it into HomeAssitant. It should bring you to a HomeAssistant console like below:

image

From there lets go into the mosquitto directory with:

cd /share/mosquitto

Then lets create the file we'll use for victron config with:

touch victron.conf

Now lets edit that file and add some config. Open in nano editor with

nano victron.conf

Add the following config and replace your.venus.ip.address with your VenusOS IP Address:

connection victron
address your.venus.ip.address:1883
topic N/# in 0 victron/
topic R/# out 0 victron/
topic W/# out 0 victron/

Hit cntrl + x and then y and enter at the prompt to save. Go back to the Mosquitto Broker AddOn and restart the service.

Add a MQTT User in HomeAssistant

In HA you need to create a User account that will be used to login to the MQTT Server you just setup. In HA go to Settings > People and select the Users tab at the top. Create a user with a username & password, note this for the next couple steps:

image

If you have issues on your network logging into your MQTT service try disabling Can only log in from the local network.

Create a KeepAlive Automation

The MQTT service on Victron needs to be kept alive. We do this by sending a keep-alive message every 30-seconds.

In HomeAssistant go to Settings > Automations & Scenes, create a new Automation called Victron MQTT KeepAlive. The trigger should be Time Pattern and set to every 30 seconds which is expressed as /30

image

Then the action should be Call Service and select MQTT: Publish. The topic is victron/R/your-venus-id/system/0/Serial, payload: {}. Hit save and you're done.

image

Verify Mosquitto has Victron data!

Open the MQTT GUI/Application (I use MQTT Explorer). For the Host provide the IP Address of your HomeAssistant. For User/Pass use the one you just created:

image

If everything is setup properly, you should start to see data from your Victron Equipment show up. It will be under the victron/N key. Make note of the ID beneath that, mine below is b827eb5c4de. This is the unique ID for your Victron System and you'll need to reference in your sensors later.

image

If this is working, you've done all the hard stuff!

Add the MQTT Integration in HA

This integration allows HA to use data from MQTT as sensors..etc. Go to Settings > Devices & Services and click Add Integration at the bottom. When prompted add the IP of your HomeAssistant instance, and the username/password of the mqtt user you created.

Add Sensors to HomeAssistant (the fun part)

You should now be able to start adding sensors in HomeAssistant that pull data from your VenusOS Device. Use the FileEditor in HomeAssistant, there should be a button in the left Navigation Pane if you've installed the AddOn. From there open the configuration.yaml file and add this line:

mqtt: !include mqtt.yaml

Please note the organization of my config, I breakout sensor, template, mqtt...etc, into their own files. This makes organization and editing way easier then stuffing everying in one file. Mine looks like this:

image

Now create a new file in the config dir called mqtt.yaml to match. Do this by clicking the folder icon in the top left and then clicking the New File icon.

Once you're in that new file you can start adding sensors. Below are some sensors to get you started. Replace your-venus-id with the unique ID we noted above. Note that the exact paths for your system may be different than mine. Use the MQTT Explorer to find the data you might want

sensor:
  # Battery percentage
  - state_topic: "victron/N/your-venus-id/system/0/Batteries"
    name: "Battery Percent"
    unique_id: "battery_percent"
    device_class: battery
    value_template: '{{ value_json.value[0].soc | round(0) }}'
    unit_of_measurement: "%"
  
  # AC Loads
  - state_topic: "victron/N/your-venus-id/system/0/Ac/Consumption/L1/Power"
    name: "AC Loads"
    unique_id: "ac_loads"
    device_class: power
    value_template: '{{ value_json.value }}'
    unit_of_measurement: "W"
    icon: mdi:power-socket-uk
    
  # DC Loads
  - name: "DC Loads"
    device_class: power
    unique_id: "dc_loads"
    state_topic: "victron/N/your-venus-id/system/0/Dc/System/Power"
    value_template: '{{ value_json.value|float(0)|round(0) }}'
    unit_of_measurement: "W"
    icon: mdi:power
    
  # Net Solar Production
  - name: "Current Solar Production"
    unique_id: "net_solar_production"
    device_class: power
    state_topic: "victron/N/your-venus-id/system/0/Dc/Pv/Power"
    value_template: '{{ value_json.value|float(0)|round(0) }}'
    unit_of_measurement: "W"
    icon: mdi:solar-power
  
  # Battery Voltage
  - name: "Battery Voltage"
    unique_id: "battery_voltage"
    device_class: voltage
    state_topic: "victron/N/your-venus-id/system/0/Dc/Battery/Voltage"
    value_template: '{{ value_json.value|float(0)|round(1) }}'
    unit_of_measurement: "V"

  # Battery Temp (If you have a temp sensor)
  - name: "Battery Temp"
    device_class: temperature
    unique_id: "battery_temperature"
    state_topic: "victron/N/your-venus-id/system/0/Dc/Battery/Temperature"
    value_template: '{{ ((value_json.value * 9/5) + 32) | round(0) }}'
    unit_of_measurement: "°F"

  # Net load going in/out of your battery
  - name: "Battery Load"
    unique_id: "battery_load"
    device_class: power
    state_topic: "victron/N/your-venus-id/system/0/Batteries"
    value_template: '{{ value_json.value[0].power|float(0)|round(0) }}'
    unit_of_measurement: "W"
    
  # Current State of your Inverter
  - name: "Inverter State"
    unique_id: "inverter_state"
    state_topic: "victron/N/your-venus-id/system/0/SystemState/State"
    value_template: >
      {% if value_json.value == 0 %}
        Off
      {% elif value_json.value == 2 %}
        VE.Bus Fault condition
      {% elif value_json.value == 3 %}
        Bulk
      {% elif value_json.value == 4 %}
        Absorption
      {% elif value_json.value == 5 %}
        Float
      {% elif value_json.value == 6 %}
        Storage
      {% elif value_json.value == 7 %}
        Equalize
      {% elif value_json.value == 9 %}
        Inverting
      {% elif value_json.value == 10 %}
        Assisting
      {% elif value_json.value == 256 %}
        Discharging
      {% elif value_json.value == 257 %}
        Sustain
      {% else %}
        Error - No Data
      {% endif %}
  
  # Current state of your charge controller
  - name: "Solar Charger State"
    unique_id: "solar_charger_state"
    state_topic: "victron/N/your-venus-id/solarcharger/289/State"
    value_template: >
      {% if value_json.value == 0 %}
        Off
      {% elif value_json.value == 2 %}
        Fault
      {% elif value_json.value == 3 %}
        Bulk
      {% elif value_json.value == 4 %}
        Absorption
      {% elif value_json.value == 5 %}
        Float
      {% elif value_json.value == 6 %}
        Storage
      {% elif value_json.value == 7 %}
        Equalize
      {% else %}
        Error - No Data
      {% endif %}

  # Estimated Time until battery is empty based on current load.
  # These calculations were copied from victrons code to mimic how they display it
  - name: "Battery Remaining"
    unique_id: "battery_remaining"
    icon: mdi:timer-sand
    state_topic: "victron/N/your-venus-id/system/0/Dc/Battery/TimeToGo"
    value_template: >
      {% set battery_load = states('sensor.battery_load') | int(0) %}

      {% if value is not defined %}
        Error
      {% elif value == '{"value": null}' or battery_load > 0 %}

      {% else %}
        {% set seconds = value_json.value | round(0) | int %}
        {% set days = (seconds / 86400) | round(0, 'floor') | int %}
        {% set hours = ((seconds - days * 86400) / 3600) | round(0, 'floor') | int %}
        {% set minutes = ((seconds - hours * 3600) / 60) | round(0, 'floor') | int %}

        {% if 2 > days >= 1 %}
          {{days}} Day
        {% elif days >= 2 %}
          {{days}} Days
        {% elif hours > 0 %}
          {{hours}} Hours
        {% elif minutes > 0 %}
          {{minutes}} Minutes
        {% endif %}
      {% endif %}

Restart your HA for the sensors to be loaded.

Add Sensors to your Dashboard

You can now add sensors to your Dashboards! Even better are to start writing automations based on your power. How you organize them is up to you, if you're intersted in my exact layout let me know and I can share more

image

I hope this tutorial was helpful, and enjoy!

HomeAssistant Energy Dashboard

HomeAssistant requires Integral sensors in order to properly track power usage. In my setup I have AC + DC Loads (consuming), Solar Loads (producing), and a Generator. I also have a battery system which requires Battery In + Battery out. I'll go over creating all of those now.

image

Please see my note higher up in this doc about how I organize my configuration.yaml file. You will need to create sensor.yaml and template.yaml files if you want to use the organization I have.

Calulating Net Solar

This one is easy, just use sensor.net_solar_production. This is the value of ALL your production, even if you have multiple charge controllers. In your sensors.yaml add the follow integral sensor:

- platform: integration
  unique_id: "total_solar_kwh"
  source: sensor.net_solar_production
  unit_prefix: k
  round: 3

Calculating Net Consumption

If you only have AC loads, just add the following in your sensors.yaml:

- platform: integration
  unique_id: "total_power_consumed"
  source: sensor.ac_loads
  unit_prefix: k
  round: 3

If you have both AC & DC loads, you'll need to first create a Template sensor that combines them both. In template.yaml add:

- name: total_power_consuming
  unique_id: "total_power_consuming"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: >
    {% set dc_loads = states('sensor.dc_loads') | int(0) %}
    {% set ac_loads = states('sensor.ac_loads') | int(0) %}
    {{ dc_loads + ac_loads }}

Then add the following in your sensors.yaml:

- platform: integration
  unique_id: "total_power_consumed"
  source: sensor.total_power_consuming
  unit_prefix: k
  round: 3

Calculating Battery In/Out

You'll first need to create two template sensors that differentiate between power going to the battery and power coming from the battery. Add these to your template.yaml:

- name: total_battery_out
  unique_id: "total_battery_out"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: > # Only returns a value when load on battery is negative (consuming)
    {% set battery_load = states('sensor.battery_load') | int(0) %}
    {% if battery_load < 0 %}
      {{ battery_load | abs }}
    {% else %}
      0
    {% endif %}
- name: total_battery_in
  unique_id: "total_battery_in"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: > # Only returns a value when load on battery is positive (charging)
    {% set battery_load = states('sensor.battery_load') | int(0) %}
    {% if battery_load >= 0 %}
      {{ battery_load }}
    {% else %}
      0
    {% endif %}

Now you can add the following to sensors.yaml:

- platform: integration
  unique_id: "total_battery_in_kwh"
  source: sensor.total_battery_in
  unit_prefix: k
  round: 3
- platform: integration
  unique_id: "total_battery_out_kwh"
  source: sensor.total_battery_out
  unit_prefix: k
  round: 3

Calculating Generator/Other power

Skip this unless you have some sort of external AC Input you want to capture. I have a generator that I mark as "grid power". This comes from the AC Input of my multiplus. Depending on your AC Input you can name it whatever you want. In my MQTT.yaml I have this sensor which pulls the numbers from the AC Input of the multiplus:

- name: "Generator"
  unique_id: "Generator Load"
  device_class: power
  state_topic: "victron/N/your-venus-id/system/0/Ac/Genset/L1/Power"
  value_template: '{{ value_json.value|float(0)|round(0) }}'
  unit_of_measurement: "W"
  icon: mdi:engine

Then in sensors.yaml I add the following:

- platform: integration
  unique_id: "total_generator_kwh"
  source: sensor.generator
  unit_prefix: k
  round: 3

Setting up the Energy Dashboard

In HomeAssistant go to Settings>Dashboards>Energy or click here.

Add the integral sensors we just created: image

This dashboard will take at least two-hours to start collecting and showing data, so be patient. Enjoy!

@KidA001
Copy link
Author

KidA001 commented Feb 17, 2024

If I do the calculation using the method on the left, the calculation is more accurate(green).

Oh cool, I wasn't familiar with that. Looks like the default is trapezoidal. I'll try it out myself and update the documentation if it seems stable. Thanks!

@markandersonus
Copy link

I can't select my solar for some reason, anyone got any idea why there is no statistic available to select for solar? The sensor is returning the correct value

Here's my MQTT (value is populated)

Net Solar Production

  • state_topic: "victron/N/d41243b515fb/system/0/Dc/Pv/Power"
    name: "Victron Current Solar Production"
    unique_id: "victron_net_solar_production"
    device_class: power
    value_template: "{{ value_json.value|float(0)|round(0) }}"
    unit_of_measurement: "W"
    icon: mdi:solar-power

Here's my sensor (shows correct value in HA)

Total Solar

  • platform: integration
    unique_id: "victron_total_solar_kwh"
    source: sensor.victron_net_solar_production
    unit_prefix: k
    round: 3

Here's template (not sure if I need it)

Solar energy

- name: victron_total_solar_production
  unique_id: "victron_total_solar_production"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: >
    {% set solar_production = states('sensor.victron_net_solar_production') | int(0) %}
    {{ solar_production }}

@FrankieHAi
Copy link

I saw mentioned somewhere not to use MQQT to communicate between VenusOS and HA on rpi if the VenusOS was "exposed to the internet"

Can someone please explain what this means?

Mu VenusOS pi is networked on the same wifi cellular hotspot with all my HA gear. It has communication with VRM.
Is it risky to add mqqt communication between VenusOS and HA in this case?

@KidA001
Copy link
Author

KidA001 commented Feb 27, 2024

I saw mentioned somewhere not to use MQQT to communicate between VenusOS and HA on rpi if the VenusOS was "exposed to the internet"

Can someone please explain what this means?

Mu VenusOS pi is networked on the same wifi cellular hotspot with all my HA gear. It has communication with VRM. Is it risky to add mqqt communication between VenusOS and HA in this case?

When you enable MQTT on VenusOS it is available on your local network, but it is not exposed to the public/internet. Only if you explicitly forward the MQTT port on your router to your VenusOS IP Address would it be open to the internet. It is no less secure than any device running on your local network.

@olingphilo
Copy link

I can't select my solar for some reason, anyone got any idea why there is no statistic available to select for solar? The sensor is returning the correct value

Here's my MQTT (value is populated)

Net Solar Production

  • state_topic: "victron/N/d41243b515fb/system/0/Dc/Pv/Power"
    name: "Victron Current Solar Production"
    unique_id: "victron_net_solar_production"
    device_class: power
    value_template: "{{ value_json.value|float(0)|round(0) }}"
    unit_of_measurement: "W"
    icon: mdi:solar-power

Here's my sensor (shows correct value in HA)

Total Solar

  • platform: integration
    unique_id: "victron_total_solar_kwh"
    source: sensor.victron_net_solar_production
    unit_prefix: k
    round: 3

Here's template (not sure if I need it)

Solar energy

- name: victron_total_solar_production
  unique_id: "victron_total_solar_production"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: >
    {% set solar_production = states('sensor.victron_net_solar_production') | int(0) %}
    {{ solar_production }}

Screenshot 2024-03-06 084259

@olingphilo
Copy link

Hello , i got into a similar situation like you did and here is how i sorted it out.

Step 1: install the Riemann sum integral sensor integration. if its already installed browse to the helper tab of devices and services and create a new helper(select Riemann sum integral sensor)
Step 2: configure it as follows :
Name: give it any name as fit.
Input sensor: select the enity "net_solar_production"
integration method: Trapezoidal rule
Precision: 2
Metric prefix: kilo
Time unit: hours
Step 3 : submit
Step 4: proceed to sensors.yaml and create the following

        - platform: integration
           unique_id: "total_solar_kwh"
           source: sensor.victron_mppt (this should be the sensor id you created using the Riemann sum integral sensor  integration)
           unit_prefix: k
           round: 3

Step 5: restart home assistanr
Step 6: proceed to the energy dashboard and you should be able to select the appropiate sensor.

I can't select my solar for some reason, anyone got any idea why there is no statistic available to select for solar? The sensor is returning the correct value

Here's my MQTT (value is populated)

Net Solar Production

  • state_topic: "victron/N/d41243b515fb/system/0/Dc/Pv/Power"
    name: "Victron Current Solar Production"
    unique_id: "victron_net_solar_production"
    device_class: power
    value_template: "{{ value_json.value|float(0)|round(0) }}"
    unit_of_measurement: "W"
    icon: mdi:solar-power

Here's my sensor (shows correct value in HA)

Total Solar

  • platform: integration
    unique_id: "victron_total_solar_kwh"
    source: sensor.victron_net_solar_production
    unit_prefix: k
    round: 3

Here's template (not sure if I need it)

Solar energy

- name: victron_total_solar_production
  unique_id: "victron_total_solar_production"
  unit_of_measurement: "W"
  state_class: measurement
  device_class: power
  state: >
    {% set solar_production = states('sensor.victron_net_solar_production') | int(0) %}
    {{ solar_production }}

Hello , i got into a similar situation like you did and here is how i sorted it out.

Step 1: install the Riemann sum integral sensor integration. if its already installed browse to the helper tab of devices and services and create a new helper(select Riemann sum integral sensor)
Step 2: configure it as follows :
Name: give it any name as fit.
Input sensor: select the enity "net_solar_production"
integration method: Trapezoidal rule
Precision: 2
Metric prefix: kilo
Time unit: hours
Step 3 : submit
Step 4: proceed to sensors.yaml and create the following

        - platform: integration
           unique_id: "total_solar_kwh"
           source: sensor.victron_mppt (this should be the sensor id you created using the Riemann sum integral sensor  integration)
           unit_prefix: k
           round: 3

Step 5: restart home assistanr
Step 6: proceed to the energy dashboard and you should be able to select the appropiate sensor.

@rechena
Copy link

rechena commented Mar 6, 2024

Thanks for this, I'm using this code but recently I started to have issues with the TimeToGo it won't update to infinite.... although in the victron shows infinite. I posted on the post in HA Forum but realised I might get more help here.

The sensor works, but by some reason when it goes from “time” back to null, the sensor state stays on the previous value that was a number, is anyone having the same issue? Seems it only started to happen recently, I tried recreate the sensor, add a new one and the same still happens. Looking at the MQTT this is what I have in the history.

@KidA001
Copy link
Author

KidA001 commented Mar 7, 2024

Thanks for this, I'm using this code but recently I started to have issues with the TimeToGo it won't update to infinite.... although in the victron shows infinite. I posted on the post in HA Forum but realized I might get more help here.

The sensor works, but by some reason when it goes from “time” back to null, the sensor state stays on the previous value that was a number, is anyone having the same issue? Seems it only started to happen recently, I tried recreate the sensor, add a new one and the same still happens. Looking at the MQTT this is what I have in the history.

Yeah something changes on Victron's end with an update, I saw the same. Here is my updated code, I've updated the gist as well:

- name: "Battery Remaining"
  unique_id: "battery_remaining"
  icon: mdi:timer-sand
  state_topic: "victron/N/your-venus-id/system/0/Dc/Battery/TimeToGo"
  value_template: >
    {% set battery_load = states('sensor.battery_load') | int(0) %}

    {% if value is not defined %}
      Error
    {% elif value == '{"value": null}' or battery_load > 0 %}

    {% else %}
      {% set seconds = value_json.value | round(0) | int %}
      {% set days = (seconds / 86400) | round(0, 'floor') | int %}
      {% set hours = ((seconds - days * 86400) / 3600) | round(0, 'floor') | int %}
      {% set minutes = ((seconds - hours * 3600) / 60) | round(0, 'floor') | int %}

      {% if 2 > days >= 1 %}
        {{days}} Day
      {% elif days >= 2 %}
        {{days}} Days
      {% elif hours > 0 %}
        {{hours}} Hours
      {% elif minutes > 0 %}
        {{minutes}} Minutes
      {% endif %}
    {% endif %}

@rechena
Copy link

rechena commented Mar 8, 2024

Thanks for the reply, still not working, but now I'm getting an TemplateSyntaxError

TemplateSyntaxError: expected token 'name', got '|'

Seems its not happy with this line here:

  {% elif value == '{"value": null}' || battery_load > 0 %}

If I remove the || battery_load >0

Result type: string
62.5

 

 62

{'value': Undefined}

value_template: > 
      
        Error

@KidA001
Copy link
Author

KidA001 commented Mar 8, 2024

Thanks for the reply, still not working, but now I'm getting an TemplateSyntaxError

TemplateSyntaxError: expected token 'name', got '|'

Seems its not happy with this line here:

  {% elif value == '{"value": null}' || battery_load > 0 %}

If I remove the || battery_load >0

Result type: string
62.5

 

 62

{'value': Undefined}

value_template: > 
      
        Error

sorry, needed to correct my or statement, should be or not ||

@rechena
Copy link

rechena commented Mar 9, 2024

Absolute legend, it worked :) Thanks

@patatman
Copy link

patatman commented Apr 9, 2024

Just leaving a comment to show my appreciation for this document! Works like a charm thanks!

@Przedzik
Copy link

Hi, I am new on Git Hub and have to say Gret Job on this integration!!.
However I try add an extra entity for the test and take it from my mqtt explorer added to the configuration but after reboot I cant get the extra entity in Home Assistant, I am missing a step or something?
this is a code I added
thanks, anybody for help :)

AC Grid

  • state_topic: "victron/N/my Cerbo id/system/0/Ac/Grid/L1/Power"
    name: "AC Grid"
    unique_id: "ac_grid"
    device_class: power
    value_template: '{{ value_json.value }}'
    unit_of_measurement: "W"
    icon: mdi:power-socket-uk

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment