Victron to Grafana with VEDirect
Background
I have a solar set-up which powers a server to run some of my sites. The solar charge controller is made by Victron, who offer a multitude of monitoring solutions including purchasing an additional module or installing Victron OS on a Raspberry Pi.
As there will always be a server attached to the charge controller, I decided to implement a simpler monitoring solution. The charge controller has a JST header, which with a USB VE.Direct interface cable can be used to record the live status.
The charge controller emits packets of data at 1 second intervals. The contents of which varies between devices. The data is stored in InfluxDB where it is displayed on a Grafana dashboard.
Step by step
Bind the Victron VE.Direct cable
To make sure the Victron device is always connected to the same port I use udev rules.
After plugging in the device run this command:
dmesg | grep ttyUSB
Look for the port name of the connected device such as /dev/ttyUSB0
.
Then run this with the name of the port:
udevadm info -a -n /dev/ttyUSB0
Scroll down until you find this information
ATTRS{idProduct}=="6015"
ATTRS{idVendor}=="0403"
Then create a udev rule:
sudo nano /etc/udev/rules.d/99-victron.rules
# add:
SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", SYMLINK+="victron"
Reload the udev rules:
sudo udevadm control --reload-rules
sudo udevadm trigger
The device is now accessible at /dev/victron
.
Download the NodeJS script
The code that stores the data in Influx can be found here. I run it with PM2.
Install InfluxDB
Follow the installation steps for InfluxDB V2 on the Influx website. Once installed, go to http://localhost:8086
to access the dashboard. Create a username and password for an admin account as prompted and login, then create a bucket.
Next, create an API token from the Load Data
section. The first token is for the NodeJS script to add data (write access only for your bucket).
Add the NodeJS token to a .env file in the project directory, as well as the organisation and bucket name:
PORT=/dev/victron
INFLUX_URL=http://localhost:8086
INFLUX_TOKEN=
INFLUX_ORG=
INFLUX_BUCKET=
Install Grafana
Follow the install guide on the Grafana website for your distribution.
Access the dashboard at http://localhost:3000
. Then go to
Connections -> Add new connection
.
Search for InfluxDB and in the setup page input the Influx URL: http://localhost:8086
. Go back to the Influx dashboard and create a new token for Grafana (read access only for your bucket) and paste it in the token section. Fill in the Organisation and Default Bucket.
Create the dashboard
Go to
Dashboards -> New -> New Dashboard
to create a dashboard.
Then add a new visualisation.
The first visualisation
queries
section, make sure influxdb is set as the data source and write a query like this:
from(bucket: "SolarData")
|> range(start: -1d)
|> filter(fn: (r) => r._measurement == "vedirect" and r._field == "voltage")
|> group()
|> sort(columns: ["_time"])
This query, selects from the SolarData
bucket in influx a range from now to 1 day ago. It then filters the results from the measurement source vedirect
which was chosen in the NodeJS script:
const point = new Point("vedirect").floatField("voltage", parseFloat(data.V));
It then groups the multiple tables to flatten the data into a single table and makes sure they are sorted by time. The most recent data point is the last one in the table.
After refreshing the query you can switch to the table view to view the raw data.
Click on Time Series
in the top right and change the graph type to Gauge. Give the panel a title, then make sure that it selects the last (most recent) value:
Change the units to Millivolt and enter the maximum and minimum voltages that you want displayed:
At the bottom you can add the thresholds of the outer ring:
Additionally
Grafana can query for any question you have about the data. For example:
- What is the lowest voltage during the night?
- How many hours does it take to charge the battery each morning?
My dashboard also includes the data from a BME680 temperature sensor: