Commit 208eadd3 authored by Eric Duminil's avatar Eric Duminil
Browse files

Merge branch 'develop'

parents b48d4d18 a9b0db5d
Pipeline #3221 passed with stage
in 1 minute and 40 seconds
......@@ -22,6 +22,7 @@ namespace web_server {
const char *script_template;
void handleWebServerRoot();
void handlePageNotFound();
void handleWebServerCommand();
#ifdef AMPEL_CSV
void handleDeleteCSV();
......@@ -64,7 +65,7 @@ namespace web_server {
#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"
"<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'>&#11044;</li>\n" // LED
"</ul></div></div>\n"
......@@ -72,16 +73,15 @@ namespace web_server {
// 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;\n"
"document.getElementById('led').style.color=['hsl(',hue,',100%%,50%%)'].join('');\n"
"</script>\n");
body_template =
PSTR("<div class='pure-g'>\n"
"<div class='pure-u-1' id='graph'></div>\n" // Graph placeholder
"</script>\n"
"<div class='pure-g'>\n"
"<div class='pure-u-1' id='graph'></div>\n"// Graph placeholder
"</div>\n"
"<div class='pure-g'>\n"
//Sensor table
"<table id='table' class='pure-table-striped pure-u-1 pure-u-md-1-2'>\n"
"<tr><th colspan='2'>%s</th></tr>\n"
"<table id='table' class='pure-table-striped pure-u-1 pure-u-md-1-2'>\n");
body_template =
PSTR("<tr><th colspan='2'>%s</th></tr>\n"
"<tr><td>CO<sub>2</sub> concentration</td><td>%5d ppm</td></tr>\n"
"<tr><td>Temperature</td><td>%.1f&#8451;</td></tr>\n"
"<tr><td>Humidity</td><td>%.1f%%</td></tr>\n"
......@@ -108,14 +108,17 @@ namespace web_server {
#endif
"<tr><th colspan='2'>Sensor</th></tr>\n"
"<tr><td>Temperature offset</td><td>%.1fK</td></tr>\n" //TODO: Read it from sensor?
"<tr><td>Auto-calibration?</td><td>%s</td></tr>\n"
"<tr><td>Local address</td><td><a href='http://%s.local/'>%s.local</a></td></tr>\n"
"<tr><td>Local IP</td><td><a href='http://%s'>%s</a></td></tr>\n"
"<tr><td>Free heap space</td><td>%6d bytes</td></tr>\n"
"<tr><td>Largest heap block</td><td>%6d bytes</td></tr>\n"
"<tr><td>Max loop duration</td><td>%5d ms</td></tr>\n"
"<tr><td>Board</td><td>%s</td></tr>\n"
"<tr><td>Uptime</td><td>%2d d %4d h %02d min %02d s</td></tr>\n"
"</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'/>"
......@@ -130,7 +133,7 @@ namespace web_server {
#ifdef AMPEL_CSV
"<script>\n"
"document.body.style.cursor = 'default';\n"
"fetch('./%s',{credentials:'include'})\n"
"fetch('%s',{credentials:'include'})\n"
".then(response=>response.text())\n"
".then(csvText=>csvToTable(csvText))\n"
".then(htmlTable=>addLogTableToPage(htmlTable))\n"
......@@ -173,15 +176,16 @@ namespace web_server {
// Web-server
http.on("/", handleWebServerRoot);
http.on("/command", handleWebServerCommand);
#ifdef AMPEL_CSV
http.on("/" + csv_writer::filename, handleWebServerCSV);
http.on(csv_writer::filename, handleWebServerCSV); //NOTE: csv_writer should have been initialized first.
http.on("/delete_csv", HTTP_POST, handleDeleteCSV);
#endif
http.onNotFound(handlePageNotFound);
http.begin();
Serial.print(F("You can access this sensor via http://"));
Serial.print(SENSOR_ID);
Serial.print(ampel.sensorId);
Serial.print(F(".local (might be unstable) or http://"));
Serial.println(WiFi.localIP());
}
......@@ -207,44 +211,49 @@ namespace web_server {
//NOTE: Splitting in multiple parts in order to use less RAM
char content[2000]; // Update if needed
// Header size : 1611 - Body size : 1800 - Script size : 1920
// INFO - Header size : 1767 - Body size : 1812 - Script size : 1909
// Header
snprintf_P(content, sizeof(content), header_template, sensor::co2, SENSOR_ID.c_str(),
WiFi.localIP().toString().c_str()
snprintf_P(content, sizeof(content), header_template, sensor::co2, ampel.sensorId, wifi::local_ip
#ifdef AMPEL_CSV
, csv_writer::filename.c_str()
, csv_writer::filename
#endif
);
Serial.print(F("INFO - Header size : "));
Serial.print(strlen(content));
http.setContentLength(CONTENT_LENGTH_UNKNOWN);
http.send_P(200, PSTR("text/html"), content);
// Body
snprintf_P(content, sizeof(content), body_template, SENSOR_ID.c_str(), sensor::co2, sensor::temperature,
sensor::humidity, sensor::timestamp.c_str(), config::measurement_timestep,
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.c_str(), config::csv_interval, csv_writer::getAvailableSpace() / 1024,
csv_writer::last_successful_write, config::csv_interval, csv_writer::getAvailableSpace() / 1024,
#endif
#ifdef AMPEL_MQTT
mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish.c_str(), config::sending_interval,
mqtt::connected ? "Yes" : "No", mqtt::last_successful_publish, config::mqtt_sending_interval,
#endif
#if defined(AMPEL_LORAWAN) && defined(ESP32)
lorawan::connected ? "Yes" : "No", LMIC_FREQUENCY_PLAN, lorawan::last_transmission.c_str(),
lorawan::connected ? "Yes" : "No", LMIC_FREQUENCY_PLAN, lorawan::last_transmission,
config::lorawan_sending_interval,
#endif
config::temperature_offset, SENSOR_ID.c_str(), SENSOR_ID.c_str(), WiFi.localIP().toString().c_str(),
WiFi.localIP().toString().c_str(), get_free_heap_size(), max_loop_duration, BOARD, dd, hh, mm, ss);
config::temperature_offset, config::auto_calibrate_sensor ? "Yes" : "No", ampel.sensorId, ampel.sensorId,
wifi::local_ip, wifi::local_ip, ESP.getFreeHeap(), esp_get_max_free_block_size(), ampel.max_loop_duration,
ampel.board, dd, hh, mm, ss);
Serial.print(F(" - Body size : "));
http.sendContent(content);
Serial.print(strlen(content));
// Script
snprintf_P(content, sizeof(content), script_template
#ifdef AMPEL_CSV
, csv_writer::filename.c_str(), SENSOR_ID.c_str()
, csv_writer::filename, ampel.sensorId
#endif
);
Serial.print(F(" - Script size : "));
Serial.println(strlen(content));
http.sendContent(content);
}
......@@ -255,7 +264,9 @@ namespace web_server {
}
if (FS_LIB.exists(csv_writer::filename)) {
fs::File csv_file = FS_LIB.open(csv_writer::filename, "r");
http.sendHeader("Content-Length", String(csv_file.size()));
char csv_size[10];
snprintf(csv_size, sizeof(csv_size), "%d", csv_file.size());
http.sendHeader("Content-Length", csv_size);
http.streamFile(csv_file, F("text/csv"));
csv_file.close();
} else {
......@@ -267,14 +278,23 @@ namespace web_server {
if (!shouldBeAllowed()) {
return http.requestAuthentication(DIGEST_AUTH);
}
Serial.print("Removing CSV file...");
Serial.print(F("Removing CSV file..."));
FS_LIB.remove(csv_writer::filename);
Serial.println(" Done!");
Serial.println(F(" Done!"));
http.sendHeader("Location", "/");
http.send(303);
}
#endif
void handleWebServerCommand() {
if (!shouldBeAllowed()) {
return http.requestAuthentication(DIGEST_AUTH);
}
http.sendHeader("Location", "/");
http.send(303);
sensor_console::runCommand(http.arg("send").c_str());
}
void handlePageNotFound() {
http.send(404, F("text/plain"), F("404: Not found"));
}
......
#ifndef WEB_SERVER_H_
#define WEB_SERVER_H_
#if defined(ESP8266)
# include <ESP8266WebServer.h>
#elif defined(ESP32)
......@@ -8,7 +9,9 @@
#include "config.h"
#include "util.h"
#include "wifi_util.h"
#include "co2_sensor.h"
#include "sensor_console.h"
#ifdef AMPEL_CSV
# include "csv_writer.h"
#endif
......
......@@ -12,34 +12,39 @@ namespace config {
#endif
}
// Initialize Wi-Fi
void WiFiConnect(const String &hostname) {
//NOTE: WiFi Multi could allow multiple SSID and passwords.
WiFi.persistent(false); // Don't write user & password to Flash.
WiFi.mode(WIFI_STA); // Set ESP to be a WiFi-client only
namespace wifi {
char local_ip[16]; // "255.255.255.255\0"
// Initialize Wi-Fi
void connect(const char *hostname) {
//NOTE: WiFi Multi could allow multiple SSID and passwords.
WiFi.persistent(false); // Don't write user & password to Flash.
WiFi.mode(WIFI_STA); // Set ESP to be a WiFi-client only
#if defined(ESP8266)
WiFi.hostname(hostname);
#elif defined(ESP32)
WiFi.setHostname(hostname.c_str());
WiFi.setHostname(hostname);
#endif
Serial.print(F("WiFi - Connecting to "));
Serial.println(config::wifi_ssid);
WiFi.begin(config::wifi_ssid, config::wifi_password);
Serial.print(F("WiFi - Connecting to "));
Serial.println(config::wifi_ssid);
WiFi.begin(config::wifi_ssid, config::wifi_password);
// Wait for connection, at most wifi_timeout seconds
for (int i = 0; i <= config::wifi_timeout && (WiFi.status() != WL_CONNECTED); i++) {
led_effects::showRainbowWheel();
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
led_effects::showKITTWheel(color::green);
Serial.println();
Serial.print(F("WiFi - Connected! IP address: "));
Serial.println(WiFi.localIP());
} else {
//TODO: Allow sensor to work as an Access Point, in order to define SSID & password?
led_effects::showKITTWheel(color::red);
Serial.println(F("Connection to WiFi failed"));
// Wait for connection, at most wifi_timeout seconds
for (int i = 0; i <= config::wifi_timeout && (WiFi.status() != WL_CONNECTED); i++) {
led_effects::showRainbowWheel();
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
led_effects::showKITTWheel(color::green);
Serial.println();
Serial.print(F("WiFi - Connected! IP address: "));
IPAddress address = WiFi.localIP();
snprintf(local_ip, sizeof(local_ip), "%d.%d.%d.%d", address[0], address[1], address[2], address[3]);
Serial.println(local_ip);
} else {
//TODO: Allow sensor to work as an Access Point, in order to define SSID & password?
led_effects::showKITTWheel(color::red);
Serial.println(F("Connection to WiFi failed"));
}
}
}
......@@ -5,6 +5,9 @@
#include "util.h"
#include "led_effects.h"
void WiFiConnect(const String &hostname);
namespace wifi {
extern char local_ip[];
void connect(const char *hostname);
}
#endif
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