125 lines
4.9 KiB
JavaScript

const datastore = require('../store/data.js')
const { appendTopic } = require('../utils/index.js')
module.exports = function (RED) {
function SwitchNode (config) {
// create node in Node-RED
RED.nodes.createNode(this, config)
const node = this
node.status({})
const states = ['off', 'on']
// which group are we rendering this widget
const group = RED.nodes.getNode(config.group)
const evts = {
// runs on UI interaction
// value = true | false from the ui-switch
onChange: async function (msg, value) {
// ensure we have latest instance of the widget's node
const wNode = RED.nodes.getNode(node.id)
// retrieve the assigned on/off value
const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, wNode)
const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, wNode)
msg.payload = value ? on : off
if (config.topic || config.topicType) {
msg = await appendTopic(RED, config, node, msg)
}
if (!config.passthru && config.decouple) {
wNode.send(msg)
} else {
node.status({
fill: value ? 'green' : 'red',
shape: 'ring',
text: value ? states[1] : states[0]
})
datastore.save(group.getBase(), node, msg)
// simulate Node-RED node receiving an input
wNode.send(msg)
}
},
onInput: async function (msg, send) {
let error = null
// ensure we have latest instance of the widget's node
const wNode = RED.nodes.getNode(node.id)
// retrieve the assigned on/off value
const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, wNode)
const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, wNode)
if (msg.payload === undefined) {
// may be setting class dynamically or something else that doesn't require a payload
datastore.save(group.getBase(), node, msg)
if (config.passthru) {
send(msg)
}
} else {
if (typeof msg.payload === 'object') {
if (JSON.stringify(msg.payload) === JSON.stringify(on)) {
msg.payload = on
} else if (JSON.stringify(msg.payload) === JSON.stringify(off)) {
msg.payload = off
} else {
// throw Node-RED error
error = 'Invalid payload value'
}
} else {
if (msg.payload === true || msg.payload === on) {
msg.payload = on
} else if (msg.payload === false || msg.payload === off) {
msg.payload = off
} else {
// throw Node-RED error
error = 'Invalid payload value'
}
}
if (!error) {
// store the latest msg passed to node
datastore.save(group.getBase(), node, msg)
node.status({
fill: (msg.payload === true || msg.payload === on) ? 'green' : 'red',
shape: 'ring',
text: (msg.payload === true || msg.payload === on) ? states[1] : states[0]
})
if (config.passthru) {
send(msg)
}
} else {
const err = new Error(error)
err.type = 'warn'
throw err
}
}
},
beforeSend: async function (msg) {
// ensure we have latest instance of the widget's node
const wNode = RED.nodes.getNode(node.id)
msg = await appendTopic(RED, config, wNode, msg)
return msg
}
}
const on = RED.util.evaluateNodeProperty(config.onvalue, config.onvalueType, node)
const off = RED.util.evaluateNodeProperty(config.offvalue, config.offvalueType, node)
config.evaluated = {
on,
off
}
// inform the dashboard UI that we are adding this node
group.register(node, config, evts)
}
RED.nodes.registerType('ui-switch', SwitchNode)
}