UNPKG

node-red-contrib-power-saver

Version:

A module for Node-RED that you can use to turn on and off a switch based on power prices

244 lines (218 loc) 7.5 kB
<script type="text/javascript"> const defaultDaysGat = { Mon: true, Tue: true, Wed: true, Thu: true, Fri: true, Sat: true, Sun: true }; RED.nodes.registerType("ps-general-add-tariff", { category: "Power Saver", color: "#a6bbcf", defaults: { name: { value: "Add General Tariff" }, periods: { value: [ { start: "22", value: 0.0 }, { start: "06", value: 0.0 }, ], validate: function () { return !this.periods.some((p) => !/^(\d+\.\d*)|(\d+)$/.test("" + p.value)); }, }, validFrom: { value: null, required: false, validate: RED.validators.regex(/^$|^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$/), }, validTo: { value: null, required: false, validate: RED.validators.regex(/^$|^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$/), }, days: { value: { ...defaultDaysGat } }, }, hours: [ "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", ], inputs: 1, outputs: 1, icon: "font-awesome/fa-plus", color: "#FFCC66", label: function () { return this.name || "Add Tariff"; }, oneditprepare: function () { const createElement = function (type, attrs = [], children = []) { const el = document.createElement(type); attrs.forEach((attr) => { el.setAttribute(attr[0], attr[1]); }); children.forEach((child) => { el.append(child); }); return el; }; const createInputPart = function (name, i, text, inpStyle, value) { const id = `node-input-${name}-${i}`; const label = createElement( "label", [ ["for", id], ["style", "margin-right: 10px;"], ], [] ); label.innerHTML = text; const inp = createElement("input", [ ["type", "text"], ["id", id], ["style", `width: 80px; ${inpStyle};`], ]); inp.value = value; return createElement("span", [["style", "text-align: right;"]], [label, inp]); }; const addPeriod = function (periods) { const prev = periods[periods.length - 1].start; const next = prev === "23" ? "00" : "" + (parseInt(prev) + 1); periods.push({ start: next, value: null }); drawPeriods(periods); }; const removePeriod = function (periods, i) { periods.splice(i, 1); drawPeriods(periods); RED.nodes.dirty(true); }; const drawPeriods = function (periods) { document.getElementById("node-input-period-container").replaceChildren(); for (let i = 0; i < periods.length; i++) { let period = periods[i]; const timeEl = createInputPart("fromTime", i, "From time:", "margin-right: 20px;", period.start); const valEl = createInputPart("value", i, "Value:", "margin-right: 20px;", period.value); let li; if (periods.length > 1) { // Delete button const delButton = document.createElement("button"); delButton.setAttribute("style", "width: 24px;"); delButton.innerText = "X"; delButton.addEventListener("click", () => { removePeriod(periods, i); }); li = createElement("div", [["style", "text-align: left;"]], [timeEl, valEl, delButton]); } else { li = createElement("div", [["style", "text-align: left;"]], [timeEl, valEl]); } $("#node-input-period-container").append(li); $("#node-input-fromTime-" + i).typedInput({ types: [ { value: "fromTime", options: hours.map((h) => ({ value: h, label: h + ":00" })), }, ], }); $("#node-input-fromTime-" + i).change(function () { periods[i].start = this.value; RED.nodes.dirty(true); }); $("#node-input-value-" + i).change(function () { periods[i].value = this.value; RED.nodes.dirty(true); }); } }; const drawDays = function (days) { const dayNames = Object.keys(days); document.getElementById("node-input-days-container").replaceChildren(); for (let i = 0; i < dayNames.length; i++) { let day = dayNames[i]; const id = `node-input-day-${i}`; const label = createElement( "label", [ ["for", id], ["style", " margin: 4px 10px 0px 2px;width: 30px; text-align: left;"], ], [] ); label.innerHTML = day; const attrs = [ ["name", "node-input-day"], ["type", "checkbox"], ["id", id], ["style", `width: 15px; margin: 2px 0px 5px 5px;`], ]; if (days[day]) { attrs.push(["checked", ""]); } const inp = createElement("input", attrs); inp.value = dayNames[i]; const el = createElement("span", [["style", "text-align: right;"]], [inp, label]); $("#node-input-days-container").append(el); $("#node-input-day-" + i).change(function (e) { days[day] = $(this).is(":checked"); RED.nodes.dirty(true); }); } }; drawPeriods(this.periods); $("#add-period-button").on("click", () => { addPeriod(this.periods); }); if (!this.days) { // To support nodes created before this was developed this.days = { ...defaultDaysGat }; } drawDays(this.days); }, }); </script> <script type="text/html" data-template-name="ps-general-add-tariff"> <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="Name" /> </div> <div class="form-row node-input-period-container-row"> <div id="node-input-period-container"></div> </div> <div class="form-row"> <button type="button" id="add-period-button" class="red-ui-button">Add period</button> </div> <div class="form-row"> <label for="node-input-days-container"><i class="fa fa-calendar-o"></i> Days</label> <span id="node-input-days-container"></span> </div> <h3>Optional:</h3> <div class="form-row"> <label for="node-input-validFrom"><i class="fa fa-calendar"></i> Valid from date</label> <input type="text" id="node-input-validFrom" placeholder="YYYY-MM-DD" /> </div> <div class="form-row"> <label for="node-input-validTo"><i class="fa fa-calendar"></i> Valid to date</label> <input type="text" id="node-input-validTo" placeholder="YYYY-MM-DD" /> </div> </script> <script type="text/markdown" data-help-name="ps-general-add-tariff"> # Add Tariff A node to add a tariff that is fixed for periods of the day/year to the price before it is sent to the strategy nodes. Use this node between the receive-price node and any of the strategy nodes. Please read more in the [node documentation](https://powersaver.no/nodes/ps-general-add-tariff.html) </script>