diff --git a/index.html b/index.html index 1a36dc1..90c7445 100644 --- a/index.html +++ b/index.html @@ -1,3 +1,4 @@ + @@ -21,7 +22,7 @@ } .name { - flex: 2; + flex: 3; } .header { @@ -47,6 +48,18 @@ background-color: indianred; } + .switchOn { + background-color: palegreen; + } + + .switchOff { + background-color: indianred; + } + + .switchCycle { + background-color: lightskyblue; + } + #info { display: none; } @@ -59,12 +72,13 @@
Name
Status
-
Initial
+
Countdown
Auto Aus
Auto An
-
Ein
-
Aus
-
Zyklus
+
+
+
+
Initial
@@ -109,6 +123,48 @@ } } + const SECOND = 1000; + const MINUTE = (60 * SECOND); + const HOUR = (60 * MINUTE); + const DAY = (24 * HOUR); + + function countdownString(relayData, millis) { + const rest = Math.ceil((millis - relayData.stateMillis - (Date.now() - dataAge)) / SECOND) * SECOND; + if (millis <= 0 || (relayData.onCount === 0 && !relayData.state)) { + return "-"; + } + const days = rest / DAY; + const hours = rest / HOUR; + const minutes = rest / MINUTE; + const seconds = rest / SECOND; + if (days >= 1) { + return Math.floor(days) + "d " + Math.floor(hours % 24) + "h " + Math.ceil(minutes % 60) + "m " + Math.ceil(seconds % 60) + "s"; + } + if (hours >= 1) { + return Math.floor(hours) + "h " + Math.floor(minutes % 60) + "m " + Math.ceil(seconds % 60) + "s"; + } + if (minutes >= 1) { + return Math.floor(minutes) + "m " + Math.ceil(seconds % 60) + "s"; + } + if (seconds >= 1) { + return Math.ceil(rest / SECOND) + "s"; + } + return "Warte..."; + } + + function updateCountdown(relayTag, relayData) { + const tag = relayTag.getElementsByClassName("countdown")[0]; + if (relayData.state) { + tag.innerText = countdownString(relayData, relayData.onMillis); + } else { + tag.innerText = countdownString(relayData, relayData.offMillis); + } + } + + let data; + + let dataAge; + function request(query = "") { if (timeout) { clearTimeout(timeout); @@ -119,13 +175,15 @@ r.open("GET", getUrl(`set?${query}`)); r.onreadystatechange = () => { if (r.readyState === 4 && r.status === 200) { - const data = JSON.parse(r.response); + data = JSON.parse(r.response); + dataAge = Date.now(); title.innerText = data.hostname; for (let index = 0; index < data.relays.length; index++) { const relayData = data.relays[index]; const relayTag = document.getElementById("relay" + index) || create(index); updateValue(relayTag, "name", "input", relayData.name); updateState(relayTag, relayData.state); + updateCountdown(relayTag, relayData); updateValue(relayTag, "onMillis", "input", relayData.onMillis); updateValue(relayTag, "offMillis", "input", relayData.offMillis); updateValue(relayTag, "initial", "select", relayData.initial); @@ -157,7 +215,7 @@ function newButton(relayIndex, relayTag, clazz, key, value, text) { const div = newDiv(relayIndex, relayTag, clazz); - const button = document.createElement("button") + const button = document.createElement("div") button.innerText = text; button.onclick = () => set(key, relayIndex, value); div.append(button); @@ -190,16 +248,30 @@ newInput(relayIndex, relayTag, "name", "text"); newDiv(relayIndex, relayTag, "state"); - newSelect(relayIndex, relayTag, "initial", [["OFF", "Aus"], ["ON", "Ein"], ["CYCLE", "Zyklus"]]); + newDiv(relayIndex, relayTag, "countdown"); newInput(relayIndex, relayTag, "onMillis", "number"); newInput(relayIndex, relayTag, "offMillis", "number"); newButton(relayIndex, relayTag, "switchOn", "state", "true", "Ein"); newButton(relayIndex, relayTag, "switchOff", "state", "false", "Aus"); newButton(relayIndex, relayTag, "switchCycle", "onCount", -1, "Zyklus"); + newSelect(relayIndex, relayTag, "initial", [["OFF", "Aus"], ["ON", "Ein"], ["CYCLE", "Zyklus"]]); return relayTag; } request(); + + function update() { + if (!data) { + return; + } + for (let index = 0; index < data.relays.length; index++) { + const relayData = data.relays[index]; + const relayTag = document.getElementById("relay" + index) || create(index); + updateCountdown(relayTag, relayData); + } + } + + setInterval(() => update(), 500); \ No newline at end of file