Merge branch 'develop'
This commit is contained in:
commit
99e8a0fa82
21 changed files with 1281 additions and 861 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* -text
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
.DS_store
|
.DS_store
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
This build is based on: https://github.com/mariusmotea/diyHue/tree/master/Lights/Arduino/Generic_Dimmable_Light
|
This project is based on: https://github.com/mariusmotea/diyHue/tree/master/Lights/Arduino/Generic_Dimmable_Light
|
||||||
|
|
||||||
|
Most of the code was generated by ChatGPT.
|
||||||
|
|
||||||
The controller I use is a old NodeMCU v1.0, which is connected to 4x D4184 MOS breakout boards. See NodeMCU pins table beyond.
|
The controller I use is a old NodeMCU v1.0, which is connected to 4x D4184 MOS breakout boards. See NodeMCU pins table beyond.
|
||||||
The cable I use is a https://amzn.eu/d/0jigRCh. I cut it in half and attached it to the MOS boards.
|
The cable I use is a https://amzn.eu/d/0jigRCh. I cut it in half and attached it to the MOS boards.
|
||||||
|
|
319
firmware/data/bottom.js
Normal file
319
firmware/data/bottom.js
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
function addTabListener() {
|
||||||
|
try {
|
||||||
|
var tabMain = document.getElementById("tab-lights");
|
||||||
|
var tabConfig = document.getElementById("tab-config");
|
||||||
|
var tabTDE = document.getElementById("tab-tde");
|
||||||
|
var amain = document.getElementById("tab-a-lights");
|
||||||
|
var acfg = document.getElementById("tab-a-config");
|
||||||
|
var atde = document.getElementById("tab-a-tde");
|
||||||
|
amain.addEventListener("click", function() {
|
||||||
|
tabMain.classList.add("visible");
|
||||||
|
tabConfig.classList.remove("visible");
|
||||||
|
tabTDE.classList.remove("visible");
|
||||||
|
amain.classList.add("pure-button-primary");
|
||||||
|
acfg.classList.remove("pure-button-primary");
|
||||||
|
atde.classList.remove("pure-button-primary");
|
||||||
|
});
|
||||||
|
acfg.addEventListener("click", function() {
|
||||||
|
tabMain.classList.remove("visible");
|
||||||
|
tabConfig.classList.add("visible");
|
||||||
|
tabTDE.classList.remove("visible");
|
||||||
|
amain.classList.remove("pure-button-primary");
|
||||||
|
acfg.classList.add("pure-button-primary");
|
||||||
|
atde.classList.remove("pure-button-primary");
|
||||||
|
});
|
||||||
|
atde.addEventListener("click", function() {
|
||||||
|
tabMain.classList.remove("visible");
|
||||||
|
tabConfig.classList.remove("visible");
|
||||||
|
tabTDE.classList.add("visible");
|
||||||
|
amain.classList.remove("pure-button-primary");
|
||||||
|
acfg.classList.remove("pure-button-primary");
|
||||||
|
atde.classList.add("pure-button-primary");
|
||||||
|
createTable();
|
||||||
|
fillTableFromJson();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error: load listener of the tab action listener management: " + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
addTabListener();
|
||||||
|
});
|
||||||
|
function loadGraphData() {
|
||||||
|
console.log('----> generate graph <----');
|
||||||
|
$.getJSON('/tc_data_blocks_read', function(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']);
|
||||||
|
channel2.push(data['tcdata'][i]['ch2']);
|
||||||
|
channel3.push(data['tcdata'][i]['ch3']);
|
||||||
|
channel4.push(data['tcdata'][i]['ch4']);
|
||||||
|
}
|
||||||
|
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, 255],
|
||||||
|
},
|
||||||
|
shapes: [{
|
||||||
|
type: 'line',
|
||||||
|
x0: index,
|
||||||
|
y0: 0,
|
||||||
|
x1: index,
|
||||||
|
y1: 255,
|
||||||
|
line: {
|
||||||
|
color: 'lightgrey',
|
||||||
|
width: 3,
|
||||||
|
dash: 'dot'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
Plotly.newPlot('plot_chart', [trace1, trace2, trace3, trace4], layout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setInterval(loadGraphData, 10000);
|
||||||
|
loadGraphData();
|
||||||
|
function updateLightState() {
|
||||||
|
console.log('----> setting bri and power switch <----');
|
||||||
|
for (let i = 1; i <= {{LIGHT_COUNT}}; i++) {
|
||||||
|
const lightURL = `http://{{IP_ADDRESS}}/state?light=${i}`;
|
||||||
|
fetch(lightURL).then(response => response.json()).then(data => {
|
||||||
|
const briSlider = document.getElementById(`bri${i - 1}`);
|
||||||
|
const briSliderVal = document.getElementById(`bri${i - 1}_val`);
|
||||||
|
const onLinkOn = document.getElementById(`on${i - 1}_on`);
|
||||||
|
const onLinkOff = document.getElementById(`on${i - 1}_off`);
|
||||||
|
briSlider.value = data.bri;
|
||||||
|
briSliderVal.innerHTML = (Math.round((data.bri * 100.0 / 255.0) * 100) / 100).toFixed(2);
|
||||||
|
if (data.on == true) {
|
||||||
|
onLinkOn.classList.add('pure-button-primary');
|
||||||
|
onLinkOff.classList.remove('pure-button-primary');
|
||||||
|
} else {
|
||||||
|
onLinkOn.classList.remove('pure-button-primary');
|
||||||
|
onLinkOff.classList.add('pure-button-primary');
|
||||||
|
}
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setInterval(updateLightState, 10000);
|
||||||
|
updateLightState();
|
||||||
|
function updatePWMValues() {
|
||||||
|
console.log('----> setting pwm data <----');
|
||||||
|
for (let i = 0; i < {{LIGHT_COUNT}}; i++) {
|
||||||
|
const lightID = i + 1;
|
||||||
|
const pwmElement = document.getElementById(`light${i}_pwm`);
|
||||||
|
const pwmElementTxt = document.getElementById(`light${i}_pwm_txt`);
|
||||||
|
if (pwmElement) {
|
||||||
|
const url = `http://{{IP_ADDRESS}}/state?light=${lightID}`;
|
||||||
|
fetch(url).then(response => response.json()).then(data => {
|
||||||
|
const pwmValue = ((Math.round((data.curpwm - ((data.curpwm >= {{PWM_MIN}}) ? {{PWM_MIN}} : 0)) / {{PWM_MAX}} * 10000) / 100).toFixed(2));
|
||||||
|
pwmElement.innerText = pwmValue.toString();
|
||||||
|
pwmElement.value = pwmValue;
|
||||||
|
pwmElementTxt.innerText = pwmValue.toString();
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatePWMValues();
|
||||||
|
setInterval(updatePWMValues, 5000);
|
||||||
|
var links = document.querySelectorAll('[id^="on"][id$="_off"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
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.send();
|
||||||
|
updateLightState();
|
||||||
|
this.classList.add('pure-button-primary');
|
||||||
|
document.getElementById('on'+id+'_on').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var links = document.querySelectorAll('[id^="on"][id$="_on"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
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.send();
|
||||||
|
updateLightState();
|
||||||
|
this.classList.add('pure-button-primary');
|
||||||
|
document.getElementById('on'+id+'_off').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
function createTable() {
|
||||||
|
var table = document.createElement("table");
|
||||||
|
table.border = "1";
|
||||||
|
var headerRow = document.createElement("tr");
|
||||||
|
var headers = ["Hour", "Minute", "Ch1", "Ch2", "Ch3", "Ch4"];
|
||||||
|
headers.forEach(header => {
|
||||||
|
var th = document.createElement("th");
|
||||||
|
th.innerHTML = header;
|
||||||
|
headerRow.appendChild(th);
|
||||||
|
});
|
||||||
|
table.appendChild(headerRow);
|
||||||
|
for (var i = 1; i <= 10; i++) {
|
||||||
|
var tr = document.createElement("tr");
|
||||||
|
var tdHour = createSelectCell(23, 0);
|
||||||
|
tdHour.id = "hour" + i;
|
||||||
|
tr.appendChild(tdHour);
|
||||||
|
var tdMinute = createSelectCell(59, 0);
|
||||||
|
tdMinute.id = "minute" + i;
|
||||||
|
tr.appendChild(tdMinute);
|
||||||
|
var tdCh1 = createSelectCell(100, 0);
|
||||||
|
tdCh1.id = "ch1_" + i;
|
||||||
|
tr.appendChild(tdCh1);
|
||||||
|
var tdCh2 = createSelectCell(100, 0);
|
||||||
|
tdCh2.id = "ch2_" + i;
|
||||||
|
tr.appendChild(tdCh2);
|
||||||
|
var tdCh3 = createSelectCell(100, 0);
|
||||||
|
tdCh3.id = "ch3_" + i;
|
||||||
|
tr.appendChild(tdCh3);
|
||||||
|
var tdCh4 = createSelectCell(100, 0);
|
||||||
|
tdCh4.id = "ch4_" + i;
|
||||||
|
tr.appendChild(tdCh4);
|
||||||
|
table.appendChild(tr);
|
||||||
|
}
|
||||||
|
var container = document.getElementById("table-container");
|
||||||
|
container.innerHTML = "";
|
||||||
|
container.classList.add("pure-form");
|
||||||
|
container.appendChild(table);
|
||||||
|
}
|
||||||
|
function createSelectCell(max, value) {
|
||||||
|
var select = document.createElement("select");
|
||||||
|
for (var i = 0; i <= max; i++) {
|
||||||
|
var option = document.createElement("option");
|
||||||
|
option.value = i;
|
||||||
|
option.text = i;
|
||||||
|
select.appendChild(option);
|
||||||
|
}
|
||||||
|
select.value = value;
|
||||||
|
var row = document.createElement("td");
|
||||||
|
row.appendChild(select);
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
function fillTableFromJson() {
|
||||||
|
fetch('http://{{IP_ADDRESS}}/tc_data_blocks_read')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
var tcdata = data.tcdata;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function createJsonFromTable() {
|
||||||
|
var tableRows = document.querySelectorAll("table tr");
|
||||||
|
var tcdata = [];
|
||||||
|
for (var i = 1; i <= 10; i++) {
|
||||||
|
var row = document.getElementById("hour" + i).parentNode;
|
||||||
|
var hour = parseInt(row.cells[0].childNodes[0].value);
|
||||||
|
var min = parseInt(row.cells[1].childNodes[0].value);
|
||||||
|
var ch1 = Math.round(parseInt(row.cells[2].childNodes[0].value) * 2.55);
|
||||||
|
var ch2 = Math.round(parseInt(row.cells[3].childNodes[0].value) * 2.55);
|
||||||
|
var ch3 = Math.round(parseInt(row.cells[4].childNodes[0].value) * 2.55);
|
||||||
|
var ch4 = Math.round(parseInt(row.cells[5].childNodes[0].value) * 2.55);
|
||||||
|
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) {
|
||||||
|
console.log('Data successfully sent to server!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
|
@ -1,253 +1,19 @@
|
||||||
<!-- bottom -->
|
<!-- bottom -->
|
||||||
<script>
|
<div id="tab-tde" class=""> <!-- timing editor -->
|
||||||
var tabMain = document.getElementById("tab-lights");
|
<div id="tc-edit-container" class="">
|
||||||
var tabConfig = document.getElementById("tab-config");
|
<br>
|
||||||
var tabTDE = document.getElementById("tab-tde");
|
<label>
|
||||||
|
<strong>Timming control data editor</strong>
|
||||||
var amain = document.getElementById("tab-a-lights");
|
</label>
|
||||||
var acfg = document.getElementById("tab-a-config");
|
<br>
|
||||||
var atde = document.getElementById("tab-a-tde");
|
<div id="table-container">
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
document.getElementById("tab-a-lights").addEventListener("click", function() {
|
<a href="#" class="pure-button pure-button-primary" onclick="sendDataToServer();">save</a>
|
||||||
tabMain.classList.add("visible");
|
</div>
|
||||||
tabConfig.classList.remove("visible");
|
</div> <!-- end of tab-tde -->
|
||||||
tabTDE.classList.remove("visible");
|
<script src="http://{{IP_ADDRESS}}/js_bottom">
|
||||||
|
|
||||||
amain.classList.add("pure-button-primary");
|
|
||||||
acfg.classList.remove("pure-button-primary");
|
|
||||||
atde.classList.remove("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("tab-a-config").addEventListener("click", function() {
|
|
||||||
tabMain.classList.remove("visible");
|
|
||||||
tabConfig.classList.add("visible");
|
|
||||||
tabTDE.classList.remove("visible");
|
|
||||||
|
|
||||||
amain.classList.remove("pure-button-primary");
|
|
||||||
acfg.classList.add("pure-button-primary");
|
|
||||||
atde.classList.remove("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("tab-a-tde").addEventListener("click", function() {
|
|
||||||
tabMain.classList.remove("visible");
|
|
||||||
tabConfig.classList.remove("visible");
|
|
||||||
tabTDE.classList.add("visible");
|
|
||||||
|
|
||||||
amain.classList.remove("pure-button-primary");
|
|
||||||
acfg.classList.remove("pure-button-primary");
|
|
||||||
atde.classList.add("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
function loadGraphData() {
|
|
||||||
console.log('----> generate graph <----');
|
|
||||||
$.getJSON('/tc_data_blocks', function(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']);
|
|
||||||
channel2.push(data['tcdata'][i]['ch2']);
|
|
||||||
channel3.push(data['tcdata'][i]['ch3']);
|
|
||||||
channel4.push(data['tcdata'][i]['ch4']);
|
|
||||||
}
|
|
||||||
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.");
|
|
||||||
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, 255],
|
|
||||||
},
|
|
||||||
shapes: [{
|
|
||||||
type: 'line',
|
|
||||||
x0: index,
|
|
||||||
y0: 0,
|
|
||||||
x1: index,
|
|
||||||
y1: 255,
|
|
||||||
line: {
|
|
||||||
color: 'lightgrey',
|
|
||||||
width: 3,
|
|
||||||
dash: 'dot'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
Plotly.newPlot('plot_chart', [trace1, trace2, trace3, trace4], layout);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setInterval(loadGraphData, 10000);
|
|
||||||
loadGraphData();
|
|
||||||
|
|
||||||
function updateLightState() {
|
|
||||||
console.log('----> setting bri and power switch <----');
|
|
||||||
for (let i = 1; i <= {{LIGHT_COUNT}}; i++) {
|
|
||||||
const lightURL = `http://{{IP_ADDRESS}}/state?light=${i}`;
|
|
||||||
fetch(lightURL).then(response => response.json()).then(data => {
|
|
||||||
const briSlider = document.getElementById(`bri${i - 1}`);
|
|
||||||
const briSliderVal = document.getElementById(`bri${i - 1}_val`);
|
|
||||||
const onLinkOn = document.getElementById(`on${i - 1}_on`);
|
|
||||||
const onLinkOff = document.getElementById(`on${i - 1}_off`);
|
|
||||||
briSlider.value = data.bri;
|
|
||||||
briSliderVal.innerHTML = (Math.round((data.bri * 100.0 / 255.0) * 100) / 100).toFixed(2);
|
|
||||||
console.log('data.on ' + i + ' = ' + data.on);
|
|
||||||
if (data.on == true) {
|
|
||||||
onLinkOn.classList.add('pure-button-primary');
|
|
||||||
onLinkOff.classList.remove('pure-button-primary');
|
|
||||||
} else {
|
|
||||||
onLinkOn.classList.remove('pure-button-primary');
|
|
||||||
onLinkOff.classList.add('pure-button-primary');
|
|
||||||
}
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setInterval(updateLightState, 10000);
|
|
||||||
updateLightState();
|
|
||||||
|
|
||||||
function updatePWMValues() {
|
|
||||||
console.log('----> setting pwm data <----');
|
|
||||||
for (let i = 0; i < {{LIGHT_COUNT}}; i++) {
|
|
||||||
const lightID = i + 1;
|
|
||||||
const pwmElement = document.getElementById(`light${i}_pwm`);
|
|
||||||
const pwmElementTxt = document.getElementById(`light${i}_pwm_txt`);
|
|
||||||
if (pwmElement) {
|
|
||||||
const url = `http://{{IP_ADDRESS}}/state?light=${lightID}`;
|
|
||||||
fetch(url).then(response => response.json()).then(data => {
|
|
||||||
const pwmValue = ((Math.round((data.curpwm - ((data.curpwm >= {{PWM_MIN}}) ? {{PWM_MIN}} : 0)) / {{PWM_MAX}} * 10000) / 100).toFixed(2));
|
|
||||||
console.log('curpwm[' + i + '] = ' + data.curpwm + ' = ' + pwmValue);
|
|
||||||
pwmElement.innerText = pwmValue.toString();
|
|
||||||
pwmElement.value = pwmValue;
|
|
||||||
pwmElementTxt.innerText = pwmValue.toString();
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatePWMValues();
|
|
||||||
setInterval(updatePWMValues, 5000);
|
|
||||||
|
|
||||||
|
|
||||||
var links = document.querySelectorAll('[id^="on"][id$="_off"]');
|
|
||||||
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
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.send();
|
|
||||||
updateLightState();
|
|
||||||
this.classList.add('pure-button-primary');
|
|
||||||
document.getElementById('on'+id+'_on').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var links = document.querySelectorAll('[id^="on"][id$="_on"]');
|
|
||||||
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
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.send();
|
|
||||||
updateLightState();
|
|
||||||
this.classList.add('pure-button-primary');
|
|
||||||
document.getElementById('on'+id+'_off').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -6,7 +6,3 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div><!-- end of lights control tab -->
|
</div><!-- end of lights control tab -->
|
||||||
|
|
||||||
<div id="tab-tde"> <!-- timing editor -->
|
|
||||||
Not implemented yet.
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -9,22 +9,7 @@
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css">
|
<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<style>
|
<link rel="stylesheet" href="http://{{IP_ADDRESS}}/css">
|
||||||
#tab-lights, #tab-config, #tab-tde {
|
|
||||||
display: none;
|
|
||||||
background-color: #ffffff;
|
|
||||||
color: black;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
#tab-lights.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#tab-config.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#tab-tde.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -57,52 +42,9 @@ display: block;
|
||||||
<input id="transition" name="transition" type="text" placeholder="10" value="{{TRANSITION_TIME}}">
|
<input id="transition" name="transition" type="text" placeholder="10" value="{{TRANSITION_TIME}}">
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<script>
|
<script src="http://{{IP_ADDRESS}}/js_top">
|
||||||
var links = document.querySelectorAll('[id^="tc_on"]');
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true);
|
|
||||||
xhr.send();
|
|
||||||
console.log('tc=true call');
|
|
||||||
document.getElementById('tc_on').classList.add('pure-button-primary');
|
|
||||||
document.getElementById('tc_off').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var links = document.querySelectorAll('[id^="tc_off"]');
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true);
|
|
||||||
xhr.send();
|
|
||||||
console.log('tc=false call');
|
|
||||||
document.getElementById('tc_off').classList.add('pure-button-primary');
|
|
||||||
document.getElementById('tc_on').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let timeoutId;
|
|
||||||
function sendSliderValue(x) {
|
|
||||||
x = x - 1;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
var value = document.getElementById(`bri${x}`).value;
|
|
||||||
var url = `http://{{IP_ADDRESS}}/?bri${x}=${value}`;
|
|
||||||
fetch(url).then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
console.log(`Sent slider value ${value} to ${url}`);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(`Error sending slider value to ${url}: ${error}`);
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<br>
|
<br>
|
||||||
<table border=0>
|
<table border=0>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
|
43
firmware/data/style.css
Normal file
43
firmware/data/style.css
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#tab-lights, #tab-config, #tab-tde {
|
||||||
|
display: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: black;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#tab-lights.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#tab-config.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#tab-tde.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.pure-table td {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.pure-form input[type="number"] {
|
||||||
|
width: 60px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.pure-form select {
|
||||||
|
width: 80px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.pure-button {
|
||||||
|
background-color: #5a5a5a;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.pure-button:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
38
firmware/data/top.js
Normal file
38
firmware/data/top.js
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
var links = document.querySelectorAll('[id^="tc_on"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true);
|
||||||
|
xhr.send();
|
||||||
|
document.getElementById('tc_on').classList.add('pure-button-primary');
|
||||||
|
document.getElementById('tc_off').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var links = document.querySelectorAll('[id^="tc_off"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true);
|
||||||
|
xhr.send();
|
||||||
|
document.getElementById('tc_off').classList.add('pure-button-primary');
|
||||||
|
document.getElementById('tc_on').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
let timeoutId;
|
||||||
|
function sendSliderValue(x) {
|
||||||
|
x = x - 1;
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
var value = document.getElementById(`bri${x}`).value;
|
||||||
|
var url = `http://{{IP_ADDRESS}}/?bri${x}=${value}`;
|
||||||
|
fetch(url).then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`Error sending slider value to ${url}: ${error}`);
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
|
@ -472,13 +472,39 @@ void init_webserver()
|
||||||
server.send(200, "text/plain", output);
|
server.send(200, "text/plain", output);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.on("/tc_data_blocks", []()
|
server.on("/tc_data_blocks_read", []()
|
||||||
{
|
{
|
||||||
String output = tc_getJsonData();
|
String output = tc_getJsonData();
|
||||||
|
|
||||||
server.send(200, "application/json", output);
|
server.send(200, "application/json", output);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.on("/tc_data_blocks_store", []()
|
||||||
|
{
|
||||||
|
if (server.hasArg("data"))
|
||||||
|
{
|
||||||
|
String jsonData = server.arg("data");
|
||||||
|
Serial.println("Received: " + jsonData);
|
||||||
|
tc_jsonDataBlocksToEEPROM(jsonData);
|
||||||
|
server.send(200, "text/html", "tcdata saved");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/js_top", []()
|
||||||
|
{
|
||||||
|
server.send(200, "text/html", replacePlaceholder(loadSPIFFSFile("/top.js")));
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/js_bottom", []()
|
||||||
|
{
|
||||||
|
server.send(200, "text/html", replacePlaceholder(loadSPIFFSFile("/bottom.js")));
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on("/css", []()
|
||||||
|
{
|
||||||
|
server.send(200, "text/css", loadSPIFFSFile("/style.css"));
|
||||||
|
});
|
||||||
|
|
||||||
server.on("/", []()
|
server.on("/", []()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -703,6 +729,11 @@ String genConfigHTML()
|
||||||
return replacePlaceholder(getConfigHTML());
|
return replacePlaceholder(getConfigHTML());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String genTCEditHTML()
|
||||||
|
{
|
||||||
|
return replacePlaceholder(getTCDataEditHTML());
|
||||||
|
}
|
||||||
|
|
||||||
String genLightControlHTML()
|
String genLightControlHTML()
|
||||||
{
|
{
|
||||||
String http_content = "";
|
String http_content = "";
|
||||||
|
@ -868,6 +899,14 @@ String getConfigHTML()
|
||||||
|
|
||||||
//********************************//
|
//********************************//
|
||||||
|
|
||||||
|
String getTCDataEditHTML()
|
||||||
|
{
|
||||||
|
// load file
|
||||||
|
return loadSPIFFSFile("/tc_data_edit.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
//********************************//
|
||||||
|
|
||||||
String getLightControlHTML()
|
String getLightControlHTML()
|
||||||
{
|
{
|
||||||
// load file
|
// load file
|
||||||
|
|
401
firmware/html/bottom.js
Normal file
401
firmware/html/bottom.js
Normal file
|
@ -0,0 +1,401 @@
|
||||||
|
function addTabListener() {
|
||||||
|
//console.log("Try to add tab listener");
|
||||||
|
try {
|
||||||
|
var tabMain = document.getElementById("tab-lights");
|
||||||
|
var tabConfig = document.getElementById("tab-config");
|
||||||
|
var tabTDE = document.getElementById("tab-tde");
|
||||||
|
|
||||||
|
var amain = document.getElementById("tab-a-lights");
|
||||||
|
var acfg = document.getElementById("tab-a-config");
|
||||||
|
var atde = document.getElementById("tab-a-tde");
|
||||||
|
|
||||||
|
|
||||||
|
amain.addEventListener("click", function() {
|
||||||
|
//console.log("Switch to main lights tab");
|
||||||
|
tabMain.classList.add("visible");
|
||||||
|
tabConfig.classList.remove("visible");
|
||||||
|
tabTDE.classList.remove("visible");
|
||||||
|
|
||||||
|
amain.classList.add("pure-button-primary");
|
||||||
|
acfg.classList.remove("pure-button-primary");
|
||||||
|
atde.classList.remove("pure-button-primary");
|
||||||
|
});
|
||||||
|
|
||||||
|
acfg.addEventListener("click", function() {
|
||||||
|
//console.log("Switch to config tab");
|
||||||
|
tabMain.classList.remove("visible");
|
||||||
|
tabConfig.classList.add("visible");
|
||||||
|
tabTDE.classList.remove("visible");
|
||||||
|
|
||||||
|
amain.classList.remove("pure-button-primary");
|
||||||
|
acfg.classList.add("pure-button-primary");
|
||||||
|
atde.classList.remove("pure-button-primary");
|
||||||
|
});
|
||||||
|
|
||||||
|
atde.addEventListener("click", function() {
|
||||||
|
//console.log("Switch to TDE tab");
|
||||||
|
tabMain.classList.remove("visible");
|
||||||
|
tabConfig.classList.remove("visible");
|
||||||
|
tabTDE.classList.add("visible");
|
||||||
|
|
||||||
|
amain.classList.remove("pure-button-primary");
|
||||||
|
acfg.classList.remove("pure-button-primary");
|
||||||
|
atde.classList.add("pure-button-primary");
|
||||||
|
|
||||||
|
createTable(); // recreate the table on timing data editor tab
|
||||||
|
fillTableFromJson();
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error: load listener of the tab action listener management: " + error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
addTabListener();
|
||||||
|
});
|
||||||
|
|
||||||
|
function loadGraphData() {
|
||||||
|
console.log('----> generate graph <----');
|
||||||
|
$.getJSON('/tc_data_blocks_read', function(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']);
|
||||||
|
channel2.push(data['tcdata'][i]['ch2']);
|
||||||
|
channel3.push(data['tcdata'][i]['ch3']);
|
||||||
|
channel4.push(data['tcdata'][i]['ch4']);
|
||||||
|
}
|
||||||
|
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, 255],
|
||||||
|
},
|
||||||
|
shapes: [{
|
||||||
|
type: 'line',
|
||||||
|
x0: index,
|
||||||
|
y0: 0,
|
||||||
|
x1: index,
|
||||||
|
y1: 255,
|
||||||
|
line: {
|
||||||
|
color: 'lightgrey',
|
||||||
|
width: 3,
|
||||||
|
dash: 'dot'
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
Plotly.newPlot('plot_chart', [trace1, trace2, trace3, trace4], layout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setInterval(loadGraphData, 10000);
|
||||||
|
loadGraphData();
|
||||||
|
|
||||||
|
function updateLightState() {
|
||||||
|
console.log('----> setting bri and power switch <----');
|
||||||
|
for (let i = 1; i <= {{LIGHT_COUNT}}; i++) {
|
||||||
|
const lightURL = `http://{{IP_ADDRESS}}/state?light=${i}`;
|
||||||
|
fetch(lightURL).then(response => response.json()).then(data => {
|
||||||
|
const briSlider = document.getElementById(`bri${i - 1}`);
|
||||||
|
const briSliderVal = document.getElementById(`bri${i - 1}_val`);
|
||||||
|
const onLinkOn = document.getElementById(`on${i - 1}_on`);
|
||||||
|
const onLinkOff = document.getElementById(`on${i - 1}_off`);
|
||||||
|
briSlider.value = data.bri;
|
||||||
|
briSliderVal.innerHTML = (Math.round((data.bri * 100.0 / 255.0) * 100) / 100).toFixed(2);
|
||||||
|
//console.log('data.on ' + i + ' = ' + data.on);
|
||||||
|
if (data.on == true) {
|
||||||
|
onLinkOn.classList.add('pure-button-primary');
|
||||||
|
onLinkOff.classList.remove('pure-button-primary');
|
||||||
|
} else {
|
||||||
|
onLinkOn.classList.remove('pure-button-primary');
|
||||||
|
onLinkOff.classList.add('pure-button-primary');
|
||||||
|
}
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setInterval(updateLightState, 10000);
|
||||||
|
updateLightState();
|
||||||
|
|
||||||
|
function updatePWMValues() {
|
||||||
|
console.log('----> setting pwm data <----');
|
||||||
|
for (let i = 0; i < {{LIGHT_COUNT}}; i++) {
|
||||||
|
const lightID = i + 1;
|
||||||
|
const pwmElement = document.getElementById(`light${i}_pwm`);
|
||||||
|
const pwmElementTxt = document.getElementById(`light${i}_pwm_txt`);
|
||||||
|
if (pwmElement) {
|
||||||
|
const url = `http://{{IP_ADDRESS}}/state?light=${lightID}`;
|
||||||
|
fetch(url).then(response => response.json()).then(data => {
|
||||||
|
const pwmValue = ((Math.round((data.curpwm - ((data.curpwm >= {{PWM_MIN}}) ? {{PWM_MIN}} : 0)) / {{PWM_MAX}} * 10000) / 100).toFixed(2));
|
||||||
|
//console.log('curpwm[' + i + '] = ' + data.curpwm + ' = ' + pwmValue);
|
||||||
|
pwmElement.innerText = pwmValue.toString();
|
||||||
|
pwmElement.value = pwmValue;
|
||||||
|
pwmElementTxt.innerText = pwmValue.toString();
|
||||||
|
}).catch(error => console.error(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatePWMValues();
|
||||||
|
setInterval(updatePWMValues, 5000);
|
||||||
|
|
||||||
|
// Suche nach allen Links auf der Seite mit IDs von on0_off bis on3_off
|
||||||
|
var links = document.querySelectorAll('[id^="on"][id$="_off"]');
|
||||||
|
// Füge einen Klick-Listener zu jedem Link hinzu
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
// Verhindere, dass der Link die Seite neu lädt
|
||||||
|
event.preventDefault();
|
||||||
|
// Extrahiere die Zahl aus der ID des Links
|
||||||
|
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);
|
||||||
|
// Sende die Anfrage im Hintergrund
|
||||||
|
xhr.send();
|
||||||
|
updateLightState();
|
||||||
|
this.classList.add('pure-button-primary');
|
||||||
|
document.getElementById('on'+id+'_on').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Suche nach allen Links auf der Seite mit IDs von on0_off bis on3_off
|
||||||
|
var links = document.querySelectorAll('[id^="on"][id$="_on"]');
|
||||||
|
// Füge einen Klick-Listener zu jedem Link hinzu
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
// Verhindere, dass der Link die Seite neu lädt
|
||||||
|
event.preventDefault();
|
||||||
|
// Extrahiere die Zahl aus der ID des Links
|
||||||
|
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);
|
||||||
|
// Sende die Anfrage im Hintergrund
|
||||||
|
xhr.send();
|
||||||
|
updateLightState();
|
||||||
|
this.classList.add('pure-button-primary');
|
||||||
|
document.getElementById('on'+id+'_off').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function createTable() {
|
||||||
|
// Erstelle eine Tabelle
|
||||||
|
var table = document.createElement("table");
|
||||||
|
table.border = "1";
|
||||||
|
|
||||||
|
// Erstelle eine Kopfzeile
|
||||||
|
var headerRow = document.createElement("tr");
|
||||||
|
|
||||||
|
// Füge die Spaltenüberschriften hinzu
|
||||||
|
var headers = ["Hour", "Minute", "Ch1", "Ch2", "Ch3", "Ch4"];
|
||||||
|
headers.forEach(header => {
|
||||||
|
var th = document.createElement("th");
|
||||||
|
th.innerHTML = header;
|
||||||
|
headerRow.appendChild(th);
|
||||||
|
});
|
||||||
|
table.appendChild(headerRow);
|
||||||
|
|
||||||
|
// Erstelle Zeilen mit Zellen für jedes Element
|
||||||
|
for (var i = 1; i <= 10; i++) {
|
||||||
|
var tr = document.createElement("tr");
|
||||||
|
|
||||||
|
// Stunde
|
||||||
|
var tdHour = createSelectCell(23, 0);
|
||||||
|
tdHour.id = "hour" + i;
|
||||||
|
tr.appendChild(tdHour);
|
||||||
|
|
||||||
|
// Minute
|
||||||
|
var tdMinute = createSelectCell(59, 0);
|
||||||
|
tdMinute.id = "minute" + i;
|
||||||
|
tr.appendChild(tdMinute);
|
||||||
|
|
||||||
|
// ch1
|
||||||
|
var tdCh1 = createSelectCell(100, 0);
|
||||||
|
tdCh1.id = "ch1_" + i;
|
||||||
|
tr.appendChild(tdCh1);
|
||||||
|
|
||||||
|
// ch2
|
||||||
|
var tdCh2 = createSelectCell(100, 0);
|
||||||
|
tdCh2.id = "ch2_" + i;
|
||||||
|
tr.appendChild(tdCh2);
|
||||||
|
|
||||||
|
// ch3
|
||||||
|
var tdCh3 = createSelectCell(100, 0);
|
||||||
|
tdCh3.id = "ch3_" + i;
|
||||||
|
tr.appendChild(tdCh3);
|
||||||
|
|
||||||
|
// ch4
|
||||||
|
var tdCh4 = createSelectCell(100, 0);
|
||||||
|
tdCh4.id = "ch4_" + i;
|
||||||
|
tr.appendChild(tdCh4);
|
||||||
|
|
||||||
|
table.appendChild(tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
var container = document.getElementById("table-container");
|
||||||
|
container.innerHTML = "";
|
||||||
|
container.classList.add("pure-form");
|
||||||
|
container.appendChild(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSelectCell(max, value) {
|
||||||
|
// Erstelle ein neues select-Element
|
||||||
|
var select = document.createElement("select");
|
||||||
|
|
||||||
|
// Füge Optionen hinzu
|
||||||
|
for (var i = 0; i <= max; i++) {
|
||||||
|
var option = document.createElement("option");
|
||||||
|
option.value = i;
|
||||||
|
option.text = i;
|
||||||
|
select.appendChild(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wähle die Option aus, die dem übergebenen Wert entspricht
|
||||||
|
select.value = value;
|
||||||
|
|
||||||
|
// Erstelle eine neue Zellenreihe und -zelle
|
||||||
|
var row = document.createElement("td");
|
||||||
|
row.appendChild(select);
|
||||||
|
|
||||||
|
// Gib die Zelle zurück
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillTableFromJson() {
|
||||||
|
// Lade JSON-Daten
|
||||||
|
fetch('http://{{IP_ADDRESS}}/tc_data_blocks_read')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
// Fülle die Tabelle mit Daten
|
||||||
|
var tcdata = data.tcdata;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function createJsonFromTable() {
|
||||||
|
var tableRows = document.querySelectorAll("table tr");
|
||||||
|
var tcdata = [];
|
||||||
|
for (var i = 1; i <= 10; i++) {
|
||||||
|
|
||||||
|
var row = document.getElementById("hour" + i).parentNode;
|
||||||
|
var hour = parseInt(row.cells[0].childNodes[0].value);
|
||||||
|
var min = parseInt(row.cells[1].childNodes[0].value);
|
||||||
|
var ch1 = Math.round(parseInt(row.cells[2].childNodes[0].value) * 2.55);
|
||||||
|
var ch2 = Math.round(parseInt(row.cells[3].childNodes[0].value) * 2.55);
|
||||||
|
var ch3 = Math.round(parseInt(row.cells[4].childNodes[0].value) * 2.55);
|
||||||
|
var ch4 = Math.round(parseInt(row.cells[5].childNodes[0].value) * 2.55);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
console.log('Data successfully sent to server!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
|
@ -1,251 +1,19 @@
|
||||||
<!-- bottom -->
|
<!-- bottom -->
|
||||||
<script>
|
<div id="tab-tde" class=""> <!-- timing editor -->
|
||||||
var tabMain = document.getElementById("tab-lights");
|
<div id="tc-edit-container" class="">
|
||||||
var tabConfig = document.getElementById("tab-config");
|
<br>
|
||||||
var tabTDE = document.getElementById("tab-tde");
|
<label>
|
||||||
|
<strong>Timming control data editor</strong>
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<div id="table-container">
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<a href="#" class="pure-button pure-button-primary" onclick="sendDataToServer();">save</a>
|
||||||
|
</div>
|
||||||
|
</div> <!-- end of tab-tde -->
|
||||||
|
|
||||||
var amain = document.getElementById("tab-a-lights");
|
<script src="http://{{IP_ADDRESS}}/js_bottom">
|
||||||
var acfg = document.getElementById("tab-a-config");
|
|
||||||
var atde = document.getElementById("tab-a-tde");
|
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("tab-a-lights").addEventListener("click", function() {
|
|
||||||
tabMain.classList.add("visible");
|
|
||||||
tabConfig.classList.remove("visible");
|
|
||||||
tabTDE.classList.remove("visible");
|
|
||||||
|
|
||||||
amain.classList.add("pure-button-primary");
|
|
||||||
acfg.classList.remove("pure-button-primary");
|
|
||||||
atde.classList.remove("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("tab-a-config").addEventListener("click", function() {
|
|
||||||
tabMain.classList.remove("visible");
|
|
||||||
tabConfig.classList.add("visible");
|
|
||||||
tabTDE.classList.remove("visible");
|
|
||||||
|
|
||||||
amain.classList.remove("pure-button-primary");
|
|
||||||
acfg.classList.add("pure-button-primary");
|
|
||||||
atde.classList.remove("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("tab-a-tde").addEventListener("click", function() {
|
|
||||||
tabMain.classList.remove("visible");
|
|
||||||
tabConfig.classList.remove("visible");
|
|
||||||
tabTDE.classList.add("visible");
|
|
||||||
|
|
||||||
amain.classList.remove("pure-button-primary");
|
|
||||||
acfg.classList.remove("pure-button-primary");
|
|
||||||
atde.classList.add("pure-button-primary");
|
|
||||||
});
|
|
||||||
|
|
||||||
function loadGraphData() {
|
|
||||||
console.log('----> generate graph <----');
|
|
||||||
$.getJSON('/tc_data_blocks', function(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']);
|
|
||||||
channel2.push(data['tcdata'][i]['ch2']);
|
|
||||||
channel3.push(data['tcdata'][i]['ch3']);
|
|
||||||
channel4.push(data['tcdata'][i]['ch4']);
|
|
||||||
}
|
|
||||||
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.");
|
|
||||||
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, 255],
|
|
||||||
},
|
|
||||||
shapes: [{
|
|
||||||
type: 'line',
|
|
||||||
x0: index,
|
|
||||||
y0: 0,
|
|
||||||
x1: index,
|
|
||||||
y1: 255,
|
|
||||||
line: {
|
|
||||||
color: 'lightgrey',
|
|
||||||
width: 3,
|
|
||||||
dash: 'dot'
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
Plotly.newPlot('plot_chart', [trace1, trace2, trace3, trace4], layout);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setInterval(loadGraphData, 10000);
|
|
||||||
loadGraphData();
|
|
||||||
|
|
||||||
function updateLightState() {
|
|
||||||
console.log('----> setting bri and power switch <----');
|
|
||||||
for (let i = 1; i <= {{LIGHT_COUNT}}; i++) {
|
|
||||||
const lightURL = `http://{{IP_ADDRESS}}/state?light=${i}`;
|
|
||||||
fetch(lightURL).then(response => response.json()).then(data => {
|
|
||||||
const briSlider = document.getElementById(`bri${i - 1}`);
|
|
||||||
const briSliderVal = document.getElementById(`bri${i - 1}_val`);
|
|
||||||
const onLinkOn = document.getElementById(`on${i - 1}_on`);
|
|
||||||
const onLinkOff = document.getElementById(`on${i - 1}_off`);
|
|
||||||
briSlider.value = data.bri;
|
|
||||||
briSliderVal.innerHTML = (Math.round((data.bri * 100.0 / 255.0) * 100) / 100).toFixed(2);
|
|
||||||
console.log('data.on ' + i + ' = ' + data.on);
|
|
||||||
if (data.on == true) {
|
|
||||||
onLinkOn.classList.add('pure-button-primary');
|
|
||||||
onLinkOff.classList.remove('pure-button-primary');
|
|
||||||
} else {
|
|
||||||
onLinkOn.classList.remove('pure-button-primary');
|
|
||||||
onLinkOff.classList.add('pure-button-primary');
|
|
||||||
}
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setInterval(updateLightState, 10000);
|
|
||||||
updateLightState();
|
|
||||||
|
|
||||||
function updatePWMValues() {
|
|
||||||
console.log('----> setting pwm data <----');
|
|
||||||
for (let i = 0; i < {{LIGHT_COUNT}}; i++) {
|
|
||||||
const lightID = i + 1;
|
|
||||||
const pwmElement = document.getElementById(`light${i}_pwm`);
|
|
||||||
const pwmElementTxt = document.getElementById(`light${i}_pwm_txt`);
|
|
||||||
if (pwmElement) {
|
|
||||||
const url = `http://{{IP_ADDRESS}}/state?light=${lightID}`;
|
|
||||||
fetch(url).then(response => response.json()).then(data => {
|
|
||||||
const pwmValue = ((Math.round((data.curpwm - ((data.curpwm >= {{PWM_MIN}}) ? {{PWM_MIN}} : 0)) / {{PWM_MAX}} * 10000) / 100).toFixed(2));
|
|
||||||
console.log('curpwm[' + i + '] = ' + data.curpwm + ' = ' + pwmValue);
|
|
||||||
pwmElement.innerText = pwmValue.toString();
|
|
||||||
pwmElement.value = pwmValue;
|
|
||||||
pwmElementTxt.innerText = pwmValue.toString();
|
|
||||||
}).catch(error => console.error(error));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatePWMValues();
|
|
||||||
setInterval(updatePWMValues, 5000);
|
|
||||||
|
|
||||||
// Suche nach allen Links auf der Seite mit IDs von on0_off bis on3_off
|
|
||||||
var links = document.querySelectorAll('[id^="on"][id$="_off"]');
|
|
||||||
// Füge einen Klick-Listener zu jedem Link hinzu
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
// Verhindere, dass der Link die Seite neu lädt
|
|
||||||
event.preventDefault();
|
|
||||||
// Extrahiere die Zahl aus der ID des Links
|
|
||||||
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);
|
|
||||||
// Sende die Anfrage im Hintergrund
|
|
||||||
xhr.send();
|
|
||||||
updateLightState();
|
|
||||||
this.classList.add('pure-button-primary');
|
|
||||||
document.getElementById('on'+id+'_on').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// Suche nach allen Links auf der Seite mit IDs von on0_off bis on3_off
|
|
||||||
var links = document.querySelectorAll('[id^="on"][id$="_on"]');
|
|
||||||
// Füge einen Klick-Listener zu jedem Link hinzu
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
// Verhindere, dass der Link die Seite neu lädt
|
|
||||||
event.preventDefault();
|
|
||||||
// Extrahiere die Zahl aus der ID des Links
|
|
||||||
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);
|
|
||||||
// Sende die Anfrage im Hintergrund
|
|
||||||
xhr.send();
|
|
||||||
updateLightState();
|
|
||||||
this.classList.add('pure-button-primary');
|
|
||||||
document.getElementById('on'+id+'_off').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,3 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div><!-- end of lights control tab -->
|
</div><!-- end of lights control tab -->
|
||||||
|
|
||||||
<div id="tab-tde"> <!-- timing editor -->
|
|
||||||
Not implemented yet.
|
|
||||||
</div>
|
|
||||||
|
|
|
@ -9,22 +9,7 @@
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css">
|
<link rel="stylesheet" href="https://unpkg.com/purecss@0.6.2/build/pure-min.css">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<style>
|
<link rel="stylesheet" href="http://{{IP_ADDRESS}}/css">
|
||||||
#tab-lights, #tab-config, #tab-tde {
|
|
||||||
display: none;
|
|
||||||
background-color: #ffffff;
|
|
||||||
color: black;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
#tab-lights.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#tab-config.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
#tab-tde.visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -57,49 +42,7 @@
|
||||||
<input id="transition" name="transition" type="text" placeholder="10" value="{{TRANSITION_TIME}}">
|
<input id="transition" name="transition" type="text" placeholder="10" value="{{TRANSITION_TIME}}">
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<script>
|
<script src="http://{{IP_ADDRESS}}/js_top">
|
||||||
var links = document.querySelectorAll('[id^="tc_on"]');
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true);
|
|
||||||
xhr.send();
|
|
||||||
console.log('tc=true call');
|
|
||||||
document.getElementById('tc_on').classList.add('pure-button-primary');
|
|
||||||
document.getElementById('tc_off').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
var links = document.querySelectorAll('[id^="tc_off"]');
|
|
||||||
links.forEach(function(link) {
|
|
||||||
link.addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true);
|
|
||||||
xhr.send();
|
|
||||||
console.log('tc=false call');
|
|
||||||
document.getElementById('tc_off').classList.add('pure-button-primary');
|
|
||||||
document.getElementById('tc_on').classList.remove('pure-button-primary');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
let timeoutId;
|
|
||||||
function sendSliderValue(x) {
|
|
||||||
x = x - 1;
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
var value = document.getElementById(`bri${x}`).value;
|
|
||||||
var url = `http://{{IP_ADDRESS}}/?bri${x}=${value}`;
|
|
||||||
fetch(url).then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`HTTP error! status: ${response.status}`);
|
|
||||||
}
|
|
||||||
console.log(`Sent slider value ${value} to ${url}`);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(`Error sending slider value to ${url}: ${error}`);
|
|
||||||
});
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<br>
|
<br>
|
||||||
<table border=0>
|
<table border=0>
|
||||||
|
|
43
firmware/html/style.css
Normal file
43
firmware/html/style.css
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#tab-lights, #tab-config, #tab-tde {
|
||||||
|
display: none;
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: black;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#tab-lights.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#tab-config.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#tab-tde.visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.pure-table td {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
.pure-form input[type="number"] {
|
||||||
|
width: 60px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.pure-form select {
|
||||||
|
width: 80px;
|
||||||
|
height: 26px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.pure-button {
|
||||||
|
background-color: #5a5a5a;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.pure-button:hover {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
42
firmware/html/top.js
Normal file
42
firmware/html/top.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
var links = document.querySelectorAll('[id^="tc_on"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=true', true);
|
||||||
|
xhr.send();
|
||||||
|
//console.log('tc=true call');
|
||||||
|
document.getElementById('tc_on').classList.add('pure-button-primary');
|
||||||
|
document.getElementById('tc_off').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var links = document.querySelectorAll('[id^="tc_off"]');
|
||||||
|
links.forEach(function(link) {
|
||||||
|
link.addEventListener('click', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'http://{{IP_ADDRESS}}/?tc=false', true);
|
||||||
|
xhr.send();
|
||||||
|
//console.log('tc=false call');
|
||||||
|
document.getElementById('tc_off').classList.add('pure-button-primary');
|
||||||
|
document.getElementById('tc_on').classList.remove('pure-button-primary');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
let timeoutId;
|
||||||
|
function sendSliderValue(x) {
|
||||||
|
x = x - 1;
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
var value = document.getElementById(`bri${x}`).value;
|
||||||
|
var url = `http://{{IP_ADDRESS}}/?bri${x}=${value}`;
|
||||||
|
fetch(url).then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
//console.log(`Sent slider value ${value} to ${url}`);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`Error sending slider value to ${url}: ${error}`);
|
||||||
|
});
|
||||||
|
}, 500);
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ uint8_t example_timer_data_block[] = {
|
||||||
18, 0, 205, 205, 205, 205, // 4: 80% all for 5 hours
|
18, 0, 205, 205, 205, 205, // 4: 80% all for 5 hours
|
||||||
19, 0, 50, 50, 50, 50, // 5: 20% all
|
19, 0, 50, 50, 50, 50, // 5: 20% all
|
||||||
19, 30, 50, 0, 50, 0, // 6: 20% all blues
|
19, 30, 50, 0, 50, 0, // 6: 20% all blues
|
||||||
20, 0, 25, 0, 25, 0, // 9: disabled
|
20, 0, 25, 0, 25, 0, // 9: 10% all blues
|
||||||
20, 30, 25, 0, 0, 0, // 7: 10% ch1 blues
|
20, 30, 25, 0, 0, 0, // 7: 10% ch1 blues
|
||||||
21, 0, 0, 0, 0, 0, // 8: 0% all
|
21, 0, 0, 0, 0, 0, // 8: 0% all
|
||||||
};
|
};
|
||||||
|
@ -180,6 +180,12 @@ void tc_update_main()
|
||||||
|
|
||||||
if (target_data_block >= NUMBER_OF_TIMER_DATA_BLOCKS)
|
if (target_data_block >= NUMBER_OF_TIMER_DATA_BLOCKS)
|
||||||
{
|
{
|
||||||
|
// we are not between two valid data points, do nothing
|
||||||
|
// TODO check if setting all lights to false is correct here
|
||||||
|
for (uint8_t i = 0; i < LIGHTS_COUNT; i++)
|
||||||
|
{
|
||||||
|
light_state[i] = false;
|
||||||
|
}
|
||||||
target_data_block = 255;
|
target_data_block = 255;
|
||||||
current_target_data_block = 255;
|
current_target_data_block = 255;
|
||||||
return;
|
return;
|
||||||
|
@ -371,7 +377,7 @@ bool tc_check_no_data_block()
|
||||||
uint8_t e = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS);
|
uint8_t e = EEPROM.read(EEPROM_TIMING_DATA_ADDRESS);
|
||||||
//Serial.println(e);
|
//Serial.println(e);
|
||||||
|
|
||||||
if (e == 255)
|
if (e > 23) // the maximum value for tis memory section is 23
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -409,25 +415,90 @@ String tc_getJsonData()
|
||||||
|
|
||||||
void tc_jsonDataBlocksToEEPROM(String json_data_string)
|
void tc_jsonDataBlocksToEEPROM(String json_data_string)
|
||||||
{
|
{
|
||||||
StaticJsonDocument<512> doc;
|
StaticJsonDocument<1289> doc;
|
||||||
deserializeJson(doc, json_data_string);
|
deserializeJson(doc, json_data_string);
|
||||||
|
|
||||||
|
Serial.println("Reading data from json data:");
|
||||||
// Loop through each data block in the JSON data and store it in the tc_data array
|
// Loop through each data block in the JSON data and store it in the tc_data array
|
||||||
for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++)
|
for (uint8_t i = 0; i < NUMBER_OF_TIMER_DATA_BLOCKS; i++)
|
||||||
{
|
{
|
||||||
JsonObject obj = doc[i];
|
//Serial.println("<< " + (String)i);
|
||||||
tc_data[i].hh = obj["hour"];
|
|
||||||
tc_data[i].mm = obj["min"];
|
JsonObject obj = doc["tcdata"][i];
|
||||||
tc_data[i].ch1 = obj["ch1"];
|
|
||||||
tc_data[i].ch2 = obj["ch2"];
|
// Check and set the limits of the hour value
|
||||||
tc_data[i].ch3 = obj["ch3"];
|
int hour = obj["hour"];
|
||||||
tc_data[i].ch4 = obj["ch4"];
|
if (hour < 0) {
|
||||||
|
hour = 0;
|
||||||
|
} else if (hour > 23) {
|
||||||
|
hour = 23;
|
||||||
|
}
|
||||||
|
tc_data[i].hh = hour;
|
||||||
|
Serial.print("hour = " + (String)tc_data[i].hh + " " + (String)obj["hour"] + " ");
|
||||||
|
|
||||||
|
// Check and set the limits of the minute value
|
||||||
|
int minute = obj["min"];
|
||||||
|
if (minute < 0) {
|
||||||
|
minute = 0;
|
||||||
|
} else if (minute > 59) {
|
||||||
|
minute = 59;
|
||||||
|
}
|
||||||
|
tc_data[i].mm = minute;
|
||||||
|
Serial.print("minute = " + (String)tc_data[i].mm + " " + (String)obj["min"] + " ");
|
||||||
|
|
||||||
|
// Check and set the limits of the ch1 value
|
||||||
|
int ch1 = obj["ch1"];
|
||||||
|
if (ch1 < 0) {
|
||||||
|
ch1 = 0;
|
||||||
|
} else if (ch1 > 255) {
|
||||||
|
ch1 = 255;
|
||||||
|
}
|
||||||
|
tc_data[i].ch1 = ch1;
|
||||||
|
Serial.print("ch1 = " + (String)tc_data[i].ch1 + " " + (String)obj["ch1"] + " ");
|
||||||
|
|
||||||
|
// Check and set the limits of the ch2 value
|
||||||
|
int ch2 = obj["ch2"];
|
||||||
|
if (ch2 < 0) {
|
||||||
|
ch2 = 0;
|
||||||
|
} else if (ch2 > 255) {
|
||||||
|
ch2 = 255;
|
||||||
|
}
|
||||||
|
tc_data[i].ch2 = ch2;
|
||||||
|
Serial.print("ch2 = " + (String)tc_data[i].ch2 + " " + (String)obj["ch2"] + " ");
|
||||||
|
|
||||||
|
// Check and set the limits of the ch3 value
|
||||||
|
int ch3 = obj["ch3"];
|
||||||
|
if (ch3 < 0) {
|
||||||
|
ch3 = 0;
|
||||||
|
} else if (ch3 > 255) {
|
||||||
|
ch3 = 255;
|
||||||
|
}
|
||||||
|
tc_data[i].ch3 = ch3;
|
||||||
|
Serial.print("ch3 = " + (String)tc_data[i].ch3 + " " + (String)obj["ch3"] + " ");
|
||||||
|
|
||||||
|
// Check and set the limits of the ch4 value
|
||||||
|
int ch4 = obj["ch4"];
|
||||||
|
if (ch4 < 0) {
|
||||||
|
ch4 = 0;
|
||||||
|
} else if (ch4 > 255) {
|
||||||
|
ch4 = 255;
|
||||||
|
}
|
||||||
|
tc_data[i].ch4 = ch4;
|
||||||
|
Serial.println("ch4 = " + (String)tc_data[i].ch4 + " " + (String)obj["ch4"] + "\n---");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Serial.println("Writing to EEPROM...");
|
||||||
// Write the tc_data array to the EEPROM
|
// Write the tc_data array to the EEPROM
|
||||||
for (uint16_t i = 0; i < (NUMBER_OF_TIMER_DATA_BLOCKS * LENGTH_OF_TIMER_DATA_BLOCK); i++)
|
for (uint16_t i = 0; i < (NUMBER_OF_TIMER_DATA_BLOCKS * LENGTH_OF_TIMER_DATA_BLOCK); i++)
|
||||||
{
|
{
|
||||||
|
//Serial.println(" " + (String)(EEPROM_TIMING_DATA_ADDRESS + i) + " " + (String)(*((uint8_t*)&tc_data + i)));
|
||||||
|
|
||||||
EEPROM.write(EEPROM_TIMING_DATA_ADDRESS + i, *((uint8_t*)&tc_data + i));
|
EEPROM.write(EEPROM_TIMING_DATA_ADDRESS + i, *((uint8_t*)&tc_data + i));
|
||||||
|
/*if (((i+1) % 6 == 0))
|
||||||
|
{
|
||||||
|
Serial.println("---");
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
cat $1 | sed -e"s/^ *//ig" | sed -e "s/^\/\/.*//ig"
|
# Remove leading whitespace and comments starting with //
|
||||||
|
sed -e 's/^[[:space:]]*//' -e '/^\/\/.*/d' $1 |
|
||||||
|
# Remove one line comments starting with //
|
||||||
|
sed -e 's/^\/\/.*$//' |
|
||||||
|
# Remove trailing comments starting with //
|
||||||
|
sed -e 's/ \/\/.*$//' |
|
||||||
|
# Remove empty lines
|
||||||
|
sed '/^\s*$/d'
|
||||||
|
|
|
@ -5,3 +5,6 @@ bash ../../tools/html2string.sh ../html/index_template_middle.html > index_templ
|
||||||
bash ../../tools/html2string.sh ../html/index_template_bottom.html > index_template_bottom.html
|
bash ../../tools/html2string.sh ../html/index_template_bottom.html > index_template_bottom.html
|
||||||
bash ../../tools/html2string.sh ../html/config_template.html > config_template.html
|
bash ../../tools/html2string.sh ../html/config_template.html > config_template.html
|
||||||
bash ../../tools/html2string.sh ../html/light_control_template.html > light_control_template.html
|
bash ../../tools/html2string.sh ../html/light_control_template.html > light_control_template.html
|
||||||
|
bash ../../tools/html2string.sh ../html/top.js > top.js
|
||||||
|
bash ../../tools/html2string.sh ../html/bottom.js > bottom.js
|
||||||
|
cp -av ../html/style.css .
|
||||||
|
|
Loading…
Reference in a new issue