UNPKG

node-red-contrib-dirigera

Version:

A Node-Red Node for controlling Ikea Dirigera hub.

211 lines (204 loc) 8.92 kB
<script type="text/javascript"> RED.nodes.registerType('dirigera-config', { category: 'config', defaults: { name: { value: "" }, }, credentials: { hubAddress: { type: "text" }, hubAccessCode: { type: "text" }, }, label: function () { return this.name || "dirigeraHub" }, oneditprepare: function () { const node = this $('#node-input-lookup-hubAccessCode-tip').hide() $('#node-input-lookup-hubAccessCode-button').click(function () { $('#node-input-lookup-hubAccessCode-tip').text('Press button on hub now within 60 sec !!!') $('#node-input-tip-image').attr("src", "https://raw.githubusercontent.com/zinen/node-red-contrib-dirigera/main/image/push-button.jpg") $('#node-input-lookup-hubAccessCode-tip').show() $('#node-config-input-hubAccessCode').val('') $.get('ikeaDirigera/auth', { hubAddress: $('#node-config-input-hubAddress').val(), clientName: $('#node-config-input-name').val() }, function (resp) { let response = JSON.parse(resp) if (response.error || !response.access_token) { $('#node-input-lookup-hubAccessCode-tip').text('Error: ' + response.error) $('#node-input-tip-image').attr("src", "") return } $('#node-input-lookup-hubAccessCode-tip').text('Access code received OK. Ready to save this config') $('#node-input-tip-image').attr("src", "") $('#node-config-input-hubAccessCode').val(response.access_token) }) }) } }) </script> <script type="text/html" data-template-name="dirigera-config"> <div class="form-row"> <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-config-input-name" placeholder="Optional name. See help text."> </div> <div class="form-row"> <label for="node-config-input-hubAddress"><i class="fa fa-globe"></i> Hub address ip/hostname</label> <div style="width: 70%; display: inline-flex;"> <input type="text" id="node-config-input-hubAddress" placeholder="192.168.1.4" style="flex-grow: 1;"> <!-- <a id="node-input-lookup-hubAddress-button" class="editor-button" style="margin-left: 10px;"><i class="fa fa-refresh"></i></a> --> </div> </div> <div class="form-row"> <label for="node-config-input-hubAccessCode"><i class="fa fa-key"></i> Access code</label> <div style="width: 70%; display: inline-flex;"> <input type="text" id="node-config-input-hubAccessCode" placeholder="Auto filled. Press ==>" style="flex-grow: 1;" autocomplete="off"> <a id="node-input-lookup-hubAccessCode-button" class="editor-button" style="margin-left: 10px;">Get access code</a> </div> </div> <div class="form-row"> <div class="form-tips" id="node-input-lookup-hubAccessCode-tip">.</div> <img id="node-input-tip-image" src="" alt=""> </div> </div> </script> <script type="text/html" data-help-name="dirigera-config"> <p>If name is filled when requesting access token this name can be found in the Dirigera app. Else it defaults to <code>node-red-dirigera</code></p> <p>You can later redefine this name but that wont update the name inside the Dirigera app.</p> </script> <script type="text/javascript"> const updateTypes = (node) => { let configNodeId = $('#node-input-server').find(":selected").val() if (configNodeId == null || configNodeId === '_ADD_') return $.get('ikeaDirigera/dirigera', { nodeId: configNodeId }, function (resp) { if (!resp) return let response = JSON.parse(resp) if (response.error) { console.error('Node-red Dirigera node error: ' + response.error) return } $('#node-input-choiceType').find('option').remove() let deviceTypes = Object.keys(response) if (!Array.isArray(deviceTypes) || deviceTypes.length <= 0) return $.each(deviceTypes, function (i, deviceTypes) { let opt = {} // opt.value = deviceTypes opt.text = deviceTypes if (node.choiceType === opt.text) { opt.selected = "selected" } $('#node-input-choiceType').append($('<option>', opt)) }) $('#node-input-choiceType').change(function () { updateChoiceList(response, node.choiceId) }) updateChoiceList(response, node.choiceId) }) } const updateChoiceList = (response, choiceId) => { $('#node-input-choiceId').find('option').remove() let listItems = response[$('#node-input-choiceType').val()] if (!Array.isArray(listItems) || listItems.length <= 0) return $.each(listItems, function (i, room) { let opt = {} opt.value = room.id opt.text = room.name if (choiceId === opt.value) { opt.selected = "selected" } $('#node-input-choiceId').append($('<option>', opt)) }) } RED.nodes.registerType('dirigera', { category: 'homesmart', color: '#fbd914', defaults: { name: { value: "" }, server: { type: "dirigera-config", required: true }, choiceType: { value: "" }, choiceTitle: { value: "" }, choiceId: { value: "" }, choiceIcon: { value: "" }, outputs: { value: 1 } }, inputs: 1, outputs: 1, icon: function () { switch (this.choiceType) { case "blinds": return 'font-awesome/fa-window-maximize' case "light": return "font-awesome/fa-lightbulb-o" case "controller": return 'font-awesome/fa-power-off' case "scene": return 'font-awesome/fa-sitemap' case "speaker": return 'font-awesome/fa-volume-up' case "outlet": return 'font-awesome/fa-plug' default: break } return 'font-awesome/fa-home' }, label: function () { if (this.name) return this.name if (this.choiceId === "-1") return "Dirigera Hub" if (this.choiceId && String(this.choiceId).includes('override')) return this.choiceType + ' with id override' return this.name || this.choiceTitle || "Dirigera Hub" }, oneditprepare: function () { const node = this $('#node-input-choiceType').append($('<option>', { text: 'Waiting for data' })) $('#node-input-choiceId').append($('<option>', { text: 'Waiting for data' })) updateTypes(node) $('#node-input-server').change(function () { $('#node-input-choiceType').find('option').remove() $('#node-input-choiceId').find('option').remove() updateTypes(node) }) }, oneditsave: function () { this.choiceTitle = $('#node-input-choiceId').find(":selected").text() this.outputs = $('#node-input-choiceType').find(":selected").text() == 'scene' ? 0 : 1 } }) </script> <script type="text/html" data-template-name="dirigera"> <div class="form-row"> <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Optional name"> </div> <div class="form-row"> <label for="node-input-server"><i class="fa fa-cog"></i> Config</label> <input type="text" id="node-input-server"> </div> <div class="form-row"> <label for="node-input-choiceType"><i class="fa fa-home"></i> Type</label> <select value="" id="node-input-choiceType"> </select> </div> <div class="form-row"> <label for="node-input-choiceId">Choose from list</label> <select value="" id="node-input-choiceId"> </select> </div> </script> <script type="text/html" data-help-name="dirigera"> <p>Get status and apply changes to the Dirigera hub</p> <p><i>If dropdowns are empty deploy config and look again.</i></p> <h3>Input</h3> <dl class="message-properties"> <dt>payload<span class="property-type">bool | number | string</span></dt> <dd>Gets status on any input. If <code>msg.topic</code> is defined this sets the payload sent to Dirigera.</dd> <dt class="optional">topic <span class="property-type">string</span></dt> <dd>If defined will change this attribute on devices in the chosen room. Scene trigger does not support this.</dd> <dt>deviceId/roomId<span class="property-type">string</span></dt> <dd>Override must be chosen from dropdown for this to work. Input string of ID as seen in status output.</dd> </dl> <h3>Output</h3> <dl class="message-properties"> <dt>payload<span class="property-type">object | array</span></dt> <dd>Return output data from the hub.</dd> <dt class="optional">availableTopics <span class="property-type">array</span></dt> <dd>On status request tells which topics are supported</dd> </dl> </script>