victron-vrm-api
Version:
Interface with the Victron Energy VRM API
488 lines (449 loc) • 26 kB
HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script type="text/javascript">
function checkSelectedAPIType() {
[
'users', 'installations', 'widgets', 'dynamic-ess', 'instalations_and_widgets'
].map( x => { $('#input-'+x).hide() })
const selected = $('select#node-input-api_type').val()
$('#input-'+selected).show()
if (selected === 'installations' || selected === 'widgets') {
$('#input-instalations_and_widgets').show()
}
}
function checkSelectedInstallations() {
[
'stats', 'gps-download'
].map( x => { $('#input-'+x).hide() })
const selected = $('select#node-input-installations').val()
if (selected === 'stats') { $('#input-stats').show() }
if (selected === 'gps-download' ) { $('#input-gps-download').show()}
}
function checkSelectedUsers() {
[
'users-idUser'
].map( x => { $('#input-'+x).hide() })
const selected = $('select#node-input-users').val()
if (selected !== 'me') { $('#input-users-idUser').show() }
}
RED.nodes.registerType('vrm-api', {
category: 'Victron Energy',
paletteLabel: 'VRM API',
color: '#f7ab3e',
defaults: {
vrm: {value: "", type: "config-vrm-api"},
name: { value: "" },
api_type: { value: "", validate: RED.validators.regex(/^(users|installations|widgets|dynamic-ess)$/)},
// users
idUser: { value: "", validate: RED.validators.regex(/^(|[0-9]{1,12})$/)},
users: { value: "", required: false},
// installations
idSite: { value: "", validate: RED.validators.regex(/^(|[0-9]{1,12}|\{\{(node|flow|global)\..*\}\}|)$/)},
installations: { value: "", required: false},
attribute: {value: "", required: false},
stats_interval: {value: ""},
show_instance: {value: false},
stats_start: {value: ""},
stats_end: {value: ""},
use_utc: { value: false },
gps_start: {value: '', required: false },
gps_end: {value: '', required: false },
// widgets
// taking idSite from installations
widgets: { value: "", required: false},
instance: {value: "", required: false},
// dess
vrm_id: {value: "", validate: RED.validators.regex(/^(|[0-9a-zA-Z]{1,16})$/),required: false},
country: {value: "", required: false},
b_max: {value: "", required: false},
tb_max: {value: "", required: false},
fb_max: {value: "", required: false},
tg_max: {value: "", required: false},
fg_max: {value: "", required: false},
b_cycle_cost: {value: "", required: false},
buy_price_formula: {value: "", required: false},
sell_price_formula: {value: "", required: false},
green_mode_on: {value: "", required: false},
feed_in_possible: {value: "", required: false},
feed_in_control_on: {value: "", required: false},
b_goal_hour: {value: "", required: false},
b_goal_SOC: {value: "", required: false},
store_in_global_context: {value: false},
verbose: { value: false }
},
inputs: 1,
outputs: 1,
icon: "victronenergy.svg",
label: function () {
if (this.name) {
return this.name
}
var label = this.api_type
switch (this.api_type) {
case 'users': {
label += ' - ' + this.users
}
break;
case 'installations': {
if ( this.installations === 'stats' ) {
label += ' - Stats: ' + this.attribute
} else {
label += ' - ' + this.installations
}
}
break;
case 'widgets': {
label += ' - ' + this.widgets
}
}
return label;
},
oneditprepare: function oneditprepare() {
checkSelectedAPIType()
flatpickr("#node-input-gps_start", {
enableTime: true,
dateFormat: "Y-m-d H:i"
})
flatpickr("#node-input-gps_end", {
enableTime: true,
dateFormat: "Y-m-d H:i"
})
}
});
</script>
<script type="text/html" data-template-name="vrm-api">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-vrm"><i class="fa fa-tag"></i> VRM</label>
<input type="text" id="node-input-vrm" placeholder="VRM">
</div>
<div class="form-row">
<label for="node-input-api_type"><i class="fa fa-location-arrow"></i> API type</label>
<select id="node-input-api_type" required onchange="checkSelectedAPIType()">
<option value="users">Users</option>
<option value="installations">Installations</option>
<option value="widgets">Widgets</option>
<option value="dynamic-ess">Dynamic ESS</option>
</select>
</div>
<div id="input-users">
<div class="form-row">
<label for="node-input-users"><i class="fa fa-location-arrow"></i> Users</label>
<select id="node-input-users" onchange="checkSelectedUsers()">
<option value="installations">All installations/sites</option>
<option value="me">Basic user information</option>
</select>
</div>
<div id="input-users-idUser">
<div class="form-row">
<label for="node-input-idUser"><i class="fa fa-id-card"></i> User id</label>
<input type="text" id="node-input-idUser" placeholder="User id">
</div>
</div>
</div>
<div id="input-instalations_and_widgets">
<div class="form-row">
<label for="node-input-idSite"><i class="fa fa-id-card"></i> VRM site id</label>
<input type="text" id="node-input-idSite" placeholder="VRM site id">
</div>
</div>
<div id="input-installations">
<div class="form-row">
<label for="node-input-installations"><i class="fa fa-location-arrow"></i> Installation</label>
<select id="node-input-installations" onchange="checkSelectedInstallations()">
<option value="alarms">Get Alarms</option>
<option value="post-alarms">Add Alarm</option>
<option value="gps-download">GPS tracks</option>
<option value="system-overview">Connected devices for a given installation</option>
<option value="diagnostics">Diagnostic data for an installation</option>
<option value="tags">Get installation tags</option>
<option value="stats">Installation stats</option>
<option value="dynamic-ess-settings">Get Dynamic ESS configuration</option>
<option value="patch-dynamic-ess-settings">Modify Dynamic ESS configuration</option>
<option value="post-dynamic-ess-settings">Add Dynamic ESS configuration</option>
</select>
</div>
<div id="input-stats">
<div class="form-row">
<label for="node-input-attribute"><i class="fa fa-location-pencil"></i> Attribute</label>
<select id="node-input-attribute">
<option value="Bc">Battery direct use</option>
<option value="Bg">Battery to grid</option>
<option value="bs">Battery SoC</option>
<option value="Gc">Grid direct use</option>
<option value="Gb">Grid to battery</option>
<option value="Pc">Solar direct use</option>
<option value="Pb">Solar to battery</option>
<option value="kwh">Total kWh</option>
<option value="consumption">Consumption</option>
<option value="vrm_consumption_fc">Consumption Forecast</option>
<option value="vrm_pv_inverter_yield_fc">PV Inverter Yield Forecast</option>
<option value="vrm_pv_charger_yield_fc">PV Solar Charger Yield Forecast</option>
<option value="vrm_solar_irradiance">Solar Irradiance</option>
<option value="vrm_solar_irradiance_fc">Solar Irradiance Forecast</option>
<option value="solar_yield">Solar Yield</option>
<option value="total_solar_yield">Total Solar Yield</option>
<option value="solar_yield_forecast">Solar Yield Forecast</option>
<option value="dynamic_ess">Dynamic ESS</option>
</select>
</div>
<div class="form-row">
<label for="node-input-stats_interval"><i class="fa fa-barcode"></i> Interval</label>
<select id="node-input-stats_interval">
<option value="15mins">15 minutes</option>
<option selected="selected" value="hours">hours</option>
<option value="2hours">2 hours</option>
<option value="days">days</option>
<option value="weeks">weeks</option>
<option value="months">months</option>
<option value="years">years</option>
</select>
</div>
<div class="form-row">
<label for="node-input-stats_start"><i class="fa fa-calendar"></i> Start</label>
<select id="node-input-stats_start">
<option value="-31536000">-1 year</option>
<option value="-7257600">-12 weeks</option>
<option value="-2419200">-4 weeks</option>
<option value="-604800">-1 week</option>
<option value="-259200">-72 hours</option>
<option value="-172800">-48 hours</option>
<option value="-86400">-24 hours</option>
<option value="boy">beginning of yesterday</option>
<option value="bod">beginning of day</option>
<option value="bot">beginning of tomorrow</option>
<option selected="selected" value="0">now</option>
</select>
</div>
<div class="form-row">
<label for="node-input-stats_end"><i class="fa fa-calendar"></i> End</label>
<select id="node-input-stats_end">
<option value="0">now</option>
<option value="eod">end of day</option>
<option value="eoy">end of yesterday</option>
<option selected="selected" value="86400">+24 hours</option>
### tfx add more interval options
<option selected="selected" value="172800">+48 hours</option>
<option selected="selected" value="259200">+72 hours</option>
<option selected="selected" value="604800">+1 week</option>
### /tfx
</select>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" id="node-input-use_utc" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-use_utc"><i class="fa fa-power"></i> Use universal time (UTC) instead of the local time?</label>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" id="node-input-show_instance" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-show_instance"><i class="fa fa-power"></i> Group attributes by instance?</label>
</div>
</div>
</div>
<div id="input-gps-download">
<div class="form-row">
<label for="node-input-gps_start"><i class="fa fa-calendar"></i> Timestamp from which to fetch data</label>
<input type="text" id="node-input-gps_start" placeholder="Unix timestamp">
</div>
<div class="form-row">
<label for="node-input-gps_end"><i class="fa fa-calendar"></i> Timestamp tp which to fetch data</label>
<input type="text" id="node-input-gps_end" placeholder="Unix timestamp">
</div>
</div>
<div id="input-widgets">
<div class="form-row">
<label for="node-input-widgets"><i class="fa fa-location-arrow"></i> Widgets</label>
<select id="node-input-widgets">
<option value="BatterySummary">Battery summary data</option>
<option value="BMSDiagnostics">BMS diagnostics summary data</option>
<option value="HistoricData">Historic summary data</option>
<option value="IOExtenderInOut">IO extender input and output summary data</option>
<option value="LithiumBMS">Lithium BMS summary data</option>
<option value="DCMeter">DC meter summary data</option>
<option value="EvChargerSummary">EV charger summary data</option>
<option value="MeteorologicalSensor">Meteorological summary data</option>
<option value="GlobalLinkSummary">GlobalLink summary data</option>
<option value="MotorSummary">Motor summary data</option>
<option value="PVInverterStatus">PV inverter summary data</option>
<option value="SolarChargerSummary">Solar charger summary data</option>
<option value="Status">System overview summary data</option>
<option value="TankSummary">Tank summary data</option>
<option value="TempSummaryAndGraph">Temperature summary data</option>
</select>
</div>
<div class="form-row">
<label for="node-input-instance"><i class="fa fa-id-card"></i> Instance</label>
<input type="text" id="node-input-instance" placeholder="Instance for which to retrieve data, defaults to 0">
</div>
</div>
<div id="input-dynamic-ess">
<div class="form-row">
<label for="node-input-vrm_id"><i class="fa fa-id-card"></i> VRM id</label>
<input type="text" id="node-input-vrm_id" placeholder="VRM id" >
</div>
<div class="form-row">
<label for="node-input-country">Country / Energy region</label>
<select id="node-input-country" >
<option value="at">Austria (at)</option>
<option value="be">Belgium (be)</option>
<option value="bg">Bulgaria (bg)</option>
<option value="hr">Croatia (hr)</option>
<option value="cz">Czech Republic (cz)</option>
<option value="dk-1">Denmark (dk-1)</option>
<option value="dk-2">Denmark (dk-2)</option>
<option value="ee">Estonia (ee)</option>
<option value="fi">Finland (fi)</option>
<option value="fr">France (fr)</option>
<option value="de">Germany (de)</option>
<option value="gr">Greece (gr)</option>
<option value="hu">Hungary (hu)</option>
<option value="it-calabria">Italy - Calabria (it-calabria)</option>
<option value="it-centre-north">Italy - Centre-North (it-centre-north)</option>
<option value="it-centre-south">Italy - Centre-South (it-centre-south)</option>
<option value="it-north">Italy - North (it-north)</option>
<option value="it-sacoac">Italy - SACOAC (it-sacoac)</option>
<option value="it-sadodc">Italy - SACODC (it-sacodc)</option>
<option value="it-sardinia">Italy - Sardinia (it-sardinia)</option>
<option value="it-sicily">Italy - Sicily (it-sicily)</option>
<option value="it-south">Italy - South (it-south)</option>
<option value="lv">Latvia (lv)</option>
<option value="lt">Lithuania (lt)</option>
<option value="lu">Luxembourg (lu)</option>
<option value="me">Montenegro (me)</option>
<option value="nl">Netherlands (nl)</option>
<option value="mk">North Macedonia (mk)</option>
<option value="no-1">Norway (no-1)</option>
<option value="no-2">Norway (no-2)</option>
<option value="no-2nsl">Norway (no-2nsl)</option>
<option value="no-3">Norway (no-3)</option>
<option value="no-4">Norway (no-4)</option>
<option value="no-5">Norway (no-5)</option>
<option value="pl">Poland (pl)</option>
<option value="pt">Portugal (pt)</option>
<option value="ro">Romania (ro)</option>
<option value="rs">Serbia (rs)</option>
<option value="sk">Slovakia (sk)</option>
<option value="si">Slovenia (si)</option>
<option value="es">Spain (es)</option>
<option value="se-1">Sweden - SE1 (se-1)</option>
<option value="se-2">Sweden - SE2 (se-2)</option>
<option value="se-3">Sweden - SE3 (se-3)</option>
<option value="se-4">Sweden - SE4 (se-4)</option>
<option value="ch">Switzerland (ch)</option>
<option value="ua-ips">Ukraine - IPS (ua-ips)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-b_max"><i class="fa fa-battery-full"></i> B max</label>
<input type="text" id="node-input-b_max" placeholder="Usable battery capacity (kWh)">
</div>
<div class="form-row">
<label for="node-input-tb_max"><i class="fa fa-battery-full"></i> TB max</label>
<input type="text" id="node-input-tb_max" placeholder="Amount the battery charges in one hour (kW)">
</div>
<div class="form-row">
<label for="node-input-fb_max"><i class="fa fa-battery-full"></i> FB max</label>
<input type="text" id="node-input-fb_max" placeholder="Amount the battery discharges in one hour (kW)">
</div>
<div class="form-row">
<label for="node-input-tg_max"><i class="fa fa-battery-full"></i> TG max</label>
<input type="text" id="node-input-tg_max" placeholder="Amount the grid can receive (to grid) in one hour (kW)">
</div>
<div class="form-row">
<label for="node-input-fg_max"><i class="fa fa-battery-full"></i> FG max</label>
<input type="text" id="node-input-fg_max" placeholder="Amount the grid can provide (from grid) in one hour (kW)">
</div>
<div class="form-row">
<label for="node-input-b_cycle_cost"><i class="fa fa-money"></i> Battery cycle costs</label>
<input type="text" id="node-input-b_cycle_cost" placeholder="Battery cycle costs">
</div>
<div class="form-row">
<label for="node-input-buy_price_formula"><i class="fa fa-pencil"></i> Buy price</label>
<input type="text" id="node-input-buy_price_formula" placeholder="The buy price formula">
</div>
<div class="form-row">
<label for="node-input-sell_price_formula"><i class="fa fa-pencil"></i> Sell price</label>
<input type="text" id="node-input-sell_price_formula" placeholder="The sell price formula">
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" checked id="node-input-green_mode_on" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-green_mode_on">Green mode: <br /><ul><li>Only excess solar is fed back to grid</li><li>Avoid feeding in from battery</li><li>Use Smart-charging when needed</li></ul></label>
</div>
<div class="form-row">
<label for="node-input-b_goal_SOC"><i class="fa fa-battery-half"></i> b_goal SOC (%)</label>
<input type="text" id="node-input-b_goal_SOC" placeholder="Target SOC to reach at b_goal hour.">
<p> Must be above min SOC. Set to <code>0</code> to disable this feature.</p>
</div>
<div class="form-row">
<label for="node-input-b_goal_hour"><i class="fa fa-clock-o"></i> b_goal hour</label>
<input type="text" id="node-input-b_goal_hour" placeholder="Hour to reach b_goal SOC">
<p> Default: <code>0</code> = midnight</p>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" checked id="node-input-feed_in_possible" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="width: 70%" for="node-input-feed_in_possible"> Feed in possible: Can you sell back to the grid?</label>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" checked id="node-input-feed_in_control_on" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-feed_in_control_on"> Feed-in control: Allow control over the feed-in variable (turn it off automatically when the prices are negative)?</label>
</div>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" id="node-input-store_in_global_context" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-store_in_global_context"> Store the response in the global context?</label>
</div>
<div class="form-row" style="margin-bottom:0px;">
<input type="checkbox" id="node-input-verbose" style="display:inline-block; margin-left:8px; width:auto; vertical-align:top;">
<label style="min-width:390px" for="node-input-verbose"> Verbose: show the used <em>url</em> in the debug tab?</label>
</div>
</script>
<script type="text/markdown" data-help-name="vrm-api">
Interface with the Victron Energy VRM API.
### Inputs
: payload (string|number|json) : the trigger to query the VRM API
### Outputs
: payload (json) : the vrm answer
The output of the answer depends on the selected configuration. See the [VRM API documentation](https://vrm-api-docs.victronenergy.com/#)
in case you need assistance with interpreting the output.
Note that the site id is the multi-digit number you see in the url of your vrm-site. If you need the user id, query
the _basic user information_ first.
### Configuration
: Name (string) : The name of the node
: VRM (config) : The configuration node
: VRM site id (number) : The site to query
: API type (string) : The query type
: Store (boolean) : Store the respones in the global context?
: Verbose (boolean) : Show the used _url_ in the debug tab?
There are currently 4 API types to choose from:
- Users
- Installations
- Widgets
- Dynamic ESS
Depending on the API type, more or less extra fields appear.
In case of installation `stats` there appear some extra configuration options
: Attribute (string) : Which attribute to fetch
: Interval (string) : Time between retrieved data points
: Show instance (boolean) : If checked, attributes will be grouped by instance
: Start (integer) : Timestamp from which to fetch data
: End (integer) : Timestamp to which to fetch data
: UTC (boolean) : Use universal time (UTC) instead of the local time?
: Group by instance (boolean): Group attributes by instance?
In case of installation `dess` there are even more configuration options.
Note that instead of filling out the number of the VRM site id for installations and widgets in the box, you
can also use context variables, e.g. `{{flow.siteId}}` or `{{global.vrmId}}`. This allows to query the site
that has been set in this context field. Of course you need to make sure that context contains a valid VRM site id first.
### Details
This node makes it easy to use the VRM API for data retrieval. Though not all possible API calls have been implemented, it can
be used for retrieving and creating alarms and fetching installations statistics. It can also be used to retrieve the solar forecast
data.
In order to allow the node to query your site, an [access-token](https://vrm.victronenergy.com/access-tokens) needs to be created and filled
out in the configuration node.
If the data is to be stored in the global context, it will be saved under `vrm_api.${site_id}_${installation}`.
### References
Please use either the issues on the GitHub site or the Node-RED space on our community for questions, troubleshooting and suggestions.
- [GitHub](https://github.com/dirkjanfaber/victron-vrm-api) - The nodes GitHub repository.
- [Community](https://community.victronenergy.com/smart-spaces/71/node-red.html) - Node-RED space in the Victron Energy community.
- [VRM API documentation](https://vrm-api-docs.victronenergy.com/#) - The VRM API documentation.
</script>