diff --git a/3d/Super Vihelmo-Trug-2.stl b/3d/Super Vihelmo-Trug-2.stl new file mode 100644 index 0000000..817abf6 Binary files /dev/null and b/3d/Super Vihelmo-Trug-2.stl differ diff --git a/3d/Super Vihelmo-Trug-3.stl b/3d/Super Vihelmo-Trug-3.stl new file mode 100644 index 0000000..74685c4 Binary files /dev/null and b/3d/Super Vihelmo-Trug-3.stl differ diff --git a/3d/Super Vihelmo-Trug-4.stl b/3d/Super Vihelmo-Trug-4.stl new file mode 100644 index 0000000..b8a0bbf Binary files /dev/null and b/3d/Super Vihelmo-Trug-4.stl differ diff --git a/3d/Super Vihelmo-Trug-5.stl b/3d/Super Vihelmo-Trug-5.stl new file mode 100644 index 0000000..655fdbf Binary files /dev/null and b/3d/Super Vihelmo-Trug-5.stl differ diff --git a/3d/Super Vihelmo-Trug.stl b/3d/Super Vihelmo-Trug.stl new file mode 100644 index 0000000..b4d8798 Binary files /dev/null and b/3d/Super Vihelmo-Trug.stl differ diff --git a/README.md b/README.md index f43b7ae..fa69e73 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,6 @@ All except of the timing control data block. You have to click at the link "reset timing control data" on the webinterface. +Sample schematics (no NodeMCU pins defined in there) + +![Sample schematics](pic/schematics.png) diff --git a/firmware/data/bottom.js b/firmware/data/bottom.js index 976c0d9..8459e2f 100644 --- a/firmware/data/bottom.js +++ b/firmware/data/bottom.js @@ -13,6 +13,7 @@ tabTDE.classList.remove("visible"); amain.classList.add("pure-button-primary"); acfg.classList.remove("pure-button-primary"); atde.classList.remove("pure-button-primary"); +loadGraphData(); }); acfg.addEventListener("click", function() { tabMain.classList.remove("visible"); @@ -50,10 +51,10 @@ var channel3 = []; var channel4 = []; for (var i = 0; i < data['tcdata'].length; i++) { time.push(data['tcdata'][i]['hour'] + ':' + (data['tcdata'][i]['min'] < 10 ? '0' : '') + data['tcdata'][i]['min']); -channel1.push(data['tcdata'][i]['ch1']); -channel2.push(data['tcdata'][i]['ch2']); -channel3.push(data['tcdata'][i]['ch3']); -channel4.push(data['tcdata'][i]['ch4']); +channel1.push(data['tcdata'][i]['ch1'] * 100 / 255); +channel2.push(data['tcdata'][i]['ch2'] * 100 / 255); +channel3.push(data['tcdata'][i]['ch3'] * 100 / 255); +channel4.push(data['tcdata'][i]['ch4'] * 100 / 255); } currenttime.push(data['currenttime']['hour']); currenttime.push(data['currenttime']['min']); @@ -130,7 +131,7 @@ tickangle: -45, }, yaxis: { title: 'Brightness', -range: [0, 255], +range: [0, 100], }, shapes: [{ type: 'line', @@ -150,6 +151,119 @@ Plotly.newPlot('plot_chart', [trace1, trace2, trace3, trace4], layout); } setInterval(loadGraphData, 10000); loadGraphData(); +function loadTCGraphData() { +console.log('----> generate tc data graph <----'); +var data = JSON.parse(createJsonFromTable()); +var currenttime = []; +var time = []; +var channel1 = []; +var channel2 = []; +var channel3 = []; +var channel4 = []; +for (var i = 0; i < data['tcdata'].length; i++) { +time.push(data['tcdata'][i]['hour'] + ':' + (data['tcdata'][i]['min'] < 10 ? '0' : '') + data['tcdata'][i]['min']); +channel1.push(data['tcdata'][i]['ch1'] * 100 / 255); +channel2.push(data['tcdata'][i]['ch2'] * 100 / 255); +channel3.push(data['tcdata'][i]['ch3'] * 100 / 255); +channel4.push(data['tcdata'][i]['ch4'] * 100 / 255); +} +currenttime.push(data['currenttime']['hour']); +currenttime.push(data['currenttime']['min']); +var currentTimeStr = currenttime[0] + ':' + (currenttime[1] < 10 ? '0' : '') + currenttime[1]; +var index = time.indexOf(currentTimeStr); +if (index === -1) { +var lowerIndex = -1; +var upperIndex = -1; +for (var i = 0; i < time.length - 1; i++) { +const currentDate = new Date(); +const year = currentDate.getFullYear(); +const month = (currentDate.getMonth() + 1).toString().padStart(2, '0'); +const day = currentDate.getDate().toString().padStart(2, '0'); +const dateString = `${year}-${month}-${day}`; +const start = moment(dateString + ' ' + time[i], 'YYYY-MM-DD HH:mm'); +const curr = moment(dateString + ' ' + currentTimeStr, 'YYYY-MM-DD HH:mm'); +const end = moment(dateString + ' ' + time[i + 1], 'YYYY-MM-DD HH:mm'); +if (curr.isBetween(start, end)) { +lowerIndex = i; +upperIndex = i + 1; +break; +} +} +if (lowerIndex === -1 || upperIndex === -1) { +console.log("Error: Current time not found in time array and not between two elements in time array. Fixing it..."); +lowerIndex = 0; +upperIndex = 1; +var tmp1 = time[0].split(':'); +currenttime[0] = tmp1[0]; +currenttime[1] = tmp1[1]; +} +var lowerTime = time[lowerIndex].split(":"); +var upperTime = time[upperIndex].split(":"); +var timeDiff = (currenttime[0] - lowerTime[0]) + ((currenttime[1] - lowerTime[1]) / 60); +var indexFloat = lowerIndex + timeDiff / ((upperTime[0] - lowerTime[0]) + ((upperTime[1] - lowerTime[1]) / 60)); +} else { +} +if (indexFloat > index) { +index = indexFloat; +} +var trace1 = { +x: time, +y: channel1, +name: 'Channel 1', +type: 'scatter', +mode: 'lines+markers', +}; +var trace2 = { +x: time, +y: channel2, +name: 'Channel 2', +type: 'scatter', +mode: 'lines+markers', +}; +var trace3 = { +x: time, +y: channel3, +name: 'Channel 3', +type: 'scatter', +mode: 'lines+markers', +}; +var trace4 = { +x: time, +y: channel4, +name: 'Channel 4', +type: 'scatter', +mode: 'lines+markers', +}; +var layout = { +title: 'Timing Control Data Blocks', +xaxis: { +title: 'Time', +tickangle: -45, +}, +yaxis: { +title: 'Brightness', +range: [0, 100], +}, +shapes: [{ +type: 'line', +x0: index, +y0: 0, +x1: index, +y1: 255, +line: { +color: 'lightgrey', +width: 3, +dash: 'dot' +} +}] +}; +Plotly.newPlot('tc_plot_chart', [trace1, trace2, trace3, trace4], layout); +} +setInterval(function() { +if (document.getElementById('tab-tde').classList.contains('visible')) { +loadTCGraphData(); +} +}, 2000); function updateLightState() { console.log('----> setting bri and power switch <----'); for (let i = 1; i <= {{LIGHT_COUNT}}; i++) { @@ -196,9 +310,36 @@ var links = document.querySelectorAll('[id^="on"][id$="_off"]'); links.forEach(function(link) { link.addEventListener('click', function(event) { event.preventDefault(); +var id_full = this.id; var id = this.id.replace('on', '').replace('_off', ''); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?on' + id + '=false&transition=' + document.getElementById('transition').value, true); +xhr.onreadystatechange = function () { +if (xhr.readyState === 4) { +var button = document.getElementById(id_full); +if (xhr.status === 200) { +button.classList.remove("pure-button-primary"); +button.classList.add("success"); +button.innerHTML = "Disabled!"; +setTimeout(function () { +button.classList.remove("success"); +button.classList.add("pure-button-primary"); +button.innerHTML = "OFF"; +}, 2000); +console.log('Data successfully sent to server!'); +} else { +button.classList.remove("pure-button-primary"); +button.classList.add("error"); +button.innerHTML = "Error!"; +setTimeout(function () { +button.classList.remove("error"); +button.classList.add("pure-button-primary"); +button.innerHTML = "OFF"; +}, 2000); +console.log('Error while sending data to server.'); +} +} +}; xhr.send(); updateLightState(); this.classList.add('pure-button-primary'); @@ -209,9 +350,36 @@ var links = document.querySelectorAll('[id^="on"][id$="_on"]'); links.forEach(function(link) { link.addEventListener('click', function(event) { event.preventDefault(); +var id_full = this.id; var id = this.id.replace('on', '').replace('_on', ''); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?on' + id + '=true&transition=' + document.getElementById('transition').value, true); +xhr.onreadystatechange = function () { +if (xhr.readyState === 4) { +var button = document.getElementById(id_full); +if (xhr.status === 200) { +button.classList.remove("pure-button-primary"); +button.classList.add("success"); +button.innerHTML = "Enabled!"; +setTimeout(function () { +button.classList.remove("success"); +button.classList.add("pure-button-primary"); +button.innerHTML = "ON"; +}, 2000); +console.log('Data successfully sent to server!'); +} else { +button.classList.remove("pure-button-primary"); +button.classList.add("error"); +button.innerHTML = "Error!"; +setTimeout(function () { +button.classList.remove("error"); +button.classList.add("pure-button-primary"); +button.innerHTML = "ON"; +}, 2000); +console.log('Error while sending data to server.'); +} +} +}; xhr.send(); updateLightState(); this.classList.add('pure-button-primary'); @@ -231,22 +399,22 @@ headerRow.appendChild(th); table.appendChild(headerRow); for (var i = 1; i <= 10; i++) { var tr = document.createElement("tr"); -var tdHour = createSelectCell(23, 0); +var tdHour = createSelectCell(23, 0, 1); tdHour.id = "hour" + i; tr.appendChild(tdHour); -var tdMinute = createSelectCell(59, 0); +var tdMinute = createSelectCell(59, 0, 1); tdMinute.id = "minute" + i; tr.appendChild(tdMinute); -var tdCh1 = createSelectCell(100, 0); +var tdCh1 = createSelectCell(100, 0, 1); tdCh1.id = "ch1_" + i; tr.appendChild(tdCh1); -var tdCh2 = createSelectCell(100, 0); +var tdCh2 = createSelectCell(100, 0, 1); tdCh2.id = "ch2_" + i; tr.appendChild(tdCh2); -var tdCh3 = createSelectCell(100, 0); +var tdCh3 = createSelectCell(100, 0, 1); tdCh3.id = "ch3_" + i; tr.appendChild(tdCh3); -var tdCh4 = createSelectCell(100, 0); +var tdCh4 = createSelectCell(100, 0, 1); tdCh4.id = "ch4_" + i; tr.appendChild(tdCh4); table.appendChild(tr); @@ -256,9 +424,9 @@ container.innerHTML = ""; container.classList.add("pure-form"); container.appendChild(table); } -function createSelectCell(max, value) { +function createSelectCell(max, value, step) { var select = document.createElement("select"); -for (var i = 0; i <= max; i++) { +for (var i = 0; i <= max; i += step) { var option = document.createElement("option"); option.value = i; option.text = i; @@ -278,11 +446,12 @@ for (var i = 0; i < tcdata.length; i++) { var row = document.getElementById("hour" + (i+1)).parentNode; row.cells[0].childNodes[0].value = tcdata[i].hour; row.cells[1].childNodes[0].value = tcdata[i].min; -row.cells[2].childNodes[0].value = parseInt(tcdata[i].ch1 * 100 / 255); -row.cells[3].childNodes[0].value = parseInt(tcdata[i].ch2 * 100 / 255); -row.cells[4].childNodes[0].value = parseInt(tcdata[i].ch3 * 100 / 255); -row.cells[5].childNodes[0].value = parseInt(tcdata[i].ch4 * 100 / 255); +row.cells[2].childNodes[0].value = parseInt(Math.round(tcdata[i].ch1 * 100 / 255)); +row.cells[3].childNodes[0].value = parseInt(Math.round(tcdata[i].ch2 * 100 / 255)); +row.cells[4].childNodes[0].value = parseInt(Math.round(tcdata[i].ch3 * 100 / 255)); +row.cells[5].childNodes[0].value = parseInt(Math.round(tcdata[i].ch4 * 100 / 255)); } +loadTCGraphData(); }); } function createJsonFromTable() { @@ -300,20 +469,40 @@ tcdata.push({hour: hour, min: min, ch1: ch1, ch2: ch2, ch3: ch3, ch4: ch4}); } var currentTime = {hour: new Date().getHours(), min: new Date().getMinutes()}; var jsonData = {tcdata: tcdata, currenttime: currentTime}; -console.log("jsonData = " + JSON.stringify(jsonData)); return JSON.stringify(jsonData); } function sendDataToServer() { var jsonData = createJsonFromTable(); var urlEncodedData = encodeURIComponent(jsonData); var url = 'http://{{IP_ADDRESS}}/tc_data_blocks_store?data=' + urlEncodedData; -console.log("url so save = " + url); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); -xhr.onreadystatechange = function() { -if (xhr.readyState === 4 && xhr.status === 200) { +xhr.onreadystatechange = function () { +if (xhr.readyState === 4) { +var button = document.getElementById("save-button"); +if (xhr.status === 200) { +button.classList.remove("pure-button-primary"); +button.classList.add("success"); +button.innerHTML = "Saved!"; +setTimeout(function () { +button.classList.remove("success"); +button.classList.add("pure-button-primary"); +button.innerHTML = "save"; +}, 2000); console.log('Data successfully sent to server!'); +} else { +button.classList.remove("pure-button-primary"); +button.classList.add("error"); +button.innerHTML = "Error!"; +setTimeout(function () { +button.classList.remove("error"); +button.classList.add("pure-button-primary"); +button.innerHTML = "save"; +}, 2000); +console.log('Error while sending data to server.'); +} } }; xhr.send(); +loadTCGraphData(); } diff --git a/firmware/data/config_template.html b/firmware/data/config_template.html index 820b72a..da7ca3b 100644 --- a/firmware/data/config_template.html +++ b/firmware/data/config_template.html @@ -1,70 +1,70 @@ -
-
-
- -
- - -
-
- - -
-
- -
- - -
-
- - -
-
- -
- -ON -OFF -
-
- - -
-
- - -
-
- - -
-
- - -
-
- -
-
-
+
+
+
+ +
+ + +
+
+ + +
+
+ +
+ + +
+
+ + +
+
+ +
+ +ON +OFF +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
diff --git a/firmware/data/index_template_bottom.html b/firmware/data/index_template_bottom.html index c1156c1..f401ad3 100644 --- a/firmware/data/index_template_bottom.html +++ b/firmware/data/index_template_bottom.html @@ -6,10 +6,20 @@ Timming control data editor
-
+ + + + + +
+
+
+
+
+

-save +save
- +

Light {{LIGHT_NUMBER}}

+
+ +ON +OFF +
+
+ + +  +9 +% +
+ + +  + +% + +
diff --git a/firmware/data/style.css b/firmware/data/style.css index e39a471..9788312 100644 --- a/firmware/data/style.css +++ b/firmware/data/style.css @@ -40,4 +40,7 @@ cursor: pointer; } .pure-button:hover { background-color: #333; +} +.top-align { +vertical-align: top; } \ No newline at end of file diff --git a/firmware/data/top.js b/firmware/data/top.js index 373f487..7c1839a 100644 --- a/firmware/data/top.js +++ b/firmware/data/top.js @@ -4,6 +4,32 @@ link.addEventListener('click', function(event) { event.preventDefault(); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true); +xhr.onreadystatechange = function () { +if (xhr.readyState === 4) { +var button = document.getElementById("tc_on"); +if (xhr.status === 200) { +button.classList.remove("pure-button-primary"); +button.classList.add("success"); +button.innerHTML = "Enabled!"; +setTimeout(function () { +button.classList.remove("success"); +button.classList.add("pure-button-primary"); +button.innerHTML = "ON"; +}, 2000); +console.log('Data successfully sent to server!'); +} else { +button.classList.remove("pure-button-primary"); +button.classList.add("error"); +button.innerHTML = "Error!"; +setTimeout(function () { +button.classList.remove("error"); +button.classList.add("pure-button-primary"); +button.innerHTML = "ON"; +}, 2000); +console.log('Error while sending data to server.'); +} +} +}; xhr.send(); document.getElementById('tc_on').classList.add('pure-button-primary'); document.getElementById('tc_off').classList.remove('pure-button-primary'); @@ -15,6 +41,32 @@ link.addEventListener('click', function(event) { event.preventDefault(); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true); +xhr.onreadystatechange = function () { +if (xhr.readyState === 4) { +var button = document.getElementById("tc_off"); +if (xhr.status === 200) { +button.classList.remove("pure-button-primary"); +button.classList.add("success"); +button.innerHTML = "Disabled!"; +setTimeout(function () { +button.classList.remove("success"); +button.classList.add("pure-button-primary"); +button.innerHTML = "OFF"; +}, 2000); +console.log('Data successfully sent to server!'); +} else { +button.classList.remove("pure-button-primary"); +button.classList.add("error"); +button.innerHTML = "Error!"; +setTimeout(function () { +button.classList.remove("error"); +button.classList.add("pure-button-primary"); +button.innerHTML = "OFF"; +}, 2000); +console.log('Error while sending data to server.'); +} +} +}; xhr.send(); document.getElementById('tc_off').classList.add('pure-button-primary'); document.getElementById('tc_on').classList.remove('pure-button-primary'); diff --git a/firmware/html/bottom.js b/firmware/html/bottom.js index c19e1bd..69dc709 100644 --- a/firmware/html/bottom.js +++ b/firmware/html/bottom.js @@ -19,6 +19,8 @@ function addTabListener() { amain.classList.add("pure-button-primary"); acfg.classList.remove("pure-button-primary"); atde.classList.remove("pure-button-primary"); + + loadGraphData(); // reload the graph }); acfg.addEventListener("click", function() { @@ -64,10 +66,10 @@ function loadGraphData() { var channel4 = []; for (var i = 0; i < data['tcdata'].length; i++) { time.push(data['tcdata'][i]['hour'] + ':' + (data['tcdata'][i]['min'] < 10 ? '0' : '') + data['tcdata'][i]['min']); - channel1.push(data['tcdata'][i]['ch1']); - channel2.push(data['tcdata'][i]['ch2']); - channel3.push(data['tcdata'][i]['ch3']); - channel4.push(data['tcdata'][i]['ch4']); + channel1.push(data['tcdata'][i]['ch1'] * 100 / 255); + channel2.push(data['tcdata'][i]['ch2'] * 100 / 255); + channel3.push(data['tcdata'][i]['ch3'] * 100 / 255); + channel4.push(data['tcdata'][i]['ch4'] * 100 / 255); } currenttime.push(data['currenttime']['hour']); currenttime.push(data['currenttime']['min']); @@ -155,7 +157,7 @@ function loadGraphData() { }, yaxis: { title: 'Brightness', - range: [0, 255], + range: [0, 100], }, shapes: [{ type: 'line', @@ -176,6 +178,135 @@ function loadGraphData() { setInterval(loadGraphData, 10000); loadGraphData(); +function loadTCGraphData() { + console.log('----> generate tc data graph <----'); + + var data = JSON.parse(createJsonFromTable()); + //console.log(data); + var currenttime = []; + var time = []; + var channel1 = []; + var channel2 = []; + var channel3 = []; + var channel4 = []; + for (var i = 0; i < data['tcdata'].length; i++) { + time.push(data['tcdata'][i]['hour'] + ':' + (data['tcdata'][i]['min'] < 10 ? '0' : '') + data['tcdata'][i]['min']); + channel1.push(data['tcdata'][i]['ch1'] * 100 / 255); + channel2.push(data['tcdata'][i]['ch2'] * 100 / 255); + channel3.push(data['tcdata'][i]['ch3'] * 100 / 255); + channel4.push(data['tcdata'][i]['ch4'] * 100 / 255); + } + currenttime.push(data['currenttime']['hour']); + currenttime.push(data['currenttime']['min']); + //console.log(currenttime); + var currentTimeStr = currenttime[0] + ':' + (currenttime[1] < 10 ? '0' : '') + currenttime[1]; + var index = time.indexOf(currentTimeStr); + if (index === -1) { + var lowerIndex = -1; + var upperIndex = -1; + for (var i = 0; i < time.length - 1; i++) { + //console.log(time[i] + ' <= ' + currentTimeStr + ' >= ' + time[i + 1]); + const currentDate = new Date(); + const year = currentDate.getFullYear(); + const month = (currentDate.getMonth() + 1).toString().padStart(2, '0'); + const day = currentDate.getDate().toString().padStart(2, '0'); + const dateString = `${year}-${month}-${day}`; + const start = moment(dateString + ' ' + time[i], 'YYYY-MM-DD HH:mm'); + const curr = moment(dateString + ' ' + currentTimeStr, 'YYYY-MM-DD HH:mm'); + const end = moment(dateString + ' ' + time[i + 1], 'YYYY-MM-DD HH:mm'); + //console.log(start.format('YYYY-MM-DD HH:mm') + ' <= ' + curr.format('YYYY-MM-DD HH:mm') + ' >= ' + end.format('YYYY-MM-DD HH:mm')); + //console.log(curr.isBetween(start, end)); + if (curr.isBetween(start, end)) { + lowerIndex = i; + upperIndex = i + 1; + break; + } + } + //console.log('lowerIndex=' + lowerIndex); + //console.log('upperIndex=' + upperIndex); + if (lowerIndex === -1 || upperIndex === -1) { + console.log("Error: Current time not found in time array and not between two elements in time array. Fixing it..."); + lowerIndex = 0; + upperIndex = 1; + var tmp1 = time[0].split(':'); + //console.log('tmp1 = ' + tmp1); + currenttime[0] = tmp1[0]; + currenttime[1] = tmp1[1]; + } + var lowerTime = time[lowerIndex].split(":"); + var upperTime = time[upperIndex].split(":"); + var timeDiff = (currenttime[0] - lowerTime[0]) + ((currenttime[1] - lowerTime[1]) / 60); + var indexFloat = lowerIndex + timeDiff / ((upperTime[0] - lowerTime[0]) + ((upperTime[1] - lowerTime[1]) / 60)); + //console.log("Index (float): " + indexFloat); + } else { + //console.log("Index (integer): " + index); + //console.log("Index (float): " + index); + } + if (indexFloat > index) { + index = indexFloat; + } + //console.log("index in graph >>>" + index); + var trace1 = { + x: time, + y: channel1, + name: 'Channel 1', + type: 'scatter', + mode: 'lines+markers', + }; + var trace2 = { + x: time, + y: channel2, + name: 'Channel 2', + type: 'scatter', + mode: 'lines+markers', + }; + var trace3 = { + x: time, + y: channel3, + name: 'Channel 3', + type: 'scatter', + mode: 'lines+markers', + }; + var trace4 = { + x: time, + y: channel4, + name: 'Channel 4', + type: 'scatter', + mode: 'lines+markers', + }; + var layout = { + title: 'Timing Control Data Blocks', + xaxis: { + title: 'Time', + tickangle: -45, + }, + yaxis: { + title: 'Brightness', + range: [0, 100], + }, + shapes: [{ + type: 'line', + x0: index, + y0: 0, + x1: index, + y1: 255, + line: { + color: 'lightgrey', + width: 3, + dash: 'dot' + } + }] + }; + Plotly.newPlot('tc_plot_chart', [trace1, trace2, trace3, trace4], layout); + +} + +setInterval(function() { + if (document.getElementById('tab-tde').classList.contains('visible')) { + loadTCGraphData(); + } +}, 2000); + function updateLightState() { console.log('----> setting bri and power switch <----'); for (let i = 1; i <= {{LIGHT_COUNT}}; i++) { @@ -230,10 +361,39 @@ links.forEach(function(link) { // Verhindere, dass der Link die Seite neu lädt event.preventDefault(); // Extrahiere die Zahl aus der ID des Links + var id_full = this.id; var id = this.id.replace('on', '').replace('_off', ''); // Erstelle eine neue Anfrage an die entsprechende URL var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?on' + id + '=false&transition=' + document.getElementById('transition').value, true); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var button = document.getElementById(id_full); + if (xhr.status === 200) { + button.classList.remove("pure-button-primary"); + button.classList.add("success"); + button.innerHTML = "Disabled!"; + setTimeout(function () { + button.classList.remove("success"); + button.classList.add("pure-button-primary"); + button.innerHTML = "OFF"; + }, 2000); + console.log('Data successfully sent to server!'); + } else { + button.classList.remove("pure-button-primary"); + button.classList.add("error"); + button.innerHTML = "Error!"; + setTimeout(function () { + button.classList.remove("error"); + button.classList.add("pure-button-primary"); + button.innerHTML = "OFF"; + }, 2000); + console.log('Error while sending data to server.'); + } + } + }; + // Sende die Anfrage im Hintergrund xhr.send(); updateLightState(); @@ -249,10 +409,39 @@ links.forEach(function(link) { // Verhindere, dass der Link die Seite neu lädt event.preventDefault(); // Extrahiere die Zahl aus der ID des Links + var id_full = this.id; var id = this.id.replace('on', '').replace('_on', ''); // Erstelle eine neue Anfrage an die entsprechende URL var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?on' + id + '=true&transition=' + document.getElementById('transition').value, true); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var button = document.getElementById(id_full); + if (xhr.status === 200) { + button.classList.remove("pure-button-primary"); + button.classList.add("success"); + button.innerHTML = "Enabled!"; + setTimeout(function () { + button.classList.remove("success"); + button.classList.add("pure-button-primary"); + button.innerHTML = "ON"; + }, 2000); + console.log('Data successfully sent to server!'); + } else { + button.classList.remove("pure-button-primary"); + button.classList.add("error"); + button.innerHTML = "Error!"; + setTimeout(function () { + button.classList.remove("error"); + button.classList.add("pure-button-primary"); + button.innerHTML = "ON"; + }, 2000); + console.log('Error while sending data to server.'); + } + } + }; + // Sende die Anfrage im Hintergrund xhr.send(); updateLightState(); @@ -283,32 +472,32 @@ function createTable() { var tr = document.createElement("tr"); // Stunde - var tdHour = createSelectCell(23, 0); + var tdHour = createSelectCell(23, 0, 1); tdHour.id = "hour" + i; tr.appendChild(tdHour); // Minute - var tdMinute = createSelectCell(59, 0); + var tdMinute = createSelectCell(59, 0, 1); tdMinute.id = "minute" + i; tr.appendChild(tdMinute); // ch1 - var tdCh1 = createSelectCell(100, 0); + var tdCh1 = createSelectCell(100, 0, 1); tdCh1.id = "ch1_" + i; tr.appendChild(tdCh1); // ch2 - var tdCh2 = createSelectCell(100, 0); + var tdCh2 = createSelectCell(100, 0, 1); tdCh2.id = "ch2_" + i; tr.appendChild(tdCh2); // ch3 - var tdCh3 = createSelectCell(100, 0); + var tdCh3 = createSelectCell(100, 0, 1); tdCh3.id = "ch3_" + i; tr.appendChild(tdCh3); // ch4 - var tdCh4 = createSelectCell(100, 0); + var tdCh4 = createSelectCell(100, 0, 1); tdCh4.id = "ch4_" + i; tr.appendChild(tdCh4); @@ -321,12 +510,12 @@ function createTable() { container.appendChild(table); } -function createSelectCell(max, value) { +function createSelectCell(max, value, step) { // Erstelle ein neues select-Element var select = document.createElement("select"); // Füge Optionen hinzu - for (var i = 0; i <= max; i++) { + for (var i = 0; i <= max; i += step) { var option = document.createElement("option"); option.value = i; option.text = i; @@ -355,11 +544,13 @@ function fillTableFromJson() { var row = document.getElementById("hour" + (i+1)).parentNode; row.cells[0].childNodes[0].value = tcdata[i].hour; row.cells[1].childNodes[0].value = tcdata[i].min; - row.cells[2].childNodes[0].value = parseInt(tcdata[i].ch1 * 100 / 255); - row.cells[3].childNodes[0].value = parseInt(tcdata[i].ch2 * 100 / 255); - row.cells[4].childNodes[0].value = parseInt(tcdata[i].ch3 * 100 / 255); - row.cells[5].childNodes[0].value = parseInt(tcdata[i].ch4 * 100 / 255); + row.cells[2].childNodes[0].value = parseInt(Math.round(tcdata[i].ch1 * 100 / 255)); + row.cells[3].childNodes[0].value = parseInt(Math.round(tcdata[i].ch2 * 100 / 255)); + row.cells[4].childNodes[0].value = parseInt(Math.round(tcdata[i].ch3 * 100 / 255)); + row.cells[5].childNodes[0].value = parseInt(Math.round(tcdata[i].ch4 * 100 / 255)); } + + loadTCGraphData(); }); } @@ -380,7 +571,7 @@ function createJsonFromTable() { } var currentTime = {hour: new Date().getHours(), min: new Date().getMinutes()}; var jsonData = {tcdata: tcdata, currenttime: currentTime}; - console.log("jsonData = " + JSON.stringify(jsonData)); + //console.log("jsonData = " + JSON.stringify(jsonData)); return JSON.stringify(jsonData); } @@ -388,14 +579,34 @@ function sendDataToServer() { var jsonData = createJsonFromTable(); var urlEncodedData = encodeURIComponent(jsonData); var url = 'http://{{IP_ADDRESS}}/tc_data_blocks_store?data=' + urlEncodedData; - console.log("url so save = " + url); var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4 && xhr.status === 200) { - console.log('Data successfully sent to server!'); - } + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var button = document.getElementById("save-button"); + if (xhr.status === 200) { + button.classList.remove("pure-button-primary"); + button.classList.add("success"); + button.innerHTML = "Saved!"; + setTimeout(function () { + button.classList.remove("success"); + button.classList.add("pure-button-primary"); + button.innerHTML = "save"; + }, 2000); + console.log('Data successfully sent to server!'); + } else { + button.classList.remove("pure-button-primary"); + button.classList.add("error"); + button.innerHTML = "Error!"; + setTimeout(function () { + button.classList.remove("error"); + button.classList.add("pure-button-primary"); + button.innerHTML = "save"; + }, 2000); + console.log('Error while sending data to server.'); + } + } }; xhr.send(); - } - + loadTCGraphData(); // update the tc data graph +} diff --git a/firmware/html/index_template_bottom.html b/firmware/html/index_template_bottom.html index a72b1b7..37d78fd 100644 --- a/firmware/html/index_template_bottom.html +++ b/firmware/html/index_template_bottom.html @@ -6,10 +6,21 @@ Timming control data editor
-
-
+ + + + + +
+
+
+
+
+
+
+
- save + save diff --git a/firmware/html/index_template_middle.html b/firmware/html/index_template_middle.html index 2b948ab..4b5e267 100644 --- a/firmware/html/index_template_middle.html +++ b/firmware/html/index_template_middle.html @@ -1,7 +1,7 @@ -
+
diff --git a/firmware/html/index_template_top.html b/firmware/html/index_template_top.html index 3ac1cf8..5d4956f 100644 --- a/firmware/html/index_template_top.html +++ b/firmware/html/index_template_top.html @@ -47,5 +47,5 @@
-
+ diff --git a/firmware/html/light_control_template.html b/firmware/html/light_control_template.html index be21046..bc62ab1 100644 --- a/firmware/html/light_control_template.html +++ b/firmware/html/light_control_template.html @@ -7,13 +7,13 @@ OFF
- +   9 %
- +   diff --git a/firmware/html/style.css b/firmware/html/style.css index e39a471..9788312 100644 --- a/firmware/html/style.css +++ b/firmware/html/style.css @@ -40,4 +40,7 @@ cursor: pointer; } .pure-button:hover { background-color: #333; +} +.top-align { +vertical-align: top; } \ No newline at end of file diff --git a/firmware/html/top.js b/firmware/html/top.js index 73dd43b..bf4ddaa 100644 --- a/firmware/html/top.js +++ b/firmware/html/top.js @@ -4,6 +4,34 @@ links.forEach(function(link) { event.preventDefault(); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var button = document.getElementById("tc_on"); + if (xhr.status === 200) { + button.classList.remove("pure-button-primary"); + button.classList.add("success"); + button.innerHTML = "Enabled!"; + setTimeout(function () { + button.classList.remove("success"); + button.classList.add("pure-button-primary"); + button.innerHTML = "ON"; + }, 2000); + console.log('Data successfully sent to server!'); + } else { + button.classList.remove("pure-button-primary"); + button.classList.add("error"); + button.innerHTML = "Error!"; + setTimeout(function () { + button.classList.remove("error"); + button.classList.add("pure-button-primary"); + button.innerHTML = "ON"; + }, 2000); + console.log('Error while sending data to server.'); + } + } + }; + xhr.send(); //console.log('tc=true call'); document.getElementById('tc_on').classList.add('pure-button-primary'); @@ -16,6 +44,34 @@ links.forEach(function(link) { event.preventDefault(); var xhr = new XMLHttpRequest(); xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true); + + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + var button = document.getElementById("tc_off"); + if (xhr.status === 200) { + button.classList.remove("pure-button-primary"); + button.classList.add("success"); + button.innerHTML = "Disabled!"; + setTimeout(function () { + button.classList.remove("success"); + button.classList.add("pure-button-primary"); + button.innerHTML = "OFF"; + }, 2000); + console.log('Data successfully sent to server!'); + } else { + button.classList.remove("pure-button-primary"); + button.classList.add("error"); + button.innerHTML = "Error!"; + setTimeout(function () { + button.classList.remove("error"); + button.classList.add("pure-button-primary"); + button.innerHTML = "OFF"; + }, 2000); + console.log('Error while sending data to server.'); + } + } + }; + xhr.send(); //console.log('tc=false call'); document.getElementById('tc_off').classList.add('pure-button-primary'); diff --git a/pic/schematics.png b/pic/schematics.png new file mode 100644 index 0000000..f03a73b Binary files /dev/null and b/pic/schematics.png differ