diff --git a/ampel-firmware/ampel-firmware.ino b/ampel-firmware/ampel-firmware.ino index ffdc229dceeebaada9aee4204b57b159cf891d0d..bc0e3c2ef7cef07876b4fcddc650146b2a6d33aa 100644 --- a/ampel-firmware/ampel-firmware.ino +++ b/ampel-firmware/ampel-firmware.ino @@ -111,9 +111,7 @@ void setup() { sensor::initialize(); -#ifdef AMPEL_CSV csv_writer::initialize(ampel.sensorId); -#endif #ifdef AMPEL_WIFI // Structure doesn't make sense anymore wifi::defineCommands(); @@ -161,10 +159,10 @@ void loop() { checkSerialInput(); if (sensor::processData()) { -#ifdef AMPEL_CSV - //TODO: Check if not in AP mode. Lines get written with 1970 otherwise. - csv_writer::logIfTimeHasCome(sensor::timestamp, sensor::co2, sensor::temperature, sensor::humidity); -#endif + if (config::csv_active()) { + //TODO: Check if not in AP mode. Lines get written with 1970 otherwise. + csv_writer::logIfTimeHasCome(sensor::timestamp, sensor::co2, sensor::temperature, sensor::humidity); + } #if defined(AMPEL_WIFI) if (config::mqtt_active()) { diff --git a/ampel-firmware/web_config.cpp b/ampel-firmware/web_config.cpp index f7bad77c6e6da2c572ffa382ec56f2cd37aa8957..5791f718ab796b066fd840e08a02494e1bdcbbca 100644 --- a/ampel-firmware/web_config.cpp +++ b/ampel-firmware/web_config.cpp @@ -292,9 +292,12 @@ namespace config { bool &daylight_saving_time = web_config::dstParam.value(); // CSV + bool csv_active() { + return web_config::csvParams.isActive(); + } uint16_t &csv_interval = web_config::csvTimestepParam.value(); -// MQTT + // MQTT bool mqtt_active() { return web_config::mqttParams.isActive(); } diff --git a/ampel-firmware/web_config.h b/ampel-firmware/web_config.h index 8a8dce9e5e74d6c600b51001b3396175fa98b881..5e67ebe98384506b6d4dc9471cc570e8fb9b8e40 100644 --- a/ampel-firmware/web_config.h +++ b/ampel-firmware/web_config.h @@ -28,7 +28,7 @@ namespace config { extern bool &daylight_saving_time; // [true / false] //CSV - //TODO: Add use_csv + bool csv_active(); extern uint16_t &csv_interval; // [s] // MQTT diff --git a/ampel-firmware/web_server.cpp b/ampel-firmware/web_server.cpp index 5398708cda965a0bb64c3f1f9c1dbcb4d441bb2c..37ed6e7d075282b03046d2070236027cc16dc52c 100644 --- a/ampel-firmware/web_server.cpp +++ b/ampel-firmware/web_server.cpp @@ -7,9 +7,7 @@ #include "wifi_util.h" #include "co2_sensor.h" #include "sensor_console.h" -#ifdef AMPEL_CSV -# include "csv_writer.h" -#endif +#include "csv_writer.h" #include "mqtt.h" #ifdef AMPEL_LORAWAN # include "lorawan.h" @@ -50,10 +48,8 @@ namespace web_server { void handlePageNotFound(); void handleWebServerCommand(); -#ifdef AMPEL_CSV void handleDeleteCSV(); void handleWebServerCSV(); -#endif void definePages() { header_template = @@ -79,12 +75,10 @@ namespace web_server { "<div class='pure-u-1'><ul class='pure-menu pure-menu-horizontal pure-menu-list'>\n" "<li class='pure-menu-item'><a href='/config' class='pure-menu-link'>Config</a></li>\n" "<li class='pure-menu-item'><a href='#table' class='pure-menu-link'>Info</a></li>\n" -#ifdef AMPEL_CSV "<li class='pure-menu-item'><a href='#graph' class='pure-menu-link'>Graph</a></li>\n" "<li class='pure-menu-item'><a href='#log' class='pure-menu-link'>Log</a></li>\n" "<li class='pure-menu-item'><a href='%s' class='pure-menu-link'>Download CSV</a></li>\n" -#endif - "<li class='pure-menu-item' id='led'>⬤</li>\n" // LED + "<li class='pure-menu-item' id='led'>⬤</li>\n"// LED "</ul></div></div>\n" "<script>\n" // Show a colored dot on the webpage, with a similar color than on LED Ring. @@ -104,12 +98,10 @@ namespace web_server { "<tr><td>Humidity</td><td>%.1f%%</td></tr>\n" "<tr><td>Last measurement</td><td>%s</td></tr>\n" "<tr><td>Measurement timestep</td><td>%5d s</td></tr>\n" -#ifdef AMPEL_CSV "<tr><th colspan='2'>CSV</th></tr>\n" "<tr><td>Last write</td><td>%s</td></tr>\n" "<tr><td>Timestep</td><td>%5d s</td></tr>\n" "<tr><td>Available drive space</td><td>%d kB</td></tr>\n" -#endif "<tr><th colspan='2'>MQTT</th></tr>\n" "<tr><td>Connected?</td><td>%s</td></tr>\n" "<tr><td>Last publish</td><td>%s</td></tr>\n" @@ -137,68 +129,62 @@ namespace web_server { "</table>\n" "<div id='log' class='pure-u-1 pure-u-md-1-2'></div>\n" "<form action='/command'><input type='text' id='send' name='send'><input type='submit' value='Send'></form>\n" -#ifdef AMPEL_CSV "<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'/>" "</form>\n" -#endif "</div>\n"); script_template = PSTR( "<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-firmware' target='_blank'>Source code</a>\n" "<a href='https://transfer.hft-stuttgart.de/gitlab/co2ampel/ampel-documentation' target='_blank'>Documentation</a>\n" -#ifdef AMPEL_CSV - "<script>\n" - "document.body.style.cursor = 'default';\n" - "fetch('%s',{credentials:'include'})\n" - ".then(response=>response.text())\n" - ".then(csvText=>csvToTable(csvText))\n" - ".then(htmlTable=>addLogTableToPage(htmlTable))\n" - ".then(_=>Plotly.newPlot('graph',data,layout,{displaylogo:false}))\n" - ".catch(e=>console.error(e));\n" - "xs=[];\n" - "data=[{x:xs,y:[],type:'scatter',name:'CO<sub>2</sub>',line:{color:'#2ca02c'}},\n" - "{x:xs,y:[],type:'scatter',name:'Temperature',yaxis:'y2',line:{color:'#ff7f0e',dash:'dot'}},\n" - "{x:xs,y:[],type:'scatter',name:'Humidity',yaxis:'y3',line:{color:'#1f77b4',dash:'dot'}}];\n" - "layout={height:600,title:'%s',legend:{xanchor:'right',x:0.2,y:1.0},\n" - "xaxis:{domain:[0.0,0.85]},yaxis:{ticksuffix:'ppm',range:[0,2000],dtick:200},\n" - "yaxis2:{overlaying:'y',side:'right',ticksuffix:'°C',position:0.9,anchor:'free',range:[0,30],dtick:3},\n" - "yaxis3:{overlaying:'y',side:'right',ticksuffix:'%%',position:0.95,anchor:'free',range:[0,100],dtick:10}\n" - "};\n" - "function csvToTable(csvText) {\n" - "csvText=csvText.trim();\n" - "lines=csvText.split('\\n');\n" - "table=document.createElement('table');\n" - "table.className='pure-table-striped';\n" - "n=lines.length;\n" - "lines.forEach((line,i)=>{\n" - "fields=line.split(';');\n" - "xs.push(fields[0]);\n" - "data[0]['y'].push(fields[1]);\n" - "data[1]['y'].push(fields[2]);\n" - "data[2]['y'].push(fields[3]);\n" - "if(i>4 && i<n-12){if(i==5){fields=['...','...','...','...']}else{return;}}\n" - "row=document.createElement('tr');\n" - "fields.forEach((field,index)=>{\n" - "cell=document.createElement(i<2?'th':'td');\n" - "cell.appendChild(document.createTextNode(field));\n" - "row.appendChild(cell);});\n" - "table.appendChild(row);});\n" - "return table;}\n" - "function addLogTableToPage(table){document.getElementById('log').appendChild(table);}\n" - "</script>\n" -#endif - "</body>\n" - "</html>"); + "<script>\n" + "document.body.style.cursor = 'default';\n" + "fetch('%s',{credentials:'include'})\n" + ".then(response=>response.text())\n" + ".then(csvText=>csvToTable(csvText))\n" + ".then(htmlTable=>addLogTableToPage(htmlTable))\n" + ".then(_=>Plotly.newPlot('graph',data,layout,{displaylogo:false}))\n" + ".catch(e=>console.error(e));\n" + "xs=[];\n" + "data=[{x:xs,y:[],type:'scatter',name:'CO<sub>2</sub>',line:{color:'#2ca02c'}},\n" + "{x:xs,y:[],type:'scatter',name:'Temperature',yaxis:'y2',line:{color:'#ff7f0e',dash:'dot'}},\n" + "{x:xs,y:[],type:'scatter',name:'Humidity',yaxis:'y3',line:{color:'#1f77b4',dash:'dot'}}];\n" + "layout={height:600,title:'%s',legend:{xanchor:'right',x:0.2,y:1.0},\n" + "xaxis:{domain:[0.0,0.85]},yaxis:{ticksuffix:'ppm',range:[0,2000],dtick:200},\n" + "yaxis2:{overlaying:'y',side:'right',ticksuffix:'°C',position:0.9,anchor:'free',range:[0,30],dtick:3},\n" + "yaxis3:{overlaying:'y',side:'right',ticksuffix:'%%',position:0.95,anchor:'free',range:[0,100],dtick:10}\n" + "};\n" + "function csvToTable(csvText) {\n" + "csvText=csvText.trim();\n" + "lines=csvText.split('\\n');\n" + "table=document.createElement('table');\n" + "table.className='pure-table-striped';\n" + "n=lines.length;\n" + "lines.forEach((line,i)=>{\n" + "fields=line.split(';');\n" + "xs.push(fields[0]);\n" + "data[0]['y'].push(fields[1]);\n" + "data[1]['y'].push(fields[2]);\n" + "data[2]['y'].push(fields[3]);\n" + "if(i>4 && i<n-12){if(i==5){fields=['...','...','...','...']}else{return;}}\n" + "row=document.createElement('tr');\n" + "fields.forEach((field,index)=>{\n" + "cell=document.createElement(i<2?'th':'td');\n" + "cell.appendChild(document.createTextNode(field));\n" + "row.appendChild(cell);});\n" + "table.appendChild(row);});\n" + "return table;}\n" + "function addLogTableToPage(table){document.getElementById('log').appendChild(table);}\n" + "</script>\n" + "</body>\n" + "</html>"); // Web-server web_config::http.on("/", handleWebServerRoot); web_config::http.on("/command", handleWebServerCommand); -#ifdef AMPEL_CSV - web_config::http.on(csv_writer::filename, handleWebServerCSV); //NOTE: csv_writer should have been initialized first. + web_config::http.on(csv_writer::filename, handleWebServerCSV); web_config::http.on("/delete_csv", HTTP_POST, handleDeleteCSV); -#endif } // Allow access if http_user or http_password are empty, or if provided credentials match @@ -228,11 +214,8 @@ namespace web_server { char content[2000]; // Update if needed // INFO - Header size : 1767 - Body size : 1991 - Script size : 1909 - snprintf_P(content, sizeof(content), header_template, sensor::co2, ampel.sensorId, wifi::local_ip -#ifdef AMPEL_CSV - , csv_writer::filename -#endif - ); + snprintf_P(content, sizeof(content), header_template, sensor::co2, ampel.sensorId, wifi::local_ip, + csv_writer::filename); // Serial.print(F("INFO - Header size : ")); // Serial.print(strlen(content)); @@ -241,11 +224,9 @@ namespace web_server { // Body snprintf_P(content, sizeof(content), body_template, ampel.sensorId, sensor::co2, sensor::temperature, - sensor::humidity, sensor::timestamp, config::measurement_timestep, -#ifdef AMPEL_CSV - csv_writer::last_successful_write, config::csv_interval, csv_writer::getAvailableSpace() / 1024, -#endif - mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish, config::mqtt_sending_interval, + sensor::humidity, sensor::timestamp, config::measurement_timestep, csv_writer::last_successful_write, + config::csv_interval, csv_writer::getAvailableSpace() / 1024, mqtt::connected ? "Yes" : "No", + mqtt::last_successful_publish, config::mqtt_sending_interval, #if defined(AMPEL_LORAWAN) && defined(ESP32) lorawan::connected ? "Yes" : "No", config::lorawan_frequency_plan, lorawan::last_transmission, config::lorawan_sending_interval, @@ -259,18 +240,13 @@ namespace web_server { web_config::http.sendContent(content); // Script - snprintf_P(content, sizeof(content), script_template -#ifdef AMPEL_CSV - , csv_writer::filename, ampel.sensorId -#endif - ); + snprintf_P(content, sizeof(content), script_template, csv_writer::filename, ampel.sensorId); // Serial.print(F(" - Script size : ")); // Serial.println(strlen(content)); web_config::http.sendContent(content); } -#ifdef AMPEL_CSV void handleWebServerCSV() { if (!shouldBeAllowed()) { return web_config::http.requestAuthentication(DIGEST_AUTH); @@ -297,7 +273,6 @@ namespace web_server { web_config::http.sendHeader("Location", "/"); web_config::http.send(303); } -#endif void handleWebServerCommand() { if (!shouldBeAllowed()) {