Skip to content

Commit

Permalink
Disable system relay if it is not on manual mode
Browse files Browse the repository at this point in the history
Disable the usage of system relay 0 if it is set on any other mode than
manual. An approppriate warning and info on how to change the relay function
is shown below the relay select in this case. Trying to trigger a
previously deployed relay with any other mode than manual will show a
warning message on Node-RED's debug panel. Restructure the relay service
logic to get rid of regular expressions. Use more functional style.
  • Loading branch information
pkronstrom committed Jan 21, 2019
1 parent 8b438e9 commit 8c40710
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/nodes/input-battery.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
.hidden {
display: none
}
#statusmessage {
.form-tips {
margin-bottom: 12px;
}
</style>
30 changes: 27 additions & 3 deletions src/nodes/output-relay.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
<select id="node-input-service"></select>
</div>

<div class="form-row">
<div class="form-warning hidden" id="warningmessage"></div>

<div class="form-row" id="relay-state">
<label> State </label>
<input type="radio" name="value" value="on">On</input>
<input type="radio" name="value" value="off">Off</input>
Expand Down Expand Up @@ -41,7 +43,9 @@
let altName = 'Relay';
if (this.service) {
let svc = JSON.parse(this.service);
altName = `Relay - ${svc.name} - ${this.state}`
altName = svc.disabled
? `Relay - ${svc.name} - disabled`
: `Relay - ${svc.name} - ${this.state}`
}
return this.name || altName;
},
Expand Down Expand Up @@ -87,6 +91,21 @@
$("input[name='value']").change(function() {
$("#node-input-state").val(this.value);
});

selectElem.change((e) => {
let selected = $(e.target).val() || _this.service;
// Ensure, that the selected relay isn't disabled
if (selected) {
let serviceObj = JSON.parse(selected);
if (serviceObj.disabled) {
$('#warningmessage').text(serviceObj.warning).show()
$("input[name='value']").attr('disabled', true);
} else {
$('#warningmessage').hide();
$("input[name='value']").attr('disabled', false);
}
}
});
}
});

Expand All @@ -98,10 +117,15 @@
clear: none;
margin: -4px 4px 0px 12px;
}
.form-warning {
color: red;
font-size: 0.9em;
max-width: 30em;
}
.hidden {
display: hidden;
}
#statusmessage {
.form-tips, .form-warning {
margin-bottom: 12px;
}
</style>
9 changes: 7 additions & 2 deletions src/nodes/output-relay.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
module.exports = function(RED) {
"use strict";

const mapping = require('../services/servicemapping');

function OutputRelay(config) {
RED.nodes.createNode(this, config)

Expand All @@ -19,7 +21,6 @@ module.exports = function(RED) {
case 'off':
return 0
case 'toggle':
// Ideally the initial state would be fetched from the relay itself
toggleState = 1 - toggleState
return toggleState
}
Expand All @@ -28,7 +29,11 @@ module.exports = function(RED) {
this.on("input", function(msg) {
let path = this.service.paths[0].path
let service = this.service.service
this.client.publish(service, path, stateToMessage(this.state))

if (!this.service.disabled)
this.client.publish(service, path, stateToMessage(this.state))
else
this.warn(mapping.RELAY_MODE_WARNING('another'))
});

}
Expand Down
14 changes: 13 additions & 1 deletion src/services/servicemapping.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,20 @@ const RELAY = (service, path, name) => {
}
}

const RELAY_FUNCTIONS = {
0: 'alarm',
1: 'generator',
2: 'manual',
3: 'tank pump'
}

const RELAY_MODE_WARNING = (func) =>
`This relay is reserved for ${func} function. Please navigate to Settings > Relay and change it to manual.`

module.exports = {
BATTERY,
BATTERY_PATHS,
RELAY
RELAY,
RELAY_FUNCTIONS,
RELAY_MODE_WARNING
}
75 changes: 45 additions & 30 deletions src/services/systemconfiguration.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const mapping = require('./servicemapping');
const _ = require('lodash')
const debug = require('debug')('node-red-contrib-victron:systemconfiguration')
const debug = require('debug')('node-red-contrib-victron:systemconfiguartion')

/**
* SystemConfiguration contains information on the given Venus system.
Expand All @@ -17,8 +17,8 @@ class SystemConfiguration {
}

/**
* Builds the edit form layout for the battery node.
* Filters the dbus cache for available battery services.
* Build the edit form layout for the battery node.
* Filter the dbus cache for available battery services.
*/
getBatteryServices() {
// filter the dbus cache for battery services
Expand All @@ -40,40 +40,54 @@ class SystemConfiguration {

}
/**
* Builds the edit form for the relay node.
* Filters the cache for system and battery relays.
* Build the edit form for the relay node.
* Filter the cache for system and battery relays.
*/
getRelayServices() {
// Iterate over previously found devices and look for /Relay/X paths
let services = [];
Object.keys(this.cache).forEach(svc => {
Object.keys(this.cache[svc]).forEach(path => {
if (_.startsWith(path, '/Relay')) {

// Node label is based on the given service
let name = ''
if (_.startsWith(svc, 'com.victronenergy.battery')) {
let batteryRe = /\bbattery\.(.*)/
let batterySvc = batteryRe.exec(svc)

name = this.cache[svc]['/CustomName'] || this.cache[svc]['/ProductName'] || batterySvc[1]
}
else if (_.startsWith(svc, 'com.victronenergy.system')) {
let relayPathRe = /\/Relay\/(\d)+\/State/
let systemRelayIdx = relayPathRe.exec(path)
name = systemRelayIdx !== null ? `Venus device (${systemRelayIdx[1]})` : ''
}

services.push(mapping.RELAY(svc, path, name))
// Build a relay object representing the relay node settings in node-red UI
const buildRelayObject = (service, path) => {
if (service.startsWith('com.victronenergy.system')) {
const relayIndex = path.split('/')[2] || ''
const name = `Venus device (${relayIndex})`

let relayObject = mapping.RELAY(service, path, name)

// Special case for system relay 0 - only allow usage if relay function is set to manual
if (relayIndex === '0') {
const systemRelayFunction = this.cache['com.victronenergy.settings']['/Settings/Relay/Function']
if (systemRelayFunction !== 2) { // manual
relayObject["disabled"] = true
relayObject["warning"] = mapping.RELAY_MODE_WARNING(mapping.RELAY_FUNCTIONS[systemRelayFunction])
}
}
})
})

return services;
return relayObject
}
if (service.startsWith('com.victronenergy.battery')) {
const name = this.cache[service]['/CustomName']
|| this.cache[service]['/ProductName']
|| service.split('.').pop()

return mapping.RELAY(service, path, name)
}
}

// Filter all paths that begin with '/Relay'.
// Construct and return an array of relay nodes representing their settings.
return Object.entries(this.cache)
.reduce((acc, [service, pathObj]) => {
Object.keys(pathObj)
.filter(path => path.startsWith('/Relay'))
.map(relayPath => acc.push(
buildRelayObject(service, relayPath))
)
return acc
}, []);
}

/**
* Lists all currently available services. This list is used to populate the nodes' edit dialog.
* List all currently available services. This list is used to populate the nodes' edit dialog.
* E.g. if a battery monitor is available, all the given battery monitor services are listed
* in the input-battery node.
*
Expand All @@ -82,7 +96,8 @@ class SystemConfiguration {
listAvailableServices(device=null) {
let services = {
"battery": this.getBatteryServices(),
"relay": this.getRelayServices()
"relay": this.getRelayServices(),
"cache": this.cache
};

return device !== null
Expand Down
1 change: 0 additions & 1 deletion src/services/victronclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ class VictronClient {
{
onError: msg => debug(`[ERROR] ${msg}`),
onServiceChange: (changeType, serviceName) => {
debug(`[SERVICE ${changeType}] ${serviceName}`)
if (changeType === 'DELETE' && serviceName !== null) {
delete this.system.cache[serviceName]
}
Expand Down

0 comments on commit 8c40710

Please sign in to comment.