Commit c6fb16c8 authored by Eric Duminil's avatar Eric Duminil
Browse files

Distributing html more evenly

parent 73317ec1
Pipeline #5858 passed with stage
in 2 minutes and 21 seconds
...@@ -48,49 +48,49 @@ namespace web_server { ...@@ -48,49 +48,49 @@ namespace web_server {
// "<meta http-equiv='refresh' content='%d'>" // "<meta http-equiv='refresh' content='%d'>"
"</head>" "</head>"
"<body>" "<body>"
"<div class='pure-g'><div class='pure-u-1'><div class='pure-menu'><p class='pure-menu-heading'>HfT-Stuttgart CO<sub>2</sub> Ampel</p></div></div>" "<div class='pure-g'><div class='pure-u-1'><div class='pure-menu'><p class='pure-menu-heading'>HfT-Stuttgart CO<sub>2</sub> Ampel</p></div></div>"
"<div class='pure-u-1'><ul class='pure-menu pure-menu-horizontal pure-menu-list'>" "<div class='pure-u-1'><ul class='pure-menu pure-menu-horizontal pure-menu-list'>"
"<li class='pure-menu-item'><a href='/config' class='pure-menu-link'>Config</a></li>" "<li class='pure-menu-item'><a href='/config' class='pure-menu-link'>Config</a></li>"
"<li class='pure-menu-item'><a href='#table' class='pure-menu-link'>Info</a></li>" "<li class='pure-menu-item'><a href='#table' class='pure-menu-link'>Info</a></li>"
"<li class='pure-menu-item'><a href='#graph' class='pure-menu-link'>Graph</a></li>" "<li class='pure-menu-item'><a href='#graph' class='pure-menu-link'>Graph</a></li>");
"<li class='pure-menu-item'><a href='#log' class='pure-menu-link'>Log</a></li>"
"<li class='pure-menu-item'><a href='%s' class='pure-menu-link'>Download CSV</a></li>"
"<li class='pure-menu-item' id='led'>&#11044;</li>"// LED
"</ul></div></div>"
"<script>"
// Show a colored dot on the webpage, with a similar color than on LED Ring.
"hue=(1-(Math.min(Math.max(parseInt(document.title),500),1600)-500)/1100)*120;"
"document.getElementById('led').style.color=['hsl(',hue,',100%%,50%%)'].join('');"
"</script>"
"<div class='pure-g'>"
"<div class='pure-u-1' id='graph'></div>"// Graph placeholder
"</div>"
"<div class='pure-g'>"
"<table id='table' class='pure-table-striped pure-u-1 pure-u-md-1-2'>");
body1_template = PSTR("<tr><th colspan='2'>%s</th></tr>" body1_template = PSTR("<li class='pure-menu-item'><a href='#log' class='pure-menu-link'>Log</a></li>"
"<li class='pure-menu-item'><a href='%s' class='pure-menu-link'>Download CSV</a></li>"
"<li class='pure-menu-item' id='led'>&#11044;</li>" // LED
"</ul></div></div>"
"<script>"
// Show a colored dot on the webpage, with a similar color than on LED Ring.
"hue=(1-(Math.min(Math.max(parseInt(document.title),500),1600)-500)/1100)*120;"
"document.getElementById('led').style.color=['hsl(',hue,',100%%,50%%)'].join('');"
"</script>"
"<div class='pure-g'>"
"<div class='pure-u-1' id='graph'></div>"// Graph placeholder
"</div>"
"<div class='pure-g'>"
"<table id='table' class='pure-table-striped pure-u-1 pure-u-md-1-2'>"
"<tr><th colspan='2'>%s</th></tr>"
"<tr><td>CO<sub>2</sub></td><td>%5d ppm</td></tr>" "<tr><td>CO<sub>2</sub></td><td>%5d ppm</td></tr>"
"<tr><td>Temperature</td><td>%.1f&#8451;</td></tr>" "<tr><td>Temperature</td><td>%.1f&#8451;</td></tr>"
"<tr><td>Humidity</td><td>%.1f%%</td></tr>" "<tr><td>Humidity</td><td>%.1f%%</td></tr>"
"<tr><td>Last measurement</td><td>%s</td></tr>" "<tr><td>Last measurement</td><td>%s</td></tr>"
"<tr><td>Timestep</td><td>%5d s</td></tr>" "<tr><td>Timestep</td><td>%5d s</td></tr>"
"<tbody>" "<tbody %s>"
"<tr><th colspan='2'>CSV</th></tr>" //TODO: Gray out if !config::csv_active "<tr><th colspan='2'>CSV</th></tr>"//TODO: Gray out if !config::csv_active
"<tr><td>Last write</td><td>%s</td></tr>" "<tr><td>Last write</td><td>%s</td></tr>"
"<tr><td>Interval</td><td>%5d s</td></tr>" "<tr><td>Interval</td><td>%5d s</td></tr>"
"<tr><td>Available space</td><td>%d kB</td></tr>" "<tr><td>Available space</td><td>%d kB</td></tr>"
"</tbody>" "</tbody>"
"<tbody>" "<tbody %s>"
"<tr><th colspan='2'>MQTT</th></tr>" "<tr><th colspan='2'>MQTT</th></tr>"
"<tr><td>Connected?</td><td>%s</td></tr>" "<tr><td>Connected?</td><td>%s</td></tr>"
"<tr><td>Last publish</td><td>%s</td></tr>" "<tr><td>Last publish</td><td>%s</td></tr>"
"<tr><td>Interval</td><td>%5d s</td></tr>" "<tr><td>Interval</td><td>%5d s</td></tr>"
"</tbody>"); "</tbody>");
body2_template = body2_template =
PSTR( PSTR(
#if defined(ESP32) #if defined(ESP32)
"<tbody>" "<tbody %s>"
"<tr><th colspan='2'>LoRaWAN</th></tr>" "<tr><th colspan='2'>LoRaWAN</th></tr>"
"<tr><td>Connected?</td><td>%s</td></tr>" "<tr><td>Connected?</td><td>%s</td></tr>"
"<tr><td>Frequency</td><td>%s MHz</td></tr>" "<tr><td>Frequency</td><td>%s MHz</td></tr>"
...@@ -118,56 +118,54 @@ namespace web_server { ...@@ -118,56 +118,54 @@ namespace web_server {
"<form action='/delete_csv' method='POST' onsubmit=\"return confirm('Are you really sure you want to delete all data?') && (document.body.style.cursor = 'wait');\">" "<form action='/delete_csv' method='POST' onsubmit=\"return confirm('Are you really sure you want to delete all data?') && (document.body.style.cursor = 'wait');\">"
"<input type='submit' value='Delete CSV'/>" "<input type='submit' value='Delete CSV'/>"
"</form>" "</form>"
"</div>"); "</div>"
"<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-firmware' target='_blank'>Source code</a>&nbsp;"
"<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-documentation' target='_blank'>Documentation</a>");
script_template = script_template = PSTR("<script>"
PSTR( "document.body.style.cursor = 'default';"
"<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-firmware' target='_blank'>Source code</a>" "fetch('%s',{credentials:'include'})"
"<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-documentation' target='_blank'>Documentation</a>" ".then(response=>response.text())"
"<script>" ".then(csvText=>csvToTable(csvText))"
"document.body.style.cursor = 'default';" ".then(htmlTable=>addLogTableToPage(htmlTable))"
"fetch('%s',{credentials:'include'})" ".then(_=>Plotly.newPlot('graph',data,layout,{displaylogo:false}))"
".then(response=>response.text())" ".catch(e=>console.error(e));"
".then(csvText=>csvToTable(csvText))" "xs=[];"
".then(htmlTable=>addLogTableToPage(htmlTable))" "data=[{x:xs,y:[],type:'scatter',name:'CO<sub>2</sub>',line:{color:'#2ca02c'}},"
".then(_=>Plotly.newPlot('graph',data,layout,{displaylogo:false}))" "{x:xs,y:[],type:'scatter',name:'Temperature',yaxis:'y2',line:{color:'#ff7f0e',dash:'dot'}},"
".catch(e=>console.error(e));" "{x:xs,y:[],type:'scatter',name:'Humidity',yaxis:'y3',line:{color:'#1f77b4',dash:'dot'}}];"
"xs=[];" "layout={height:600,title:'%s',legend:{xanchor:'right',x:0.2,y:1.0},"
"data=[{x:xs,y:[],type:'scatter',name:'CO<sub>2</sub>',line:{color:'#2ca02c'}}," "xaxis:{domain:[0.0,0.85]},yaxis:{ticksuffix:'ppm',range:[0,2000],dtick:200},"
"{x:xs,y:[],type:'scatter',name:'Temperature',yaxis:'y2',line:{color:'#ff7f0e',dash:'dot'}}," "yaxis2:{overlaying:'y',side:'right',ticksuffix:'°C',position:0.9,anchor:'free',range:[0,30],dtick:3},"
"{x:xs,y:[],type:'scatter',name:'Humidity',yaxis:'y3',line:{color:'#1f77b4',dash:'dot'}}];" "yaxis3:{overlaying:'y',side:'right',ticksuffix:'%%',position:0.95,anchor:'free',range:[0,100],dtick:10}"
"layout={height:600,title:'%s',legend:{xanchor:'right',x:0.2,y:1.0}," "};"
"xaxis:{domain:[0.0,0.85]},yaxis:{ticksuffix:'ppm',range:[0,2000],dtick:200}," "function csvToTable(csvText){"
"yaxis2:{overlaying:'y',side:'right',ticksuffix:'°C',position:0.9,anchor:'free',range:[0,30],dtick:3}," "csvText=csvText.trim();"
"yaxis3:{overlaying:'y',side:'right',ticksuffix:'%%',position:0.95,anchor:'free',range:[0,100],dtick:10}" "lines=csvText.split('\\n');"
"};" "table=document.createElement('table');"
"function csvToTable(csvText){" "table.className='pure-table-striped';"
"csvText=csvText.trim();" "n=lines.length;"
"lines=csvText.split('\\n');" "lines.forEach((line,i)=>{"
"table=document.createElement('table');" "fields=line.split(';');"
"table.className='pure-table-striped';" //Don't display points without time
"n=lines.length;" "if (!fields[0].includes('1970-')){"
"lines.forEach((line,i)=>{" "xs.push(fields[0]);"
"fields=line.split(';');" "data[0]['y'].push(fields[1]);"
//Don't display points without time "data[1]['y'].push(fields[2]);"
"if (!fields[0].includes('1970-')){" "data[2]['y'].push(fields[3]);"
"xs.push(fields[0]);" "};"
"data[0]['y'].push(fields[1]);" "if(i>4 && i<n-12){if(i==5){fields=['...','...','...','...']}else{return;}}"
"data[1]['y'].push(fields[2]);" "row=document.createElement('tr');"
"data[2]['y'].push(fields[3]);" "fields.forEach((field,index)=>{"
"};" "cell=document.createElement(i<2?'th':'td');"
"if(i>4 && i<n-12){if(i==5){fields=['...','...','...','...']}else{return;}}" "cell.appendChild(document.createTextNode(field));"
"row=document.createElement('tr');" "row.appendChild(cell);});"
"fields.forEach((field,index)=>{" "table.appendChild(row);});"
"cell=document.createElement(i<2?'th':'td');" "return table;}"
"cell.appendChild(document.createTextNode(field));" "function addLogTableToPage(table){document.getElementById('log').appendChild(table);}"
"row.appendChild(cell);});" "</script>"
"table.appendChild(row);});" "</body>"
"return table;}" "</html>");
"function addLogTableToPage(table){document.getElementById('log').appendChild(table);}"
"</script>"
"</body>"
"</html>");
// Web-server // Web-server
web_config::http.on("/", handleWebServerRoot); web_config::http.on("/", handleWebServerRoot);
...@@ -202,10 +200,9 @@ namespace web_server { ...@@ -202,10 +200,9 @@ namespace web_server {
//NOTE: Splitting in multiple parts in order to use less RAM. Higher than 2000 apparently crashes the ESP8266 //NOTE: Splitting in multiple parts in order to use less RAM. Higher than 2000 apparently crashes the ESP8266
char content[2000]; char content[2000];
// Current size (with Lorawan): // Current size (with Lorawan):
// INFO - Header size : 1826 - Body size : 2005 - Script size : 1904 // INFO - Header size : 1685 - Body1 size : 843 - Body2 size : 1395 - Script size : 1918
snprintf_P(content, sizeof(content), header_template, sensor::co2, config::ampel_name(), wifi::local_ip, snprintf_P(content, sizeof(content), header_template, sensor::co2, config::ampel_name(), wifi::local_ip);
csv_writer::filename);
Serial.print(F("INFO - Header size : ")); Serial.print(F("INFO - Header size : "));
Serial.print(strlen(content)); Serial.print(strlen(content));
...@@ -213,10 +210,11 @@ namespace web_server { ...@@ -213,10 +210,11 @@ namespace web_server {
web_config::http.send_P(200, PSTR("text/html"), content); web_config::http.send_P(200, PSTR("text/html"), content);
// Body // Body
snprintf_P(content, sizeof(content), body1_template, config::ampel_name(), sensor::co2, sensor::temperature, snprintf_P(content, sizeof(content), body1_template, csv_writer::filename, config::ampel_name(), sensor::co2,
sensor::humidity, sensor::timestamp, config::measurement_timestep, csv_writer::last_successful_write, sensor::temperature, sensor::humidity, sensor::timestamp, config::measurement_timestep,
config::csv_interval, csv_writer::getAvailableSpace() / 1024, mqtt::connected ? "Yes" : "No", config::is_csv_active() ? "" : "hidden", csv_writer::last_successful_write, config::csv_interval,
mqtt::last_successful_publish, config::mqtt_sending_interval); csv_writer::getAvailableSpace() / 1024, config::is_mqtt_active() ? "" : "hidden",
mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish, config::mqtt_sending_interval);
Serial.print(F(" - Body1 size : ")); Serial.print(F(" - Body1 size : "));
Serial.print(strlen(content)); Serial.print(strlen(content));
...@@ -224,8 +222,8 @@ namespace web_server { ...@@ -224,8 +222,8 @@ namespace web_server {
snprintf_P(content, sizeof(content), body2_template, snprintf_P(content, sizeof(content), body2_template,
#if defined(ESP32) #if defined(ESP32)
lorawan::connected ? "Yes" : "No", config::lorawan_frequency_plan, lorawan::last_transmission, config::is_lorawan_active() ? "" : "hidden", lorawan::connected ? "Yes" : "No", config::lorawan_frequency_plan,
config::lorawan_sending_interval, lorawan::last_transmission, config::lorawan_sending_interval,
#endif #endif
config::temperature_offset, config::auto_calibrate_sensor ? "Yes" : "No", config::ampel_name(), config::temperature_offset, config::auto_calibrate_sensor ? "Yes" : "No", config::ampel_name(),
config::ampel_name(), wifi::local_ip, wifi::local_ip, ampel.macAddress, ESP.getFreeHeap(), config::ampel_name(), wifi::local_ip, wifi::local_ip, ampel.macAddress, ESP.getFreeHeap(),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment