UNPKG

node-red-contrib-zigbee2mqtt-devices

Version:
325 lines (286 loc) 12.9 kB
<style> .config-group { background: #EEE; padding: 20px 15px 1px 15px; margin: 10px 0px; } .config-group .red-ui-typedInput-container { width: 100% !important; } .config-sub-group { margin-left: 8px; border-left: 5px solid #ddd; padding-left: 7px; } /* PROPERTIES PANELS */ /* Font Awesome Icons shall have all the same width */ .zigbee2mqtt-devices-properties .form-row>label>.fa { width: 16px; text-align: center; } .zigbee2mqtt-devices-slider input[type=range] { width: 60%; display: inline; } .zigbee2mqtt-devices-slider input[type=text] { width: 9%; display: inline; } .zigbee2mqtt-error-box { border: 1px solid rgb(255, 0, 0); margin: 10px auto; width: 380px; padding: 7px; color: white; background: rgb(244, 67, 54); text-align: center; } .zigbee2mqtt-error-box button{ margin-left: 10px; } </style> <script type="text/javascript"> function refresh() { RED.nodes.eachNode(function (node) { }); } /* TODO: implement the tab, removed for now RED.sidebar.addTab({ id: "zigbee2mqtt", label: "Zigbee 2 MQTT", name: "zigbee2mqtt", content: "<div class=\"nr-db-sb\">TODO: Add overview of all devices</div>", closeable: true, pinned: true, iconClass: "fa fa-cloud", disableOnEdit: true, onchange: function () { refresh(); } });*/ if (RED.bavaria === undefined) { RED.bavaria = { validators: { range: function (min, max) { return function (v) { return v <= max && v >= min; } } }, converters: { hexToRgb: function (hex) { if (hex.startsWith("#")) { hex = hex.substring(1); } if (hex.length === 3) { hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } if (hex.length != 6) { return { r: 0, g: 0, b: 0 } } var int16 = parseInt(hex, 16); return { r: (int16 >> 16) & 255, g: (int16 >> 8) & 255, b: int16 & 255 } }, rgbToHex: function (r, g, b) { r = parseInt(r).toString(16); g = parseInt(g).toString(16); b = parseInt(b).toString(16); if (r.length == 1) r = "0" + r; if (g.length == 1) g = "0" + g; if (b.length == 1) b = "0" + b; return "#" + r + g + b; } }, ui: { addNumInput: function (element) { $(element).typedInput({ type: "num", types: ["num"], }); }, addNumInputs: function (elements) { elements.forEach(RED.bavaria.ui.addNumInput); }, addNumRangeInput: function (element, min, max) { RED.bavaria.ui.addNumInput(element); var validator = RED.bavaria.validators.range(min, max); $(element).change(function () { var valid = validator($(this).val()); var targetElement = $(this).parent().find('.red-ui-typedInput-container'); if (!valid) { targetElement.addClass('input-error'); } else { targetElement.removeClass('input-error'); } }); }, addNumRangeInputs: function (elements, min, max) { elements.forEach(element => { RED.bavaria.ui.addNumRangeInput(element, min, max); }); }, addMultiInput: function (node, name) { var value = node["payload" + name]; var type = node["type" + name]; var options = { type: type, types: ["str", "json", "num", "bool"] }; const index = options.types.indexOf(type); if (index > -1) { options.types.splice(index, 1); options.types.splice(0, 0, type); } console.log(options); $("#node-input-payload" + name).typedInput(options); }, saveMultiInput: function (node, name) { var splits = $("#node-input-payload" + name).next().children("button").children("span").children("img").first().attr("src").split("/"); var type = splits[splits.length - 1].split(".")[0]; switch (type) { case "az": type = "str"; break; case "09": type = "num"; break; case "bool": type = "bool"; break; case "json": type = "json"; break; } node["customPayload" + name] = $("#node-input-payload" + name).val() !== ""; node["type" + name] = type; } }, devices: { loadDevices: function (selectedDevice, deviceType, vendor, model, emptyOption = false, inputId = "#node-input-deviceName") { var bridgeId = $("#node-input-bridge").val().replace(".", "_"); $.getJSON(`z2m/devices/${bridgeId}/${deviceType}/${vendor}/${model}`, function (data) { $(inputId).empty(); if (emptyOption === true) { $(inputId).append("<option disabled selected value> -- select an option -- </option>"); } data.devices.forEach(e => { $(inputId).append("<option>" + e.friendly_name + "</option>"); }); $(inputId).val(selectedDevice); }); }, createDeviceSelector: function ( rowId, deviceName, deviceType = "all", vendor = "all", model = "all", isConfig = false, devicePropertyName = "deviceName", bridgePropertyName = "bridge" ) { let inputId = `input-${devicePropertyName}`; let bridgeId = `input-bridge`; if (isConfig === true) { inputId = "node-config-" + inputId; bridgeId = "node-config-" + bridgeId; } else { inputId = "node-" + inputId; bridgeId = "node-" + bridgeId; } let label = $("<label></label>") .attr("for", inputId) .append( $("<i></i>") .addClass("fa") .addClass("fa-microchip")) .append(" Device"); let select = $("<select></select>").attr("id", inputId).attr("style", "margin:0px 4px;"); let button = $("<button></button>") .attr("id", "refresh-button-" + inputId) .attr("type", "button") .addClass("red-ui-button") .append($("<i></i>") .addClass("fa") .addClass("fa-search")) .append(" refresh"); let errorBox = $("<div></div>") .attr("id", "device-error" + inputId) .addClass("zigbee2mqtt-error-box") .hide(); $("#" + rowId) .prepend(errorBox) .prepend(button) .prepend(select) .prepend(label); let loadDevices = function (inputId, htmlBridgeId, selectedDevice, deviceType = "all", vendor = "all", model = "all") { var bridgeId = $("#" + htmlBridgeId).val().replace(".", "_"); $.getJSON(`z2m/devices/${bridgeId}/${deviceType}/${vendor}/${model}`, function (data) { let select = $("#" + inputId); select.empty(); if (!data.success) { $("#device-error" + inputId) .html(data.message) .append( $("<button></button>") .text("Switch to manual entry") .click(() => { let textbox = $("<input />", { "type": "text", "value": selectedDevice }); textbox.attr("id", inputId) .attr("style", "margin-left: 4px;") .attr("placeholder", "Enter friendly_name"); $("#" + inputId).replaceWith(textbox); $("#refresh-button-" + inputId).remove(); $("#device-error" + inputId).hide(); }) ); $("#device-error" + inputId).show(); } else { $("#device-error" + inputId).hide(); } select.append("<option disabled selected value> -- select an option -- </option>"); data.devices.forEach(e => { select.append("<option>" + e.friendly_name + "</option>"); }); select.val(selectedDevice); }).fail(function () { $("#device-error" + inputId) .html("Failed to request device-list!") .append( $("<button></button>") .text("Switch to manual entry") .click(() => { let textbox = $("<input />", { "type": "text", "value": selectedDevice }); textbox.attr("id", inputId) .attr("style", "margin-left: 4px;") .attr("placeholder", "Enter friendly_name"); $("#" + inputId).replaceWith(textbox); $("#refresh-button-" + inputId).remove(); $("#device-error" + inputId).hide(); }) ); $("#device-error" + inputId).show(); }); } button.click(() => { loadDevices(inputId, bridgeId, deviceName, deviceType, vendor, model); }); let bridgeIdSelector = "#" + bridgeId; $(bridgeIdSelector).change(function () { loadDevices(inputId, bridgeId, deviceName, deviceType, vendor, model); }); } } } } </script>