UNPKG

node-red-contrib-knx-ultimate

Version:

Control your KNX and KNX Secure intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control, ETS group address importer, and KNX routing between interfaces. Easy to use and highly configurable.

248 lines (210 loc) 11.9 kB
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script> <script type="text/javascript"> RED.nodes.registerType('knxUltimateAlerter', { category: "KNX Ultimate", color: '#C7E9C0', defaults: { //buttonState: {value: true}, server: { type: "knxUltimate-config", required: false }, name: { value: "" }, property: { value: "payload", required: true, validate: RED.validators.typedInput("propertyType") }, propertyType: { value: "msg" }, rules: { value: [{ t: "eq", v: "", vt: "str" }] }, whentostart: { value: "ifnewalert" }, timerinterval: { value: "2" }, initialreadGAInRules: { value: "1" }, }, inputs: 1, outputs: 3, outputLabels: function (index) { if (index === 0) return "Emits a message for each alerted device, at selectable intervals."; if (index === 1) return "Emits a unique message containing all alerted devices."; if (index === 2) return "Emits a message containing only the last alerted device."; }, icon: "node-alerter-icon.svg", label: function () { return (this.outputRBE == true ? "|rbe| " : "") + (this.name || this.topic || "KNX Alerter") + (this.inputRBE == true ? " |rbe|" : "") }, paletteLabel: "KNX Alerter", // button: { // enabled: function() { // // return whether or not the button is enabled, based on the current // // configuration of the node // return !this.changed // }, // visible: function() { // // return whether or not the button is visible, based on the current // // configuration of the node // return this.hasButton // }, // //toggle: "buttonState", // onclick: function() {} // }, oneditprepare: function () { // Go to the help panel try { RED.sidebar.show("help"); } catch (error) { } var node = this; var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node // 19/02/2020 Used to get the server sooner als deploy. $("#node-input-server").change(function () { try { oNodeServer = RED.nodes.node($(this).val()); } catch (error) { } }); // Scene configuration var previousValueType = { value: "prev", label: this._("switch.previous"), hasValue: false }; function resizeRule(rule) { } $("#node-input-rule-container").css('min-height', '350px').css('min-width', '450px').editableList({ addItem: function (container, i, opt) { // row, index, data // opt.r is: { topic: rowRuleTopic, devicename: rowRuleDeviceName, longdevicename: rowRuleLongDeviceName} var rule = opt.r; if (!opt.hasOwnProperty('i')) { opt._i = Math.floor((0x99999 - 0x10000) * Math.random()).toString(); } container.css({ overflow: 'hidden', whiteSpace: 'nowrap' }); var row = $('<div class="form-row"/>').appendTo(container); var oTopicField = $("<input/>", { class: "rowRuleTopic", type: "text", placeholder: "GA or devicename", style: "width:20%; margin-left: 5px; text-align: left;" }).appendTo(row); var finalspan = $('<span/>', { style: "" }).appendTo(row); finalspan.append(' <span class="node-input-rule-index"></span> '); var orowRuleDeviceName = $('<input/>', { maxlength: "14", class: "rowRuleDeviceName", type: "text", style: "width:30%; margin-left: 0px; text-align: left;font-style: italic;", placeholder: "Name (max 14 chars)" }).appendTo(row); var orowRuleLongDeviceName = $('<input/>', { class: "rowRuleLongDeviceName", type: "text", style: "width:45%; margin-left: 0px; text-align: left;", placeholder: "Long name" }).appendTo(row); oTopicField.on("change", function () { resizeRule(container); }); // Autocomplete suggestion with ETS csv File oTopicField.autocomplete({ minLength: 0, source: function (request, response) { $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => { response($.map(data, function (value, key) { var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt); if (htmlUtilsfullCSVSearch(sSearch, request.term + " 1.")) { return { label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display value: value.ga // Value } } else { return null; } })); }); }, select: function (event, ui) { // Sets Datapoint and device name automatically var sDevName = ui.item.label.split("#")[1].trim(); try { sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim(); orowRuleDeviceName.val(sDevName.substr(0, 14)); orowRuleLongDeviceName.val(sDevName); } catch (error) { } } }); oTopicField.on('focus.knxUltimateAlerter click.knxUltimateAlerter', function () { try { $(this).autocomplete('search', ''); } catch (error) { /* empty */ } }); try { if (oNodeServer && oNodeServer.id) KNX_enableSecureFormatting(oTopicField, oNodeServer.id); } catch (e) {} oTopicField.val(rule.topic); orowRuleDeviceName.val(rule.devicename); orowRuleLongDeviceName.val(rule.longdevicename); oTopicField.change(); }, removeItem: function (opt) { }, resizeItem: resizeRule, sortItems: function (rules) { }, sortable: true, removable: true }); // Put some spaces after the container $('<br/><br/><br/><br/><br/><br/><br/><br/>').insertAfter($("#node-input-rule-container")); // 10/03/2020 For each rule, create a row for (var i = 0; i < this.rules.length; i++) { var rule = this.rules[i]; $("#node-input-rule-container").editableList('addItem', { r: rule, i: i }); } }, oneditsave: function () { // Return to the info tab try { RED.sidebar.show("info"); } catch (error) { } var node = this; var rules = $("#node-input-rule-container").editableList('items'); node.rules = []; rules.each(function (i) { var rule = $(this); var rowRuleTopic = rule.find(".rowRuleTopic").val(); var rowRuleDeviceName = rule.find(".rowRuleDeviceName").val(); var rowRuleLongDeviceName = rule.find(".rowRuleLongDeviceName").val(); node.rules.push({ topic: rowRuleTopic, devicename: rowRuleDeviceName, longdevicename: rowRuleLongDeviceName }); }); this.propertyType = $("#node-input-property").typedInput('type'); }, oneditresize: function (size) { var node = this; var rows = $("#dialog-form>div:not(.node-input-rule-container-row)"); var height = size.height; for (var i = 0; i < rows.length; i++) { height -= $(rows[i]).outerHeight(true); } var editorRow = $("#dialog-form>div.node-input-rule-container-row"); height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom"))); height += 16; $("#node-input-rule-container").editableList('height', height); } }) </script> <script type="text/html" data-template-name="knxUltimateAlerter"> <div class="form-row"> <b><span data-i18n="knxUltimateAlerter.title"></span></b> <br/><br/> <label for="node-input-server"> <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAKnRFWHRDcmVhdGlvbiBUaW1lAEZyIDYgQXVnIDIwMTAgMjE6NTI6MTkgKzAxMDD84aS8AAAAB3RJTUUH3gYYCicNV+4WIQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAARnQU1BAACxjwv8YQUAAACUSURBVHjaY2CgFZg5c+Z/ZEyWAZ8+f/6/ZsWs/xoamqMGkGrA6Wla/1+fVARjEBuGsSoGmY4eZSCNL59d/g8DIDbIAHR14OgFGQByKjIGKX5+6/T///8gGMQGiV1+/B0Fg70GIkD+RMYgxf/O5/7//2MSmAZhkBi6OrgB6Bg5DGB4ajr3f2xqsYYLSDE2THJUDg0AAAqyDVd4tp4YAAAAAElFTkSuQmCC"></img> <span data-i18n="knxUltimateAlerter.properties.node-input-server"></span> </label> <input type="text" id="node-input-server"> </div> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="knxUltimateAlerter.properties.node-input-name"></span> </label> <input type="text" id="node-input-name" data-i18n="[placeholder]knxUltimateAlerter.properties.node-input-name" style="flex:1 1 240px; min-width:240px; max-width:240px;"> </div> <div class="form-row"> <label for="node-input-whentostart"><i class="fa fa-repeat"></i> <span data-i18n="knxUltimateAlerter.properties.node-input-whentostart"></span> </label> <select id="node-input-whentostart"> <option value="manualstart" data-i18n="knxUltimateAlerter.selectlists.manualstart"></option> <option value="ifnewalert" data-i18n="knxUltimateAlerter.selectlists.ifnewalert"></option> </select> </div> <div class="form-row"> <label for="node-input-timerinterval" style="width:70%"><i class="fa fa-clock-o"></i> <span data-i18n="knxUltimateAlerter.properties.node-input-timerinterval"></span> </label> <input type="text" id="node-input-timerinterval" style="width:10%"> </div> <br/> <br/> <dt><i class="fa fa-code-fork"></i>&nbsp; <span data-i18n="knxUltimateAlerter.other.sceneConfig"></dt> <br/> <div class="form-row" id="divNode-input-initialreadGAInRules"> &nbsp;&nbsp;<label style="width:60%" for="node-input-initialreadGAInRules"> <i class="fa fa-question-circle-o"></i> <span data-i18n="knxUltimateAlerter.properties.node-input-initialreadGAInRules"></span> </label> <select style="width:30%" id="node-input-initialreadGAInRules"> <option value="0" data-i18n="knxUltimateAlerter.properties.node-input-initialread0"></option> <option value="1" data-i18n="knxUltimateAlerter.properties.node-input-initialread1"></option> </select> </div> <div class="form-row node-input-rule-container-row"> <ol id="node-input-rule-container"></ol> </div> <div class="form-row"> <p><span data-i18n="knxUltimateAlerter.other.add"></p> </div> </script>