125 lines
4.9 KiB
JavaScript
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)
|
|
}
|