UNPKG

node-red-contrib-mobius-flow-dali

Version:

Node-RED nodes to work with MOBiUSFlow and DALI devices

288 lines (270 loc) 13.4 kB
<!-- Copyright (C) 2020, IAConnects Technology Limited All Rights Reserved ALL INFORMATION CONTAINED HEREIN IS, AND REMAINS THE PROPERTY OF IACONNECTS TECHNOLOGY LIMITED AND ITS SUPPLIERS, IF ANY. THE INTELLECTUAL AND TECHNICAL CONCEPTS CONTAINED HEREIN ARE PROPRIETARY TO IACONNECTS TECHNOLOGY LIMITED AND ITS SUPPLIERS AND ARE PROTECTED BY TRADE SECRET OR COPYRIGHT LAW. DISSEMINATION OF THIS INFORMATION OR REPRODUCTION OF THIS MATERIAL IS STRICTLY FORBIDDEN UNLESS PRIOR WRITTEN PERMISSION IS OBTAINED FROM IACONNECTS TECHNOLOGY LIMITED. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --> <script type="text/html" data-template-name="dali collection"> <div class="form-row"> <label for="node-input-selectionMethod" style="width: 160px;"><i class="fa fa-hand-pointer-o"></i> Selection Method</label> <select type="text" id="node-input-selectionMethod" style="display: inline-block; width: 247px; vertical-align: middle;"> <option value='ins'>By Object Instance</option> <option value='addr'>By DALI Address</option> </select> </div> <div class="form-row node-input-groups-container-row"> <label for="node-input-groups-container"><i class="fa fa-bars"></i> Groups</label> <ol id="node-input-groups-container"></ol> </div> <hr> <div id="time-row" class="form-row"> <label style="width: 200px" for="node-input-errtime"><i class="fa fa-clock-o"></i> Error Check Interval</label> <input type="text" id="node-input-errtime" placeholder="Time" style="text-align:left; width:50px !important">&nbsp; <select id="node-input-errtimeUnits" style="width:120px !important"> <option value="seconds"> Seconds</option> <option value="minutes"> Minutes</option> <option value="hours"> Hours</option> </select> </div> <div class="form-row"> <label style="width:auto; margin-right: 10px;" for="node-input-autoGrouping"><i class="fa fa-magic"></i> Auto-Group </label> <input type="checkbox" id="node-input-autoGrouping" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div id="intervals"> <div id="time-row" class="form-row"> <label style="width: 200px" for="node-input-time"><i class="fa fa-clock-o"></i> Grouping Interval</label> <input type="text" id="node-input-time" placeholder="Time" style="text-align:left; width:50px !important">&nbsp; <select id="node-input-timeUnits" style="width:120px !important"> <option value="seconds"> Seconds</option> <option value="minutes"> Minutes</option> <option value="hours"> Hours</option> </select> </div> </div> <hr> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-input-name" style="width: 180px;"> </div> </script> <script type="text/javascript"> RED.nodes.registerType('dali collection', { category: 'dali', color: '#ffd11a', defaults: { name: {value: ''}, autoGrouping: {value: true, required: true}, errtime: {value: '5'}, errtimeUnits: {value: 'minutes'}, time: {value: '5'}, timeUnits: {value: 'minutes'}, groups: {value:[{short: '', groupNum: '0', con: ''}]}, selectionMethod: {value: 'ins', required: true} }, inputs: 1, outputs: 1, outputLabels: ['Command Out'], icon: 'dali-icon.png', align: 'left', paletteLabel: 'dali collection', label: function() { return this.name||`DALI Collection`; }, labelStyle: function() { return this.name ? 'node_label_italic':''; }, oneditprepare: function () { var node = this; $("#node-input-time").spinner({min:1}); $("#node-input-errtime").spinner({min:1}); const formSettings = { regex: '', label: '', style: '' } function updateContainerSettings() { if ($("#node-input-selectionMethod").val() === 'ins') { formSettings.regex = "^(([0][0]([0]([0-9]|[A-F])|[1-3]([0-9]|[A-F])))([-]([0][0]([0]([0-9]|[A-F])|[1-3]([0-9]|[A-F])))|))((|[,](|[ ])((([0][0]([0]([0-9]|[A-F])|[1-3]([0-9]|[A-F])))([-]([0][0]([0]([0-9]|[A-F])|[1-3]([0-9]|[A-F])))|))))+)$"; formSettings.label = '<div>Instances:</div>'; formSettings.style = 'width: 200px; margin-left: 22px; text-align: left;'; } else { formSettings.regex = "^(([0-9]|[1-5][0-9]|[6][0-3])([-]([0-9]|[1-5][0-9]|[6][0-3])|))((|[,](|[ ])((([0-9]|[1-5][0-9]|[6][0-3])([-]([0-9]|[1-5][0-9]|[6][0-3])|))))+)$"; formSettings.label = '<div>Addresses:</div>'; formSettings.style = 'width: 200px; margin-left: 16px; text-align: left;'; } } updateContainerSettings(); /** Create the groups container and populate it */ $('#node-input-groups-container').css('min-height', '300px').css('min-width', '450px').editableList ({ addButton: "add", removable: true, sortable: true, addItem: function (container, i, group) { container.css({ overflow: 'hidden', whiteSpace: 'nowrap' }); // Add a default group if it does not exist if (!group.hasOwnProperty("short")) { group = {short: '', groupNum: '0', con: null}; } let pattern = $("#node-input-selectionMethod").val(); var row = $(formSettings.label).appendTo(container); var shortField = $('<input/>',{ class: "node-input-group-short", type: "text", style: formSettings.style, pattern: formSettings.regex }).appendTo(row); var groupNumField = $('<select/>',{class: "node-input-group-groupNum", style: "width:auto; margin-left: 5px; text-align: center;"}).appendTo(row); groupNumField.append($("<option></option>").val('0').text('Group 0')); groupNumField.append($("<option></option>").val('1').text('Group 1')); groupNumField.append($("<option></option>").val('2').text('Group 2')); groupNumField.append($("<option></option>").val('3').text('Group 3')); groupNumField.append($("<option></option>").val('4').text('Group 4')); groupNumField.append($("<option></option>").val('5').text('Group 5')); groupNumField.append($("<option></option>").val('6').text('Group 6')); groupNumField.append($("<option></option>").val('7').text('Group 7')); groupNumField.append($("<option></option>").val('8').text('Group 8')); groupNumField.append($("<option></option>").val('9').text('Group 9')); groupNumField.append($("<option></option>").val('10').text('Group 10')); groupNumField.append($("<option></option>").val('11').text('Group 11')); groupNumField.append($("<option></option>").val('12').text('Group 12')); groupNumField.append($("<option></option>").val('13').text('Group 13')); groupNumField.append($("<option></option>").val('14').text('Group 14')); groupNumField.append($("<option></option>").val('15').text('Group 15')); groupNumField.append($("<option></option>").val('-1').text('Short')); var row2 = $('<div>Connection:</div>').appendTo(container); var conField = $('<select/>',{class: "node-input-group-con", style: "width:298px; margin-left: 10px; margin-top: 5px; margin-bottom: 5px; text-align: center;"}).appendTo(row2); RED.nodes.eachConfig((n) => { if (n.type === 'dali-connection') { conField.append($("<option></option>").val(n.id).text(n.name)); } }); // Populate the new stat shortField.val(group.short); groupNumField.val(group.groupNum); conField.val(group.con); } }); $("#circuit-busy-message-row").hide(); $("#circuit-failed-message-row").hide(); // If no stat exists, create a default one if (!node.groups) { console.log('Test Point A'); node.groups = [group = {short: '', groupNum: '0', con: ''}]; } // Populate list with all saved filters setTimeout(() => { for (let i = 0; i < node.groups.length; i++) { let group = node.groups[i]; $("#node-input-groups-container").editableList('addItem', group); } }, 50); //repopule list using change address regex function repopulate() { let groups = $("#node-input-groups-container").editableList('items'); entries = []; groups.each(function (i) { var group = $(this); let short = group.find(".node-input-group-short").val(); let con = group.find(".node-input-group-con").val(); let groupNum = group.find(".node-input-group-groupNum").val(); entries.push({short: short, groupNum: groupNum, con: con}); }); $("#node-input-groups-container").editableList('empty'); for (let i = 0; i < entries.length; i++) { let entry = entries[i]; $("#node-input-groups-container").editableList('addItem', entry); } } $("#node-input-selectionMethod").change(function() { updateContainerSettings(); repopulate() }); }, oneditresize(size) { var rows = $("#dialog-form>div:not(.node-input-groups-container-row)"); var height = size.height; for (var i=0; i<rows.size(); i++) { height -= $(rows[i]).outerHeight(true); } var editorRow = $("#dialog-form>div.node-input-groups-container-row"); height -= 4 * ((parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")))); $("#node-input-groups-container").editableList('height',height); }, oneditsave: function() { let groups = $("#node-input-groups-container").editableList('items'); let node = this; node.groups= []; groups.each(function (i) { var group = $(this); let short = group.find(".node-input-group-short").val(); let con = group.find(".node-input-group-con").val(); let groupNum = group.find(".node-input-group-groupNum").val(); node.groups.push({short: short, groupNum: groupNum, con: con}); }); } }); </script> <script type="text/html" data-help-name="dali collection"> <p>MOBiUS DALI Collection.</p> <h3>Configuration Page</h3> <dl class="message-properties"> <dt>Configure Connections <span class="property-type">connection</span></dt> <dd>Allows for configuration of DALI cricuits.</dd> <dt>Selection Method <span class="property-type">choice</span></dt> <dd>The method to select DALI fittings.</dd> <dt>Addresses / Instances <span class="property-type">number</span></dt> <dd>The list of DALI short addresses (0-63) or Mobius object instances (0001-003F).</dd> <dt>Group <span class="property-type">number</span></dt> <dd>The DALI group number.</dd> <dt>Connection <span class="property-type">number</span></dt> <dd>The connection to the DALI Circuit.</dd> </dl> <h3>Input: </h3> <dl class="message-properties"> <dt>payload.level <span class="property-type">number</span></dt> <dd>The desired lighting level (0-100%).</dd> </dl> <h3>Output</h3> <dl class="message-properties"> <dt>payload <span class="property-type">object</span></dt> <dd>A breakdown of the number of failures related to LED lamps.</dd> </dl> <h4>Overview</h4> <p>Sends lighting level commands to all addresses within collection. Automatically checks the error status of all luminaires within collection and reports this at the specified interval. </p> <h4>Grouping</h4> <p>DALI groups can be configured within the node configuration. The node will automatically send DALI grouping commands to ensure the DALI devices are within the correct groups. The node will also performing a full ungrouping process at the specified interval. Following any ungrouping process the node will perform a regrouping process. </p> <h4>Address Range</h4> <p>Short address range to be input in any valid format involving commas and dashes e.g. ( 0-63 ) or ( 0,1 ) or ( 0, 1, 10-20 ). Examples involving any address < 0 or > 63 are invalid. examples starting or ending in a comma or dash are invalid e.g. ( ,1 ) or ( 1, 2, ) or ( 1, 2, 3-5, 8- ). Any example containing letters, symbols or further punctuation are invalid. The same principle applies to instance selection e.g. (0001-0005, 0008) etc.</p> <p align="center" style="color:#000080">iaconnects © 2020</p> <br> <p align="center" style="color:#000080">ER 2020</p> </script>