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) }