UNPKG

node-red-contrib-knx-ultimate

Version:

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

300 lines (240 loc) 13.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) { } } }).focus(function () { $(this).autocomplete('search', $(this).val() + 'exactmatch'); }); 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>&nbsp&nbsp<span style="color:red" data-i18n="[html]knxUltimateAlerter.helplink"></span> <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"> </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">Start alert cycle manually via incoming message></option> <option value="ifnewalert">Start the alert cycle with each new alerted device</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> <script type="text/markdown" data-help-name="knxUltimateAlerter"> With the Alerter node you can signal to a display or to the node-red-contrib-tts-ultimate node (audio feedback) if the selected devices are alerted, i.e. they have payload **true**. The node issues messages at specified intervals (one message at a time) containing the details of each alerted device. For example, the node can tell you how many and which windows are open. <br/> The node receives the values of the devices directly from the KNX BUS. Furthermore, you can send personalized messages to the node, not linked to KNX devices. <br/> The example page explains how to use the node. <br/> - **Gateway** > KNX gateway selected. It is also possible not to select any gateway; in this case, only incoming messages to the node will be considered. - **Name** > Node name. - **Alerting cycle start type** > Here you can select the event that will skip the start of sending messages from alerted devices. - **Interval between each MSG (in seconds)** > Interval between each outgoing message from the node. ## DEVICES TO MONITOR Here you can add devices to monitor. <br/> Enter the device name or its group address. <br/> - **Read value of each device on connection/reconnect** > On connection/reconnection, the node will send a 'read' request each device belonging to the list. - **ADD button** > Add a row to the list. - **Device's rows** > The first field is the group address (but you can also enter any text, which you can use with inbound messages, see the example page), the second is the device name **(MAX 14 CHARS)**, the third is the long device name. - **DELETE button** > Removes a device from the list. <p> <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/Alerter-Configuration" target="_blank"><i class="fa fa-info-circle"></i>&nbsp Config help</a><br/> <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/SampleAlerter" target="_blank"><i class="fa fa-code"></i>&nbsp Samples</a>. </p> <p> <a href="https://www.paypal.com/donate/?hosted_button_id=S8SKPUBSPK758" target="_blank"> <img src='https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/CodiceQR.png' width='30%'> </a> </p> </script>