UNPKG

node-red-contrib-wled3

Version:
283 lines (250 loc) 11 kB
<script type="text/javascript"> RED.nodes.registerType("wled2", { category: "function", color: "#a6bbcf", defaults: { address: { value: "", required: true }, segmentId: {value: 0, validate: RED.validators.number() }, brightness: { value: 128 }, delay: { value: 0, validate: RED.validators.number() }, color1: { value: "#000000" }, color2: { value: "#000000" }, color3: { value: "#000000" }, effect: { value: 0 }, effectIntensity: { value: 128 }, effectSpeed: { value: 128 }, name: { value: "" }, palette: { value: "0" }, preset: { value: 0 }, state: { value: "on" }, debug: { value: "off" }, }, inputs: 1, outputs: 1, icon: "wled.png", label: function() { return this.name || "wled2"; }, labelStyle: function() { return this.name ? "node_label_italic" : ""; }, oneditprepare: function() { if (this.preset === "") { this.preset = 0; } $("#node-input-address").change({ currentEffect: this.effect, currentPalette: this.palette }, loadDropdowns); $("#node-input-delay").typedInput({ type: "num", types: ["num"], }); $("#node-config-discover").click(function() { if ($("#node-input-address").prop("tagName") === "INPUT") { searchAndSelectWled(); } else { manualWledIP(); } }); // Swaps the server input field to a text box with the current server value in it. function manualWledIP() { var current = $("#node-input-address").val(); $("#node-input-address").replaceWith('<input type="text" id="node-input-address" style="width: 100%"/>'); $("#node-input-address").val(current); } // Swaps the server input field to a dropdown and triggers auto-discovery. async function searchAndSelectWled() { var current = $("#node-input-address").val(); $("#node-input-address").replaceWith('<select id="node-input-address" style="width: 100%"></select>'); $("#node-input-address").append( '<option selected="selected" value="null">Searching for WLED devices...</option>', ); try { const devices = await $.getJSON("wled2/discover"); if (!devices || devices.length == 0) { RED.notify("No WLED devices found", "error"); } $("#node-input-address").empty(); devices.map(device => { $("#node-input-address").append( `<option value="${device.address}">${device.address} ${device.name ? `(${device.name})` : ""}</option>`, ); }); $("#node-input-address").val(current); } catch (e) { RED.notify(`Unable to discover devices: ${e.responseText}`); } } function populateDropdown(dropdownId, items) { const dropdown = $(dropdownId); // Clear out all the old options, if any, first $(`${dropdownId} option`).remove(); items.map(item => { const newOption = $(`<option value="${item.id}">${item.name}</option>`); dropdown.append(newOption); }); } async function getSortedEffects() { const server = $("#node-input-address").val(); if (!server) return; // Request the list of effects from the WLED device via the backend. // This works around https/http issues when running this node in a // NodeRed instance installed on Home Assistant. let effects = await $.getJSON(`wled2/effects/${server}`); if (!effects || effects.length == 0) { RED.notify("No effects found.", "error"); } // Drop the first item in the list, which is the default, before sorting. Then sort the list // and add the default back in at the top. const defaultEffect = effects.shift(); effects = effects.sort((a, b) => { if (a.name == b.name) return 0; if (a.name < b.name) return -1; if (a.name > b.name) return 1; }); effects.unshift(defaultEffect); return effects; } async function getSortedPalettes() { const server = $("#node-input-address").val(); if (!server) return; // Request the list of palettes from the WLED device via the backend. // This works around https/http issues when running this node in a // NodeRed instance installed on Home Assistant. let palettes = await $.getJSON(`wled2/palettes/${server}`); if (!palettes || palettes.length == 0) { RED.notify("No palettes found.", "error"); } // Drop the first item in the list, which is the default, before sorting. Then sort the list // and add the default back in at the top. const defaultPalette = palettes.shift(); palettes = palettes.sort((a, b) => { if (a.name == b.name) return 0; if (a.name < b.name) return -1; if (a.name > b.name) return 1; }); palettes.unshift(defaultPalette); return palettes; } async function loadDropdowns({ data: { currentEffect, currentPalette } }) { // Attempt to retrieve from the WLED device const server = $("#node-input-address").val(); if (!server) return; // Populate the effects dropdown from the device directly try { const effects = await getSortedEffects(); populateDropdown("#node-input-effect", effects); $(`#node-input-effect option[value=${currentEffect}]`).attr("selected", "selected"); } catch (e) { RED.notify(`Unable to retrieve list of effects from WLED device. ${e}`, "error"); } // Populate the palettes dropdown from the device directly try { const palettes = await getSortedPalettes(); populateDropdown("#node-input-palette", palettes); $(`#node-input-palette option[value=${currentPalette}]`).attr("selected", "selected"); } catch (e) { RED.notify(`Unable to retrieve list of palettes from WLED device. ${e}`, "error"); } } }, }); </script> <script type="text/html" data-template-name="wled2"> <div class="form-row"> <label for="node-input-name"><i class="icon-tag"></i> Name</label> <input type="text" id="node-input-name" placeholder="Name"> </div> <div class="form-row"> <label for="node-input-address"><i class="icon-server"></i> WLED server</label> <div style="display: inline-block; position: relative; width: 70%; height: 20px;"> <div style="position: absolute; left: 0px; right: 40px;"> <input type="text" id="node-input-address" placeholder="127.0.0.1" style="width: 100%"> </div> <a id="node-config-discover" class="editor-button" style="position: absolute; right: 0px; top: 0px;"> <i class="fa fa-search"></i> </a> </div> </div> <div class="form-row"> <label for="node-input-segmentId"><i class="icon-tag"></i> Segment ID</label> <input type="number" step="1" min="0" max="65535" placeholder="0" id="node-input-segmentId" /> </div> <div class="form-row"> <label for="node-input-state"><i class="icon-tag"></i> State</label> <select id="node-input-state"> <option value="on">on</option> <option value="off">off</option> <option value="toggle">toggle</option> </select> </div> <div class="form-row"> <label for="node-input-brightness"><i class="icon-tag"></i> Level</label> <input type="range" id="node-input-brightness" min="1" max="255"> </div> <div class="form-row"> <label for="node-input-color1"><i class="icon-tag"></i> Color</label> <input type="color" id="node-input-color1"> </div> <div class="form-row"> <label for="node-input-color2"><i class="icon-tag"></i> Color 2</label> <input type="color" id="node-input-color2"> </div> <div class="form-row"> <label for="node-input-color3"><i class="icon-tag"></i> Color 3</label> <input type="color" id="node-input-color3"> </div> <div class="form-row"> <label for="node-input-effect"><i class="icon-server"></i> Effect</label> <select id="node-input-effect"></select> </div> <div class="form-row"> <label for="node-input-effectSpeed"><i class="icon-tag"></i> Effect speed</label> <input type="range" id="node-input-effectSpeed" min="0" max="255"> </div> <div class="form-row"> <label for="node-input-effectIntensity"><i class="icon-tag"></i> Effect intensity</label> <input type="range" id="node-input-effectIntensity" min="0" max="255"> </div> <div class="form-row"> <label for="node-input-palette"><i class="icon-server"></i> Palette</label> <select id="node-input-palette"></select> </div> <div class="form-row"> <label for="node-input-preset"><i class="icon-tag"></i> Preset</label> <input type="number" step="1" min="0" max="65535" placeholder="0" id="node-input-preset" /> </div> <div class="form-row"> <label for="node-input-delay"><i class="fa fa-clock-o"></i> Delay before changing to solid (in seconds)</label> <input type="text" id="node-input-delay" placeholder="0"> </div> <div class="form-row"> <label for="node-input-debug"><i class="icon-tag"></i> Debug</label> <select id="node-input-debug"> <option value="off">off</option> <option value="on">on</option> </select> <small>output payload to debug window using node.warn</small> </div> </script> <script type="text/html" data-help-name="wled2"> <p>A node for controlling lights via WLED with segment support</p> <h3>Inputs</h3> <dl class="message-properties"> <dt>payload <span class="property-type">json</span> </dt> <dd>The WLED settings to set on the WLED device. These override any values specified in the node's properties.</dd> <dt>payload.segRange <span class="property-type">number</span> </td> <dd>The segment range to apply the settings to. <code>0</code> to <code>segRange</code> </dd> </dl> <ol class="node-ports"> <li>Standard output <dl class="message-properties"> <dt>payload <span class="property-type">json</span></dt> <dd>The payload that was received as input.</dd> </dl> </li> </ol> </script> <script type="text/javascript"></script>