<!doctype html> <html> <head> <style></style> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Light setup - {{LIGHT_NAME}}</title> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script src="https://cdn.plot.ly/plotly-latest.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"> </head> <body> <fieldset> <h3>{{LIGHT_NAME}}</h3> <div class="pure-form pure-form-aligned"> <div class="pure-controls"> <span class="pure-form-message"> <a href="/?alert=1">alert</a> <a href="/?reset=1">reset</a> <a href="/?resettc">reset timing control data</a> <a href="/update">update</a> </span> <label for="cb" class="pure-checkbox"></label> </div> <br> <div class="pure-control-group"> <label for="tc_on"> <strong>Timing control</strong> </label> <a id="tc_on" class="pure-button {{TC_LINK_PRIMARY_ON}}" href="#">ON</a> <a id="tc_off" class="pure-button {{TC_LINK_PRIMARY_OFF}}" href="#">OFF</a> </div> <script> 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'); }); }); </script> <br> <div class="pure-control-group"> <label for="transition">Transition time (s)</label> <input id="transition" name="transition" type="text" placeholder="10" value="{{TRANSITION_TIME}}"> </div> <br> <script> 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> <br> <table border=0> <tr> <td> {{LIGHTS_CONTROL}} </td> <td> <div id="plot_chart"></div> </td> </tr> </table> {{CONFIG_PAGE}} <script> 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); </script> </div> </fieldset> </body> </html>