Victron VRM Portal API data integration

First you need to get your credentials using POST to https://vrmapi.victronenergy.com/v2/auth/login with your VRM user ID and password (those you would use to connect to VRM web)
This gives you back a token (short-lived) and your idUser which is typically 5 digits long

Second you use GET to https://vrmapi.victronenergy.com/v2/users/your_user_id_here/installations to get the list of installations associated with this user id. idSite is what you are looking for and it is usually also a 5 digit number

Then you run the GET https://vrmapi.victronenergy.com/v2/installations/your_installation_id_here/diagnostics?count=1000 to get to the data.

If you are using the short-lived token use Bearer insert_your_token_here in the header of the request
If you are using long-lived tokens, use Token insert_your_token_here in the header of the request

Hope you can make it work.

Than you very much, i dont know the reason i can´t get the data, but i found a way to get the data i need with
https://vrmapi.victronenergy.com/v2/users/XXXXX/installations?extended=1
i don´t need more, this is enought for me

Thanks very much, you are great :wink:

I found the error
" This endpoint can be used to retrieve all most recent logged data for a given installation. It can only be accessed if the current logged in user has Full access to the specified installation. Endpoint:

/v2/installations/{idSite}/diagnostics?count=1000
```"

Im not a profesional installer, i´m only a user, i think i don´t have a full access acount

I’m not a professional installer myself and it works well. How did you create your user in VRM? Maybe that’s the issue.

Up to here All working, Ill keep going. (up until POSTMAN finishes, now going to HA)
Only thing was missing is that on the last step you need to input the installation ID instead of the user ID.
To get the Installation ID you need to do another “Get” to: https://vrmapi.victronenergy.com/v2/users/USERID/installations

Using header tab
key: X-Authorization
Value: Token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

And you will receive the “idSite” value. that you need to use in the last step.

SO many thanks for this guide, I have ZERO knowledge about coding/programing, and so far so good!

(if you could edit your comment and include it, others will appreciate it)

Systems up and running, Last thing I need to create is a traker entity from the info gathered from the VRM portal

Current state:

1 Like

This is great,

I got this working using MODBUS:

I got it running this way for about 1 year now
Here is my code if anyone wants to use it:

###############################################################

Victron Sensor Configurations

com.victronenergy.system

###############################################################

“V”= scale: 0.1

“A”= scale: 0.1

###############################################################
sensor:

  • platform: modbus
    scan_interval: 10
    registers:
    • name: “Battery Power”
      hub: victron
      unit_of_measurement: “W”
      slave: 100
      register: 842

    • name: “Battery SOC” # // Best battery state of charge, determined from different measurements. read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “%”
      scale: 1
      precision: 1
      slave: 100
      register: 843

    • name: “Battery Voltage” # // Battery Voltage determined from different measurements. In order of preference: BMV-voltage (V), Multi-DC-Voltage (CV), MPPT-DC-Voltage (ScV), Charger voltage //com.victronenergy.system
      hub: victron
      unit_of_measurement: “V”
      scale: 0.1
      precision: 1
      slave: 100
      register: 840

    • name: “Battery Current” # // Postive: battery begin charged. Negative: battery being discharged read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “A”
      scale: 0.1
      precision: 1
      slave: 100
      register: 841

    • name: “Battery Power” # // Postive: battery begin charged. Negative: battery being discharged read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “W”
      scale: 1
      precision: 1
      slave: 100
      register: 842

    • name: “Battery State”
      hub: victron
      scale: 1
      precision: 1
      slave: 100
      register: 844

    • name: “Battery Consumed Amphours”
      hub: victron
      unit_of_measurement: “Ah”
      scale: -10
      precision: 1
      slave: 100
      register: 845

    • name: “Battery Time to Go” #\ Special value: 0 = charging read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “s”
      scale: 0.01
      precision: 1
      slave: 100
      register: 846

    • name: “Eskom Grid” #\ Power supplied by Grid to system. read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “W”
      scale: 1
      precision: 1
      slave: 100
      register: 820

    • name: “AC Loads” #\ Power supplied by Inverter to loads. read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “W”
      scale: 1
      precision: 1
      slave: 100
      register: 817

    • name: “Active input source” #\ Power supplied by Grid to system. read from //com.victronenergy.system
      hub: victron
      unit_of_measurement: “W” # \ 0=Not available;1=Grid;2=Generator;3=Eskom power;240=Not connected
      scale: 1
      precision: 1
      slave: 100
      register: 826

- name: “Grid lost alarm” # \ 0=Ok;2=Alarm

hub: victron

scale: 1

precision: 1

slave: 261

register: 64

- name: “VE.Bus state” # \ 0=Off;1=Low Power;2=Fault;3=Bulk;4=Absorption;5=Float;6=Storage;7=Equalize;8=Passthru;9=Inverting;10=Power assist;11=Power supply;252=Bulk protection

hub: victron

scale: 1

precision: 1

slave: 261

register: 31

###############################################################

Sensor Configurations - com.victronenergy.solarcharger

###############################################################

  - name: " Solar Charge state" # \\ 0=Off;2=Fault;3=Bulk;4=Absorption;5=Float;6=Storage;7=Equalize;11=Other (Hub-1);252=External control
    hub: victron
    scale: 1
    precision: 1
    slave: 243
    register: 775

  - name: " PV voltage" # \\ Not available if multiple VE.Can chargers are combined
    hub: victron
    unit_of_measurement: "V"
    scale: 0.01
    slave: 243
    register: 776

  - name: " PV Current" # \\ Not available if multiple VE.Can chargers are combined
    hub: victron
    unit_of_measurement: "A"
    scale: 0.01
    precision: 1
    slave: 243
    register: 776

  - name: " PV Power" # \\ Not available if multiple VE.Can chargers are combined
    hub: victron
    unit_of_measurement: "W"
    scale: 0.1
    precision: 1
    slave: 243
    register: 789
    
  - name: " Yield today" # \\ Today's yield
    hub: victron
    unit_of_measurement: "kWh"
    scale: 10
    precision: 1
    slave: 243
    register: 784

  - name: " Maximum charge power today" # \\ Today's maximum power
    hub: victron
    unit_of_measurement: "kWh"
    scale: 1
    precision: 1
    slave: 243
    register: 785

  - name: " Yield Yesterday" # \\ Yesterdays's yield
    hub: victron
    unit_of_measurement: "kWh"
    scale: 10
    precision: 1
    slave: 243
    register: 786

  - name: " Maximum charge power yesterday" # \\ Yesterdays's maximum power
    hub: victron
    unit_of_measurement: "kWh"
    scale: 1
    precision: 1
    slave: 243
    register: 785

  - name: "Battery Temperature" # \\ Degrees celsius
    hub: victron
    scale: 10
    precision: 1
    slave: 243
    register: 773

###############################################################

Sensor Configurations - com.victronenergy.tank

###############################################################
- name: “Tank Capacity” # \ Tank Informaiton Capacity
hub: victron
scale: 10000
precision: 1
slave: 22
register: 3001

  - name: "Tank Levels" # \\ Tank Informaiton Levels
    hub: victron
    scale: 10000
    precision: 1
    slave: 22
    register: 3004

Good to see you got it to work with modbus. It is a very powerful protocol which I use for my swimming pool equipment (automatic filters and saline chlorinator) but it takes some time to learn.

When I started this thread 3 years ago I was new to HA and most of the possible integrations as well as to Victron but I did have some experience with APIs and remote calls so I naturally went that way.

In the meantime, I’ve learned a few things and have moved on with my installation. When I started out I had a small 6 panel 1.8kWatt installation running a pump and irrigation system. Since then I built my off-grid house with 13kW installed power, 2 Fronius PV inverters and 3 Victron Multiplus II, 18kWh Lithium batteries and a 10kW gas generator as back-up just in case. This system is powering a rather complex set of installations and I wanted more robust and resilient solution which needed to be 100% local and not dependent on availability of internet connection.

Lo and behold I “discovered” the fact the Victron CCGX or any implementation of their VenusOS software has an embedded MQTT server publishing all the data. I don’t know if this feature was already present in 2017 but at that time I didn’t look for it as I wasn’t aware or knew how to use MQTT.

The advantage of using MQTT integration with HA is that, assuming your HA and VenuOS instances are on the same network, it is not dependant on internet connection, which is what I was looking for. Furthermore, it is quite easy and user friendly to set-up.

1 - Enable MQTT on the Victron VenusOS device by going into Settings/Services/Enable MQTT on LAN (SSL)

2 - Test the connection using for instance MQTT Explorer pointing to the IP of the VenusOS device and port 1883 (standard port). You will see the N-topic with the device mac-address. At this stage you will probably not see any sensor data because the VenusOS device MPTT server needs a keepalive signal every 30-so seconds, otherwise it just goes silent

3 - Install a Mosquito broker on your HA instance (I use the official add-on which works perfectly) and configure it to your taste. In my case, as I have 2 VenusOS devices (one for the well-house PV installation, another one for the mani house) I needed to set-up “Customize = true” and set-up 2 connections in /share/mosquitto/mosquitto.conf specifying the top topic (but you can specify lower level topics if you want to)

connection casa
address 192.168.X.XXX:1883
topic N/b827ebbbwxyz/# in
topic R/b827ebbbwxyz/# out

connection caseta
address 192.168.X.XXX:1883
topic N/04a316c4wxyz/# in
topic R/04a316c4wxyz/# out

This setting allows the HA MQTT broker to connect to both VenusOS instances. You can go further and customise the topic command with prefix and so forth as explained in Mosquito Broker documentation but in my case I didn’t think that was worth the trouble

4 - Enable the integration in HA in Configuration/Integrations adding MQTT and pointing it to your HA instance IP

5 - Create an automation for the keepalive of each of the VenusOS MQTT server

- id: '1604576260450'
  alias: mqtt keep alive pour caseta
  description: ''
  trigger:
  - platform: time_pattern
    seconds: /30
  condition: []
  action:
  - data:
      topic: R/04a316c4wxyz/system/0/Serial
    service: mqtt.publish
  mode: single

6 - Using MQTT Explorer browse through all the data exposed by your VenusOS device and select what you want/need to create HA sensors

7 - Enjoy

3 Likes

Thank you !

I was able to easily adapt this to the data I get out from VRM.

Anybody know how to set a static icon for these template sensors?
Or maybe even a dynamic one that changes color on voltage / current? hmm

Hi Luis,
I am kind flashed from this post and just tried to adapt it. I’ve got the API part running, but am a little bit lost with the HA part. For my excuse, I’m using HA for about 2 months and don’t have that much experience with it.
So my question: Is it possible to have your config files for the VRM integration in HA?
I really don’t have a clue, where to integrate the stuff.

Thank you and cheers

serdal

1 Like

Hi.
In my opinion the best option is to go the MQTT way and not the API way.
Easier to set-up, less yaml configuration and your side and more robust as it works within your own network and is not internet dependent.
A few messages above I wrote a simple set wise approach to get it working. Have you looked into it? If you have any questions happy to help.
Cheers.

Hi,
yes I actually saw the post. But I would like to adapt the API way, because my installations are mobile and not integrated in a LAN. I use WiFi-Hotspots for connecting the installations to the VRM portal.
I really need help, or a hint, how to come up withe the HA part. If I include the yaml (victron.yaml) in the configuration.yaml with the token part, I got an error: “Component error: victron - Integration ‘victron’ not found.”
So, if you have nothing better to do than having a look to my problem, I would be very happy.

Thanks a lot

You don’t add Victron integration as there is none. you need to use rest API platform and extract the sensors one by one as explained below.

The data you want are “sensors” and either you add them in your config.yaml or create a sensor.yaml file and add the following line

sensor: !include sensor.yaml

in your configuration.yaml file (thus telling HA that it should look for sensor definition in the sensor.yaml file).

In the sensor.yaml file you declare the parameters of your viltron installation with the following lines

# Victron call for current installation data
- platform: rest
  name: vrm data
  json_attributes:
   - success
   - records
   - num_records
  resource: https://vrmapi.victronenergy.com/v2/installations/<your installation number here>/diagnostics?count=1000
  headers:
    X-Authorization: Token <your token here>
  value_template: '{{ value_json.records[0].timestamp }}'

The values between <…> are those corresponding to your installation number and token (the < and > are omitted, just put the values).

You can then retrieve each specific value using the following sensor of template platform (one per value you want to extract):

- platform: template
sensors:
    battery:
      friendly_name: 'Battery'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "SOC" and item["instance"] == 288 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}' unit_of_measurement: '%'

The “instance” number (in the example 288) is something you need to identify yourself in your own installation as this is a number the Victron CCGX or control unit allocates to the equipment connected to it. You can find that out by looking into the VRM web portal device list.

Let me know if it works for you. Good luck

1 Like

Great!
Thanks so lot. I’ll give it a try as soon as I am on my desk again.

Cheers

Just tried it out.
Code is included in sensor.yaml and this is included in configuration.yaml correctly.
YAML check is ok, but HA Config Validator says:
Error loading /config/configuration.yaml: while parsing a block mapping in “/config/sensors.yaml”,
line 39, column 7 expected , but found ‘’ in “/config/sensors.yaml”,
line 40, column 204.

Any clue?

Code is:

#sensors:
- platform: template
  sensors:
    curent_temp:
       value_template: "{{ state_attr('weather.openweathermap','temperature') | round(0) }}"
       friendly_name: "curent temperature"
    curent_weather:
      value_template: "{{ states('weather.openweathermap') | default('Unknown') }}"
      friendly_name: "curent weather"
      

- platform: fritzbox_callmonitor
  name: Phone
  host: '192.168.178.1'
  port: '1012'
  username: 'xxxx'
  password: 'xxxx'
  phonebook: 0
  prefixes:
    - '+49'
    - '+4930'
    - '030'

# Victron call for current installation data
- platform: rest
  name: vrm data
  json_attributes:
   - success
   - records
   - num_records
  resource: https://vrmapi.victronenergy.com/v2/installations/xxxx/diagnostics?count=1000
  headers:
    X-Authorization: Token xxxx xxxx xxxx xxxx
  value_template: '{{ value_json.records[0].timestamp }}'
  
- platform: template
  sensors:
    battery:
      friendly_name: 'Battery'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "SOC" and item["instance"] == 288 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}' unit_of_measurement: '%'

Just copied your code to have an instance to for trying.
Sorry for hesitating you with that.

I checked out by adding the REST sensor to my configuration and testing with one sensor, the battery (in my case the instance number is 512).
Apart from getting your Token and installation number right, as well as the instance numbers, the error was with the fact that a CR/LF (new line of sorts) was missing for the unit_of_measurement.
This is the code I’m using and it works well, check it out.
you can test if the REST call is working well by using Postman and issuing the command with the correct headers. You will get the full json output and can a) confirm you’re doing it right and b) check-out the data you want/need.
Test it and let me know if it works.
Oh, once you have gone past the parser error and re-start HA, you can check if you get any data back in HA with the Developer Tools/States. And check the templating in Developer Tools/Templates. Get used to using these tools as they are really helpful in understanding what’s going on and will save you a lot of time.

# Victron call for current installation data
- platform: rest
  name: vrm data
  json_attributes:
   - success
   - records
   - num_records
  resource: https://vrmapi.victronenergy.com/v2/installations/<number>/diagnostics?count=1000
  headers:
    X-Authorization: Bearer <manycharactersinhere>
  value_template: '{{ value_json.records[0].timestamp }}'

- platform: template
  sensors:
    vrm_battery:
      friendly_name: 'Battery'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "SOC" and item["instance"] == 512 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: '%'

Hi Luis,

it took some time to hassle a bit with my configuration and understanding how things work AND waiting for HA to restart quit a lot of trials.
First of all: It looks like it works! Thank you so much for all the hints and help!
I’m getting a lot of data back from the API and as you can see in below code, I tried to pick some data out and show on HA Lovelace, but the only entry is the ‘State Of Charge’.
Any other will not, even though I get values back when using ‘sensor.vrm_data’ to check everything in dev-tools/states.
The system which I request with the API calls is up and running - I can see the life data on the vrm-portal site.
I can’t see my fault, if there is one. Do you…?

- platform: template
  sensors:
    vrm_battery:
      friendly_name: 'VRM Battery SoC'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "SOC" and item["instance"] == 512 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: '%'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_consum:
      friendly_name: 'VRM Battery Ah'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "CE" and item["instance"] == 512 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'Ah'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_loadavg:
      friendly_name: 'VRM Battery Load Avg'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "la2" and item["instance"] == 384 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: '%'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_iv:
      friendly_name: 'VRM Battery Input voltage phase 1'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "IV1" and item["instance"] == 8 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'VAC'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_ii:
      friendly_name: 'VRM Battery Input current phase 1'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "II1" and item["instance"] == 8 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'A'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_ip:
      friendly_name: 'VRM Battery Input power'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "IP1" and item["instance"] == 17 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'W'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_ov:
      friendly_name: 'VRM Battery output voltage'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "OV1" and item["instance"] == 20 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'V'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_oi:
      friendly_name: 'VRM Battery output current'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "OI1" and item["instance"] == 23 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: 'A'
    scan_interval: 
      value_template: 20

- platform: template
  sensors:
    vrm_temp:
      friendly_name: 'VRM Battery temperature'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "CT" and item["instance"] == 521 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: '°C'
    scan_interval: 
      value_template: 20

Thank you in advance.

Hi there. I believe the issue might be related to the scan_interval which you seem to define as a value_template.
By default REST scan interval is 30 seconds, so you can leave at that if it suits you.
Otherwise my understanding is that you would have this in your file if you really want the 20 seconds.
Why don’t you give it a try?

- platform: template
  sensors:
    vrm_temp:
      friendly_name: 'VRM Battery temperature'
      value_template: '{% for item in states.sensor.vrm_data.attributes.records if item["code"] == "CT" and item["instance"] == 521 %}{{ item["formattedValue"][:-2] | float() | round(1) }}{% endfor %}'
      unit_of_measurement: '°C'
      scan_interval: 20
1 Like

Hi, I see. I already remove scan_interval, but still the same issue.
Only the first entry (“SoC”) is giving data back.

Looks like this:
HA_vrm

Any idea?

??? Beats me. I assume you checked the “instance” number in VRM as you seem to have single and double-digit ones whereas I thought they were all 3 digit.
What do you see in the sensor.vrm_data? This should give you a hint as to the instance number.

1 Like