Example Flows - victronenergy/node-red-contrib-victron GitHub Wiki

Victron Energy Node-RED Documentation

All example flows have a json snippet attached to them. The flows can be easily imported in Node-RED by opening the top-right corner menu and clicking Import > Clipboard.

Do note that you might still need to add extra nodes to the palette (via alt-shift-p -> Install). Also note that after importing a flow, you might need to adjust the nodes to point to your hardware.

Please feel free to add your own Victron Energy (related) node examples here.

Table of Contents

  1. Scheduled Control
  2. Combining Inputs
  3. Temperature Dashboard
  4. Location Based Scheduling
  5. Monitor Disk Usage
  6. Relay Switching
  7. MQTT Disk Space Monitoring
  8. Solar Forecasting
  9. Threshold Control
  10. Load Shedding and MinSOC
  11. Only Messages at Regular Intervals
  12. Run Generator at Certain Time
  13. Venus Reboot

Scheduled Control

Trigger based scheduling

This example uses a built-in inject node to trigger a message at specified times every day. It turns the inverter/charger on every morning at 6:00 AM (06:00) and switches it back off at 10:00 PM (22:00).

Simple interval

[{"id":"aaa14838.e2a268","type":"inject","z":"c0b678ed1e45492c","name":"Trigger 'ON' at 22:00","repeat":"","crontab":"00 22 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"3","payloadType":"num","x":340,"y":220,"wires":[["87b4cc47.a7886"]]},{"id":"e2730bab.207058","type":"inject","z":"c0b678ed1e45492c","name":"Trigger 'OFF' at 6:00","repeat":"","crontab":"00 06 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"4","payloadType":"num","x":340,"y":260,"wires":[["87b4cc47.a7886"]]},{"id":"87b4cc47.a7886","type":"victron-output-vebus","z":"c0b678ed1e45492c","service":"com.victronenergy.vebus/257","path":"/Mode","serviceObj":{"service":"com.victronenergy.vebus/257","name":"Quattro 24/3000/70-2x50"},"pathObj":{"path":"/Mode","type":"enum","name":"Switch Position","enum":{"1":"Charger Only","2":"Inverter Only","3":"On","4":"Off"},"writable":true},"initial":"","name":"","onlyChanges":true,"x":660,"y":240,"wires":[]}]

Do note that Node-RED is using the same timezone, as it has been set in the Remote Console. So if you encounter offsets in hours, make sure to check it there. After changing the timezone in the Remote Console, Node-RED needs to be restarted in order to start working with the new timezone.

Event based scheduling

Often it would be handy to force the device to stay in a specific mode during scheduled timeframes -- a user might for example (accidentally) change the device mode during the week. Since Node-RED is event-based, an approach, where incoming device state is actively monitored might be more useful. By default, all the input nodes send an update of the measured value every 5 seconds. On change the updates are send directly (about once a second). Also see issue #143.

Simple interval

[{"id":"1346a631.1b11da","type":"victron-input-vebus","z":"f00026185b490b05","service":"com.victronenergy.vebus/257","path":"/Mode","serviceObj":{"service":"com.victronenergy.vebus/257","name":"Quattro 24/3000/70-2x50"},"pathObj":{"path":"/Mode","type":"enum","name":"Switch Position","enum":{"1":"Charger Only","2":"Inverter Only","3":"On","4":"Off"}},"initial":"","name":"Quattro | Switch Position","onlyChanges":false,"x":210,"y":140,"wires":[["8d024799.d140a8"]]},{"id":"6163995.147aa68","type":"victron-output-vebus","z":"f00026185b490b05","service":"com.victronenergy.vebus/257","path":"/Mode","serviceObj":{"service":"com.victronenergy.vebus/257","name":"Quattro 24/3000/70-2x50"},"pathObj":{"path":"/Mode","type":"enum","name":"Switch Position","enum":{"1":"Charger Only","2":"Inverter Only","3":"On","4":"Off"},"writable":true},"initial":"","name":"Quattro | Switch Position","onlyChanges":true,"x":970,"y":140,"wires":[]},{"id":"8d024799.d140a8","type":"function","z":"f00026185b490b05","name":"is it night?","func":"// get current hours\nconst hr = new Date().getHours();\n\n// trigger a message if the time is between 12am and 6am or 'night'\nif (hr >= 23 || hr <= 6) {\n    return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":140,"wires":[["9d6486c9.60dd58"]]},{"id":"f7030089.433bd","type":"change","z":"f00026185b490b05","name":"set to 'off'","rules":[{"t":"set","p":"payload","pt":"msg","to":"4","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":760,"y":140,"wires":[["6163995.147aa68"]]},{"id":"9d6486c9.60dd58","type":"switch","z":"f00026185b490b05","name":"if not 'off'","property":"payload","propertyType":"msg","rules":[{"t":"neq","v":"4","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":600,"y":140,"wires":[["f7030089.433bd"]]}]

The same inject node can be used to trigger flows at a specific day of the week (such as "every Sunday at 12pm") or at specific intervals on scheduled day and time (such as "trigger every 15 minutes, on Mondays and Sundays between 5pm and 7 pm").

For scheduling based on special days, random offsets, based on dusk, dawn or other timing, use the node-red-big-timer node. This node can be installed via the menu (Manage palette -> Install)

Combining inputs

Charge batteries only using night time rates – unless the SoC is critically low

The following flow tries to maximise the electricity cost savings by charging the batteries only during night time -- unless the battery level is critically low.

The incoming message from the inverter/charger (Quattro) is routed to one of the switchnode outputs based on the battery level (Stat of Charge, SoC):

  1. If the battery level is below 25%, charge it regardless of the time of the day
  2. If the battery level is between 25% and 50%, charge at night and use battery power (inverter only mode) during the daytime
  3. otherwise (50% - 100% SoC) use battery battery power (inverter only mode)

Optimising night time rates

[{"id":"a7e1312e.5108a","type":"victron-input-battery","z":"6d4dca549d196382","service":"com.victronenergy.battery/0","path":"/Soc","serviceObj":{"service":"com.victronenergy.battery/0","name":"De Lynx Shunt"},"pathObj":{"path":"/Soc","type":"float","name":"State of charge (%)"},"initial":"","name":"","onlyChanges":false,"x":180,"y":260,"wires":[["967c021a.4e981"]]},{"id":"7a66435e.a64fcc","type":"victron-output-vebus","z":"6d4dca549d196382","service":"com.victronenergy.vebus/257","path":"/Mode","serviceObj":{"service":"com.victronenergy.vebus/257","name":"Quattro 24/3000/70-2x50"},"pathObj":{"path":"/Mode","type":"enum","name":"Switch Position","enum":{"1":"Charger Only","2":"Inverter Only","3":"On","4":"Off"},"writable":true},"initial":"","name":"","onlyChanges":true,"x":1160,"y":260,"wires":[]},{"id":"95d75091.0ac12","type":"change","z":"6d4dca549d196382","name":"Charger Only (grid input, charge batteries)","rules":[{"t":"set","p":"payload","pt":"msg","to":"1","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":720,"y":180,"wires":[["1898bb04.622815"]]},{"id":"f5995c2.c28a4a","type":"change","z":"6d4dca549d196382","name":"Inverter Only (no grid, use batteries)","rules":[{"t":"set","p":"payload","pt":"msg","to":"2","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":730,"y":340,"wires":[["1898bb04.622815"]]},{"id":"967c021a.4e981","type":"switch","z":"6d4dca549d196382","name":"SoC Switch","property":"payload","propertyType":"msg","rules":[{"t":"lt","v":"25","vt":"str"},{"t":"lt","v":"50","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":3,"x":410,"y":260,"wires":[["95d75091.0ac12"],["e174d8df.3ed888"],["f5995c2.c28a4a"]]},{"id":"1898bb04.622815","type":"rbe","z":"6d4dca549d196382","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":930,"y":260,"wires":[["7a66435e.a64fcc"]]},{"id":"e174d8df.3ed888","type":"function","z":"6d4dca549d196382","name":"night?","func":"// get current hours\nconst hr = new Date().getHours();\n\n// trigger a message if the time is between 12am and 6am or 'night'\nif (hr >= 0 && hr <= 6) {\n    return [msg, null]; // input 1\n} else {\n    return [null, msg]; // input 2\n}\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":260,"wires":[["95d75091.0ac12"],["f5995c2.c28a4a"]]}]

Turn the lamp on if it's dark outside. Turn it off after 30 minutes if it's not dark anymore.

This example controls a lamp connected to a relay depending on the outside brightness. Since we have a handy SmartSolar Charger available, the PV array voltage measurement can be used to estimate the outside brightness.

This example uses built-in trigger nodes to ensure that the incoming measurements stay consistent (e.g. the measured voltage actually stays consistently below 5 volts, and is not just random noise) as well as triggering a timeout after 30 minutes, turning the light off.

  1. The switch node routes the incoming PV voltage measurement messages depending on the voltage level. If the value is less than 5V (dark outside), the message is routed to the upper output triggering the first trigger node. If the value is more than 5V, the message is routed to the second output, sending a reset message to the first trigger node (reseting the timer).
  2. The first trigger node waits for incoming messages for 60 seconds. If no 'reset' messages are received, a message with a value 1 (relay on) is sent to the second trigger node.
  3. The second trigger node forwards the relay on message and starts a 30 min timeout counter. This will trigger a 'relay off' message on timeout unless new message is received before that.

Nightlight trigger

[{"id":"593e1f3e.2f6af","type":"victron-input-solarcharger","z":"c8efceb1ae745fd6","service":"com.victronenergy.solarcharger/277","path":"/Pv/V","serviceObj":{"service":"com.victronenergy.solarcharger/277","name":"SmartSolar MPPT 150/70"},"pathObj":{"path":"/Pv/V","type":"float","name":"PV voltage"},"name":"SmartSolar | PV voltage","onlyChanges":false,"x":220,"y":200,"wires":[["f07942df.b91a8"]]},{"id":"c693dbe0.bdbd38","type":"trigger","z":"c8efceb1ae745fd6","name":"consistently (60s) <5V","op1":"","op2":"1","op1type":"nul","op2type":"num","duration":"60","extend":false,"units":"s","reset":"","bytopic":"all","outputs":1,"x":620,"y":220,"wires":[["422bb5e.545154c"]]},{"id":"f07942df.b91a8","type":"switch","z":"c8efceb1ae745fd6","name":"","property":"payload","propertyType":"msg","rules":[{"t":"lte","v":"5","vt":"str"},{"t":"gt","v":"5","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":390,"y":200,"wires":[["c693dbe0.bdbd38"],["5af796d8.df31b8"]]},{"id":"5af796d8.df31b8","type":"change","z":"c8efceb1ae745fd6","name":"","rules":[{"t":"set","p":"reset","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":260,"wires":[["c693dbe0.bdbd38"]]},{"id":"422bb5e.545154c","type":"trigger","z":"c8efceb1ae745fd6","name":"30 min timeout","op1":"","op2":"0","op1type":"pay","op2type":"num","duration":"30","extend":true,"units":"min","reset":"","bytopic":"all","outputs":1,"x":820,"y":220,"wires":[["13bac09b.cbca1f"]]},{"id":"13bac09b.cbca1f","type":"victron-output-relay","z":"c8efceb1ae745fd6","service":"com.victronenergy.system/0","path":"/Relay/1/State","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus device"},"pathObj":{"path":"/Relay/1/State","type":"enum","name":"Venus relay 2 state","enum":{"0":"Open","1":"Closed"},"writable":true},"initial":"","name":"","onlyChanges":true,"x":1060,"y":220,"wires":[]}]

Temperature dashboard

Temperature dashboard

This flow consists of a few nodes:

  • Victron Energy: Temperature Sensor
  • function: function
  • function: filter
  • dashboard: text
  • dashboard: chart

Temperature flow

We start with the temperature sensor. From the Edit Temperature Sensor node select the temperature sensor and the measurement that you want to monitor. Note that te name of the Sensor can be changed from the Venus OS GUI.

As the temperature can have a precision of several digits, we want to cut that to a single digit. We use a function node for that containing:

msg.payload = +(msg.payload.toFixed(1));

return msg;

What this does, is to fix the number to 1 digit precision. Because toFixed returns a string and not a number, we force this back to a number using the +(...) construction.

In order to only update the rest of the flow when the temperature actually changes, we add a filter node. We set this to the mode block unless value changes.

The last things we add are the dashboard nodes. In this case we add a text node and a chart.

When you create your first dashboard, you need to add a new ui_group, which in its turn requires to create a new ui_tab first. The easiest way to do this is following the defaults and adjusting them at a later moment.

[{"id":"b4b0159d120cbd01","type":"tab","label":"Example UI temperature","disabled":false,"info":""},{"id":"f6c54460b03ab6d6","type":"victron-input-temperature","z":"b4b0159d120cbd01","service":"com.victronenergy.temperature.ruuvi_fa6f64b12935","path":"/Temperature","serviceObj":{"service":"com.victronenergy.temperature.ruuvi_fa6f64b12935","name":"Engine room","paths":[{"path":"/Temperature","type":"float","name":"Temperature (C)"},{"path":"/TemperatureType","type":"enum","name":"Sensor type","enum":{"0":"Battery","1":"Fridge","2":"Generic"}}]},"pathObj":{"path":"/Temperature","type":"float","name":"Temperature (C)"},"name":"","x":210,"y":120,"wires":[["3feab55ddec56979"]]},{"id":"9bd980691459f2da","type":"rbe","z":"b4b0159d120cbd01","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":610,"y":120,"wires":[["c74fe6af3165f216","f76f31edbeaf874c"]]},{"id":"c74fe6af3165f216","type":"ui_text","z":"b4b0159d120cbd01","group":"71198c916d6c728f","order":0,"width":0,"height":0,"name":"","label":"","format":"{{msg.payload | number:1}} &deg;","layout":"row-right","className":"","x":780,"y":120,"wires":[]},{"id":"f76f31edbeaf874c","type":"ui_chart","z":"b4b0159d120cbd01","name":"","group":"71198c916d6c728f","order":1,"width":"12","height":"5","label":"Temperature engine room","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"40","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"86400","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":840,"y":200,"wires":[[]]},{"id":"3feab55ddec56979","type":"function","z":"b4b0159d120cbd01","name":"","func":"msg.payload = +(msg.payload.toFixed(1));\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":120,"wires":[["9bd980691459f2da"]]},{"id":"71198c916d6c728f","type":"ui_group","name":"Victron Energy","tab":"f3b567ee7aeff702","order":1,"disp":true,"width":"12","collapse":false,"className":""},{"id":"f3b567ee7aeff702","type":"ui_tab","name":"Home","icon":"fa-fire","disabled":false,"hidden":false}]

Location based scheduling

Location based scheduling flow

When you use the Victron devices while traveling, your physical position changes and you might want to adjust your setup based on your current location. This example shows just that using an USB connected GPS to trigger the relay at dusk and dawn. We use the context based storage of the location as input for BigTimer to set the geo_override, while defaulting to the home location on first startup until the first GPS fix. The default location is set in the function node:

msg.payload = "geo_override "+ 
  ( flow.get('longitude') || 52.35) +
  " "+( flow.get('latitude') || 5.22 )

return msg;

The json flow:

[{"id":"29a12244e2a667cb","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"4357e7a1375cf691","type":"victron-input-gps","z":"29a12244e2a667cb","service":"com.victronenergy.gps.ve_ttyUSB0","path":"/Position/Longitude","serviceObj":{"service":"com.victronenergy.gps.ve_ttyUSB0","name":"NMEA-0183 GPS (USB0)","paths":[{"path":"/Altitude","type":"float","name":"Altitude (m)"},{"path":"/Course","type":"float","name":"Course (Deg)"},{"path":"/Fix","type":"integer","name":"Fix"},{"path":"/NrOfSatellites","type":"integer","name":"Number of satellites"},{"path":"/Position/Latitude","type":"float","name":"Latitude (LAT)"},{"path":"/Position/Longitude","type":"float","name":"Longitude (LNG)"},{"path":"/Speed","type":"float","name":"Speed (m/s)"}]},"pathObj":{"path":"/Position/Longitude","type":"float","name":"Longitude (LNG)"},"name":"","x":310,"y":160,"wires":[["6e4a74f29bcab40c"]]},{"id":"5a3e501b35b780ce","type":"victron-input-gps","z":"29a12244e2a667cb","service":"com.victronenergy.gps.ve_ttyUSB0","path":"/Position/Latitude","serviceObj":{"service":"com.victronenergy.gps.ve_ttyUSB0","name":"NMEA-0183 GPS (USB0)","paths":[{"path":"/Altitude","type":"float","name":"Altitude (m)"},{"path":"/Course","type":"float","name":"Course (Deg)"},{"path":"/Fix","type":"integer","name":"Fix"},{"path":"/NrOfSatellites","type":"integer","name":"Number of satellites"},{"path":"/Position/Latitude","type":"float","name":"Latitude (LAT)"},{"path":"/Position/Longitude","type":"float","name":"Longitude (LNG)"},{"path":"/Speed","type":"float","name":"Speed (m/s)"}]},"pathObj":{"path":"/Position/Latitude","type":"float","name":"Latitude (LAT)"},"name":"","x":300,"y":240,"wires":[["7adeba7b6989a6d6"]]},{"id":"6e4a74f29bcab40c","type":"change","z":"29a12244e2a667cb","name":"","rules":[{"t":"set","p":"longitude","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":160,"wires":[["86b1f6f717479363"]]},{"id":"7adeba7b6989a6d6","type":"change","z":"29a12244e2a667cb","name":"","rules":[{"t":"set","p":"latitude","pt":"flow","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":240,"wires":[["86b1f6f717479363"]]},{"id":"ce99faf0c4095c4b","type":"function","z":"29a12244e2a667cb","name":"","func":"msg.payload = \"geo_override \"+ \n  ( flow.get('longitude') || 52.35) +\n  \" \"+( flow.get('latitude') || 5.22 )\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":320,"wires":[["1eeb46b96d9a0375"]]},{"id":"e6da11dc0b52b44a","type":"rbe","z":"29a12244e2a667cb","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":250,"y":320,"wires":[["ce99faf0c4095c4b"]]},{"id":"86b1f6f717479363","type":"link out","z":"29a12244e2a667cb","name":"","mode":"link","links":["4150a42bf9331654"],"x":895,"y":220,"wires":[]},{"id":"4150a42bf9331654","type":"link in","z":"29a12244e2a667cb","name":"","links":["86b1f6f717479363"],"x":155,"y":320,"wires":[["e6da11dc0b52b44a"]]},{"id":"1eeb46b96d9a0375","type":"bigtimer","z":"29a12244e2a667cb","outtopic":"","outpayload1":"","outpayload2":"","name":"Big Timer","comment":"","lat":0,"lon":0,"starttime":"5003","endtime":"5004","starttime2":0,"endtime2":0,"startoff":0,"endoff":0,"startoff2":0,"endoff2":0,"offs":0,"outtext1":"","outtext2":"","timeout":1440,"sun":true,"mon":true,"tue":true,"wed":true,"thu":true,"fri":true,"sat":true,"jan":true,"feb":true,"mar":true,"apr":true,"may":true,"jun":true,"jul":true,"aug":true,"sep":true,"oct":true,"nov":true,"dec":true,"day1":0,"month1":0,"day2":0,"month2":0,"day3":0,"month3":0,"day4":0,"month4":0,"day5":0,"month5":0,"day6":0,"month6":0,"day7":0,"month7":0,"day8":0,"month8":0,"day9":0,"month9":0,"day10":0,"month10":0,"day11":0,"month11":0,"day12":0,"month12":0,"d1":0,"w1":0,"d2":0,"w2":0,"d3":0,"w3":0,"d4":0,"w4":0,"d5":0,"w5":0,"d6":0,"w6":0,"xday1":0,"xmonth1":0,"xday2":0,"xmonth2":0,"xday3":0,"xmonth3":0,"xday4":0,"xmonth4":0,"xday5":0,"xmonth5":0,"xday6":0,"xmonth6":0,"xday7":0,"xmonth7":0,"xday8":0,"xmonth8":0,"xday9":0,"xmonth9":0,"xday10":0,"xmonth10":0,"xday11":0,"xmonth11":0,"xday12":0,"xmonth12":0,"xd1":0,"xw1":0,"xd2":0,"xw2":0,"xd3":0,"xw3":0,"xd4":0,"xw4":0,"xd5":0,"xw5":0,"xd6":0,"xw6":0,"suspend":false,"random":false,"randon1":false,"randoff1":false,"randon2":false,"randoff2":false,"repeat":true,"atstart":true,"odd":false,"even":false,"x":540,"y":320,"wires":[["162eafe97f1a64c2"],[],[]]},{"id":"162eafe97f1a64c2","type":"victron-output-relay","z":"29a12244e2a667cb","service":"com.victronenergy.system","path":"/Relay/0/State","serviceObj":{"service":"com.victronenergy.system","name":"Venus device","paths":[{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"},"writable":true},{"path":"/Relay/1/State","type":"enum","name":"Venus relay 2 state","enum":{"0":"Open","1":"Closed"},"writable":true}]},"pathObj":{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"},"writable":true},"initial":"","name":"","x":800,"y":320,"wires":[]}]

Monitor disk usage

Monitor disk usage flow

Though not using the Victron nodes for this flow, you might want to keep track of the disk usage of your Venus device. This flow uses the exec node to use the df command to query the used capacity of the disk. It pipes the output of df into a quite fancy awk command that filters out the ext4 filesystems of the system and outputs the information as JSON. The JSON is then converted as input for a chart with double input. The whole flow is triggerd by an inject node that repeats every 5 minutes.

Monitor disk usage dashboard

Of course this flow can be extended upon. E.g. by adding the Relay Control node to it and switching a light at a certain threshold. Make sure to check the example on relay switching (from the dashboard) too.

Do note that though the root filesystem (/) seems to be almost full, this filesystem will not fill up over time (as it is read-only). The main reason for adding it to this flow is to give an example with uses multiple inputs into a single chart.

In order to use the flow as is, the following extra modules need to be installed:

  • node-red-dashboard
  • node-red-contrib-ui-artless-gauge

The json flow:

[{"id":"2572169effe3f2b3","type":"tab","label":"Disk usage","disabled":false,"info":"","env":[]},{"id":"0daeece3186ef220","type":"exec","z":"2572169effe3f2b3","command":"df -PT | awk 'BEGIN { ORS = \"\"; print \"[ \"}; /ext4/ { printf \"%s{\\\"name\\\": \\\"%s\\\", \\\"capacity\\\": %d, \\\"mount_point\\\": \\\"%s\\\"}\", separator, $1, substr($6, 1, length($6)-1), $7; separator = \", \"}; END { print \" ]\" }'","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"df - awk to json","x":420,"y":100,"wires":[["e9e64388253a46b7"],[],[]]},{"id":"6d206705feba0284","type":"inject","z":"2572169effe3f2b3","name":"every 5 minutes","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":190,"y":100,"wires":[["0daeece3186ef220"]]},{"id":"e9e64388253a46b7","type":"function","z":"2572169effe3f2b3","name":"json to chart","func":"var df = JSON.parse(msg.payload);\n\nreturn [\n    { \"topic\": df[0].mount_point, \"payload\": df[0].capacity },\n    { \"topic\": df[1].mount_point, \"payload\": df[1].capacity },\n      ]","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":190,"y":160,"wires":[["6888ba1078a980bd","3e8e481d9b35f247"],["6888ba1078a980bd","63601ce5a6336684"]]},{"id":"6888ba1078a980bd","type":"ui_chart","z":"2572169effe3f2b3","name":"","group":"c1d025375d7da0a8","order":0,"width":"9","height":"4","label":"","chartType":"line","legend":"true","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"604800","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#d65151","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":410,"y":240,"wires":[[]]},{"id":"63601ce5a6336684","type":"ui_artlessgauge","z":"2572169effe3f2b3","group":"c1d025375d7da0a8","order":1,"width":0,"height":0,"name":"gauge /data","icon":"fa-hdd-o","label":"/data","unit":"%","layout":"radial","decimals":0,"differential":false,"minmax":true,"colorTrack":"#555555","style":"","colorFromTheme":true,"property":"payload","secondary":"secondary","inline":true,"animate":true,"sectors":[{"val":0,"col":"#16c309","t":"min","dot":0},{"val":95,"col":"#dc7118","t":"sec","dot":0},{"val":100,"col":"#dc7118","t":"max","dot":0}],"lineWidth":3,"bgcolorFromTheme":true,"diffCenter":"","x":430,"y":200,"wires":[]},{"id":"3e8e481d9b35f247","type":"ui_artlessgauge","z":"2572169effe3f2b3","group":"c1d025375d7da0a8","order":1,"width":0,"height":0,"name":"gauge /root","icon":"fa-hdd-o","label":"/root","unit":"%","layout":"radial","decimals":0,"differential":false,"minmax":true,"colorTrack":"#555555","style":"","colorFromTheme":true,"property":"payload","secondary":"secondary","inline":true,"animate":true,"sectors":[{"val":0,"col":"#16c309","t":"min","dot":0},{"val":95,"col":"#dc7118","t":"sec","dot":0},{"val":100,"col":"#dc7118","t":"max","dot":0}],"lineWidth":3,"bgcolorFromTheme":true,"diffCenter":"","x":430,"y":160,"wires":[]},{"id":"c1d025375d7da0a8","type":"ui_group","name":"Disk usage","tab":"e911cf6c5b4b89b4","order":1,"disp":true,"width":"12","collapse":true,"className":""},{"id":"e911cf6c5b4b89b4","type":"ui_tab","name":"Home","icon":"fa-disk","disabled":false,"hidden":false}]

Monitor disk usage

Monitor disk usage flow

Though not using the Victron nodes for this flow, you might want to keep track of the disk usage of your Venus device. This flow uses the exec node to use the df command to query the used capacity of the disk. It pipes the output of df into a quite fancy awk command that filters out the ext4 filesystems of the system and outputs the information as JSON. The JSON is then converted as input for a chart with double input. The whole flow is triggerd by an inject node that repeats every 5 minutes.

Monitor disk usage dashboard

Of course this flow can be extended upon. E.g. by adding the Relay Control node to it and switching a light at a certain threshold. Make sure to check the example on relay switching (from the dashboard) too.

Do note that though the root filesystem (/) seems to be almost full, this filesystem will not fill up over time (as it is read-only). The main reason for adding it to this flow is to give an example with uses multiple inputs into a single chart.

In order to use the flow as is, the following extra modules need to be installed:

  • node-red-dashboard
  • node-red-contrib-ui-artless-gauge

The json flow:

[{"id":"2572169effe3f2b3","type":"tab","label":"Disk usage","disabled":false,"info":"","env":[]},{"id":"0daeece3186ef220","type":"exec","z":"2572169effe3f2b3","command":"df -PT | awk 'BEGIN { ORS = \"\"; print \"[ \"}; /ext4/ { printf \"%s{\\\"name\\\": \\\"%s\\\", \\\"capacity\\\": %d, \\\"mount_point\\\": \\\"%s\\\"}\", separator, $1, substr($6, 1, length($6)-1), $7; separator = \", \"}; END { print \" ]\" }'","addpay":"","append":"","useSpawn":"false","timer":"","winHide":false,"oldrc":false,"name":"df - awk to json","x":420,"y":100,"wires":[["e9e64388253a46b7"],[],[]]},{"id":"6d206705feba0284","type":"inject","z":"2572169effe3f2b3","name":"every 5 minutes","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"300","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":190,"y":100,"wires":[["0daeece3186ef220"]]},{"id":"e9e64388253a46b7","type":"function","z":"2572169effe3f2b3","name":"json to chart","func":"var df = JSON.parse(msg.payload);\n\nreturn [\n    { \"topic\": df[0].mount_point, \"payload\": df[0].capacity },\n    { \"topic\": df[1].mount_point, \"payload\": df[1].capacity },\n      ]","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":190,"y":160,"wires":[["6888ba1078a980bd","3e8e481d9b35f247"],["6888ba1078a980bd","63601ce5a6336684"]]},{"id":"6888ba1078a980bd","type":"ui_chart","z":"2572169effe3f2b3","name":"","group":"c1d025375d7da0a8","order":0,"width":"9","height":"4","label":"","chartType":"line","legend":"true","xformat":"HH:mm","interpolate":"linear","nodata":"","dot":false,"ymin":"0","ymax":"100","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"604800","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#d65151","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":410,"y":240,"wires":[[]]},{"id":"63601ce5a6336684","type":"ui_artlessgauge","z":"2572169effe3f2b3","group":"c1d025375d7da0a8","order":1,"width":0,"height":0,"name":"gauge /data","icon":"fa-hdd-o","label":"/data","unit":"%","layout":"radial","decimals":0,"differential":false,"minmax":true,"colorTrack":"#555555","style":"","colorFromTheme":true,"property":"payload","secondary":"secondary","inline":true,"animate":true,"sectors":[{"val":0,"col":"#16c309","t":"min","dot":0},{"val":95,"col":"#dc7118","t":"sec","dot":0},{"val":100,"col":"#dc7118","t":"max","dot":0}],"lineWidth":3,"bgcolorFromTheme":true,"diffCenter":"","x":430,"y":200,"wires":[]},{"id":"3e8e481d9b35f247","type":"ui_artlessgauge","z":"2572169effe3f2b3","group":"c1d025375d7da0a8","order":1,"width":0,"height":0,"name":"gauge /root","icon":"fa-hdd-o","label":"/root","unit":"%","layout":"radial","decimals":0,"differential":false,"minmax":true,"colorTrack":"#555555","style":"","colorFromTheme":true,"property":"payload","secondary":"secondary","inline":true,"animate":true,"sectors":[{"val":0,"col":"#16c309","t":"min","dot":0},{"val":95,"col":"#dc7118","t":"sec","dot":0},{"val":100,"col":"#dc7118","t":"max","dot":0}],"lineWidth":3,"bgcolorFromTheme":true,"diffCenter":"","x":430,"y":160,"wires":[]},{"id":"c1d025375d7da0a8","type":"ui_group","name":"Disk usage","tab":"e911cf6c5b4b89b4","order":1,"disp":true,"width":"12","collapse":true,"className":""},{"id":"e911cf6c5b4b89b4","type":"ui_tab","name":"Home","icon":"fa-disk","disabled":false,"hidden":false}]

Relay switching (from the dashboard)

Relay switching (from the dashboard)

Adding relays to the dashboard in order to switch one of the relays is easy with the Relay node. Do make sure that the relay has been set to Manual mode from the Venus GUI or VictronConnect first.
In order to have the switch also follow the state of the relay, you need to connect it on the incoming side of the switch as well. This allows the dashboard to show relay changes that originate from a different place than the dashboard itself (e.g. from the Venus GUI).

In order to use the flow as is, the following extra module need to be installed:

  • node-red-dashboard

The json flow:

[{"id":"0e89536a19bf09a2","type":"ui_switch","z":"5c75e1854c070de0","name":"","label":"Cerbo relay 1","tooltip":"","group":"a9d0f0d6dc0f0a7e","order":0,"width":0,"height":0,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"1","onvalueType":"num","onicon":"","oncolor":"","offvalue":"0","offvalueType":"num","officon":"","offcolor":"","animate":false,"className":"","x":500,"y":400,"wires":[["dedefd55516b23c0"]]},{"id":"c4a267b7d3e8ea37","type":"victron-input-relay","z":"5c75e1854c070de0","service":"com.victronenergy.system","path":"/Relay/0/State","serviceObj":{"service":"com.victronenergy.system","name":"com.victronenergy.system","paths":[{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"}},{"path":"/Relay/1/State","type":"enum","name":"Venus relay 2 state","enum":{"0":"Open","1":"Closed"}}]},"pathObj":{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"}},"initial":"","name":"","x":620,"y":340,"wires":[["0e89536a19bf09a2"]]},{"id":"dedefd55516b23c0","type":"victron-output-relay","z":"5c75e1854c070de0","service":"com.victronenergy.system","path":"/Relay/0/State","serviceObj":{"service":"com.victronenergy.system","name":"Venus device","paths":[{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"},"writable":true},{"path":"/Relay/1/State","type":"enum","name":"Venus relay 2 state","enum":{"0":"Open","1":"Closed"},"writable":true}]},"pathObj":{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"},"writable":true},"initial":"","name":"","x":760,"y":400,"wires":[]},{"id":"a9d0f0d6dc0f0a7e","type":"ui_group","name":"Default","tab":"12a65f5c2118623e","order":1,"disp":true,"width":"6","collapse":false,"className":""},{"id":"12a65f5c2118623e","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false}]

Using MQTT to monitor disk space

Another way of monitoring the free disk space is using MQTT on your Venus device. This example does not even use the node-red-contrib-victron nodes, but uses the mqtt in and mqtt out node to get its information. Background information can be found on the dbus-mqtt README.
It is kept as simple as possible, only outputting the free diskspace to the debug node. In order to get this running, make sure that you enable the MQTT on LAN (Plaintext) service via the Venus GUI.

Monitor disk usage via MQTT

The json flow:

[{"id":"7ac6af939dc5a153","type":"group","z":"a82aad42bb7ab4a2","name":"DiskFree on /data (localhost)","style":{"label":true},"nodes":["62a1c831db1a0a14","3105b9707e773ba3","af169cb4b8a7acc6","23bd818d521f8b69"],"x":334,"y":119,"w":632,"h":142},{"id":"62a1c831db1a0a14","type":"mqtt in","z":"a82aad42bb7ab4a2","g":"7ac6af939dc5a153","name":"","topic":"N/d41243049d76/logger/0/Buffer/FreeDiskSpace","qos":"2","datatype":"auto-detect","broker":"ee3d7d8edf41c2a3","nl":false,"rap":true,"rh":0,"inputs":0,"x":540,"y":160,"wires":[["3105b9707e773ba3"]]},{"id":"3105b9707e773ba3","type":"debug","z":"a82aad42bb7ab4a2","g":"7ac6af939dc5a153","name":"mqtt localhost","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":160,"wires":[]},{"id":"af169cb4b8a7acc6","type":"mqtt out","z":"a82aad42bb7ab4a2","g":"7ac6af939dc5a153","name":"","topic":"R/d41243049d76/logger/0/Buffer/FreeDiskSpace","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"ee3d7d8edf41c2a3","x":760,"y":220,"wires":[]},{"id":"23bd818d521f8b69","type":"inject","z":"a82aad42bb7ab4a2","g":"7ac6af939dc5a153","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":450,"y":220,"wires":[["af169cb4b8a7acc6"]]},{"id":"ee3d7d8edf41c2a3","type":"mqtt-broker","name":"MQTT localhost","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]

Solar forecasting

Knowing what solar yield is expected in advance allows you to make decisions on where to get your energy. If the expected yield is low, you might want to charge your batteries from the grid, preferably at a moment where the electricity rate is low. The following example shows you how to get the predicted results, based on the lattitude, longitude, orientation, angle and power of your modules. It uses the API of http://forecast.solar/ to fetch the data. The example is still limited on just getting the data, but should give you a good starting point.

Location based solar forecasting

It uses this subflow for creating an extra node, which makes it easy to configure.

Threshold control

image

The following example has been take from the webinar.

The input is connected to the Battery Voltage, but can be overridden via the Manual input slider, once the Manual switch is selected.

The logic is that the Output State will switch on when the input is larger than the ON Threshold. And it will switch off again when the input is lower than the OFF Threshold. Before switching on and off, it will first wait for ON / OFF delay.

The layout of this page is controlled via the CSS Template node.

It uses the a few extra modules, which need to be added to the palette first:

  • node-red-dashboard
  • node-red-contrib-ui-led
  • node-red-contrib-countdown
[{"id":"c2f49fed633045e9","type":"tab","label":"Threshold Control","disabled":false,"info":""},{"id":"b93f74c788b45137","type":"change","z":"c2f49fed633045e9","name":"Set OFF_Threshold","rules":[{"t":"set","p":"OFF_Threshold","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":120,"wires":[[]]},{"id":"c783bffd55ad5148","type":"change","z":"c2f49fed633045e9","name":"Set ON_Threshold","rules":[{"t":"set","p":"ON_Threshold","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":410,"y":80,"wires":[[]]},{"id":"9beb9294ea2753be","type":"victron-output-relay","z":"c2f49fed633045e9","service":"com.victronenergy.system/0","path":"/Relay/0/State","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus device"},"pathObj":{"path":"/Relay/0/State","type":"enum","name":"Venus relay 1 state","enum":{"0":"Open","1":"Closed"},"writable":true},"initial":"0","name":"","onlyChanges":true,"x":1120,"y":360,"wires":[]},{"id":"bd1936468ed6154e","type":"change","z":"c2f49fed633045e9","name":"Set ON_Delay","rules":[{"t":"set","p":"ON_Delay","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":80,"wires":[[]]},{"id":"790deebc639303ec","type":"change","z":"c2f49fed633045e9","name":"Set OFF_Delay","rules":[{"t":"set","p":"OFF_Delay","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":120,"wires":[[]]},{"id":"3cc144d3cb79c86b","type":"ui_text","z":"c2f49fed633045e9","group":"9b4290ae01764c48","order":1,"width":4,"height":1,"name":"","label":"Input","format":"{{msg.payload}} V","layout":"row-spread","className":"","x":550,"y":720,"wires":[]},{"id":"338ac7bb5375be4b","type":"ui_slider","z":"c2f49fed633045e9","name":"","label":"OFF Threshold","tooltip":"","group":"9b4290ae01764c48","order":7,"width":0,"height":0,"passthru":true,"outs":"end","topic":"topic","topicType":"msg","min":0,"max":"100","step":1,"className":"","x":200,"y":120,"wires":[["b93f74c788b45137"]]},{"id":"c55d652923b5cea6","type":"ui_slider","z":"c2f49fed633045e9","name":"","label":"ON Threshold","tooltip":"","group":"9b4290ae01764c48","order":6,"width":0,"height":0,"passthru":true,"outs":"end","topic":"topic","topicType":"msg","min":0,"max":"100","step":1,"className":"","x":200,"y":80,"wires":[["c783bffd55ad5148"]]},{"id":"da23599cb07f8886","type":"ui_numeric","z":"c2f49fed633045e9","name":"","label":"ON Delay","tooltip":"","group":"9b4290ae01764c48","order":8,"width":4,"height":1,"wrap":false,"passthru":true,"topic":"topic","topicType":"msg","format":"{{value}} s","min":"5","max":"1000","step":"5","className":"","x":860,"y":80,"wires":[["bd1936468ed6154e"]]},{"id":"7a46fd82216aff5b","type":"ui_numeric","z":"c2f49fed633045e9","name":"","label":"OFF Delay","tooltip":"","group":"9b4290ae01764c48","order":13,"width":4,"height":1,"wrap":false,"passthru":true,"topic":"topic","topicType":"msg","format":"{{value}} s","min":"5","max":"120","step":"5","className":"","x":870,"y":120,"wires":[["790deebc639303ec"]]},{"id":"e836bd92de4d963b","type":"ui_slider","z":"c2f49fed633045e9","name":"","label":"Manual Input","tooltip":"","group":"9b4290ae01764c48","order":5,"width":0,"height":0,"passthru":true,"outs":"end","topic":"topic","topicType":"msg","min":0,"max":"100","step":"0.5","className":"","x":710,"y":680,"wires":[["c9efebadb888bad7"]]},{"id":"89d9de0972a486e0","type":"ui_led","z":"c2f49fed633045e9","order":4,"group":"9b4290ae01764c48","width":1,"height":1,"label":"","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ff0000","value":"ON","valueType":"str"},{"color":"#808080","value":"OFF","valueType":"str"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"Output LED","x":1250,"y":280,"wires":[]},{"id":"0d05522d73994155","type":"trigger","z":"c2f49fed633045e9","name":"","op1":"","op2":"0","op1type":"pay","op2type":"str","duration":"-2","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1120,"y":680,"wires":[["d7ee685a75fa76e7"]]},{"id":"906579e2414d4b3a","type":"ui_text","z":"c2f49fed633045e9","group":"9b4290ae01764c48","order":10,"width":4,"height":1,"name":"","label":"ON Countdown","format":"{{msg.payload}} s","layout":"row-spread","className":"","x":840,"y":260,"wires":[]},{"id":"ef0c9a5a1c13c0ed","type":"ui_text","z":"c2f49fed633045e9","group":"9b4290ae01764c48","order":15,"width":4,"height":1,"name":"","label":"OFF Countdown","format":"{{msg.payload}} s","layout":"row-spread","className":"","x":840,"y":380,"wires":[]},{"id":"140e9db1ef2317e6","type":"switch","z":"c2f49fed633045e9","name":"Logic","property":"payload","propertyType":"msg","rules":[{"t":"gte","v":"ON_Threshold","vt":"flow"},{"t":"lte","v":"OFF_Threshold","vt":"flow"},{"t":"else"}],"checkall":"false","repair":false,"outputs":3,"x":130,"y":320,"wires":[["2b19519cec878f93"],["1cf3289690c9ac23"],["806d310a85ecb328","baac05671f700297"]]},{"id":"861fd2edaa68d45d","type":"countdown","z":"c2f49fed633045e9","name":"ON Countdown","topic":"","payloadTimerStart":"","payloadTimerStartType":"nul","payloadTimerStop":"1","payloadTimerStopType":"num","timer":"30","resetWhileRunning":false,"outputOnReset":false,"setTimeToNewWhileRunning":false,"startCountdownOnControlMessage":true,"x":620,"y":260,"wires":[["3533636b2b76dda3"],["906579e2414d4b3a","1b6eb2b9b430e965"]]},{"id":"2b19519cec878f93","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"ON_Delay","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":260,"wires":[["baac05671f700297","fa07bbbb7fee2ada"]]},{"id":"78f1b6ac7a030a92","type":"countdown","z":"c2f49fed633045e9","name":"OFF Countdown","topic":"","payloadTimerStart":"","payloadTimerStartType":"nul","payloadTimerStop":"0","payloadTimerStopType":"num","timer":"30","resetWhileRunning":false,"outputOnReset":false,"setTimeToNewWhileRunning":false,"startCountdownOnControlMessage":true,"x":620,"y":380,"wires":[["3533636b2b76dda3"],["ef0c9a5a1c13c0ed","29bf8e0dec6e02b5"]]},{"id":"1cf3289690c9ac23","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"set","p":"topic","pt":"msg","to":"control","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"OFF_Delay","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":380,"wires":[["806d310a85ecb328","1f987e24531737c0"]]},{"id":"baac05671f700297","type":"change","z":"c2f49fed633045e9","name":"Reset","rules":[{"t":"delete","p":"topic","pt":"msg"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":340,"wires":[["78f1b6ac7a030a92"]]},{"id":"806d310a85ecb328","type":"change","z":"c2f49fed633045e9","name":"Reset","rules":[{"t":"delete","p":"topic","pt":"msg"},{"t":"set","p":"payload","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":300,"wires":[["861fd2edaa68d45d"]]},{"id":"3533636b2b76dda3","type":"change","z":"c2f49fed633045e9","name":"Set Output_State","rules":[{"t":"set","p":"Output_State","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":850,"y":320,"wires":[["9beb9294ea2753be","677be3ec8bf235f8"]]},{"id":"fa07bbbb7fee2ada","type":"switch","z":"c2f49fed633045e9","name":"Ignore","property":"Output_State","propertyType":"flow","rules":[{"t":"neq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":450,"y":260,"wires":[["861fd2edaa68d45d"]]},{"id":"1f987e24531737c0","type":"switch","z":"c2f49fed633045e9","name":"Ignore","property":"Output_State","propertyType":"flow","rules":[{"t":"neq","v":"0","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":450,"y":380,"wires":[["78f1b6ac7a030a92"]]},{"id":"d26fb724fcd8af63","type":"ui_led","z":"c2f49fed633045e9","order":12,"group":"9b4290ae01764c48","width":1,"height":1,"label":"","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ffff00","value":"1","valueType":"num"},{"color":"#808080","value":"0","valueType":"num"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"ON LED","x":960,"y":220,"wires":[]},{"id":"1b6eb2b9b430e965","type":"change","z":"c2f49fed633045e9","name":"Flash","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload % 2","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":220,"wires":[["d26fb724fcd8af63"]]},{"id":"29bf8e0dec6e02b5","type":"change","z":"c2f49fed633045e9","name":"Flash","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload % 2","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":810,"y":420,"wires":[["b11d0f52bf8618e3"]]},{"id":"b11d0f52bf8618e3","type":"ui_led","z":"c2f49fed633045e9","order":17,"group":"9b4290ae01764c48","width":1,"height":1,"label":"","labelPlacement":"left","labelAlignment":"left","colorForValue":[{"color":"#ffff00","value":"1","valueType":"num"},{"color":"#808080","value":"0","valueType":"num"}],"allowColorForValueInMessage":false,"shape":"circle","showGlow":true,"name":"OFF LED","x":960,"y":420,"wires":[]},{"id":"677be3ec8bf235f8","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"change","p":"payload","pt":"msg","from":"1","fromt":"num","to":"ON","tot":"str"},{"t":"change","p":"payload","pt":"msg","from":"0","fromt":"num","to":"OFF","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1060,"y":320,"wires":[["f191edf019425cf6","89d9de0972a486e0"]]},{"id":"f191edf019425cf6","type":"ui_text","z":"c2f49fed633045e9","group":"9b4290ae01764c48","order":3,"width":4,"height":1,"name":"","label":"Output State","format":"{{msg.payload}}","layout":"row-spread","className":"","x":1250,"y":320,"wires":[]},{"id":"8ebc5bac137769dd","type":"ui_switch","z":"c2f49fed633045e9","name":"","label":"Manual","tooltip":"","group":"9b4290ae01764c48","order":2,"width":3,"height":1,"passthru":true,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"1","onvalueType":"num","onicon":"","oncolor":"","offvalue":"0","offvalueType":"num","officon":"","offcolor":"","animate":false,"className":"","x":260,"y":600,"wires":[["17a118851af24ef4","235f5683a80e3052"]]},{"id":"17a118851af24ef4","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"set","p":"Manual_Input","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":480,"y":580,"wires":[[]]},{"id":"b4f37c652be7f69d","type":"switch","z":"c2f49fed633045e9","name":"","property":"Manual_Input","propertyType":"flow","rules":[{"t":"neq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":550,"y":680,"wires":[["e836bd92de4d963b"]]},{"id":"235f5683a80e3052","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"move","p":"payload","pt":"msg","to":"enabled","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":620,"wires":[["e836bd92de4d963b"]]},{"id":"c9efebadb888bad7","type":"change","z":"c2f49fed633045e9","name":"","rules":[{"t":"delete","p":"enabled","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":910,"y":680,"wires":[["0d05522d73994155"]]},{"id":"45a2e33eeb9b3718","type":"victron-input-system","z":"c2f49fed633045e9","service":"com.victronenergy.system/0","path":"/Dc/Battery/Voltage","serviceObj":{"service":"com.victronenergy.system/0","name":"Venus system"},"pathObj":{"path":"/Dc/Battery/Voltage","type":"float","name":"Battery voltage (V)"},"name":"","onlyChanges":false,"roundValues":"2","x":340,"y":680,"wires":[["b4f37c652be7f69d","3cc144d3cb79c86b"]]},{"id":"b84c6e30cdc87965","type":"ui_template","z":"c2f49fed633045e9","group":"9b4290ae01764c48","name":"CSS Template","order":18,"width":1,"height":1,"format":"<style>\n\n/*ui_card_panel*/\n.nr-dashboard-theme ui-card-panel {\n    background: linear-gradient(#378ce6, #1e5994);\n    border: solid 3px;\n    border-color: #e08d19;\n    border-radius: 1em;\n}\n\n.nr-dashboard-container {\n    background-color: rgba(56,125,197,.9);\n}\n\n.md-toolbar-tools {\n    background-color: #f0efeb;\n}\n\nh1 {\n        color: #272622;\n}\n\nbody.nr-dashboard-theme md-content md-card {\n    background:transparent;\n    color: #ffffff;\n}\n\n.nr-dashboard-theme .nr-dashboard-template {\n    background:transparent;\n}\n\n.nr-dashboard-theme .nr-dashboard-numeric .value {\n    background:transparent;\n    color: #ffffff;\n} \n\n.nr-dashboard-template p {\n    background-color: transparent;\n}\n\n/*ui_switch*/\n.nr-dashboard-theme .nr-dashboard-switch md-switch.md-checked .md-thumb {\n    background-color: #e08d19;\n\n}\n.nr-dashboard-theme .nr-dashboard-switch md-switch.md-checked .md-bar {\n    background-color: #ab6b13;\n}\n\n\n/*ui_slider*/\n.nr-dashboard-theme .nr-dashboard-slider .md-track-fill {\n    background-color: #e08d19;\n}\n\n.nr-dashboard-theme .nr-dashboard-slider .md-thumb:after {\n    background-color: #e08d19;\n    border-color:  #e08d19;\n}\n\n.nr-dashboard-theme .nr-dashboard-slider .md-focus-ring {\n    background-color: #e08d19;\n}\n\n.nr-dashboard-theme .nr-dashboard-slider .md-sign {\n    background-color: #e08d19;\n}\n\n.nr-dashboard-theme .nr-dashboard-slider .md-sign:after {\n    border-top-color: #e08d19 !important;\n}\n\n.layout-column>.flex-100, .layout-row>.flex-100 {\n    max-width: 75%;\n}\n\n.nr-dashboard-theme .nr-dashboard-slider md-slider.md-default-theme.md-min[md-discrete] .md-thumb:after, md-slider.md-min[md-discrete] .md-thumb:after {\n    background-color: #e08d19;\n}\n\n/* info box */\n.nr-dashboard-theme .nr-dashboard-button .md-button, \n.nr-dashboard-theme .nr-dashboard-button .md-button:hover {\n    background-color: transparent;\n}\n\n.nr-dashboard-theme h3 {\n    border-bottom: 1px solid #dcdbd7\n}\n\n</style>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"global","className":"","x":1160,"y":540,"wires":[[]]},{"id":"f07069bed2191d97","type":"link in","z":"c2f49fed633045e9","name":"link in 22","links":["d7ee685a75fa76e7"],"x":45,"y":320,"wires":[["140e9db1ef2317e6"]]},{"id":"d7ee685a75fa76e7","type":"link out","z":"c2f49fed633045e9","name":"link out 10","mode":"link","links":["f07069bed2191d97"],"x":1245,"y":680,"wires":[]},{"id":"9be917a6ff9bcd6d","type":"template","z":"c2f49fed633045e9","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<h3>Threshold control</h3>\n\n<p>\n    This example has been taken from the <a href=\"https://www.youtube.com/watch?v=8ceMtBo3orMhttps://www.youtube.com/watch?v=8ceMtBo3orM&t=552s\" target=\"_blank\">webinar</a> and shows\n    a basic <i>threshold control</i> example.\n</p>\n\n<p>\n    The input is connected to the <i>Battery Voltage</i>, but\n    can be overridden via the <i>Manual input</i> slider, once\n    the <i>Manual</i> switch is selected.\n</p>\n\n<p>\n    The logic is that the <i>Output State</i> will switch on\n    when the input is larger than the <i>ON Threshold</i>.\n    And it will switch off again when the input is lower than\n    the <i>OFF Threshold</i>. Before switching on and off, it\n    will first wait for <i>ON / OFF delay</i>.\n</p>\n\n<p>\n    The layout of this page is controlled via the <i>CSS Template</i>\n    node.\n</p>","output":"str","x":1000,"y":820,"wires":[["85b4dc70388cf060"]]},{"id":"85b4dc70388cf060","type":"ui_toast","z":"c2f49fed633045e9","position":"dialog","displayTime":"3","highlight":"","sendall":true,"outputs":1,"ok":"OK","cancel":"","raw":true,"className":"","topic":"","name":"","x":1170,"y":820,"wires":[[]]},{"id":"d19c016e95c527cb","type":"ui_button","z":"c2f49fed633045e9","name":"info","group":"9b4290ae01764c48","order":20,"width":"1","height":"1","passthru":false,"label":"","tooltip":"","color":"","bgcolor":"","className":"","icon":"info","payload":"","payloadType":"str","topic":"topic","topicType":"msg","x":850,"y":820,"wires":[["9be917a6ff9bcd6d"]]},{"id":"3c07829854baae4b","type":"inject","z":"c2f49fed633045e9","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"10","payloadType":"num","x":690,"y":100,"wires":[["da23599cb07f8886","7a46fd82216aff5b"]]},{"id":"877a7395a71f5e5a","type":"ui_spacer","z":"c2f49fed633045e9","name":"spacer","group":"9b4290ae01764c48","order":9,"width":2,"height":1},{"id":"ac8878a6766e1d37","type":"ui_spacer","z":"c2f49fed633045e9","name":"spacer","group":"9b4290ae01764c48","order":11,"width":1,"height":1},{"id":"69fbc19ed2893657","type":"ui_spacer","z":"c2f49fed633045e9","name":"spacer","group":"9b4290ae01764c48","order":14,"width":2,"height":1},{"id":"ab90a1e839bd4b4a","type":"ui_spacer","z":"c2f49fed633045e9","name":"spacer","group":"9b4290ae01764c48","order":16,"width":"1","height":"1"},{"id":"513afa192b0a34d3","type":"ui_spacer","z":"c2f49fed633045e9","name":"spacer","group":"9b4290ae01764c48","order":19,"width":"11","height":"1"},{"id":"9b4290ae01764c48","type":"ui_group","name":"Dashboard","tab":"6984a52b7f96970d","order":1,"disp":false,"width":"12","collapse":false,"className":""},{"id":"6984a52b7f96970d","type":"ui_tab","name":"Threshold Control","icon":"dashboard","order":5,"disabled":false,"hidden":false}]

Load shedding and MinSOC

When the demand for electricity exceeds the available supply, planned supply interruptions may have to be carried out. This is called load shedding and is common in South Africa (and possibly other places). When a scheduled grid loss is announced, it is usefull to fill your battery before that happens.

The EskomSePush API node can be used to set the MinSOC value of your ESS system to charge the battery, based on the stage of the shedding event. The higher the stage, the longer a load shedding event typically lasts.

For configuration of the node, you first will need to apply for a free (not for businesses) license key on https://eskomsepush.gumroad.com/l/api.

Load shedding and MinSOC (continued)

Load shedding

The switch node is used for determining the desired MinSOC value. Each stage has a different output and the change node is uses for setting the MinSOC in the msg.payload for the ESS control node.

In order to use the flow as is, the following extra module need to be installed:

  • node-red-contrib-eskomsepush
[{"id":"854cb9223eb1d95f","type":"eskomsepush","z":"7095b9db2dd9e047","name":"","licensekey":"","area":"capetown-3-helderbergvillage","statusselect":"capetown","test":false,"x":250,"y":220,"wires":[["685df7425884177e"],[]]},{"id":"685df7425884177e","type":"switch","z":"7095b9db2dd9e047","name":"Stage","property":"stage","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"2","vt":"str"},{"t":"eq","v":"3","vt":"str"},{"t":"eq","v":"4","vt":"str"},{"t":"eq","v":"5","vt":"str"},{"t":"eq","v":"6","vt":"str"},{"t":"eq","v":"7","vt":"str"},{"t":"eq","v":"8","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":9,"x":430,"y":220,"wires":[["d52bbef6b535646e"],["d52bbef6b535646e"],["9a6d3dab537b880f"],["f1c3df4e680f41a6"],["02a4b5afeb44828f"],["a4c5cec636c88ea4"],["a5f3427bd40f7aa1"],["a5f3427bd40f7aa1"],["c80133f055cc326a"]],"inputLabels":["EskomSePush API"],"outputLabels":["stage 1","stage 2","stage 3","stage 4","stage 5","stage 6","stage 7","stage 8","otherwise"]},{"id":"9a6d3dab537b880f","type":"change","z":"7095b9db2dd9e047","name":"60%","rules":[{"t":"set","p":"payload","pt":"msg","to":"60","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":140,"wires":[["c7e0a8b8221196b2"]]},{"id":"02a4b5afeb44828f","type":"change","z":"7095b9db2dd9e047","name":"80%","rules":[{"t":"set","p":"payload","pt":"msg","to":"80","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":220,"wires":[["c7e0a8b8221196b2"]]},{"id":"a5f3427bd40f7aa1","type":"change","z":"7095b9db2dd9e047","name":"100%","rules":[{"t":"set","p":"payload","pt":"msg","to":"100","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":300,"wires":[["c7e0a8b8221196b2"]]},{"id":"d811aee571fa6d6b","type":"victron-output-settings","z":"7095b9db2dd9e047","service":"com.victronenergy.settings","path":"/Settings/CGwacs/BatteryLife/MinimumSocLimit","serviceObj":{"service":"com.victronenergy.settings","name":"Venus settings"},"pathObj":{"path":"/Settings/CGwacs/BatteryLife/MinimumSocLimit","type":"float","name":"ESS Minimum SoC (unless grid fails) (%)","writable":true},"name":"","onlyChanges":false,"x":1030,"y":200,"wires":[]},{"id":"a4c5cec636c88ea4","type":"change","z":"7095b9db2dd9e047","name":"90%","rules":[{"t":"set","p":"payload","pt":"msg","to":"90","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":260,"wires":[["c7e0a8b8221196b2"]]},{"id":"f1c3df4e680f41a6","type":"change","z":"7095b9db2dd9e047","name":"70%","rules":[{"t":"set","p":"payload","pt":"msg","to":"70","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":180,"wires":[["c7e0a8b8221196b2"]]},{"id":"d52bbef6b535646e","type":"change","z":"7095b9db2dd9e047","name":"50%","rules":[{"t":"set","p":"payload","pt":"msg","to":"50","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":100,"wires":[["c7e0a8b8221196b2"]]},{"id":"c80133f055cc326a","type":"change","z":"7095b9db2dd9e047","name":"30%","rules":[{"t":"set","p":"payload","pt":"msg","to":"30","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":340,"wires":[["c7e0a8b8221196b2"]]},{"id":"c7e0a8b8221196b2","type":"junction","z":"7095b9db2dd9e047","x":760,"y":200,"wires":[["d811aee571fa6d6b"]]}]

Only messages at regular intervals

Messages at regular intervals

The Victron input nodes send out a message on each value change. If the 'only changes' checkbox is set, this will be the only output of the node. If the "only changes" checkbox is not set, the node also sends out the current value each 5 seconds.

In some cases you want more control and use the latest value on a regular interval. This can be quite easily acchieved by using the default Node-RED nodes.

Change node context store

First part is to store the value to the context by using a change node. In the edit panel, store the msg.payload to a variable under flow. (or global.). The rest of the naming is up to you, you can use dots to make an object of the context.

Inject node context read

Inject node regular intervals

Then use an inject node to inject that stored value at regular intervals.

[{"id":"c14d18fb2f366c41","type":"tab","label":"Rate limiting","disabled":false,"info":"","env":[]},{"id":"91a991fc4b0752ef","type":"victron-input-temperature","z":"c14d18fb2f366c41","service":"com.victronenergy.temperature/34","path":"/Temperature","serviceObj":{"service":"com.victronenergy.temperature/34","name":"First floor"},"pathObj":{"path":"/Temperature","type":"float","name":"Temperature (C)"},"name":"Temperature - First floor","onlyChanges":true,"roundValues":"2","x":240,"y":160,"wires":[["0947ba020ecad313"]]},{"id":"0947ba020ecad313","type":"change","z":"c14d18fb2f366c41","name":"","rules":[{"t":"set","p":"temperature.firstfloor","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":160,"wires":[[]]},{"id":"8e786c64b42c188f","type":"inject","z":"c14d18fb2f366c41","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"temperature.firstfloor","payloadType":"flow","x":280,"y":220,"wires":[["78c40d303c6084d2"]]},{"id":"78c40d303c6084d2","type":"debug","z":"c14d18fb2f366c41","name":"debug 1","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":540,"y":220,"wires":[]}]

Further reading/references:

Run generator at certain time when SOC is below 50%

The following flow creates a Generator auto start flow that checks daily at 18.00 if the SOC is below 50%. If that is the case, the generator will run for 45 minutes. If the SOC is above 50%, the second output will trigger, resulting in no action.

Flow: generator

To zoom in on some of the aspects. The SOC is stored in a context, using the change node, saving the SOC in flow.SOC.
Change node: Store SOC

The inject node runs every day at 18.00, injecting a timestamp.
Inject node: run at specific time

The switch node compares the stored SOC being less than 50%. If so, it outputs to output 1.
Switch node: check 50%

The trigger node outputs a 1 first, starting the generator. After 45 minutes, it outputs a 0 to stop the generator again.
Trigger node: run for 45 minutes

[{"id":"cf9d688b7ae528a7","type":"inject","z":"2cbcdd20e4e45c73","name":"Start generator daily at 18.00","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"00 18 * * *","once":false,"onceDelay":0.1,"topic":"Start generator","payload":"","payloadType":"date","x":230,"y":220,"wires":[["3788e2040212ca78"]]},{"id":"6f5910b8ec1ace37","type":"victron-input-battery","z":"2cbcdd20e4e45c73","service":"com.victronenergy.battery/277","path":"/Soc","serviceObj":{"service":"com.victronenergy.battery/277","name":"SmartShunt BlCI v3"},"pathObj":{"path":"/Soc","type":"float","name":"State of charge (%)"},"name":"","onlyChanges":false,"roundValues":"1","x":240,"y":160,"wires":[["3039a8bf46712c06"]]},{"id":"3039a8bf46712c06","type":"change","z":"2cbcdd20e4e45c73","name":"Store SOC","rules":[{"t":"set","p":"SOC","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":160,"wires":[[]]},{"id":"3788e2040212ca78","type":"switch","z":"2cbcdd20e4e45c73","name":"Start if SOC is <= 50 %","property":"SOC","propertyType":"flow","rules":[{"t":"lte","v":"50","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":510,"y":220,"wires":[["38217b011e840726"],[]],"outputLabels":["Start generator","Do not start generator"]},{"id":"f47d5fae60134d8f","type":"victron-output-generator","z":"2cbcdd20e4e45c73","service":"com.victronenergy.generator/0","path":"/ManualStart","serviceObj":{"service":"com.victronenergy.generator/0","name":"Generator start/stop"},"pathObj":{"path":"/ManualStart","type":"enum","name":"Manual Start","enum":{"0":"Stop generator","1":"Start generator"},"writable":true},"initial":"","name":"","onlyChanges":false,"x":1020,"y":200,"wires":[]},{"id":"38217b011e840726","type":"trigger","z":"2cbcdd20e4e45c73","name":"Run for 45 minutes","op1":"1","op2":"0","op1type":"num","op2type":"num","duration":"45","extend":false,"overrideDelay":false,"units":"min","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":750,"y":200,"wires":[["f47d5fae60134d8f"]]}]

Based on a question on community.

Venus reboot

Do note that shooting yourself in the foot is generally not the best idea, but there might be some use cases where you want to reboot the Venus device from Node-RED. Using the Custom Control node this can be easily achieved. The example flow shows you how to trigger the reboot using an inject node.

Custom control reboot
[{"id":"d3fa8a27dfe6a9c8","type":"inject","z":"d3a3da3be86b754c","name":"Reboot now","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":330,"y":200,"wires":[["e87b20edffc17690"]]},{"id":"e87b20edffc17690","type":"victron-output-custom","z":"d3a3da3be86b754c","service":"com.victronenergy.platform","path":"/Device/Reboot","serviceObj":{"service":"com.victronenergy.platform","name":"com.victronenergy.platform"},"pathObj":{"path":"/Device/Reboot","name":"/Device/Reboot","type":"number"},"name":"","onlyChanges":false,"x":690,"y":200,"wires":[]}]
⚠️ **GitHub.com Fallback** ⚠️