#include "WebServer.h" static const char WEB_ACTIONS[] PROGMEM = " Home" " Configure" " Weather" " Reset Settings" " Forget WiFi" " Firmware Update" " About"; String CHANGE_FORM = ""; // moved to config to make it dynamic static const char CLOCK_FORM[] PROGMEM = "

Display Clock when printer is off

" "

Use 24 Hour Clock (military time)

" "

Flip display orientation

" "

Flash System LED on Service Calls

" "

Use OctoPrint PSU control plugin for clock/blank

" "

Clock Sync / Weather Refresh (minutes)

"; static const char THEME_FORM[] PROGMEM = "

Theme Color

" "


" "

Use Security Credentials for Configuration Changes

" "

" "

" ""; static const char WEATHER_FORM[] PROGMEM = "

Weather Config:

" "

Display Weather when printer is off

" "" "" "

" "

Use Metric (Celsius)

" "

Weather Language

" "
" ""; static const char LANG_OPTIONS[] PROGMEM = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; static const char COLOR_THEMES[] PROGMEM = "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ""; WebServer::WebServer(GlobalDataController *globalDataController, DebugController *debugController) { this->globalDataController = globalDataController; this->debugController = debugController; } void WebServer::setup() { static WebServer* obj = this; this->server = new ESP8266WebServer(this->globalDataController->getWebserverPort()); this->serverUpdater = new ESP8266HTTPUpdateServer(); this->server->on("/", []() { obj->displayPrinterStatus(); }); this->server->on("/systemreset", []() { obj->handleSystemReset(); }); this->server->on("/forgetwifi", []() { obj->handleWifiReset(); }); this->server->on("/updateconfig", []() { obj->handleUpdateConfig(); }); this->server->on("/updateweatherconfig", []() { obj->handleUpdateWeather(); }); this->server->on("/configure", []() { obj->handleConfigure(); }); this->server->on("/configureweather", []() { obj->handleWeatherConfigure(); }); this->server->onNotFound([]() { obj->redirectHome(); }); this->serverUpdater->setup(this->server, "/update", this->globalDataController->getWebserverUsername(), this->globalDataController->getWebserverPassword()); // Start the server this->server->begin(); this->debugController->printLn("Server started"); } void WebServer::handleClient() { this->server->handleClient(); } boolean WebServer::authentication() { if (this->globalDataController->getWebserverIsBasicAuth() && (this->globalDataController->getWebserverUsername().length() >= 1 && this->globalDataController->getWebserverPassword().length() >= 1) ) { return this->server->authenticate( this->globalDataController->getWebserverUsername().c_str(), this->globalDataController->getWebserverPassword().c_str() ); } return true; // Authentication not required } void WebServer::redirectHome() { // Send them back to the Root Directory this->server->sendHeader("Location", String("/"), true); this->server->sendHeader("Cache-Control", "no-cache, no-store"); this->server->sendHeader("Pragma", "no-cache"); this->server->sendHeader("Expires", "-1"); this->server->send(302, "text/plain", ""); this->server->client().stop(); } void WebServer::displayPrinterStatus() { this->globalDataController->ledOnOff(true); BasePrinterClient *printerClient = this->globalDataController->getPrinterClient(); String html = ""; this->server->sendHeader("Cache-Control", "no-cache, no-store"); this->server->sendHeader("Pragma", "no-cache"); this->server->sendHeader("Expires", "-1"); this->server->setContentLength(CONTENT_LENGTH_UNKNOWN); this->server->send(200, "text/html", ""); this->server->sendContent(String(getHeader(true))); String displayTime = this->globalDataController->getTimeClient()->getAmPmHours() + ":" + this->globalDataController->getTimeClient()->getMinutes() + ":" + this->globalDataController->getTimeClient()->getSeconds() + " " + this->globalDataController->getTimeClient()->getAmPm(); if (this->globalDataController->getClockIs24h()) { displayTime = this->globalDataController->getTimeClient()->getHours() + ":" + this->globalDataController->getTimeClient()->getMinutes() + ":" + this->globalDataController->getTimeClient()->getSeconds(); } html += "

" + printerClient->getPrinterType() + " Monitor

"; html += "

"; if (printerClient->getPrinterType() == "Repetier") { html += "Printer Name: " + printerClient->getPrinterName() + "
"; } else { html += "Host Name: " + this->globalDataController->getPrinterHostName() + "
"; } if (printerClient->getError() != "") { html += "Status: Offline
"; html += "Reason: " + printerClient->getError() + "
"; } else { html += "Status: " + printerClient->getState(); if (printerClient->isPSUoff() && this->globalDataController->hasPrinterPsu()) { html += ", PSU off"; } html += "
"; } if (printerClient->isPrinting()) { html += "File: " + printerClient->getFileName() + "
"; float fileSize = printerClient->getFileSize().toFloat(); if (fileSize > 0) { fileSize = fileSize / 1024; html += "File Size: " + String(fileSize) + "KB
"; } int filamentLength = printerClient->getFilamentLength().toInt(); if (filamentLength > 0) { float fLength = float(filamentLength) / 1000; html += "Filament: " + String(fLength) + "m
"; } html += "Tool Temperature: " + printerClient->getTempToolActual() + "° C
"; if (printerClient->getTempBedActual() != 0 ) { html += "Bed Temperature: " + printerClient->getTempBedActual() + "° C
"; } int val = printerClient->getProgressPrintTimeLeft().toInt(); int hours = this->globalDataController->numberOfHours(val); int minutes = this->globalDataController->numberOfMinutes(val); int seconds = this->globalDataController->numberOfSeconds(val); html += "Est. Print Time Left: " + this->globalDataController->zeroPad(hours) + ":" + this->globalDataController->zeroPad(minutes) + ":" + this->globalDataController->zeroPad(seconds) + "
"; val = printerClient->getProgressPrintTime().toInt(); hours = this->globalDataController->numberOfHours(val); minutes = this->globalDataController->numberOfMinutes(val); seconds = this->globalDataController->numberOfSeconds(val); html += "Printing Time: " + this->globalDataController->zeroPad(hours) + ":" + this->globalDataController->zeroPad(minutes) + ":" + this->globalDataController->zeroPad(seconds) + "
"; html += ""; html += "

" + printerClient->getProgressCompletion() + "%
"; } else { html += "
"; } html += "

"; html += "

Time: " + displayTime + "

"; this->server->sendContent(html); // spit out what we got html = ""; /* if (DISPLAYWEATHER) { if (weatherClient.getCity(0) == "") { html += "

Please Configure Weather API

"; if (weatherClient.getError() != "") { html += "

Weather Error: " + weatherClient.getError() + "

"; } } else { html += "

" + weatherClient.getCity(0) + ", " + weatherClient.getCountry(0) + "

"; html += "
"; html += "" + weatherClient.getDescription(0) + "
"; html += weatherClient.getHumidity(0) + "% Humidity
"; html += weatherClient.getWind(0) + " " + getSpeedSymbol() + " Wind
"; html += "
"; html += "

"; html += weatherClient.getCondition(0) + " (" + weatherClient.getDescription(0) + ")
"; html += weatherClient.getTempRounded(0) + getTempSymbol(true) + "
"; html += " Map It!
"; html += "

"; } server.sendContent(html); // spit out what we got html = ""; // fresh start }*/ this->server->sendContent(String(getFooter())); this->server->sendContent(""); this->server->client().stop(); this->globalDataController->ledOnOff(false); } void WebServer::handleSystemReset() { if (!this->authentication()) { return this->server->requestAuthentication(); } this->debugController->printLn("Reset System Configuration"); if (this->globalDataController->resetConfig()) { redirectHome(); ESP.restart(); } } void WebServer::handleWifiReset() { if (!this->authentication()) { return this->server->requestAuthentication(); } //WiFiManager //Local intialization. Once its business is done, there is no need to keep it around redirectHome(); WiFiManager wifiManager; wifiManager.resetSettings(); ESP.restart(); } void WebServer::handleUpdateConfig() { boolean flipOld = this->globalDataController->isDisplayInverted(); if (!this->authentication()) { return this->server->requestAuthentication(); } if (this->server->hasArg("printer")) { this->globalDataController->getPrinterClient()->setPrinterName( this->server->arg("printer") ); } this->globalDataController->setPrinterApiKey(this->server->arg("PrinterApiKey")); this->globalDataController->setPrinterHostName(this->server->arg("PrinterHostName")); this->globalDataController->setPrinterServer(this->server->arg("PrinterAddress")); this->globalDataController->setPrinterPort(this->server->arg("PrinterPort").toInt()); this->globalDataController->setPrinterAuthUser(this->server->arg("octoUser")); this->globalDataController->setPrinterAuthPass(this->server->arg("octoPass")); this->globalDataController->setHasPrinterPsu(this->server->hasArg("hasPSU")); /*DISPLAYCLOCK = this->server->hasArg("isClockEnabled"); IS_24HOUR = this->server->hasArg("is24hour"); INVERT_DISPLAY = this->server->hasArg("invDisp"); USE_FLASH = this->server->hasArg("useFlash"); minutesBetweenDataRefresh = this->server->arg("refresh").toInt(); themeColor = this->server->arg("theme"); UtcOffset = this->server->arg("utcoffset").toFloat(); String temp = this->server->arg("userid"); temp.toCharArray(www_username, sizeof(temp)); temp = this->server->arg("stationpassword"); temp.toCharArray(www_password, sizeof(temp));*/ this->globalDataController->writeSettings(); //findMDNS(); this->globalDataController->getPrinterClient()->getPrinterJobResults(); this->globalDataController->getPrinterClient()->getPrinterPsuState(); /*if (INVERT_DISPLAY != flipOld) { ui.init(); if(INVERT_DISPLAY) display.flipScreenVertically(); ui.update(); } checkDisplay(); lastEpoch = 0; */ this->redirectHome(); } void WebServer::handleUpdateWeather() { if (!this->authentication()) { return this->server->requestAuthentication(); } //DISPLAYWEATHER = server.hasArg("isWeatherEnabled"); //WeatherApiKey = server.arg("openWeatherMapApiKey"); //CityIDs[0] = server.arg("city1").toInt(); //IS_METRIC = server.hasArg("metric"); //WeatherLanguage = server.arg("language"); this->globalDataController->writeSettings(); //isClockOn = false; // this will force a check for the display //checkDisplay(); //lastEpoch = 0; this->redirectHome(); } void WebServer::handleConfigure() { if (!this->authentication()) { return this->server->requestAuthentication(); } this->globalDataController->ledOnOff(true); BasePrinterClient *printerClient = this->globalDataController->getPrinterClient(); String html = ""; this->server->sendHeader("Cache-Control", "no-cache, no-store"); this->server->sendHeader("Pragma", "no-cache"); this->server->sendHeader("Expires", "-1"); this->server->setContentLength(CONTENT_LENGTH_UNKNOWN); this->server->send(200, "text/html", ""); html = this->getHeader(); this->server->sendContent(html); CHANGE_FORM = "

Station Config:

" "

" "

"; if (printerClient->getPrinterType() == "OctoPrint") { CHANGE_FORM += "

"; } CHANGE_FORM += "

" "

" "

" "

"; if (printerClient->getPrinterType() == "Repetier") { CHANGE_FORM += "" "

" ""; } else { CHANGE_FORM += "

"; } CHANGE_FORM += "

" "

"; if (printerClient->getPrinterType() == "Repetier") { html = ""; this->server->sendContent(html); } else { html = ""; this->server->sendContent(html); } String form = CHANGE_FORM; form.replace("%OCTOKEY%", this->globalDataController->getPrinterApiKey()); form.replace("%OCTOHOST%", this->globalDataController->getPrinterHostName()); form.replace("%OCTOADDRESS%", this->globalDataController->getPrinterServer()); form.replace("%OCTOPORT%", String(this->globalDataController->getPrinterPort())); form.replace("%OCTOUSER%", this->globalDataController->getPrinterAuthUser()); form.replace("%OCTOPASS%", this->globalDataController->getPrinterAuthPass()); this->server->sendContent(form); form = FPSTR(CLOCK_FORM); String isClockChecked = ""; if (DISPLAYCLOCK) { isClockChecked = "checked='checked'"; } form.replace("%IS_CLOCK_CHECKED%", isClockChecked); String is24hourChecked = ""; if (this->globalDataController->getClockIs24h()) { is24hourChecked = "checked='checked'"; } form.replace("%IS_24HOUR_CHECKED%", is24hourChecked); String isInvDisp = ""; if (this->globalDataController->isDisplayInverted()) { isInvDisp = "checked='checked'"; } form.replace("%IS_INVDISP_CHECKED%", isInvDisp); String isFlashLED = ""; if (USE_FLASH) { isFlashLED = "checked='checked'"; } form.replace("%USEFLASH%", isFlashLED); String hasPSUchecked = ""; if (this->globalDataController->hasPrinterPsu()) { hasPSUchecked = "checked='checked'"; } form.replace("%HAS_PSU_CHECKED%", hasPSUchecked); String options = ""; options.replace(">"+String(this->globalDataController->getClockResyncMinutes())+"<", " selected>"+String(this->globalDataController->getClockResyncMinutes())+"<"); form.replace("%OPTIONS%", options); this->server->sendContent(form); form = FPSTR(THEME_FORM); String themeOptions = FPSTR(COLOR_THEMES); themeOptions.replace(">"+String(this->globalDataController->getWebserverTheme())+"<", " selected>"+String(this->globalDataController->getWebserverTheme())+"<"); form.replace("%THEME_OPTIONS%", themeOptions); form.replace("%UTCOFFSET%", String(this->globalDataController->getClockUtcOffset())); String isUseSecurityChecked = ""; if (this->globalDataController->getWebserverIsBasicAuth()) { isUseSecurityChecked = "checked='checked'"; } form.replace("%IS_BASICAUTH_CHECKED%", isUseSecurityChecked); form.replace("%USERID%", String(this->globalDataController->getWebserverUsername())); form.replace("%STATIONPASSWORD%", String(this->globalDataController->getWebserverPassword())); this->server->sendContent(form); html = this->getFooter(); this->server->sendContent(html); this->server->sendContent(""); this->server->client().stop(); this->globalDataController->ledOnOff(false); } void WebServer::handleWeatherConfigure() { if (!this->authentication()) { return this->server->requestAuthentication(); } this->globalDataController->ledOnOff(true); String html = ""; this->server->sendHeader("Cache-Control", "no-cache, no-store"); this->server->sendHeader("Pragma", "no-cache"); this->server->sendHeader("Expires", "-1"); this->server->setContentLength(CONTENT_LENGTH_UNKNOWN); this->server->send(200, "text/html", ""); html = getHeader(); this->server->sendContent(html); String form = FPSTR(WEATHER_FORM); String isWeatherChecked = ""; if (DISPLAYWEATHER) { isWeatherChecked = "checked='checked'"; } /*form.replace("%IS_WEATHER_CHECKED%", isWeatherChecked); form.replace("%WEATHERKEY%", this->globalDataController()); form.replace("%CITYNAME1%", weatherClient.getCity(0)); form.replace("%CITY1%", String(CityIDs[0])); String checked = ""; if (IS_METRIC) { checked = "checked='checked'"; } form.replace("%METRIC%", checked); String options = FPSTR(LANG_OPTIONS); options.replace(">"+String(WeatherLanguage)+"<", " selected>"+String(WeatherLanguage)+"<"); form.replace("%LANGUAGEOPTIONS%", options); this->server->sendContent(form);*/ html = this->getFooter(); this->server->sendContent(html); this->server->sendContent(""); this->server->client().stop(); this->globalDataController->ledOnOff(false); } String WebServer::getHeader() { return this->getHeader(false); } String WebServer::getHeader(boolean refresh) { String menu = FPSTR(WEB_ACTIONS); String html = ""; html += "Printer Monitor"; html += ""; html += ""; if (refresh) { html += ""; } html += ""; html += ""; html += ""; html += ""; html += ""; html += "

Printer Monitor

"; html += ""; html += "
"; return html; } String WebServer::getFooter() { int8_t rssi = this->globalDataController->getWifiQuality(); Serial.print("Signal Strength (RSSI): "); Serial.print(rssi); this->debugController->printLn("%"); String html = "


"; html += "
"; html += ""; html += ""; return html; }