UNPKG

node-red-dashboard-2-t86

Version:

Set of Node-RED nodes to controll home automation based on Unipi Patron and DALI.

263 lines (262 loc) 9.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = main; const editor_prase_helper_1 = require("../editor-prase-helper"); var InputEvent; (function (InputEvent) { InputEvent["Push"] = "in.push"; InputEvent["Release"] = "in.release"; InputEvent["Invalid"] = "in.invalid"; })(InputEvent || (InputEvent = {})); var OutputEvent; (function (OutputEvent) { OutputEvent["ShortPress"] = "out.short"; OutputEvent["DoubleShortPress"] = "out.dblshort"; OutputEvent["LongPressStart"] = "out.long.start"; OutputEvent["ShortLongPressStart"] = "out.shortlong.start"; OutputEvent["LongPressEnd"] = "out.long.end"; OutputEvent["ShortLongPressEnd"] = "out.shortlong.end"; })(OutputEvent || (OutputEvent = {})); var State; (function (State) { State["Ready"] = "stat.ready"; State["PushedOnce"] = "stat.pushedOnce"; State["LongInProgress"] = "stat.longInProgress"; State["WaitingAnotherPush"] = "stat.waitingAnotherPush"; State["PushedTwice"] = "stat.pushedTwice"; State["ShortLongInProgress"] = "stat.shortLongInProgress"; })(State || (State = {})); function parseEditorConfig(config) { return { shortPressLimitMs: parseInt(config.shortpresslimitms), nextPressWaitMs: parseInt(config.nextpresswaitms), inputKeyPath: config.inputkeypath, pushValue: (0, editor_prase_helper_1.typedStrToValue)(config.pushvalue, config.pushvalueType), releaseValue: (0, editor_prase_helper_1.typedStrToValue)(config.releasevalue, config.releasevalueType), enabled: { short: config.shortenabled, dblShort: config.dblshortenabled, long: config.longenabled, shortLong: config.shortlongenabled }, warn: config.warn, debug: config.debug }; } class MultiButton { constructor(RED, node, config) { this.state = State.Ready; this.RED = RED; this.node = node; RED.nodes.createNode(node, config); this.pConf = parseEditorConfig(config); this.node.on('input', this.onInput.bind(this)); this.node.on('close', this.onClose.bind(this)); } onInput(msg, send, done) { this.latestSendFn = { send, done, msg }; const evt = this.eventWithMsg(msg); switch (evt) { case InputEvent.Push: this.onPush(); break; case InputEvent.Release: this.onRelease(); break; case InputEvent.Invalid: this.pConf.warn && this.node.warn(`Invalid event in message, ${msg}`); } if (done) done(); } onPush() { this.debug(`onPush`); switch (this.state) { case State.Ready: this.goPushedOnce(); return; case State.WaitingAnotherPush: this.goPushedTwice(); return; } this.invalidTransition('onPush'); } onRelease() { this.debug(`onRelease`); switch (this.state) { case State.PushedOnce: this.goWaitAnotherPush(); return; case State.PushedTwice: this.finalizeDoubleShort(); return; case State.LongInProgress: this.finalizeLong(); return; case State.ShortLongInProgress: this.finalizeShortLong(); return; } this.invalidTransition('onRelease'); } onShortPushTo() { this.debug(`onShortPushTo`); switch (this.state) { case State.PushedOnce: this.goLongStart(); return; case State.PushedTwice: this.goShortLongStart(); return; } this.invalidTransition('onShortPushTo'); } onWaitAnotherPushTo() { this.debug(`onWaitAnotherPushTo`); switch (this.state) { case State.WaitingAnotherPush: this.finalizeShort(); return; } this.invalidTransition('onWaitAnotherPushTo'); } onClose() { if (this.shortPushTo) clearTimeout(this.shortPushTo); if (this.waitAnotherPushTo) clearTimeout(this.waitAnotherPushTo); this.shortPushTo = undefined; this.waitAnotherPushTo = undefined; } goPushedOnce() { this.debug(`goPushedOnce -> State.PushedOnce\n setting short push TO`); this.storedSend(); this.resetTimeouts(); this.shortPushTo = setTimeout(this.onShortPushTo.bind(this), this.pConf.shortPressLimitMs); this.state = State.PushedOnce; } goPushedTwice() { this.debug(`goPushedTwice -> State.PushedTwice\n setting short push TO`); this.resetTimeouts(); this.shortPushTo = setTimeout(this.onShortPushTo.bind(this), this.pConf.shortPressLimitMs); this.state = State.PushedTwice; } goWaitAnotherPush() { this.state = State.WaitingAnotherPush; this.resetTimeouts(); // If there is no dbl press event enabled it's pointless to wait if (!this.pConf.enabled.dblShort && !this.pConf.enabled.shortLong) { this.debug(`goWaitAnotherPush -> State.WaitingAnotherPush\n not waiting`); this.onWaitAnotherPushTo(); return; } // There is dbl press event enabled. Let's wait if second push is comming this.debug(`goWaitAnotherPush -> State.WaitingAnotherPush\n setting wait TO`); this.waitAnotherPushTo = setTimeout(this.onWaitAnotherPushTo.bind(this), this.pConf.nextPressWaitMs); } goLongStart() { this.debug(`goLongStart -> State.LongInProgress`); this.resetTimeouts(); this.longPushStart = new Date(); this.sendOutEvent(OutputEvent.LongPressStart); this.storedSend(); this.state = State.LongInProgress; } goShortLongStart() { this.debug(`goShortLongStart -> State.ShortLongInProgress`); this.resetTimeouts(); this.longPushStart = new Date(); this.sendOutEvent(OutputEvent.ShortLongPressStart); this.storedSend(); this.state = State.ShortLongInProgress; } finalizeShort() { this.debug(`finalizeShort -> State.Ready`); this.sendOutEvent(OutputEvent.ShortPress); this.resetTimeouts(); this.state = State.Ready; } finalizeDoubleShort() { this.debug(`finalizeDoubleShort -> State.Ready`); this.sendOutEvent(OutputEvent.DoubleShortPress); this.resetTimeouts(); this.state = State.Ready; } finalizeLong() { this.debug(`finalizeLong -> State.Ready`); this.sendOutEvent(OutputEvent.LongPressEnd, { start: this.longPushStart?.getTime(), duration: (new Date()).getTime() - (this.longPushStart?.getTime() || 0) }); this.resetTimeouts(); this.state = State.Ready; } finalizeShortLong() { this.debug(`finalizeShortLong -> State.Ready`); this.sendOutEvent(OutputEvent.ShortLongPressEnd, { start: this.longPushStart?.getTime(), duration: (new Date()).getTime() - (this.longPushStart?.getTime() || 0) }); this.resetTimeouts(); this.state = State.Ready; } invalidTransition(event) { this.pConf.warn && this.node.warn(`Invalid transition ${this.state} -> ${event} -> X`); } sendOutEvent(outEvent, val) { if (!this.pConf.enabled.short && outEvent === OutputEvent.ShortPress) return; if (!this.pConf.enabled.dblShort && outEvent === OutputEvent.DoubleShortPress) return; if (!this.pConf.enabled.long && (outEvent === OutputEvent.LongPressStart || outEvent === OutputEvent.LongPressEnd)) return; if (!this.pConf.enabled.shortLong && (outEvent === OutputEvent.ShortLongPressStart || outEvent === OutputEvent.ShortLongPressEnd)) return; this.debug(`Sending event ${outEvent} value: ${val}`); if (this.storedSendFn) { this.storedSendFn.msg.payload = { event: outEvent }; if (val !== undefined) { this.storedSendFn.msg.payload.value = val; } this.storedSendFn.send(this.storedSendFn.msg); if (this.storedSendFn.done) this.storedSendFn.done(); this.storedSendFn = undefined; } } resetTimeouts() { this.debug(`resetTimeouts SPTO ${this.shortPushTo}; WAPTO ${this.waitAnotherPushTo}`); clearTimeout(this.shortPushTo); clearTimeout(this.waitAnotherPushTo); this.shortPushTo = undefined; this.waitAnotherPushTo = undefined; this.longPushStart = undefined; } storedSend() { this.storedSendFn = this.latestSendFn; } eventWithMsg(msg) { const kp = this.pConf.inputKeyPath.split('.'); let sub = msg; for (const part of kp) { if (!sub) return InputEvent.Invalid; sub = sub[part]; } if (sub === this.pConf.pushValue) return InputEvent.Push; if (sub === this.pConf.releaseValue) return InputEvent.Release; return InputEvent.Invalid; } debug(msg) { this.pConf.debug && this.node.debug(msg); } } // Register constructor function with Node-RED function main(RED) { RED.nodes.registerType('multibutton', function (config) { new MultiButton(RED, this, config); }); }