ESP3D/esp3d/webinterface.cpp
luc lebosse 2728b467a1 Code Cleaning
Implement define for MONITORING_FEATURE and MSG_FEATURE
Add better FM for SD Files
Light review of printer UI to separate sections
Add more control on Serial commands
Fix Github address
Change version to 0.8.0
Change default baud to 115200
Add Marlinkimbra support
2016-08-21 17:11:50 +02:00

3506 lines
130 KiB
C++

/*
webinterface.cpp - esp8266 configuration class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <pgmspace.h>
#include "config.h"
#include "webinterface.h"
#include "wifi.h"
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <WiFiUdp.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
extern "C" {
#include "user_interface.h"
}
#include "LinkedList.h"
#include "storestrings.h"
#include "command.h"
#ifdef SSDP_FEATURE
#include <ESP8266SSDP.h>
#endif
#define MAX_AUTH_IP 10
typedef enum {
UPLOAD_STATUS_NONE = 0,
UPLOAD_STATUS_FAILED = 1,
UPLOAD_STATUS_CANCELLED = 2,
UPLOAD_STATUS_SUCCESSFUL = 3,
UPLOAD_STATUS_ONGOING =4
} upload_status_type;
const char PAGE_404 [] PROGMEM ="<HTML>\n<HEAD>\n<title>Redirecting...</title> \n</HEAD>\n<BODY>\n<CENTER>Unknown page - you will be redirected...\n<BR><BR>\nif not redirected, <a href='http://$WEB_ADDRESS$'>click here</a>\n<BR><BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n\n<script>\nvar i = 0; \nvar x = document.getElementById(\"prg\"); \nx.max=5; \nvar interval=setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>5) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</CENTER>\n</BODY>\n</HTML>\n\n";
const char PAGE_RESTART [] PROGMEM ="<HTML>\n<HEAD>\n<title>Restarting...</title> \n</HEAD>\n<BODY>\n<CENTER>Restarting, please wait....\n<BR>\n<PROGRESS name='prg' id='prg'></PROGRESS>\n</CENTER>\n<script>\nvar i = 0;\nvar interval; \nvar x = document.getElementById(\"prg\"); \nx.max=40; \ninterval = setInterval(function(){\ni=i+1; \nvar x = document.getElementById(\"prg\"); \nx.value=i; \nif (i>40) \n{\nclearInterval(interval);\nwindow.location.href='/';\n}\n},1000);\n</script>\n</BODY>\n</HTML>\n";
const char RESTARTCMD [] PROGMEM ="<script>setTimeout(function(){window.location.href='/RESTART'},3000);</script>";
const char VALUE_11B[] PROGMEM = "11b";
const char VALUE_11N[] PROGMEM = "11n";
const char VALUE_11G[] PROGMEM = "11g";
const char VALUE_NONE[] PROGMEM = "None";
const char VALUE_LIGHT[] PROGMEM = "Light";
const char VALUE_MODEM[] PROGMEM = "Modem";
const char VALUE_ENABLED[] PROGMEM = "Enabled";
const char VALUE_DISABLED[] PROGMEM = "Disabled";
const char VALUE_WEP[] PROGMEM = "WEP";
const char VALUE_WPA[] PROGMEM = "WPA";
const char VALUE_WPA2[] PROGMEM = "WPA2";
const char VALUE_WPAWPA2[] PROGMEM = "WPA/WPA2";
const char VALUE_STARTED[] PROGMEM = "Started";
const char VALUE_STOPPED[] PROGMEM = "Stopped";
const char VALUE_NO[] PROGMEM = "No";
const char VALUE_YES[] PROGMEM = "Yes";
const char VALUE_CONNECTED[] PROGMEM = "Connected";
const char VALUE_NO_SSID[] PROGMEM = "SSID not Available!";
const char VALUE_CONNECTION_FAILED[] PROGMEM = "Connection failed!";
const char VALUE_CONNECTION_FAILED2[] PROGMEM = "Connection failed! (Wrong Password)";
const char VALUE_IDLE[] PROGMEM = "Idle";
const char VALUE_DISCONNECTED[] PROGMEM = "Disconnected";
const char VALUE_ITEM_VISIBLE[] PROGMEM = "visibility:visible;";
const char VALUE_ITEM_HIDDEN[] PROGMEM ="visibility:hidden;height:0px;width:0px;padding:0px";
const char KEY_IP[] PROGMEM ="$IP$";
const char KEY_WEB_ADDRESS[] PROGMEM ="$WEB_ADDRESS$";
const char KEY_HOSTNAME[] PROGMEM ="$HOSTNAME$";
const char KEY_HOSTNAME_VISIBLE[] PROGMEM ="$HOSTNAME_VISIBLE$";
const char KEY_NOT_APPLICABLE_4_AP[] PROGMEM ="Not applicable for Access Point";
const char KEY_PAGE_TITLE[] PROGMEM ="$PAGE_TITLE$";
const char VALUE_HOME[] PROGMEM = "Home";
const char VALUE_FW_VERSION[] PROGMEM = FW_VERSION;
const char VALUE_NOT_AVAILABLE [] PROGMEM ="Not available";
const char VALUE_NO_IP [] PROGMEM = "0.0.0.0";
const char KEY_FILE_NAME [] PROGMEM ="$FILE_NAME$";
const char KEY_SHORT_FILE_NAME [] PROGMEM ="$SHORT_FILE_NAME$";
const char KEY_MENU_HOME [] PROGMEM ="$MENU_HOME$";
const char KEY_MENU_SYSTEM [] PROGMEM ="$MENU_SYSTEM$";
const char KEY_MENU_AP [] PROGMEM ="$MENU_AP$";
const char KEY_MENU_STA [] PROGMEM ="$MENU_STA$";
const char KEY_MENU_PRINTER [] PROGMEM ="$MENU_PRINTER$";
const char KEY_MENU_SETTINGS [] PROGMEM ="$MENU_SETTINGS$";
const char KEY_MENU_ADMIN [] PROGMEM ="$MENU_ADMIN$";
const char KEY_FW_VER [] PROGMEM ="$FW_VER$";
const char KEY_CHIP_ID [] PROGMEM ="$CHIP_ID$";
const char KEY_CPU_FREQ [] PROGMEM ="$CPU_FREQ$";
const char KEY_SDK_VER [] PROGMEM ="$SDK_VER$";
const char KEY_MDNS_NAME [] PROGMEM = "$MDNS_NAME$";
const char KEY_MDNS_VISIBLE [] PROGMEM ="$MDNS_VISIBLE$";
const char KEY_CONNECTED_STATIONS_NB_ITEMS [] PROGMEM = "$CONNECTED_STATIONS_NB_ITEMS$";
const char KEY_CAPTIVE_PORTAL_STATUS [] PROGMEM = "$CAPTIVE_PORTAL_STATUS$";
const char KEY_CAPTIVE_PORTAL_VISIBLE [] PROGMEM = "$CAPTIVE_PORTAL_VISIBLE$";
const char KEY_SSDP_STATUS [] PROGMEM ="$SSDP_STATUS$";
const char KEY_SSDP_VISIBLE [] PROGMEM ="$SSDP_VISIBLE$";
const char KEY_NET_PHY [] PROGMEM ="$NET_PHY$";
const char KEY_SLEEP_MODE [] PROGMEM = "$SLEEP_MODE$";
const char KEY_BOOT_VER [] PROGMEM = "$BOOT_VER$";
const char KEY_WEB_PORT [] PROGMEM = "$WEB_PORT$";
const char KEY_DATA_PORT[] PROGMEM = "$DATA_PORT$";
const char KEY_BAUD_RATE [] PROGMEM = "$BAUD_RATE$";
const char KEY_REFRESH_PAGE [] PROGMEM = "$REFRESH_PAGE$";
const char KEY_AP_STATUS_ENABLED [] PROGMEM = "$AP_STATUS_ENABLED$";
const char KEY_AP_VISIBILITY [] PROGMEM = "$AP_VISIBILITY$";
const char KEY_AP_MAC [] PROGMEM = "$AP_MAC$";
const char KEY_AP_SSID [] PROGMEM = "$AP_SSID$";
const char KEY_AP_IS_VISIBLE [] PROGMEM = "$AP_IS_VISIBLE$";
const char KEY_AP_CHANNEL [] PROGMEM = "$AP_CHANNEL$";
const char KEY_AP_AUTH [] PROGMEM = "$AP_AUTH$";
const char KEY_AP_MAX_CON [] PROGMEM = "$AP_MAX_CON$";
const char KEY_AP_DHCP_STATUS [] PROGMEM = "$AP_DHCP_STATUS$";
const char KEY_AP_IP [] PROGMEM = "$AP_IP$";
const char KEY_AP_GW [] PROGMEM = "$AP_GW$";;
const char KEY_AP_SUBNET [] PROGMEM = "$AP_SUBNET$";;
const char KEY_STA_STATUS_ENABLED [] PROGMEM = "$STA_STATUS_ENABLED$";
const char KEY_STA_VISIBILITY [] PROGMEM = "$STA_VISIBILITY$";
const char VALUE_ACTIVE [] PROGMEM = "active";
const char KEY_STA_DHCP_STATUS [] PROGMEM = "$STA_DHCP_STATUS$";
const char KEY_STA_IP [] PROGMEM = "$STA_IP$";
const char KEY_STA_GW [] PROGMEM = "$STA_GW$";
const char KEY_STA_SUBNET [] PROGMEM = "$STA_SUBNET$";
const char KEY_STA_MAC [] PROGMEM = "$STA_MAC$";
const char KEY_STA_SSID [] PROGMEM = "$STA_SSID$";
const char KEY_STA_CHANNEL [] PROGMEM = "$STA_CHANNEL$";
const char KEY_STA_STATUS [] PROGMEM = "$STA_STATUS$";
const char KEY_FREE_MEM [] PROGMEM = "$FREE_MEM$";
const char KEY_SERVICE_PAGE [] PROGMEM = "$SERVICE_PAGE$";
const char ARG_SUBMIT [] PROGMEM = "SUBMIT";
const char KEY_MODE [] PROGMEM = "$MODE$";
const char VALUE_AP [] PROGMEM = "AP";
const char VALUE_STA [] PROGMEM = "STA";
const char VALUE_AP_STA [] PROGMEM = "AP_STA";
const char KEY_BAUD_RATE_OPTIONS_LIST [] PROGMEM ="$BAUD_RATE_OPTIONS_LIST$";
const char KEY_SLEEP_MODE_OPTIONS_LIST [] PROGMEM ="$SLEEP_MODE_OPTIONS_LIST$";
const char KEY_ERROR_MSG [] PROGMEM ="$ERROR_MSG$";
const char KEY_SUCCESS_MSG [] PROGMEM ="$SUCCESS_MSG$";
const char KEY_ERROR_MSG_VISIBILITY [] PROGMEM ="$ERROR_MSG_VISIBILITY$";
const char KEY_SUCCESS_MSG_VISIBILITY[] PROGMEM ="$SUCCESS_MSG_VISIBILITY$";
const char KEY_SUBMIT_BUTTON_VISIBILITY [] PROGMEM ="$SUBMIT_BUTTON_VISIBILITY$";
const char VALUE_CONFIG_AP [] PROGMEM = "Configuration Access Point";
const char VALUE_CONFIG_STA [] PROGMEM = "Configuration Station Client";
const char VALUE_PRINTER [] PROGMEM = "Printer Interface";
const char VALUE_HAS_ERROR [] PROGMEM = "has-error";
const char VALUE_HAS_SUCCESS [] PROGMEM = "has-success";
const char KEY_BAUD_RATE_STATUS [] PROGMEM = "$BAUD_RATE_STATUS$";
const char KEY_SLEEP_MODE_STATUS [] PROGMEM ="$SLEEP_MODE_STATUS$";
const char KEY_WEB_PORT_STATUS [] PROGMEM = "$WEB_PORT_STATUS$";
const char KEY_DATA_PORT_STATUS [] PROGMEM ="$DATA_PORT_STATUS$";
const char KEY_AP_SSID_STATUS [] PROGMEM = "$AP_SSID_STATUS$";
const char KEY_AP_PASSWORD_STATUS [] PROGMEM = "$AP_PASSWORD_STATUS$";
const char KEY_NETWORK_OPTION_LIST_STATUS [] PROGMEM = "$NETWORK_OPTION_LIST_STATUS$";
const char KEY_NETWORK_OPTION_LIST [] PROGMEM = "$NETWORK_OPTION_LIST$";
const char KEY_CHANNEL_OPTION_LIST_STATUS [] PROGMEM = "$CHANNEL_OPTION_LIST_STATUS$";
const char KEY_CHANNEL_OPTION_LIST [] PROGMEM = "$CHANNEL_OPTION_LIST$";
const char KEY_AUTH_OPTION_LIST_STATUS [] PROGMEM = "$AUTH_OPTION_LIST_STATUS$";
const char KEY_AUTH_OPTION_LIST [] PROGMEM = "$AUTH_OPTION_LIST$";
const char KEY_AP_IP_STATUS [] PROGMEM = "$AP_IP_STATUS$";
const char KEY_AP_GW_STATUS [] PROGMEM = "$AP_GW_STATUS$";
const char KEY_AP_SUBNET_STATUS [] PROGMEM = "$AP_SUBNET_STATUS$";
const char KEY_AP_PASSWORD [] PROGMEM = "$AP_PASSWORD$";
const char KEY_IS_SSID_VISIBLE_STATUS [] PROGMEM = "$IS_SSID_VISIBLE_STATUS$";
const char KEY_IS_SSID_VISIBLE [] PROGMEM = "$IS_SSID_VISIBLE$";
const char VALUE_CHECKED [] PROGMEM = "checked";
const char VALUE_SELECTED [] PROGMEM ="selected";
const char KEY_IS_STATIC_IP [] PROGMEM = "$IS_STATIC_IP$";
const char KEY_AP_STATIC_IP_STATUS [] PROGMEM = "$AP_STATIC_IP_STATUS$";
const char KEY_STA_STATIC_IP_STATUS [] PROGMEM = "$STA_STATIC_IP_STATUS$";
const char KEY_STA_SSID_STATUS [] PROGMEM = "$STA_SSID_STATUS$";
const char KEY_STA_PASSWORD_STATUS [] PROGMEM = "$STA_PASSWORD_STATUS$";
const char KEY_STA_IP_STATUS [] PROGMEM = "$STA_IP_STATUS$";
const char KEY_STA_GW_STATUS [] PROGMEM = "$STA_GW_STATUS$";
const char KEY_STA_SUBNET_STATUS [] PROGMEM = "$STA_SUBNET_STATUS$";
const char KEY_STA_PASSWORD [] PROGMEM = "$STA_PASSWORD$";
const char KEY_AVAILABLE_AP_NB_ITEMS [] PROGMEM = "$AVAILABLE_AP_NB_ITEMS$";
const char KEY_AP_SCAN_VISIBILITY [] PROGMEM = "$AP_SCAN_VISIBILITY$";
const char KEY_HOSTNAME_STATUS [] PROGMEM = "$HOSTNAME_STATUS$";
const char KEY_XY_FEEDRATE [] PROGMEM = "$XY_FEEDRATE$";
const char KEY_Z_FEEDRATE [] PROGMEM = "$Z_FEEDRATE$";
const char KEY_E_FEEDRATE [] PROGMEM = "$E_FEEDRATE$";
const char KEY_XY_FEEDRATE_STATUS [] PROGMEM = "$XY_FEEDRATE_STATUS$";
const char KEY_Z_FEEDRATE_STATUS [] PROGMEM = "$Z_FEEDRATE_STATUS$";
const char KEY_E_FEEDRATE_STATUS [] PROGMEM = "$E_FEEDRATE_STATUS$";
const char VALUE_SETTINGS [] PROGMEM = "Extra Settings";
const char KEY_REFRESH_PAGE_STATUS [] PROGMEM = "$REFRESH_PAGE_STATUS$";
const char KEY_DISCONNECT_VISIBILITY [] PROGMEM = "$DISCONNECT_VISIBILITY$";
const char VALUE_LOGIN [] PROGMEM = "Login page";
const char KEY_USER_STATUS [] PROGMEM = "$USER_STATUS$";
const char KEY_USER_PASSWORD_STATUS [] PROGMEM = "$USER_PASSWORD_STATUS$";
const char KEY_USER_PASSWORD_STATUS2 [] PROGMEM = "$USER_PASSWORD_STATUS2$";
const char KEY_USER [] PROGMEM = "$USER$";
const char KEY_USER_PASSWORD [] PROGMEM = "$USER_PASSWORD$";
const char KEY_USER_PASSWORD2 [] PROGMEM = "$USER_PASSWORD2$";
const char KEY_RETURN [] PROGMEM = "$RETURN$";
const char VALUE_CHANGE_PASSWORD [] PROGMEM = "Change Password";
const char MISSING_DATA [] PROGMEM = "Error: Missing data";
const char EEPROM_NOWRITE [] PROGMEM = "Error: Cannot write to EEPROM";
const char KEY_WEB_UPDATE [] PROGMEM = "$WEB_UPDATE_VISIBILITY$";
const char KEY_STA_SIGNAL [] PROGMEM = "$STA_SIGNAL$";
const char KEY_DATA_PORT_VISIBILITY [] PROGMEM = "$DATA_PORT_VISIBILITY$";
const char KEY_LOGIN_ID [] PROGMEM = "$LOGIN_ID$";
//TODO: should be in webserver class
bool WEBINTERFACE_CLASS::processTemplate(const char * filename, STORESTRINGS_CLASS & KeysList , STORESTRINGS_CLASS & ValuesList )
{
if(KeysList.size() != ValuesList.size()) { //Sanity check
Serial.print("Error");
return false;
}
LinkedList<FSFILE> myFileList = LinkedList<FSFILE>();
String buffer2send;
bool header_sent=false;
buffer2send="";
//open template file
FSFILE currentfile = SPIFFS.open(filename, "r");
//if error display error on web page
if (!currentfile) {
buffer2send = String(F("Error opening: ")) + filename;
web_interface->WebServer.send(200,"text/plain",buffer2send);
return false;
} else { //template is open
int b ;
String sLine;
bool bprocessing=true;
while (bprocessing) { //read all bytes
b = currentfile.read(); //from current open file
if (b!=-1) { //if not EOF
sLine+=char(b); //add to current line
if (b=='\n') { //end of line is reached
//change all variables by their values
for (int k=0; k<KeysList.size(); k++) {
sLine.replace(KeysList.get(k),ValuesList.get(k));
}
//is line an Include line ? no others command will be displayed
//but they can be used to build file name like
//$INCLUDE[$SHORT_FILENAME$-$MODE$.inc]$
int pos_tag=sLine.indexOf("$INCLUDE[");
if (pos_tag!=-1) { //if yes
//extract include file name
int pos_tag_end = sLine.indexOf("]$");
String includefilename = "/"+sLine.substring( pos_tag+strlen("$INCLUDE["),pos_tag_end);
//try to open include file
FSFILE includefile = SPIFFS.open(includefilename, "r");
if (!includefile) { //if error display it on web page
buffer2send+= String("Error opening: ") + includefilename;
} else { //if include is open lets read it, current open file is now include file
myFileList.add(currentfile);
currentfile=includefile;
}
} else { //if it is not include file
//check if there is a table to display
int pos_tag=sLine.indexOf("$CONNECTED_STATIONS[");
if (pos_tag!=-1) { //if yes
//extract line
int pos_tag_end = sLine.indexOf("]$",pos_tag);
int nb = -1;
int ipos = -1;
//part before repetitive section
String beforelinetoprocess=sLine.substring( 0,pos_tag);
//part after repetitive section
String afterlinetoprocess=sLine.substring( pos_tag_end+2);
//repetitive section itself
String linetoprocess =sLine.substring( pos_tag+strlen("$CONNECTED_STATIONS["),pos_tag_end);
String tablepart;
//get how many items
ipos=KeysList.get_index("$CONNECTED_STATIONS_NB_ITEMS$");
if (ipos >-1) {
//get value
nb=atoi(ValuesList.get(ipos));
ipos=ipos-(nb*3);
}
//do a sanity check data are there
String Last_IP_Key = "$IP_CONNECTED["+String(nb-1)+"]$";
if (nb>0 && (KeysList.get_index("$ROW_NUMBER[0]$")==ipos) &&(Last_IP_Key==KeysList.get(ipos-1+(nb*3)))) {
for (int j=0; j<nb; j++) {
String tmppart=linetoprocess + "\n";
if (ipos+j>-1) {
tmppart.replace("$ROW_NUMBER$",ValuesList.get(ipos+0+(j*3)));
tmppart.replace("$MAC_CONNECTED$",ValuesList.get(ipos+1+(j*3)));
tmppart.replace("$IP_CONNECTED$",ValuesList.get(ipos+2+(j*3)));
}
tablepart +=tmppart;
}
}
//now build back
sLine = beforelinetoprocess + tablepart + afterlinetoprocess;
}
pos_tag=sLine.indexOf("$AVAILABLE_AP[");
if (pos_tag!=-1) { //if yes
//extract line
int pos_tag_end = sLine.indexOf("]$",pos_tag);
int nb = -1;
int ipos = -1;
//part before repetitive section
String beforelinetoprocess=sLine.substring( 0,pos_tag);
//part after repetitive section
String afterlinetoprocess=sLine.substring( pos_tag_end+2);
//repetitive section itself
String linetoprocess =sLine.substring( pos_tag+strlen("$AVAILABLE_AP["),pos_tag_end);
String tablepart;
//get how many items
ipos=KeysList.get_index("$AVAILABLE_AP_NB_ITEMS$");
if (ipos >-1) {
//get value
nb=atoi(ValuesList.get(ipos));
ipos=ipos-(nb*4);
}
//do a sanity check data are there
String Last_IP_Key = "$IS_PROTECTED["+String(nb-1)+"]$";
if (nb>0 && (KeysList.get_index("$ROW_NUMBER[0]$")==ipos) &&(Last_IP_Key==KeysList.get(ipos-1+(nb*4)))) {
for (int j=0; j<nb; j++) {
String tmppart=linetoprocess + "\n";
if (ipos+j>-1) {
tmppart.replace("$ROW_NUMBER$",ValuesList.get(ipos+0+(j*4)));
tmppart.replace("$AP_SSID$",ValuesList.get(ipos+1+(j*4)));
tmppart.replace("$AP_SIGNAL$",ValuesList.get(ipos+2+(j*4)));
tmppart.replace("$IS_PROTECTED$",ValuesList.get(ipos+3+(j*4)));
}
tablepart +=tmppart;
}
}
//now build back
sLine = beforelinetoprocess + tablepart + afterlinetoprocess;
}
//add current line to buffer
buffer2send+=sLine;
//if buffer limit is reached
if (buffer2send.length()>1200) {
//if header is not send yet
if (!header_sent) {
//send header with calculated size
header_sent=true;
web_interface->WebServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
web_interface->WebServer.send(200);
web_interface->WebServer.sendHeader("Content-Type","text/html");
web_interface->WebServer.sendHeader("Cache-Control","no-cache");
}
//send data
web_interface->WebServer.sendContent(buffer2send);
//reset buffer
buffer2send="";
}
}
//reset line
sLine="";
//add a delay for safety for WDT
delay(1);
}
} else { //EOF is reached
//close current file
currentfile.close();
//if current file is not template file but included one
if (myFileList.size()>0) {
//get level +1 file description and continue
currentfile = myFileList.pop();
} else {
//we have done template parsing, let's stop reading
bprocessing=false;
}
}
}
}
//check if something is still in buffer and need to be send
if (buffer2send!="") {
//if header is not send yet
if (!header_sent) {
//send header
web_interface->WebServer.setContentLength(CONTENT_LENGTH_UNKNOWN);
web_interface->WebServer.send(200);
web_interface->WebServer.sendHeader("Content-Type","text/html");
web_interface->WebServer.sendHeader("Cache-Control","no-cache");
}
//send data
web_interface->WebServer.sendContent(buffer2send);
}
//close line
web_interface->WebServer.sendContent("");
return true;
}
// -----------------------------------------------------------------------------
// Helper for FreeMem and Firmware
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GetFreeMem(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
//FreeMem
KeysList.add(FPSTR(KEY_FREE_MEM));
ValuesList.add(CONFIG::intTostr(ESP.getFreeHeap()));
//FW Version
KeysList.add(FPSTR(KEY_FW_VER));
ValuesList.add(FPSTR(VALUE_FW_VERSION));
}
// -----------------------------------------------------------------------------
// Helper for Login ID
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GeLogin(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList,level_authenticate_type auth_level)
{
KeysList.add(FPSTR(KEY_DISCONNECT_VISIBILITY));
#ifdef AUTHENTICATION_FEATURE
if (auth_level != LEVEL_GUEST) {
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
KeysList.add(FPSTR(KEY_LOGIN_ID));
if (auth_level == LEVEL_ADMIN) ValuesList.add(FPSTR(DEFAULT_ADMIN_LOGIN));
else ValuesList.add(FPSTR(DEFAULT_USER_LOGIN));
} else
#endif
{
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_LOGIN_ID));
ValuesList.add("");
}
}
// -----------------------------------------------------------------------------
// Helper for IP+Web address
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GetIpWeb(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
String stmp;
KeysList.add(FPSTR(KEY_IP));
if (WiFi.getMode() == WIFI_STA ) {
stmp = WiFi.localIP().toString();
} else {
stmp = WiFi.softAPIP().toString();
}
ValuesList.add(stmp);
//Web address = ip + port
KeysList.add(FPSTR(KEY_WEB_ADDRESS));
if (wifi_config.iweb_port != 80) {
stmp.concat(":");
stmp.concat(wifi_config.iweb_port);
}
ValuesList.add(stmp);
}
// -----------------------------------------------------------------------------
// Helper for Wifi Mode
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GetMode(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
if (WiFi.getMode() == WIFI_STA ) {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_STA));
} else {
if (WiFi.getMode() == WIFI_AP ) {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_AP));
} else {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_AP_STA));
}
}
}
// -----------------------------------------------------------------------------
// Helper for Web ports
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GetPorts(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
//Web port
KeysList.add(FPSTR(KEY_WEB_PORT));
ValuesList.add(CONFIG::intTostr(wifi_config.iweb_port));
//Data port
KeysList.add(FPSTR(KEY_DATA_PORT));
KeysList.add(FPSTR(KEY_DATA_PORT_VISIBILITY));
#ifdef TCP_IP_DATA_FEATURE
ValuesList.add(CONFIG::intTostr(wifi_config.idata_port));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
#else
ValuesList.add(FPSTR(VALUE_NONE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
#endif
}
// -----------------------------------------------------------------------------
// Helper for Page properties
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::SetPageProp(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList,
const __FlashStringHelper *title, const __FlashStringHelper *filename)
{
String fullFilename(filename);
fullFilename.concat(".tpl");
//page title
KeysList.add(FPSTR(KEY_PAGE_TITLE));
ValuesList.add(title);
//tpl file name with extension
KeysList.add(FPSTR(KEY_FILE_NAME));
ValuesList.add(fullFilename);
//tpl file name without extension
KeysList.add(FPSTR(KEY_SHORT_FILE_NAME));
ValuesList.add(filename);
}
// -----------------------------------------------------------------------------
// Helper for DHCP (APP/STA)tus
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::GetDHCPStatus(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
KeysList.add(FPSTR(KEY_AP_DHCP_STATUS));
if (wifi_softap_dhcps_status() == DHCP_STARTED) {
ValuesList.add(FPSTR(VALUE_STARTED));
} else {
ValuesList.add(FPSTR(VALUE_STOPPED));
}
KeysList.add(FPSTR(KEY_STA_DHCP_STATUS));
if (wifi_station_dhcpc_status()==DHCP_STARTED) {
ValuesList.add(FPSTR(VALUE_STARTED));
} else {
ValuesList.add(FPSTR(VALUE_STOPPED));
}
}
// -----------------------------------------------------------------------------
// Helper for Error Msg processing
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::ProcessAlertError(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, String & smsg)
{
KeysList.add(FPSTR(KEY_ERROR_MSG));
ValuesList.add(smsg);
KeysList.add(FPSTR(KEY_SUCCESS_MSG));
ValuesList.add("");
KeysList.add(FPSTR(KEY_ERROR_MSG_VISIBILITY ));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
KeysList.add(FPSTR(KEY_SUCCESS_MSG_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_SUBMIT_BUTTON_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
}
// -----------------------------------------------------------------------------
// Helper for Success Msg processing
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::ProcessAlertSuccess(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList, String & smsg)
{
KeysList.add(FPSTR(KEY_ERROR_MSG));
ValuesList.add("");
KeysList.add(FPSTR(KEY_SUCCESS_MSG));
ValuesList.add(smsg);
KeysList.add(FPSTR(KEY_ERROR_MSG_VISIBILITY ));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_SUCCESS_MSG_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
KeysList.add(FPSTR(KEY_SUBMIT_BUTTON_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
}
// -----------------------------------------------------------------------------
// Helper for No Msg processing
// -----------------------------------------------------------------------------
void WEBINTERFACE_CLASS::ProcessNoAlert(STORESTRINGS_CLASS & KeysList, STORESTRINGS_CLASS & ValuesList)
{
KeysList.add(FPSTR(KEY_ERROR_MSG));
ValuesList.add("");
KeysList.add(FPSTR(KEY_SUCCESS_MSG));
ValuesList.add("");
KeysList.add(FPSTR(KEY_ERROR_MSG_VISIBILITY ));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_SUCCESS_MSG_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_SUBMIT_BUTTON_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
}
//root insterface
void handle_web_interface_root()
{
static const char HOME_PAGE [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /HOME\r\nCache-Control: no-cache\r\n\r\n";
web_interface->WebServer.sendContent_P(HOME_PAGE);
}
//root insterface
void handle_web_interface_home()
{
String stmp;
//long lstatus;
int istatus;
//byte bbuf;
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
struct softap_config apconfig;
struct ip_info info;
uint8_t mac [WL_MAC_ADDR_LENGTH];
//login
web_interface->GeLogin(KeysList, ValuesList,web_interface->is_authenticated());
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//Hostname
if (WiFi.getMode()==WIFI_STA ) {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_STA));
KeysList.add(FPSTR(KEY_HOSTNAME));
ValuesList.add(wifi_config.get_hostname());
KeysList.add(FPSTR(KEY_HOSTNAME_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
} else {
KeysList.add(FPSTR(KEY_HOSTNAME));
ValuesList.add(FPSTR(KEY_NOT_APPLICABLE_4_AP));
KeysList.add(FPSTR(KEY_HOSTNAME_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
if (WiFi.getMode()==WIFI_AP ) {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_AP));
} else {
KeysList.add(FPSTR(KEY_MODE));
ValuesList.add(FPSTR(VALUE_AP_STA));
}
}
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_HOME),F("home"));
//menu item
KeysList.add(FPSTR(KEY_MENU_HOME));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//Chip ID
KeysList.add(FPSTR(KEY_CHIP_ID));
ValuesList.add(CONFIG::intTostr(system_get_chip_id()));
//CPU Freq
KeysList.add(FPSTR(KEY_CPU_FREQ));
ValuesList.add(CONFIG::intTostr(system_get_cpu_freq()));
//SDK Version
KeysList.add(FPSTR(KEY_SDK_VER));
ValuesList.add(system_get_sdk_version());
//MDNS Feature
#ifdef MDNS_FEATURE
KeysList.add(FPSTR(KEY_MDNS_NAME));
stmp="http://";
stmp+=wifi_config.get_hostname();
stmp+=".local";
ValuesList.add(stmp);
KeysList.add(FPSTR(KEY_MDNS_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
#else
KeysList.add(FPSTR(KEY_MDNS_NAME));
ValuesList.add(FPSTR(VALUE_DISABLED));
KeysList.add(FPSTR(KEY_MDNS_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
#endif
//SSDP Feature
#ifdef SSDP_FEATURE
KeysList.add(FPSTR(KEY_SSDP_STATUS));
ValuesList.add(FPSTR(VALUE_ENABLED));
KeysList.add(FPSTR(KEY_SSDP_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
#else
KeysList.add(FPSTR(KEY_SSDP_STATUS));
ValuesList.add(FPSTR(VALUE_DISABLED));
KeysList.add(FPSTR(KEY_SSDP_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
#endif
//Captive portal Feature
#ifdef CAPTIVE_PORTAL_FEATURE
if (WiFi.getMode()==WIFI_AP) {
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_STATUS));
ValuesList.add(FPSTR(VALUE_ENABLED));
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
} else {
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_STATUS));
ValuesList.add(FPSTR(VALUE_DISABLED));
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
}
#else
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_STATUS));
ValuesList.add(FPSTR(VALUE_DISABLED));
KeysList.add(FPSTR(KEY_CAPTIVE_PORTAL_VISIBLE));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
#endif
//network
KeysList.add(FPSTR(KEY_NET_PHY));
if (WiFi.getPhyMode()==WIFI_PHY_MODE_11B) {
ValuesList.add(FPSTR(VALUE_11B));
} else if (WiFi.getPhyMode()==WIFI_PHY_MODE_11G) {
ValuesList.add(FPSTR(VALUE_11G));
} else {
ValuesList.add(FPSTR(VALUE_11N));
}
//sleep mode
KeysList.add(FPSTR(KEY_SLEEP_MODE));
if (WiFi.getSleepMode()==WIFI_NONE_SLEEP) {
ValuesList.add(FPSTR(VALUE_NONE));
} else if (WiFi.getSleepMode()==WIFI_LIGHT_SLEEP) {
ValuesList.add(FPSTR(VALUE_LIGHT));
} else {
ValuesList.add(FPSTR(VALUE_MODEM));
}
//Boot version
KeysList.add(FPSTR(KEY_BOOT_VER));
ValuesList.add(CONFIG::intTostr(system_get_boot_version()));
//Baud rate
KeysList.add(FPSTR(KEY_BAUD_RATE));
ValuesList.add(CONFIG::intTostr(wifi_config.baud_rate));
// Web and Data ports
web_interface->GetPorts(KeysList, ValuesList);
//AP part
if (WiFi.getMode()==WIFI_AP || WiFi.getMode()==WIFI_AP_STA) {
int client_counter=0;
struct station_info * station;
//AP is enabled
KeysList.add(FPSTR(KEY_AP_STATUS_ENABLED));
ValuesList.add(FPSTR(VALUE_ENABLED));
//set visible
KeysList.add(FPSTR(KEY_AP_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
//list of connected clients
station = wifi_softap_get_station_info();
while(station) {
//Row number
stmp = "$ROW_NUMBER["+String(client_counter)+"]$";
KeysList.add(stmp.c_str());
stmp=String(client_counter+1);
ValuesList.add(stmp);
//BSSID
stmp = "$MAC_CONNECTED["+String(client_counter)+"]$";
KeysList.add(stmp.c_str());
ValuesList.add(wifi_config.mac2str(station->bssid));
//IP
stmp = "$IP_CONNECTED["+String(client_counter)+"]$";
KeysList.add(stmp.c_str());
ValuesList.add(IPAddress((const uint8_t *)&station->ip).toString().c_str());
//increment counter
client_counter++;
//go next record
station = STAILQ_NEXT(station, next);
}
wifi_softap_free_station_info();
//Connected clients
KeysList.add(FPSTR(KEY_CONNECTED_STATIONS_NB_ITEMS));
ValuesList.add(CONFIG::intTostr(client_counter));
} else {
//AP is disabled
KeysList.add(FPSTR(KEY_AP_STATUS_ENABLED));
ValuesList.add(FPSTR(VALUE_DISABLED));
//set hide
KeysList.add(FPSTR(KEY_AP_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
//Connected clients
KeysList.add(FPSTR(KEY_CONNECTED_STATIONS_NB_ITEMS));
ValuesList.add("0");
}
//AP mac address
KeysList.add(FPSTR(KEY_AP_MAC));
ValuesList.add(wifi_config.mac2str(WiFi.softAPmacAddress(mac)));
//AP configuration
if (wifi_softap_get_config(&apconfig)) {
//SSID
KeysList.add(FPSTR(KEY_AP_SSID));
ValuesList.add((char *)(apconfig.ssid));
//AP visible or hidden
KeysList.add(FPSTR(KEY_AP_IS_VISIBLE));
if(apconfig.ssid_hidden==1) {
ValuesList.add(FPSTR(VALUE_NO));
} else {
ValuesList.add(FPSTR(VALUE_YES));
}
//Channel
KeysList.add(FPSTR(KEY_AP_CHANNEL));
ValuesList.add(CONFIG::intTostr(apconfig.channel));
//Authentification mode
KeysList.add(FPSTR(KEY_AP_AUTH));
if (apconfig.authmode==AUTH_OPEN) {
ValuesList.add(FPSTR(VALUE_NONE));
} else if (apconfig.authmode==AUTH_WEP) {
ValuesList.add(FPSTR(VALUE_WEP));
} else if (apconfig.authmode==AUTH_WPA_PSK) {
ValuesList.add(FPSTR(VALUE_WPA));
} else if (apconfig.authmode==AUTH_WPA2_PSK) {
ValuesList.add(FPSTR(VALUE_WPA2));
} else {
ValuesList.add(FPSTR(VALUE_WPAWPA2));
}
//Max connections
KeysList.add(FPSTR(KEY_AP_MAX_CON));
ValuesList.add(CONFIG::intTostr(apconfig.max_connection));
} else {
//SSID
KeysList.add(FPSTR(KEY_AP_SSID));
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
//AP visible or hidden
KeysList.add(FPSTR(KEY_AP_IS_VISIBLE));
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
//Channel
KeysList.add(FPSTR(KEY_AP_CHANNEL));
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
//Authentification mode
KeysList.add(FPSTR(KEY_AP_AUTH));
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
//Max connections
KeysList.add(FPSTR(KEY_AP_MAX_CON));
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
}
//DHCP Status
web_interface->GetDHCPStatus(KeysList, ValuesList);
//IP/GW/MASK
if (wifi_get_ip_info(SOFTAP_IF,&info)) {
//IP address
KeysList.add(FPSTR(KEY_AP_IP));
ValuesList.add(IPAddress((const uint8_t *)&(info.ip.addr)).toString().c_str());
//GW address
KeysList.add(FPSTR(KEY_AP_GW));
ValuesList.add(IPAddress((const uint8_t *)&(info.gw.addr)).toString().c_str());
//Sub Net Mask
KeysList.add(FPSTR(KEY_AP_SUBNET));
ValuesList.add(IPAddress((const uint8_t *)&(info.netmask.addr)).toString().c_str());
} else {
//IP address
KeysList.add(FPSTR(KEY_AP_IP));
ValuesList.add(FPSTR(VALUE_NO_IP));
//GW address
KeysList.add(FPSTR(KEY_AP_GW));
ValuesList.add(FPSTR(VALUE_NO_IP));
//Sub Net Mask
KeysList.add(FPSTR(KEY_AP_SUBNET));
ValuesList.add(FPSTR(VALUE_NO_IP));
}
//STA part
if (WiFi.getMode()==WIFI_STA || WiFi.getMode()==WIFI_AP_STA) {
//STA is enabled
KeysList.add(FPSTR(KEY_STA_STATUS_ENABLED));
ValuesList.add(FPSTR(VALUE_ENABLED));
//set visible
KeysList.add(FPSTR(KEY_STA_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
} else {
//STA is disabled
KeysList.add(FPSTR(KEY_STA_STATUS_ENABLED));
ValuesList.add(FPSTR(VALUE_DISABLED));
//set hide
KeysList.add(FPSTR(KEY_STA_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
}
//STA mac address
KeysList.add(FPSTR(KEY_STA_MAC));
ValuesList.add(wifi_config.mac2str(WiFi.macAddress(mac)));
//SSID used by STA
KeysList.add(FPSTR(KEY_STA_SSID));
if (WiFi.SSID().length()==0) {
ValuesList.add(FPSTR(VALUE_NOT_AVAILABLE));
} else {
ValuesList.add(WiFi.SSID().c_str());
}
//Channel
KeysList.add(FPSTR(KEY_STA_CHANNEL));
ValuesList.add(CONFIG::intTostr (wifi_get_channel()));
//Connection status
istatus = wifi_station_get_connect_status();
KeysList.add(FPSTR(KEY_STA_STATUS));
if (istatus==STATION_GOT_IP) {
ValuesList.add(FPSTR(VALUE_CONNECTED));
} else if (istatus==STATION_NO_AP_FOUND) {
ValuesList.add(FPSTR(VALUE_NO_SSID));
} else if (istatus==STATION_CONNECT_FAIL) {
ValuesList.add(FPSTR(VALUE_CONNECTION_FAILED));
} else if (istatus==STATION_WRONG_PASSWORD) {
ValuesList.add(FPSTR(VALUE_CONNECTION_FAILED2));
} else if (istatus==STATION_IDLE) {
ValuesList.add(FPSTR(VALUE_IDLE)); //should not happen
} else {
ValuesList.add(FPSTR(VALUE_DISCONNECTED));
}
//Signal strength
KeysList.add(FPSTR(KEY_STA_SIGNAL));
ValuesList.add(CONFIG::intTostr(wifi_config.getSignal(WiFi.RSSI())));
//DHCP Client status
web_interface->GetDHCPStatus(KeysList, ValuesList);
//IP address
KeysList.add(FPSTR(KEY_STA_IP));
ValuesList.add(WiFi.localIP().toString().c_str());
//GW address
KeysList.add(FPSTR(KEY_STA_GW));
ValuesList.add(WiFi.gatewayIP().toString().c_str());
//Sub Net Mask
KeysList.add(FPSTR(KEY_STA_SUBNET));
ValuesList.add(WiFi.subnetMask().toString().c_str());
//Service page / no need refresh on this page
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
//Firmware & Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/home.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
void handle_web_interface_configSys()
{
static const char NOT_AUTH_CS [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=CONFIGSYS\r\nCache-Control: no-cache\r\n\r\n";
String stmp,smsg;
//long lstatus;
int istatus;
//byte bbuf;
long ibaud=DEFAULT_BAUD_RATE;
int iweb_port =DEFAULT_WEB_PORT;
int idata_port =DEFAULT_DATA_PORT;
byte bsleepmode=DEFAULT_SLEEP_MODE;
bool msg_alert_error=false;
bool msg_alert_success=false;
long lbaudlist[] = {9600 ,19200,38400,57600,115200,230400,250000,-1};
int bmodemvaluelist[] = {WIFI_NONE_SLEEP,WIFI_LIGHT_SLEEP,WIFI_MODEM_SLEEP, -1};
const __FlashStringHelper *smodemdisplaylist[]= {FPSTR(VALUE_NONE),FPSTR(VALUE_LIGHT),FPSTR(VALUE_MODEM),FPSTR(VALUE_MODEM)};
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level != LEVEL_ADMIN) {
web_interface->WebServer.sendContent_P(NOT_AUTH_CS);
return;
}
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_HOME),F("system"));
//menu item
KeysList.add(FPSTR(KEY_MENU_SYSTEM));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//check is it is a submission or a display
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if (web_interface->WebServer.hasArg("BAUD_RATE")
&& web_interface->WebServer.hasArg("SLEEP_MODE")
#ifdef TCP_IP_DATA_FEATURE
&& web_interface->WebServer.hasArg("DATAPORT")
#endif
&& web_interface->WebServer.hasArg("WEBPORT")) {
//is each value correct ?
ibaud = web_interface->WebServer.arg("BAUD_RATE").toInt();
iweb_port = web_interface->WebServer.arg("WEBPORT").toInt();
#ifdef TCP_IP_DATA_FEATURE
idata_port = web_interface->WebServer.arg("DATAPORT").toInt();
#endif
bsleepmode = web_interface->WebServer.arg("SLEEP_MODE").toInt();
if (!(iweb_port>0 && iweb_port<65001)) {
msg_alert_error=true;
smsg.concat(F("Error: invalid port value for web port<BR>"));
KeysList.add(FPSTR(KEY_WEB_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
#ifdef TCP_IP_DATA_FEATURE
if (!(idata_port>0 && idata_port<65001)) {
msg_alert_error=true;
smsg.concat("Error: invalid port value for data port<BR>");
KeysList.add(FPSTR(KEY_DATA_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
#endif
if (iweb_port== idata_port) {
msg_alert_error=true;
smsg.concat("Error: web port and data port cannot be identical<BR>");
KeysList.add(FPSTR(KEY_WEB_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
KeysList.add(FPSTR(KEY_DATA_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (!(ibaud==9600 || ibaud==19200|| ibaud==38400|| ibaud==57600|| ibaud==115200|| ibaud==230400 || ibaud==250000)) {
msg_alert_error=true;
smsg.concat(F("Error: value for baud rate is not correct<BR>"));
KeysList.add(FPSTR(KEY_BAUD_RATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (!(bsleepmode==WIFI_NONE_SLEEP ||bsleepmode==WIFI_LIGHT_SLEEP ||bsleepmode==WIFI_MODEM_SLEEP )) {
msg_alert_error=true;
smsg.concat(F("Error: value for sleeping mode is not correct<BR>"));
KeysList.add(FPSTR(KEY_SLEEP_MODE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//if no error apply the changes
if (msg_alert_error!=true) {
if(!CONFIG::write_buffer(EP_BAUD_RATE,(const byte *)&ibaud,INTEGER_LENGTH)
||!CONFIG::write_buffer(EP_WEB_PORT,(const byte *)&iweb_port,INTEGER_LENGTH)
#ifdef TCP_IP_DATA_FEATURE
||!CONFIG::write_buffer(EP_DATA_PORT,(const byte *)&idata_port,INTEGER_LENGTH)
#endif
||!CONFIG::write_byte(EP_SLEEP_MODE,bsleepmode)) {
msg_alert_error=true;
smsg = FPSTR(EEPROM_NOWRITE);
} else {
msg_alert_success=true;
#ifdef TCP_IP_DATA_FEATURE
wifi_config.iweb_port=iweb_port;
#endif
wifi_config.idata_port=idata_port;
smsg = F("Changes saved to EEPROM, restarting....");
}
}
} else { //no submit need to get data from EEPROM
if (!CONFIG::read_buffer(EP_BAUD_RATE, (byte *)&ibaud , INTEGER_LENGTH)) {
ibaud=DEFAULT_BAUD_RATE;
}
if (!CONFIG::read_byte(EP_SLEEP_MODE, &bsleepmode )) {
bsleepmode=DEFAULT_SLEEP_MODE;
}
if (!CONFIG::read_buffer(EP_WEB_PORT, (byte *)&iweb_port , INTEGER_LENGTH)) {
iweb_port=DEFAULT_WEB_PORT;
}
wifi_config.iweb_port=iweb_port;
if (!CONFIG::read_buffer(EP_DATA_PORT, (byte *)&idata_port , INTEGER_LENGTH)) {
idata_port=DEFAULT_DATA_PORT;
}
wifi_config.idata_port=idata_port;
};
//Baud rate list
istatus = 0;
stmp="";
while (lbaudlist[istatus]>-1) {
stmp+="<OPTION VALUE=\"";
stmp+= CONFIG::intTostr(lbaudlist[istatus]);
stmp+="\" ";
if (lbaudlist[istatus]==ibaud) {
stmp+=FPSTR(VALUE_SELECTED);
}
stmp+=">" ;
stmp+=CONFIG::intTostr(lbaudlist[istatus]);
stmp+= "</OPTION>\n";
istatus++;
}
KeysList.add(FPSTR(KEY_BAUD_RATE_OPTIONS_LIST));
ValuesList.add(stmp);
//Sleep Mode
istatus = 0;
stmp="";
while (bmodemvaluelist[istatus]>-1) {
stmp+="<OPTION VALUE=\"";
stmp+= CONFIG::intTostr(bmodemvaluelist[istatus]);
stmp+="\" ";
if (bmodemvaluelist[istatus]==bsleepmode) {
stmp+=FPSTR(VALUE_SELECTED);
}
stmp+=">" ;
stmp+=smodemdisplaylist[istatus];
stmp+= "</OPTION>\n";
istatus++;
}
KeysList.add(FPSTR(KEY_SLEEP_MODE_OPTIONS_LIST));
ValuesList.add(stmp);
// Web and Data ports
web_interface->GetPorts(KeysList, ValuesList);
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else if (msg_alert_success) {
web_interface->ProcessAlertSuccess(KeysList, ValuesList, smsg);
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add(FPSTR(RESTARTCMD));
KeysList.add(FPSTR(KEY_BAUD_RATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_SLEEP_MODE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_WEB_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_DATA_PORT_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
}
else
{
web_interface->ProcessNoAlert(KeysList, ValuesList);
}
KeysList.add(FPSTR(KEY_WEB_UPDATE));
#ifdef WEB_UPDATE_FEATURE
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
#else
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
#endif
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/system.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
#ifdef AUTHENTICATION_FEATURE
void handle_password()
{
static const char NOT_AUTH_PW [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=PASSWORD\r\nCache-Control: no-cache\r\n\r\n";
String smsg;
String sPassword,sPassword2;
bool msg_alert_error=false;
bool msg_alert_success=false;
//int ipos;
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level == LEVEL_GUEST) {
web_interface->WebServer.sendContent_P(NOT_AUTH_PW);
return;
}
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_CHANGE_PASSWORD),F("password"));
//menu item
KeysList.add(FPSTR(KEY_MENU_ADMIN));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//check if it is a submission or a display
smsg="";
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if (web_interface->WebServer.hasArg("PASSWORD") && web_interface->WebServer.hasArg("PASSWORD2")) {
//Password
sPassword =web_interface->WebServer.arg("PASSWORD");
sPassword2 = web_interface->WebServer.arg("PASSWORD2");
if (!CONFIG::isLocalPasswordValid(sPassword.c_str()) ) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect password<BR>"));
KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (sPassword!=sPassword2) {
msg_alert_error=true;
smsg.concat(F("Error: Passwords do not match<BR>"));
KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS2));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//if no error apply the change
if (msg_alert_error==false) {
//save
bool res;
if (auth_level == LEVEL_ADMIN) res = CONFIG::write_string(EP_ADMIN_PWD,sPassword.c_str()) ;
else res = CONFIG::write_string(EP_USER_PWD,sPassword.c_str()) ;
if (!res) {
msg_alert_error=true;
smsg = FPSTR(EEPROM_NOWRITE);
} else {
msg_alert_success=true;
smsg = F("Changes saved to EEPROM");
}
}
}
else { //no submit, need to get data from EEPROM
//password
sPassword="";
sPassword2="";
}
//Display values
//password
KeysList.add(FPSTR(KEY_USER_PASSWORD));
ValuesList.add(sPassword);
KeysList.add(FPSTR(KEY_USER_PASSWORD2));
ValuesList.add(sPassword2);
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else if (msg_alert_success) {
web_interface->ProcessAlertSuccess(KeysList, ValuesList, smsg);
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
//Add all green
KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS2));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
}
else
{
web_interface->ProcessNoAlert(KeysList,ValuesList);
}
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/password.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
#endif
void handle_web_interface_configAP()
{
static const char NOT_AUTH_AP [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=CONFIGAP\r\nCache-Control: no-cache\r\n\r\n";
String stmp,smsg;
String sSSID,sPassword,sIP,sGW,sMask;
bool msg_alert_error=false;
bool msg_alert_success=false;
byte visible_buf;
byte static_ip_buf;
byte auth_buf;
byte channel_buf;
byte phy_mode_buf;
byte ip_sav[4];
byte gw_sav[4];
byte msk_sav[4];
int ipos;
int inetworkvaluelist []= {WIFI_PHY_MODE_11B,WIFI_PHY_MODE_11G,-1};
const __FlashStringHelper * inetworkdisplaylist []= {FPSTR(VALUE_11B),FPSTR(VALUE_11G),FPSTR(VALUE_11B)};
int iauthvaluelist[] = {AUTH_OPEN,AUTH_WPA_PSK,AUTH_WPA2_PSK,AUTH_WPA_WPA2_PSK,-1};
const __FlashStringHelper * iauthdisplaylist[] = {FPSTR(VALUE_NONE),FPSTR(VALUE_WPA),FPSTR(VALUE_WPA2),FPSTR(VALUE_WPAWPA2)};
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level != LEVEL_ADMIN) {
web_interface->WebServer.sendContent_P(NOT_AUTH_AP);
return;
}
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_CONFIG_AP),F("config_ap"));
//menu item
KeysList.add(FPSTR(KEY_MENU_AP));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//check is it is a submission or a display
smsg="";
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if (web_interface->WebServer.hasArg("SSID") && web_interface->WebServer.hasArg("PASSWORD")&& web_interface->WebServer.hasArg("NETWORK")
&& web_interface->WebServer.hasArg("AUTHENTIFICATION")&& web_interface->WebServer.hasArg("IP")
&& web_interface->WebServer.hasArg("GATEWAY")&& web_interface->WebServer.hasArg("SUBNET")
&& web_interface->WebServer.hasArg("CHANNEL")) {
//SSID
sSSID = web_interface->WebServer.arg("SSID");
if (!CONFIG::isSSIDValid(sSSID.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect SSID<BR>"));
KeysList.add(FPSTR(KEY_AP_SSID_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Password
sPassword = web_interface->WebServer.arg("PASSWORD");
if (!CONFIG::isPasswordValid(sPassword.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect password<BR>"));
KeysList.add(FPSTR(KEY_AP_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//ssid visible ?
if (web_interface->WebServer.hasArg("SSID_VISIBLE")) {
visible_buf=1;
} else {
visible_buf=0;
}
//phy mode
phy_mode_buf = byte(web_interface->WebServer.arg("NETWORK").toInt());
if (!(phy_mode_buf==WIFI_PHY_MODE_11B||phy_mode_buf==WIFI_PHY_MODE_11G) ) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect network<BR>"));
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//channel
channel_buf = byte (web_interface->WebServer.arg("CHANNEL").toInt());
if (channel_buf< 1|| channel_buf>11) {
msg_alert_error=true;
smsg.concat("Error: Incorrect channel<BR>");
KeysList.add(FPSTR(KEY_CHANNEL_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//authentification
auth_buf = byte(web_interface->WebServer.arg("AUTHENTIFICATION").toInt());
if (!(auth_buf == AUTH_OPEN || auth_buf == AUTH_WEP || auth_buf == AUTH_WPA_PSK ||
auth_buf == AUTH_WPA2_PSK || auth_buf == AUTH_WPA_WPA2_PSK)) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect authentification method<BR>"));
KeysList.add(FPSTR(KEY_AUTH_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Static IP ?
if (web_interface->WebServer.hasArg("STATIC_IP") ) {
static_ip_buf=STATIC_IP_MODE;
} else {
static_ip_buf=DHCP_MODE;
}
//IP
sIP = web_interface->WebServer.arg("IP");
if (!CONFIG::isIPValid(sIP.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect IP fortmat<BR>"));
KeysList.add(FPSTR(KEY_AP_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Gateway
sGW = web_interface->WebServer.arg("GATEWAY");
if (!CONFIG::isIPValid(sGW.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect gateway<BR>"));
KeysList.add(FPSTR(KEY_AP_GW_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//subnet
sMask = web_interface->WebServer.arg("SUBNET");
if (!CONFIG::isIPValid(sMask.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect subnet<BR>"));
KeysList.add(FPSTR(KEY_AP_SUBNET_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//if no error apply the change
if (msg_alert_error==false) {
//save
wifi_config.split_ip(sIP.c_str(),ip_sav);
wifi_config.split_ip(sGW.c_str(),gw_sav);
wifi_config.split_ip(sMask.c_str(),msk_sav);
if((!CONFIG::write_byte(EP_WIFI_MODE,AP_MODE))||
(!CONFIG::write_string(EP_SSID,sSSID.c_str()))||
(!CONFIG::write_string(EP_PASSWORD,sPassword.c_str()))||
(!CONFIG::write_byte(EP_SSID_VISIBLE,visible_buf))||
(!CONFIG::write_byte(EP_PHY_MODE,phy_mode_buf))||
(!CONFIG::write_byte(EP_CHANNEL,channel_buf)) ||
(!CONFIG::write_byte(EP_AUTH_TYPE,auth_buf)) ||
(!CONFIG::write_byte(EP_IP_MODE,static_ip_buf)) ||
(!CONFIG::write_buffer(EP_IP_VALUE,ip_sav,IP_LENGTH))||
(!CONFIG::write_buffer(EP_GATEWAY_VALUE,gw_sav,IP_LENGTH))||
(!CONFIG::write_buffer(EP_MASK_VALUE,msk_sav,IP_LENGTH))) {
msg_alert_error=true;
smsg = FPSTR(EEPROM_NOWRITE);
} else {
msg_alert_success=true;
smsg = F("Changes saved to EEPROM, restarting...");
}
}
}
else { //no submit need to get data from EEPROM
//ssid
if (!CONFIG::read_string(EP_SSID, sSSID , MAX_SSID_LENGTH) ) {
sSSID=FPSTR(DEFAULT_SSID);
}
//password
if (!CONFIG::read_string(EP_PASSWORD, sPassword , MAX_PASSWORD_LENGTH) ) {
sPassword=FPSTR(DEFAULT_PASSWORD);
}
//ssid visible ?
if (!CONFIG::read_byte(EP_SSID_VISIBLE, &visible_buf )) {
visible_buf=DEFAULT_SSID_VISIBLE;
}
//phy mode
if (!CONFIG::read_byte(EP_PHY_MODE, &phy_mode_buf )) {
phy_mode_buf=DEFAULT_PHY_MODE;
}
//authentification
if (!CONFIG::read_byte(EP_AUTH_TYPE, &auth_buf )) {
auth_buf=DEFAULT_AUTH_TYPE;
}
//channel
if (!CONFIG::read_byte(EP_CHANNEL, &channel_buf )) {
channel_buf=DEFAULT_CHANNEL;
}
//static IP ?
if (!CONFIG::read_byte(EP_IP_MODE, &static_ip_buf )) {
static_ip_buf=DEFAULT_IP_MODE;
}
//IP for static IP
if (!CONFIG::read_buffer(EP_IP_VALUE,ip_sav , IP_LENGTH) ) {
sIP=IPAddress((const uint8_t *)DEFAULT_IP_VALUE).toString();
} else {
sIP=IPAddress((const uint8_t *)ip_sav).toString();
}
//GW for static IP
if (!CONFIG::read_buffer(EP_GATEWAY_VALUE,gw_sav , IP_LENGTH) ) {
sGW=IPAddress((const uint8_t *)DEFAULT_GATEWAY_VALUE).toString();
} else {
sGW=IPAddress((const uint8_t *)gw_sav).toString();
}
//Subnet for static IP
if (!CONFIG::read_buffer(EP_MASK_VALUE,msk_sav , IP_LENGTH) ) {
sMask=IPAddress((const uint8_t *)DEFAULT_MASK_VALUE).toString();
} else {
sMask=IPAddress((const uint8_t *)msk_sav).toString();
}
}
//Display values
//ssid
KeysList.add(FPSTR(KEY_AP_SSID));
ValuesList.add(sSSID);
//password
KeysList.add(FPSTR(KEY_AP_PASSWORD));
ValuesList.add(sPassword);
//ssid visible ?
KeysList.add(FPSTR(KEY_IS_SSID_VISIBLE));
if (visible_buf==1) {
ValuesList.add(FPSTR(VALUE_CHECKED));
} else {
ValuesList.add("");
}
//network
ipos = 0;
stmp="";
while (inetworkvaluelist[ipos]>-1) {
stmp+="<OPTION VALUE=\"";
stmp+= CONFIG::intTostr(inetworkvaluelist[ipos]);
stmp+="\" ";
if (inetworkvaluelist[ipos]==phy_mode_buf) {
stmp+=FPSTR(VALUE_SELECTED);
}
stmp+=">" ;
stmp+=inetworkdisplaylist[ipos];
stmp+= "</OPTION>\n";
ipos++;
}
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST));
ValuesList.add(stmp);
//channel
stmp ="";
for (int c=1; c < 12; c++) {
stmp+="<OPTION VALUE=\"";
stmp+=CONFIG::intTostr(c);
stmp+="\" ";
if (channel_buf==c) {
stmp += FPSTR(VALUE_SELECTED);
} else {
stmp+="";
}
stmp+=" >";
stmp+=CONFIG::intTostr(c);
stmp+= "</OPTION>\n";
}
KeysList.add(FPSTR(KEY_CHANNEL_OPTION_LIST));
ValuesList.add(stmp);
//auth
ipos = 0;
stmp="";
while (iauthvaluelist[ipos]>-1) {
stmp+="<OPTION VALUE=\"";
stmp+= CONFIG::intTostr(iauthvaluelist[ipos]);
stmp+="\" ";
if (iauthvaluelist[ipos]==auth_buf) {
stmp+=FPSTR(VALUE_SELECTED);
}
stmp+=">" ;
stmp+=iauthdisplaylist[ipos];
stmp+= "</OPTION>\n";
ipos++;
}
KeysList.add(FPSTR(KEY_AUTH_OPTION_LIST));
ValuesList.add(stmp);
//static IP ?
KeysList.add(FPSTR(KEY_IS_STATIC_IP));
if (static_ip_buf==STATIC_IP_MODE) {
ValuesList.add(FPSTR(VALUE_CHECKED));
} else {
ValuesList.add("");
}
//IP for static IP
KeysList.add(FPSTR(KEY_AP_IP));
ValuesList.add(sIP);
//Gateway for static IP
KeysList.add(FPSTR(KEY_AP_GW));
ValuesList.add(sGW);
//Mask for static IP
KeysList.add(FPSTR(KEY_AP_SUBNET));
ValuesList.add(sMask);
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else if (msg_alert_success) {
web_interface->ProcessAlertSuccess(KeysList, ValuesList, smsg);
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add(FPSTR(RESTARTCMD));
//Add all green
KeysList.add(FPSTR(KEY_AP_SSID_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AP_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_IS_SSID_VISIBLE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_CHANNEL_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AUTH_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AP_STATIC_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AP_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AP_GW_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_AP_SUBNET_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
}
else
{
web_interface->ProcessNoAlert(KeysList,ValuesList);
}
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/config_ap.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
void handle_web_interface_configSTA()
{
static const char NOT_AUTH_STA [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=CONFIGSTA\r\nCache-Control: no-cache\r\n\r\n";
String stmp,smsg;
String sSSID,sPassword,sIP,sGW,sMask,sHostname;
bool msg_alert_error=false;
bool msg_alert_success=false;
byte static_ip_buf;
byte phy_mode_buf;
byte ip_sav[4];
byte gw_sav[4];
byte msk_sav[4];
bool revertSTA=false;
int ipos;
int inetworkvaluelist []= {WIFI_PHY_MODE_11B,WIFI_PHY_MODE_11G,WIFI_PHY_MODE_11N,-1};
const __FlashStringHelper * inetworkdisplaylist []= {FPSTR(VALUE_11B),FPSTR(VALUE_11G),FPSTR(VALUE_11N),FPSTR(VALUE_11B)};
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level != LEVEL_ADMIN) {
web_interface->WebServer.sendContent_P(NOT_AUTH_STA);
return;
}
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_CONFIG_STA),F("config_sta"));
//menu item
KeysList.add(FPSTR(KEY_MENU_STA));
ValuesList.add(FPSTR(VALUE_ACTIVE));
smsg="";
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if (web_interface->WebServer.hasArg("SSID") && web_interface->WebServer.hasArg("PASSWORD")&& web_interface->WebServer.hasArg("NETWORK")
&& web_interface->WebServer.hasArg("IP") && web_interface->WebServer.hasArg("GATEWAY")&& web_interface->WebServer.hasArg("SUBNET")
&& web_interface->WebServer.hasArg("HOSTNAME")) {
//SSID
sSSID = web_interface->WebServer.arg("SSID");
if (!CONFIG::isSSIDValid(sSSID.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect SSID<BR>"));
KeysList.add(FPSTR(KEY_STA_SSID_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Password
sPassword = web_interface->WebServer.arg("PASSWORD");
if (!CONFIG::isPasswordValid(sPassword.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect password<BR>"));
KeysList.add(FPSTR(KEY_STA_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Hostname
sHostname = web_interface->WebServer.arg("HOSTNAME");
if (!CONFIG::isHostnameValid(sHostname.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect hostname<BR>"));
KeysList.add(FPSTR(KEY_HOSTNAME_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//phy mode
phy_mode_buf = byte(web_interface->WebServer.arg("NETWORK").toInt());
if (!(phy_mode_buf==WIFI_PHY_MODE_11B||phy_mode_buf==WIFI_PHY_MODE_11G||phy_mode_buf==WIFI_PHY_MODE_11N) ) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect network<BR>"));
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Static IP ?
if (web_interface->WebServer.hasArg("STATIC_IP") ) {
static_ip_buf=STATIC_IP_MODE;
} else {
static_ip_buf=DHCP_MODE;
}
//IP
sIP= web_interface->WebServer.arg("IP");
if (!CONFIG::isIPValid(sIP.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect IP format<BR>"));
KeysList.add(FPSTR(KEY_STA_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Gateway
sGW = web_interface->WebServer.arg("GATEWAY");
if (!CONFIG::isIPValid(sGW.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect gateway<BR>"));
KeysList.add(FPSTR(KEY_STA_GW_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//subnet
sMask = web_interface->WebServer.arg("SUBNET");
if (!CONFIG::isIPValid(sMask.c_str())) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect subnet<BR>"));
KeysList.add(FPSTR(KEY_STA_SUBNET_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//no error ? then save
if (msg_alert_error==false) {
//save
wifi_config.split_ip(sIP.c_str(),ip_sav);
wifi_config.split_ip(sGW.c_str(),gw_sav);
wifi_config.split_ip(sMask.c_str(),msk_sav);
if((!CONFIG::write_byte(EP_WIFI_MODE,CLIENT_MODE))||
(!CONFIG::write_string(EP_SSID,sSSID.c_str()))||
(!CONFIG::write_string(EP_PASSWORD,sPassword.c_str()))||
(!CONFIG::write_string(EP_HOSTNAME,sHostname.c_str()))||
(!CONFIG::write_byte(EP_PHY_MODE,phy_mode_buf))||
(!CONFIG::write_byte(EP_IP_MODE,static_ip_buf)) ||
(!CONFIG::write_buffer(EP_IP_VALUE,ip_sav,IP_LENGTH))||
(!CONFIG::write_buffer(EP_GATEWAY_VALUE,gw_sav,IP_LENGTH))||
(!CONFIG::write_buffer(EP_MASK_VALUE,msk_sav,IP_LENGTH))) {
msg_alert_error=true;
smsg = FPSTR(EEPROM_NOWRITE);
} else {
msg_alert_success=true;
smsg = F("Changes saved to EEPROM, restarting...");
}
}
} else { //no submit, need to get data from EEPROM
//ssid
if (!CONFIG::read_string(EP_SSID, sSSID , MAX_SSID_LENGTH) ) {
sSSID=FPSTR(DEFAULT_SSID);
}
//password
if (!CONFIG::read_string(EP_PASSWORD, sPassword , MAX_PASSWORD_LENGTH) ) {
sPassword=FPSTR(DEFAULT_PASSWORD);
}
//hostname
if (!CONFIG::read_string(EP_HOSTNAME, sHostname , MAX_HOSTNAME_LENGTH) ) {
sHostname=wifi_config.get_default_hostname();
}
//phy mode
if (!CONFIG::read_byte(EP_PHY_MODE, &phy_mode_buf )) {
phy_mode_buf=DEFAULT_PHY_MODE;
}
//static IP ?
if (!CONFIG::read_byte(EP_IP_MODE, &static_ip_buf )) {
static_ip_buf=DEFAULT_IP_MODE;
}
//IP for static IP
if (!CONFIG::read_buffer(EP_IP_VALUE,ip_sav , IP_LENGTH) ) {
sIP=IPAddress((const uint8_t *)DEFAULT_IP_VALUE).toString();
} else {
sIP=IPAddress((const uint8_t *)ip_sav).toString();
}
//GW for static IP
if (!CONFIG::read_buffer(EP_GATEWAY_VALUE,gw_sav , IP_LENGTH) ) {
sGW=IPAddress((const uint8_t *)DEFAULT_GATEWAY_VALUE).toString();
} else {
sGW=IPAddress((const uint8_t *)gw_sav).toString();
}
//Subnet for static IP
if (!CONFIG::read_buffer(EP_MASK_VALUE,msk_sav , IP_LENGTH) ) {
sMask=IPAddress((const uint8_t *)DEFAULT_MASK_VALUE).toString();
} else {
sMask=IPAddress((const uint8_t *)msk_sav).toString();
}
}
//Display values
//ssid
KeysList.add(FPSTR(KEY_STA_SSID));
ValuesList.add(sSSID);
//password
KeysList.add(FPSTR(KEY_STA_PASSWORD));
ValuesList.add(sPassword);
//hostname
KeysList.add(FPSTR(KEY_HOSTNAME));
ValuesList.add(sHostname);
//network
ipos = 0;
stmp="";
while (inetworkvaluelist[ipos]>-1) {
stmp+="<OPTION VALUE=\"";
stmp+= CONFIG::intTostr(inetworkvaluelist[ipos]);
stmp+="\" ";
if (inetworkvaluelist[ipos]==phy_mode_buf) {
stmp+=FPSTR(VALUE_SELECTED);
}
stmp+=">" ;
stmp+=inetworkdisplaylist[ipos];
stmp+= "</OPTION>\n";
ipos++;
}
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST));
ValuesList.add(stmp);
//static IP ?
KeysList.add(FPSTR(KEY_IS_STATIC_IP));
if (static_ip_buf==STATIC_IP_MODE) {
ValuesList.add(FPSTR(VALUE_CHECKED));
} else {
ValuesList.add("");
}
//IP for static IP
KeysList.add(FPSTR(KEY_STA_IP));
ValuesList.add(sIP);
//Gateway for static IP
KeysList.add(FPSTR(KEY_STA_GW));
ValuesList.add(sGW);
//Mask for static IP
KeysList.add(FPSTR(KEY_STA_SUBNET));
ValuesList.add(sMask);
//do we need to do a scan and display it ?
if (!msg_alert_success) {
//if in AP mode switch to mixed mode to be able to scan
if (WiFi.getMode()!=WIFI_STA ) {
WiFi.mode(WIFI_AP_STA);
revertSTA=true;
}
int n = WiFi.scanNetworks();
for (int i = 0; i < n; ++i) {
//row number
stmp = "$ROW_NUMBER["+String(i)+"]$";
KeysList.add(stmp);
stmp=String(i+1);
ValuesList.add(stmp);
//SSID
stmp = "$AP_SSID["+String(i)+"]$";
KeysList.add(stmp);
ValuesList.add(WiFi.SSID(i).c_str());
//signal strength
stmp = "$AP_SIGNAL["+String(i)+"]$";
KeysList.add(stmp);
stmp = CONFIG::intTostr(wifi_config.getSignal(WiFi.RSSI(i))) ;
stmp += "%";
ValuesList.add(stmp);
//is protected
stmp = "$IS_PROTECTED["+String(i)+"]$";
KeysList.add(stmp);
if (WiFi.encryptionType(i) == ENC_TYPE_NONE) {
ValuesList.add(FPSTR(VALUE_NO));
} else {
ValuesList.add(FPSTR(VALUE_YES));
}
}
WiFi.scanDelete();
KeysList.add(FPSTR(KEY_AVAILABLE_AP_NB_ITEMS));
ValuesList.add(CONFIG::intTostr(n));
//revert to pure softAP
if (revertSTA) {
WiFi.mode(WIFI_AP);
}
KeysList.add(FPSTR(KEY_AP_SCAN_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_VISIBLE));
} else {
//no need to do a scan if we are going to restart
KeysList.add(FPSTR(KEY_AP_SCAN_VISIBILITY));
ValuesList.add(FPSTR(VALUE_ITEM_HIDDEN));
KeysList.add(FPSTR(KEY_AVAILABLE_AP_NB_ITEMS));
ValuesList.add(CONFIG::intTostr(0));
}
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else if (msg_alert_success) {
web_interface->ProcessAlertSuccess(KeysList, ValuesList, smsg);
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add(FPSTR(RESTARTCMD));
//Add all green
KeysList.add(FPSTR(KEY_STA_SSID_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_STA_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_NETWORK_OPTION_LIST_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_STA_STATIC_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_STA_IP_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_STA_GW_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_STA_SUBNET_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_HOSTNAME_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
}
else
{
web_interface->ProcessNoAlert(KeysList,ValuesList);
}
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/config_sta.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
void handle_web_interface_printer()
{
static const char NOT_AUTH_PRT [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=PRINTER\r\nCache-Control: no-cache\r\n\r\n";
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level == LEVEL_GUEST) {
web_interface->WebServer.sendContent_P(NOT_AUTH_PRT);
return;
}
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_PRINTER),F("printer"));
//menu item
KeysList.add(FPSTR(KEY_MENU_PRINTER));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//Refresh page time
KeysList.add(FPSTR(KEY_REFRESH_PAGE));
byte bflag;
if (!CONFIG::read_byte(EP_REFRESH_PAGE_TIME, &bflag )) {
ValuesList.add(CONFIG::intTostr(DEFAULT_REFRESH_PAGE_TIME*1000));
} else {
ValuesList.add(CONFIG::intTostr(1000*bflag));
}
int istatus;
//xy feedrate
KeysList.add(FPSTR(KEY_XY_FEEDRATE));
if (!CONFIG::read_buffer(EP_XY_FEEDRATE, (byte *)&istatus , INTEGER_LENGTH)) {
istatus=DEFAULT_XY_FEEDRATE;
}
ValuesList.add(CONFIG::intTostr(istatus));
//Z feedrate
KeysList.add(FPSTR(KEY_Z_FEEDRATE));
if (!CONFIG::read_buffer(EP_Z_FEEDRATE, (byte *)&istatus , INTEGER_LENGTH)) {
istatus=DEFAULT_Z_FEEDRATE;
}
ValuesList.add(CONFIG::intTostr(istatus));
//E feedrate
KeysList.add(FPSTR(KEY_E_FEEDRATE));
if (!CONFIG::read_buffer(EP_E_FEEDRATE, (byte *)&istatus , INTEGER_LENGTH)) {
istatus=DEFAULT_E_FEEDRATE;
}
ValuesList.add(CONFIG::intTostr(istatus));
//Serial.println("M114");
Serial.println(F("M220"));
Serial.println(F("M221"));
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
web_interface->processTemplate("/printer.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
void handle_web_settings()
{
static const char NOT_AUTH_SET [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /LOGIN?return=SETTINGS\r\nCache-Control: no-cache\r\n\r\n";
String smsg;
//int istatus;
//byte bbuf;
bool msg_alert_error=false;
bool msg_alert_success=false;
byte irefresh_page;
int ixy_feedrate,iz_feedrate,ie_feedrate;
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
level_authenticate_type auth_level= web_interface->is_authenticated();
if (auth_level == LEVEL_GUEST) {
web_interface->WebServer.sendContent_P(NOT_AUTH_SET);
return;
}
web_interface->blockserial = false;
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_SETTINGS),F("settings"));
//menu item
KeysList.add(FPSTR(KEY_MENU_SETTINGS));
ValuesList.add(FPSTR(VALUE_ACTIVE));
//check is it is a submission or a display
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if (web_interface->WebServer.hasArg("REFRESH_PAGE") && web_interface->WebServer.hasArg("XY_FEEDRATE")&& web_interface->WebServer.hasArg("Z_FEEDRATE")&& web_interface->WebServer.hasArg("E_FEEDRATE")) {
//is each value correct ?
irefresh_page = web_interface->WebServer.arg("REFRESH_PAGE").toInt();
ixy_feedrate = web_interface->WebServer.arg("XY_FEEDRATE").toInt();
iz_feedrate = web_interface->WebServer.arg("Z_FEEDRATE").toInt();
ie_feedrate = web_interface->WebServer.arg("E_FEEDRATE").toInt();
if (!(irefresh_page>=0 && irefresh_page<120)) {
msg_alert_error=true;
smsg.concat(F("Error: invalid value for refresh time<BR>"));
KeysList.add(FPSTR(KEY_REFRESH_PAGE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (!(ixy_feedrate>0 && ixy_feedrate<9999)) {
msg_alert_error=true;
smsg.concat(F("Error: invalid value for XY axis feedrate<BR>"));
KeysList.add(FPSTR(KEY_XY_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (!(iz_feedrate>0 && iz_feedrate<9999)) {
msg_alert_error=true;
smsg.concat(F("Error: invalid value for Z axis feedrate<BR>"));
KeysList.add(FPSTR(KEY_Z_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
if (!(ie_feedrate>0 && ie_feedrate<9999)) {
msg_alert_error=true;
smsg.concat(F("Error: invalid value for Extruder feedrate<BR>"));
KeysList.add(FPSTR(KEY_XY_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//if no error apply the changes
if (msg_alert_error!=true) {
if(!CONFIG::write_buffer(EP_XY_FEEDRATE,(const byte *)&ixy_feedrate,INTEGER_LENGTH)||!CONFIG::write_buffer(EP_Z_FEEDRATE,(const byte *)&iz_feedrate,INTEGER_LENGTH)||!CONFIG::write_buffer(EP_E_FEEDRATE,(const byte *)&ie_feedrate,INTEGER_LENGTH)||!CONFIG::write_byte(EP_REFRESH_PAGE_TIME,irefresh_page)) {
msg_alert_error=true;
smsg = FPSTR(EEPROM_NOWRITE);
} else {
msg_alert_success=true;
smsg = F("Changes saved to EEPROM");
}
}
} else { //no submit need to get data from EEPROM
if (!CONFIG::read_buffer(EP_XY_FEEDRATE, (byte *)&ixy_feedrate , INTEGER_LENGTH)) {
ixy_feedrate=DEFAULT_XY_FEEDRATE;
}
if (!CONFIG::read_byte(EP_REFRESH_PAGE_TIME, &irefresh_page )) {
irefresh_page=DEFAULT_REFRESH_PAGE_TIME;
}
if (!CONFIG::read_buffer(EP_Z_FEEDRATE, (byte *)&iz_feedrate , INTEGER_LENGTH)) {
iz_feedrate=DEFAULT_Z_FEEDRATE;
}
if (!CONFIG::read_buffer(EP_E_FEEDRATE, (byte *)&ie_feedrate , INTEGER_LENGTH)) {
ie_feedrate=DEFAULT_E_FEEDRATE;
}
}
//fill the variables
//refresh page
KeysList.add(FPSTR(KEY_REFRESH_PAGE));
ValuesList.add(CONFIG::intTostr(irefresh_page));
//xy feedrate
KeysList.add(FPSTR(KEY_XY_FEEDRATE));
ValuesList.add(CONFIG::intTostr(ixy_feedrate));
//Z feedrate
KeysList.add(FPSTR(KEY_Z_FEEDRATE));
ValuesList.add(CONFIG::intTostr(iz_feedrate));
//E feedrate
KeysList.add(FPSTR(KEY_E_FEEDRATE));
ValuesList.add(CONFIG::intTostr(ie_feedrate));
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else if (msg_alert_success) {
web_interface->ProcessAlertSuccess(KeysList, ValuesList, smsg);
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
KeysList.add(FPSTR(KEY_REFRESH_PAGE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_XY_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_Z_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_E_FEEDRATE_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_SUCCESS));
KeysList.add(FPSTR(KEY_SERVICE_PAGE));
ValuesList.add("");
}
else {
web_interface->ProcessNoAlert(KeysList,ValuesList);
}
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/settings.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
void handle_web_interface_status()
{
static const char NO_TEMP_LINE[] PROGMEM = "\"temperature\":\"0\",\"target\":\"0\",\"active\":\"0\"";
//we do not care if need authentication - just reset counter
web_interface->is_authenticated();
#ifdef POS_MONITORING_FEATURE
Serial.println(F("M114"));
#endif
int tagpos,tagpos2;
String buffer2send;
String value;
//start JSON answer
buffer2send="{";
#ifdef SPEED_MONITORING_FEATURE
//speed
buffer2send+="\"speed\":\""+web_interface->answer4M220 +"\",";
#endif
#ifdef FLOW_MONITORING_FEATURE
//flow
buffer2send+="\"flow\":\""+web_interface->answer4M221 +"\",";
#endif
#ifdef POS_MONITORING_FEATURE
//X position
tagpos = web_interface->answer4M114.indexOf("X:");
tagpos2 = web_interface->answer4M114.indexOf(" ",tagpos);
value=web_interface->answer4M114.substring(tagpos+2,tagpos2);
buffer2send+="\"Xpos\":\""+value +"\",";
//Y position
tagpos = web_interface->answer4M114.indexOf("Y:");
tagpos2 = web_interface->answer4M114.indexOf(" ",tagpos);
value=web_interface->answer4M114.substring(tagpos+2,tagpos2);
buffer2send+="\"Ypos\":\""+value +"\",";
//Z position
tagpos = web_interface->answer4M114.indexOf("Z:");
tagpos2 = web_interface->answer4M114.indexOf(" ",tagpos);
value=web_interface->answer4M114.substring(tagpos+2,tagpos2);
buffer2send+="\"Zpos\":\""+value +"\",";
#endif
#ifdef TEMP_MONITORING_FEATURE
//heater
buffer2send.concat(F("\"heater\":["));
//Extruder 1
buffer2send.concat(F("{\"name\":\"Extruder 1\","));
int Tpos = web_interface->answer4M105.indexOf("T0:");
byte bshift=1;
if (Tpos==-1) {
Tpos = web_interface->answer4M105.indexOf("T:");
bshift=0;
}
int slashpos = web_interface->answer4M105.indexOf(" /",Tpos);
int spacepos = web_interface->answer4M105.indexOf(" ",slashpos+2);
//have Extruder 1 ?
if(slashpos!=-1 && spacepos!=-1 ) {
buffer2send += "\"temperature\":\""+web_interface->answer4M105.substring(Tpos+2+bshift,slashpos)+
"\",\"target\":\""+web_interface->answer4M105.substring(slashpos+2,spacepos)+"\",\"active\":\"1\"";
} else { //no extruder temperature
buffer2send.concat(FPSTR(NO_TEMP_LINE));
}
buffer2send+="},";
//Extruder 2
buffer2send.concat(F("{\"name\":\"Extruder 2\","));
Tpos = web_interface->answer4M105.indexOf("T1:");
if (Tpos>-1) { //have extruder 2 ?
slashpos = web_interface->answer4M105.indexOf(" /",Tpos);
spacepos = web_interface->answer4M105.indexOf(" ",slashpos+2);
if(slashpos!=-1 && spacepos!=-1 ) {
buffer2send += "\"temperature\":\""+web_interface->answer4M105.substring(Tpos+3,slashpos)+
"\",\"target\":\""+web_interface->answer4M105.substring(slashpos+2,spacepos)+"\",\"active\":\"1\"";
} else { //no extruder temperature
buffer2send.concat(FPSTR(NO_TEMP_LINE));
}
} else { //no extruder temperature
buffer2send.concat(FPSTR(NO_TEMP_LINE));
}
buffer2send+="},";
//Bed
buffer2send.concat(F("{\"name\":\"Bed\","));
Tpos = web_interface->answer4M105.indexOf("B:");
if (Tpos>-1) {
slashpos = web_interface->answer4M105.indexOf(" /",Tpos);
spacepos = web_interface->answer4M105.indexOf(" ",slashpos+2);
if(slashpos!=-1 && spacepos!=-1 ) {
//temperature = (int)atof(web_interface->answer4M105.substring(Tpos+2,slashpos).c_str());
//target = (int)atof(web_interface->answer4M105.substring(slashpos+2,spacepos).c_str());
buffer2send += "\"temperature\":\""+web_interface->answer4M105.substring(Tpos+2,slashpos)+
"\",\"target\":\""+web_interface->answer4M105.substring(slashpos+2,spacepos)+"\",\"active\":\"1\"";
} else { //no extruder temperature
buffer2send.concat(FPSTR(NO_TEMP_LINE));
}
} else { //no extruder temperature
buffer2send.concat(FPSTR(NO_TEMP_LINE));
}
buffer2send+="}";
buffer2send+="],";
#endif
#ifdef INFO_MSG_FEATURE
//information
buffer2send.concat(F("\"InformationMsg\":["));
for (int i=0; i<web_interface->info_msg.size(); i++) {
if (i>0) {
buffer2send+=",";
}
buffer2send+="{\"line\":\"";
buffer2send+=web_interface->info_msg.get(i);
buffer2send+="\"}";
}
buffer2send+="],";
#endif
#ifdef ERROR_MSG_FEATURE
//Error
buffer2send.concat(F("\"ErrorMsg\":["));
for (int i=0; i<web_interface->error_msg.size(); i++) {
if (i>0) {
buffer2send+=",";
}
buffer2send+="{\"line\":\"";
buffer2send+=web_interface->error_msg.get(i);
buffer2send+="\"}";
}
buffer2send+="],";
#endif
#ifdef STATUS_MSG_FEATURE
//Status
buffer2send.concat(F("\"StatusMsg\":["));
for (int i=0; i<web_interface->status_msg.size(); i++) {
if (i>0) {
buffer2send+=",";
}
buffer2send+="{\"line\":\"";
buffer2send+=web_interface->status_msg.get(i);
buffer2send+="\"}";
}
buffer2send+="],";
#endif
#ifdef TEMP_MONITORING_FEATURE
//request temperature only if no feedback
if ((millis()-web_interface->last_temp)>2000) {
Serial.println(F("M105"));
}
if ((millis()-web_interface->last_temp)<30000) {
value="Connected";
} else if ((millis()-web_interface->last_temp)<60000) {
value="Busy";
} else {
value="Offline";
}
#endif
//status color
buffer2send+="\"status\":\""+value +"\"";
buffer2send+="}";
web_interface->WebServer.sendHeader("Cache-Control", "no-cache");
web_interface->WebServer.send(200, "application/json",buffer2send);
}
void SPIFFSFileupload()
{
//get authentication status
level_authenticate_type auth_level= web_interface->is_authenticated();
//Guest cannot upload
if (auth_level == LEVEL_GUEST)
{
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Error ESP upload");
return;
}
//get current file ID
HTTPUpload& upload = (web_interface->WebServer).upload();
//Upload start
//**************
if(upload.status == UPLOAD_FILE_START) {
String filename;
//according User or Admin the root is different as user is isolate to /user when admin has full access
if(auth_level == LEVEL_ADMIN) filename = upload.filename;
else filename = "/user" + upload.filename;
Serial.println("M117 Start ESP upload");
//create file
web_interface->fsUploadFile = SPIFFS.open(filename, "w");
filename = String();
//check If creation succeed
if (web_interface->fsUploadFile)
{ //if yes upload is started
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
}
else
{ //if no set cancel flag
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Error ESP create");
}
//Upload write
//**************
} else if(upload.status == UPLOAD_FILE_WRITE)
{ //check if file is availble and no error
if(web_interface->fsUploadFile && web_interface->_upload_status == UPLOAD_STATUS_ONGOING)
{
//no error so write post date
web_interface->fsUploadFile.write(upload.buf, upload.currentSize);
}
else
{ //we have a proble set flag UPLOAD_STATUS_CANCELLED
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Error ESP write");
}
//Upload end
//**************
} else if(upload.status == UPLOAD_FILE_END) {
Serial.println("M117 End ESP upload");
//check if file is still open
if(web_interface->fsUploadFile)
{ //close it
web_interface->fsUploadFile.close();
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
}
else
{ //we have a proble set flag UPLOAD_STATUS_CANCELLED
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Error ESP close");
}
//Upload cancelled
//**************
} else {
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Error ESP upload");
}
delay(0);
}
#define NB_RETRY 5
#define MAX_RESEND_BUFFER 128
void SDFileupload()
{
static char buffer_line[MAX_RESEND_BUFFER]; //if need to resend
static char previous = 0;
static int buffer_size;
static bool com_error = false;
static bool is_comment = false;
String response;
//Guest cannot upload - only admin and user
if(web_interface->is_authenticated() == LEVEL_GUEST)
{
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 SD upload failed");
LOG("SD upload failed\n");
return;
}
//retrieve current file id
HTTPUpload& upload = (web_interface->WebServer).upload();
//Upload start
//**************
if(upload.status == UPLOAD_FILE_START) {
//need to lock serial out to avoid garbage in file
(web_interface->blockserial) = true;
//init flags
buffer_size=0;
com_error = false;
is_comment = false;
previous = 0;
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
Serial.println("M117 Uploading...");
LOG(String(upload.filename));
LOG("\n");
//command to pritnter to start print
String filename = "M28 " + upload.filename;
Serial.println(filename);
Serial.flush();
//now need to purge all serial data
//let's sleep 1s
delay(1000);
for (int retry=0;retry < 400; retry++) { //time out is 5x400ms = 2000ms
//if there is something in serial buffer
if(Serial.available()){
//get size of buffer
size_t len = Serial.available();
uint8_t sbuf[len+1];
//read buffer
Serial.readBytes(sbuf, len);
//convert buffer to zero end array
sbuf[len]='\0';
//use string because easier to handle
response = (const char*)sbuf;
//if there is a wait it means purge is done
if (response.indexOf("wait")>-1)break;
}
delay(5);
}
//Upload write
//**************
//upload is on going with data coming by 2K blocks
} else if((upload.status == UPLOAD_FILE_WRITE) && (com_error == false)){//if com error no need to send more data to serial
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
for (int pos = 0; pos < upload.currentSize;pos++) //parse full post data
{
if (buffer_size < MAX_RESEND_BUFFER-1) //raise error/handle if overbuffer - copy is space available
{
//remove/ignore every comment to save transfert time and avoid over buffer issues
if (upload.buf[pos] == ';'){
is_comment = true;
previous = ';';
}
if (!is_comment){
buffer_line[buffer_size] = upload.buf[pos]; //copy current char to buffer to send/resend
buffer_size++;
//convert buffer to zero end array
buffer_line[buffer_size] = '\0';
//check it is not an end line char and line is not empty
if (((buffer_line[0] == '\n') && (buffer_size==1)) ||((buffer_line[1] == '\n') && (buffer_line[0] == '\r') && (buffer_size==2)) || ((buffer_line[0] == ' ') && (buffer_size==1)) )
{
//ignore empty line
buffer_size=0;
buffer_line[buffer_size] = '\0';
}
//line is not empty so check if last char is an end line
//if error no need to proceed
else if (((buffer_line[buffer_size-1] == '\n')) && (com_error == false)) //end of line and no error
{
//if resend use buffer
bool success = false;
//check NB_RETRY times if get no error when send line
for (int r = 0 ; r < NB_RETRY ; r++)
{
response = "";
//print out line
Serial.print(buffer_line);
LOG(buffer_line);
//ensure buffer is empty before continuing
Serial.flush();
//wait for answer with time out
for (int retry=0;retry < 30; retry++) { //time out 30x5ms = 150ms
//if there is serial data
if(Serial.available()){
//get size of available data
size_t len = Serial.available();
uint8_t sbuf[len+1];
//read serial buffer
Serial.readBytes(sbuf, len);
//convert buffer in zero end array
sbuf[len]='\0';
//use string because easier
response = (const char*)sbuf;
LOG("Retry:");
LOG(String(retry));
LOG("\n");
LOG(response);
//if buffer contain ok or wait - it means command is pass
if ((response.indexOf("wait")>-1)||(response.indexOf("ok")>-1)){
success = true;
break;
}
//if buffer contain resend then need to resend
if (response.indexOf("Resend") > -1){//if error
success = false;
break;
}
}
delay(5);
}
//if command is pass no need to retry
if (success == true)break;
//purge extra serial if any
if(Serial.available()){
//get size of available data
size_t len = Serial.available();
uint8_t sbuf[len+1];
//read serial buffer
Serial.readBytes(sbuf, len);
//convert buffer in zero end array
sbuf[len]='\0';
}
}
//if even after the number of retry still have error - then we are in error
if (!success){
//raise error
LOG("Error detected\n");
LOG(response);
com_error = true;
}
//reset buffer for next command
buffer_size = 0;
buffer_line[buffer_size] = '\0';
}
}
else { //it is a comment
if (upload.buf[pos] == '\r'){ //store if CR
previous = '\r';
}
else if (upload.buf[pos] == '\n'){ //this is the end of the comment
is_comment = false;
if (buffer_size > 0) {
if (previous == '\r') pos--;
pos--; //do a loop back and process as normal
}
previous = '\n';
}//if not just ignore and continue
else previous = upload.buf[pos];
}
}
else //raise error
{
LOG("\nlong line detected\n");
LOG(buffer_line);
com_error = true;
}
}
//Upload end
//**************
} else if(upload.status == UPLOAD_FILE_END) {
if (buffer_size > 0){//if last part does not have '\n'
//print the line
Serial.print(buffer_line);
if (is_comment && (previous == '\r'))Serial.print("\r\n");
else Serial.print("\n");
Serial.flush();
//if resend use buffer
bool success = false;
//check NB_RETRY times if get no error when send line
for (int r = 0 ; r < NB_RETRY ; r++)
{
response = "";
Serial.print(buffer_line);
Serial.flush();
//wait for answer with time out
for (int retry=0;retry < 20; retry++) { //time out
if(Serial.available()){
size_t len = Serial.available();
uint8_t sbuf[len+1];
Serial.readBytes(sbuf, len);
sbuf[len]='\0';
response = (const char*)sbuf;
if ((response.indexOf("wait")>-1)||(response.indexOf("ok")>-1)){
success = true;
break;
}
if (response.indexOf("Resend") > -1){//if error
success = false;
break;
}
}
delay(5);
}
if (success == true)break;
}
if (!success){
//raise error
LOG("Error detected 2\n");
LOG(response);
com_error = true;
}
//reset buffer for next command
buffer_size = 0;
buffer_line[buffer_size] = '\0';
}
LOG("Upload finished ");
buffer_size=0;
buffer_line[buffer_size] = '\0';
//send M29 command to close file on SD
Serial.print("\r\nM29\r\n");
Serial.flush();
web_interface->blockserial = false;
delay(1000);//give time to FW
//resend M29 command to close file on SD as first command may be lost
Serial.print("\r\nM29\r\n");
Serial.flush();
if (com_error){
LOG("with error\n");
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 SD upload failed");
Serial.flush();
}
else
{
LOG("with success\n");
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
Serial.println("M117 SD upload done");
Serial.flush();
}
//Upload cancelled
//**************
} else { //UPLOAD_FILE_ABORTED
LOG("Error, Something happened\n");
com_error = true;
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
buffer_size=0;
buffer_line[buffer_size] = '\0';
//send M29 command to close file on SD
Serial.print("\r\nM29\r\n");
Serial.flush();
web_interface->blockserial = false;
delay(1000);
//resend M29 command to close file on SD as first command may be lost
Serial.print("\r\nM29\r\n");
Serial.flush();
Serial.println("M117 SD upload failed");
Serial.flush();
}
}
#ifdef WEB_UPDATE_FEATURE
void WebUpdateUpload()
{
//only admin can update FW
if(web_interface->is_authenticated() != LEVEL_ADMIN)
{
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
Serial.println("M117 Update failed");
LOG("SD Update failed\n");
return;
}
//get current file ID
HTTPUpload& upload = (web_interface->WebServer).upload();
//Upload start
//**************
if(upload.status == UPLOAD_FILE_START) {
Serial.println(F("M117 Update Firmware"));
web_interface->_upload_status= UPLOAD_STATUS_ONGOING;
WiFiUDP::stopAll();
uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000;
if(!Update.begin(maxSketchSpace)) { //start with max available size
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
}
//Upload write
//**************
} else if(upload.status == UPLOAD_FILE_WRITE) {
//check if no error
if (web_interface->_upload_status == UPLOAD_STATUS_ONGOING)
{
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize)
{
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
}
}
//Upload end
//**************
} else if(upload.status == UPLOAD_FILE_END) {
if(Update.end(true)) { //true to set the size to the current progress
//Now Reboot
Serial.println(F("M117 Update Done"));
web_interface->_upload_status=UPLOAD_STATUS_SUCCESSFUL;
}
} else if(upload.status == UPLOAD_FILE_ABORTED) {
Serial.println(F("M117 Update Failed"));
Update.end();
web_interface->_upload_status=UPLOAD_STATUS_CANCELLED;
}
delay(0);
}
void handleUpdate()
{
//upload can be long so better to reset time out
web_interface->is_authenticated();
String jsonfile = "{\"status\":\"" ;
jsonfile+=CONFIG::intTostr(web_interface->_upload_status);
jsonfile+="\"}";
//send status
web_interface->WebServer.sendHeader("Cache-Control", "no-cache");
web_interface->WebServer.send(200, "application/json", jsonfile);
//if success restart
if (web_interface->_upload_status==UPLOAD_STATUS_SUCCESSFUL) {
web_interface->restartmodule=true;
}
}
#endif
void handleFileList()
{
level_authenticate_type auth_level = web_interface->is_authenticated();
if (auth_level == LEVEL_GUEST) {
return;
}
String path ;
String status = "Ok";
//be sure root is correct according authentication
if (auth_level == LEVEL_ADMIN) path = "/";
else path = "/user";
//get current path
if(web_interface->WebServer.hasArg("path"))path += web_interface->WebServer.arg("path") ;
//to have a clean path
path.trim();
path.replace("//","/");
if (path[path.length()-1] !='/')path +="/";
//check if query need some action
if(web_interface->WebServer.hasArg("action")) {
//delete a file
if(web_interface->WebServer.arg("action") == "delete" && web_interface->WebServer.hasArg("filename")) {
String filename;
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename = path + web_interface->WebServer.arg("filename");
filename.replace("//","/");
if(!SPIFFS.exists(filename)) {
status = shortname + F(" does not exists!");
} else {
if (SPIFFS.remove(filename))
{
status = shortname + F(" deleted");
//what happen if no "/." and no other subfiles ?
FSDIR dir = SPIFFS.openDir(path);
if (!dir.next())
{ //keep directory alive even empty
FSFILE r = SPIFFS.open(path+"/.","w");
if (r)r.close();
}
}
else {
status = F("Cannot deleted ") ;
status+=shortname ;
}
}
}
//delete a directory
if(web_interface->WebServer.arg("action") == "deletedir" && web_interface->WebServer.hasArg("filename")) {
String filename;
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename = path + web_interface->WebServer.arg("filename");
filename += "/.";
filename.replace("//","/");
if (filename != "/")
{
bool delete_error = false;
FSDIR dir = SPIFFS.openDir(path + shortname);
{
while (dir.next()) {
String fullpath = dir.fileName();
if (!SPIFFS.remove(dir.fileName())) {
delete_error = true;
status = F("Cannot deleted ") ;
status+=fullpath;
}
}
}
if (!delete_error){
status = shortname ;
status+=" deleted";
}
}
}
//create a directory
if(web_interface->WebServer.arg("action")=="createdir" && web_interface->WebServer.hasArg("filename")) {
String filename;
filename = path + web_interface->WebServer.arg("filename") +"/.";
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename.replace("//","/");
if(SPIFFS.exists(filename)) {
status = shortname + F(" already exists!");
} else {
FSFILE r = SPIFFS.open(filename,"w");
if (!r) {
status = F("Cannot create ");
status += shortname ;
}
else {
r.close();
status = shortname + F(" created");
}
}
}
}
String jsonfile = "{";
FSDIR dir = SPIFFS.openDir(path);
jsonfile+="\"files\":[";
bool firstentry=true;
String subdirlist="";
while (dir.next()) {
String filename = dir.fileName();
String size ="";
bool addtolist=true;
//remove path from name
filename = filename.substring(path.length(),filename.length());
//check if file or subfile
if (filename.indexOf("/")>-1) {
//Do not rely on "/." to define directory as SPIFFS upload won't create it but directly files
//and no need to overload SPIFFS if not necessary to create "/." if no need
//it will reduce SPIFFS available space so limit it to creation
filename = filename.substring(0,filename.indexOf("/"));
String tag="*";
tag = filename + "*";
if (subdirlist.indexOf(tag)>-1) //already in list
{
addtolist = false; //no need to add
}
else
{
size = -1; //it is subfile so display only directory, size will be -1 to describe it is directory
if (subdirlist.length()==0)subdirlist+="*";
subdirlist += filename + "*"; //add to list
}
}
else
{
//do not add "." file
if (filename!=".")
{
FSFILE f = dir.openFile("r");
size = CONFIG::formatBytes(f.size());
f.close();
}
else
{
addtolist = false;
}
}
if(addtolist)
{
if (!firstentry) {
jsonfile+=",";
} else {
firstentry=false;
}
jsonfile+="{";
jsonfile+="\"name\":\"";
jsonfile+=filename;
jsonfile+="\",\"size\":\"";
jsonfile+=size;
jsonfile+="\"";
jsonfile+="}";
}
}
jsonfile+="],";
jsonfile+="\"path\":\"" + path + "\",";
jsonfile+="\"status\":\"" + status + "\",";
FSINFO info;
SPIFFS.info(info);
jsonfile+="\"total\":\"" + CONFIG::formatBytes(info.totalBytes) + "\",";
jsonfile+="\"used\":\"" + CONFIG::formatBytes(info.usedBytes) + "\",";
jsonfile.concat(F("\"occupation\":\""));
jsonfile+= CONFIG::intTostr(100*info.usedBytes/info.totalBytes);
jsonfile+="\"";
jsonfile+="}";
path = "";
web_interface->WebServer.sendHeader("Cache-Control", "no-cache");
web_interface->WebServer.send(200, "application/json", jsonfile);
}
void handleSDFileList()
{
char tmp[255];
if (web_interface->is_authenticated() == LEVEL_GUEST) {
return;
}
LOG("List SD FILES\n")
String path="/";
String sstatus="Ok";
uint32_t totalspace = 0;
uint32_t usedspace = 0;
//get current path
if(web_interface->WebServer.hasArg("path"))path += web_interface->WebServer.arg("path") ;
//to have a clean path
path.trim();
path.replace("//","/");
if (path[path.length()-1] !='/')path +="/";
//check if query need some action
if(web_interface->WebServer.hasArg("action")) {
LOG("action requested\n")
//delete a file
if(web_interface->WebServer.arg("action") == "delete" && web_interface->WebServer.hasArg("filename")) {
LOG("delete requested\n")
String filename;
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename = path + web_interface->WebServer.arg("filename");
filename.replace("//","/");
LOG(shortname)
LOG("\n")
LOG(filename)
LOG("\n")
LOG(sstatus)
LOG("\n")
}
//delete a directory
if(web_interface->WebServer.arg("action") == "deletedir" && web_interface->WebServer.hasArg("filename")) {
LOG("deletedir requested\n")
String filename;
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename = path + web_interface->WebServer.arg("filename");
filename.replace("//","/");
LOG(shortname)
LOG("\n")
LOG(filename)
LOG("\n")
LOG(sstatus)
LOG("\n")
}
//create a directory
if(web_interface->WebServer.arg("action")=="createdir" && web_interface->WebServer.hasArg("filename")) {
String filename;
LOG("createdir requested\n")
filename = path + web_interface->WebServer.arg("filename") ;
String shortname = web_interface->WebServer.arg("filename");
shortname.replace("/","");
filename.replace("//","/");
LOG(shortname)
LOG("\n")
LOG(filename)
LOG("\n")
LOG(sstatus)
LOG("\n")
}
}
String jsonfile = "{" ;
//if action is processing do not build list
if ((web_interface->blockserial)){
LOG("Wait, blocking\n");
jsonfile+="\"status\":\"processing\",\"mode\":\"serial\"}";
}
else
{
jsonfile+="\"files\":[";
LOG("No Blocking \n");
LOG("JSON File\n");
LOG(String(web_interface->fileslist.size()));
LOG(" entries\n");
String sname;
for (int i=0; i<web_interface->fileslist.size(); i++) {
if (i>0) {
jsonfile+=",";
}
jsonfile+="{\"name\":\"";
sname = web_interface->fileslist.get(i);
#if FIRMWARE_TARGET == REPETIER4DV || FIRMWARE_TARGET == REPETIER
//check if directory or file
if (sname[0] == '/' || sname[sname.length()-1]=='/')
{
jsonfile+=sname;
jsonfile+="\",\"size\":\"";
LOG(String(i+1));
LOG(sname);
jsonfile+="-1";
LOG(" -1");
}
else //it is a file
{
//get size position
int posspace = sname.indexOf(" ");
String ssize;
if (posspace !=-1)
{
ssize = sname.substring(posspace+1);
sname = sname.substring(0,posspace);
}
jsonfile+=sname;
jsonfile+="\",\"size\":\"";
LOG(String(i+1));
LOG(sname);
LOG(" ");
jsonfile+=CONFIG::formatBytes(ssize.toInt());
LOG( CONFIG::formatBytes(ssize.toInt()));
}
#endif
#if FIRMWARE_TARGET == MARLIN || FIRMWARE_TARGET == MARLINKIMBRA || FIRMWARE_TARGET == SMOOTHIEWARE
jsonfile+=sname;
jsonfile+="\",\"size\":\"";
LOG(String(i+1));
LOG(sname);
if (sname[0] == '/' || sname[sname.length()-1]=='/')
{
jsonfile+="-1";
LOG(" -1");
}
else
{//nothing to add
jsonfile+="";
}
LOG("\n");
#endif
jsonfile+="\"}";
}
jsonfile+="],\"path\":\"";
jsonfile+=path + "\",\"mode\":\"serial\",\"status\":\"";
jsonfile+=sstatus + "\",\"total\":\"";
jsonfile+= "-1";
jsonfile+="\",\"used\":\"";
jsonfile+= "-1";
jsonfile+="\",\"occupation\":\"";
jsonfile+= "-1";
jsonfile+= "\"";
jsonfile+= "}";
LOG("JSON done\n");
}
path = String();
web_interface->WebServer.sendHeader("Cache-Control", "no-cache");
web_interface->WebServer.send(200, "application/json", jsonfile);
web_interface->blockserial = false;
}
//do a redirect to avoid to many query
//and handle not registred path
void handle_not_found()
{
static const char NOT_AUTH_NF [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /HOME\r\nCache-Control: no-cache\r\n\r\n";
if (web_interface->is_authenticated() == LEVEL_GUEST) {
web_interface->WebServer.sendContent_P(NOT_AUTH_NF);
return;
}
bool page_not_found = false;
String path = web_interface->WebServer.urlDecode(web_interface->WebServer.uri());
String contentType = web_interface->getContentType(path);
String pathWithGz = path + ".gz";
LOG("request:")
LOG(path)
LOG("\n")
LOG("type:")
LOG(contentType)
LOG("\n")
if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)) {
if(SPIFFS.exists(pathWithGz)) {
path = pathWithGz;
}
FSFILE file = SPIFFS.open(path, "r");
web_interface->WebServer.streamFile(file, contentType);
file.close();
return;
} else page_not_found = true;
if (page_not_found )
{
if (SPIFFS.exists("/404.tpl")) {
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
String stmp;
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,F("404 Page not found"),F("404"));
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/404.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
} else {
//if not template use default page
contentType=FPSTR(PAGE_404);
String stmp;
if (WiFi.getMode()==WIFI_STA ) {
stmp=WiFi.localIP().toString();
} else {
stmp=WiFi.softAPIP().toString();
}
//Web address = ip + port
String KEY_IP = FPSTR(KEY_WEB_ADDRESS);
if (wifi_config.iweb_port!=80) {
stmp+=":";
stmp+=CONFIG::intTostr(wifi_config.iweb_port);
}
contentType.replace(KEY_IP,stmp);
web_interface->WebServer.send(200,"text/html",contentType);
}
}
}
#ifdef AUTHENTICATION_FEATURE
void handle_login()
{
static const char NOT_AUTH_LOG [] PROGMEM = "HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=0\r\nLocation: /LOGIN\r\nCache-Control: no-cache\r\n\r\n";
String smsg;
String sReturn;
String sUser,sPassword;
bool msg_alert_error=false;
//bool msg_alert_success=false;
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
if (web_interface->WebServer.hasArg("DISCONNECT")) {
web_interface->WebServer.sendContent_P(NOT_AUTH_LOG);
return;
}
//check is it is a submission or a display
smsg="";
if (web_interface->WebServer.hasArg("return")) {
sReturn = web_interface->WebServer.arg("return");
}
if (web_interface->WebServer.hasArg("SUBMIT")) {
//is there a correct list of values?
if ( web_interface->WebServer.hasArg("PASSWORD")&& web_interface->WebServer.hasArg("USER")) {
//USER
sUser = web_interface->WebServer.arg("USER");
if ( !((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) || (sUser==FPSTR(DEFAULT_USER_LOGIN)))) {
msg_alert_error=true;
smsg.concat(F("Error : Incorrect User<BR>"));
KeysList.add(FPSTR(KEY_USER_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
//Password
sPassword = web_interface->WebServer.arg("PASSWORD");
String sadminPassword;
if (!CONFIG::read_string(EP_ADMIN_PWD, sadminPassword , MAX_LOCAL_PASSWORD_LENGTH)) {
sadminPassword=FPSTR(DEFAULT_ADMIN_PWD);
}
String suserPassword;
if (!CONFIG::read_string(EP_USER_PWD, suserPassword , MAX_LOCAL_PASSWORD_LENGTH)) {
suserPassword=FPSTR(DEFAULT_USER_PWD);
}
if(!(((sUser==FPSTR(DEFAULT_ADMIN_LOGIN)) && (strcmp(sPassword.c_str(),sadminPassword.c_str())==0)) ||
((sUser==FPSTR(DEFAULT_USER_LOGIN)) && (strcmp(sPassword.c_str(),suserPassword.c_str()) == 0)))) {
msg_alert_error=true;
smsg.concat(F("Error: Incorrect password<BR>"));
KeysList.add(FPSTR(KEY_USER_PASSWORD_STATUS));
ValuesList.add(FPSTR(VALUE_HAS_ERROR));
}
} else {
msg_alert_error=true;
smsg = FPSTR(MISSING_DATA);
}
//if no error login is ok
if (msg_alert_error==false) {
#ifdef AUTHENTICATION_FEATURE
auth_ip * current_auth = new auth_ip;
if(sUser==FPSTR(DEFAULT_ADMIN_LOGIN))current_auth->level = LEVEL_ADMIN;
else current_auth->level = LEVEL_USER;
current_auth->ip=web_interface->WebServer.client().remoteIP();
strcpy(current_auth->sessionID,web_interface->create_session_ID());
current_auth->last_time=millis();
if (web_interface->AddAuthIP(current_auth)) {
String header = F("HTTP/1.1 301 OK\r\nSet-Cookie: ESPSESSIONID=");
header+=current_auth->sessionID;
header+="\r\nLocation: /";
header+=sReturn;
header.concat(F("\r\nCache-Control: no-cache\r\n\r\n"));
web_interface->WebServer.sendContent(header);
return;
} else {
delete current_auth;
msg_alert_error=true;
smsg = F("Error: Too many connections");
}
#endif
}
}
else { //no submit need to get data from EEPROM
sUser=String();
//password
sPassword=String();
}
//Display values
KeysList.add(FPSTR(KEY_RETURN));
ValuesList.add(sReturn);
level_authenticate_type auth_level= web_interface->is_authenticated();
//login
web_interface->GeLogin(KeysList, ValuesList,auth_level);
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,FPSTR(VALUE_LOGIN),F("login"));
//User
KeysList.add(FPSTR(KEY_USER));
ValuesList.add(sUser);
//password
KeysList.add(FPSTR(KEY_USER_PASSWORD));
ValuesList.add(sPassword);
if (msg_alert_error) {
web_interface->ProcessAlertError(KeysList, ValuesList, smsg);
} else {
web_interface->ProcessNoAlert(KeysList,ValuesList);
}
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/login.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
}
#endif
void handle_restart()
{
static const char NOT_AUTH_NF [] PROGMEM = "HTTP/1.1 301 OK\r\nLocation: /HOME\r\nCache-Control: no-cache\r\n\r\n";
if (web_interface->is_authenticated() != LEVEL_ADMIN) {
web_interface->WebServer.sendContent_P(NOT_AUTH_NF);
return;
}
if (SPIFFS.exists("/restart.tpl")) {
STORESTRINGS_CLASS KeysList ;
STORESTRINGS_CLASS ValuesList ;
//IP+Web
web_interface->GetIpWeb(KeysList, ValuesList);
//mode
web_interface->GetMode(KeysList, ValuesList);
//page title and filenames
web_interface->SetPageProp(KeysList,ValuesList,F("Restarting..."),F("restart"));
//Firmware and Free Mem, at the end to reflect situation
web_interface->GetFreeMem(KeysList, ValuesList);
//process the template file and provide list of variables
web_interface->processTemplate("/restart.tpl", KeysList , ValuesList);
//need to clean to speed up memory recovery
KeysList.clear();
ValuesList.clear();
} else {
//if not restart template use default
String contentType=FPSTR(PAGE_RESTART);
web_interface->WebServer.send(200,"text/html",contentType);
}
web_interface->restartmodule=true;
}
void handle_web_command()
{
if (web_interface->is_authenticated() == LEVEL_GUEST) {
return;
}
//check we have proper parameter
if (web_interface->WebServer.hasArg("COM")) {
String scmd;
//decode command
scmd = web_interface->WebServer.arg("COM");
scmd.trim();
//give an ack - we need to be polite, right ?
web_interface->WebServer.send(200,"text/plain","Ok");
//if it is for ESP module [ESPXXX]<parameter>
int ESPpos = scmd.indexOf("[ESP");
if (ESPpos>-1) {
//is there the second part?
int ESPpos2 = scmd.indexOf("]",ESPpos);
if (ESPpos2>-1) {
//Split in command and parameters
String cmd_part1=scmd.substring(ESPpos+4,ESPpos2);
String cmd_part2="";
//is there space for parameters?
if (ESPpos2<scmd.length()) {
cmd_part2=scmd.substring(ESPpos2+1);
}
//if command is a valid number then execute command
if(cmd_part1.toInt()!=0) {
COMMAND::execute_command(cmd_part1.toInt(),cmd_part2);
}
//if not is not a valid [ESPXXX] command
}
}
else {
//send command to serial as no need to transfer ESP command
//to avoid any pollution if Uploading file to SDCard
if ((web_interface->blockserial) == false)Serial.println(scmd);
}
}
}
#ifdef SSDP_FEATURE
void handle_SSDP()
{
SSDP.schema(web_interface->WebServer.client());
}
#endif
//constructor
WEBINTERFACE_CLASS::WEBINTERFACE_CLASS (int port):WebServer(port)
{
//init what will handle "/"
WebServer.on("/",HTTP_ANY, handle_web_interface_root);
WebServer.on("/HOME",HTTP_ANY, handle_web_interface_home);
WebServer.on("/CONFIGSYS",HTTP_ANY, handle_web_interface_configSys);
WebServer.on("/CONFIGAP",HTTP_ANY, handle_web_interface_configAP);
WebServer.on("/CONFIGSTA",HTTP_ANY, handle_web_interface_configSTA);
WebServer.on("/STATUS",HTTP_ANY, handle_web_interface_status);
WebServer.on("/SETTINGS",HTTP_ANY, handle_web_settings);
WebServer.on("/PRINTER",HTTP_ANY, handle_web_interface_printer);
WebServer.on("/CMD",HTTP_ANY, handle_web_command);
WebServer.on("/RESTART",HTTP_GET, handle_restart);
#ifdef WEB_UPDATE_FEATURE
WebServer.on("/UPDATE",HTTP_ANY, handleUpdate,WebUpdateUpload);
#endif
WebServer.on("/FILES", HTTP_ANY, handleFileList,SPIFFSFileupload);
WebServer.on("/SDFILES", HTTP_ANY, handleSDFileList,SDFileupload);
#ifdef AUTHENTICATION_FEATURE
WebServer.on("/LOGIN", HTTP_ANY, handle_login);
WebServer.on("/PASSWORD", HTTP_ANY, handle_password);
#endif
//Captive portal Feature
#ifdef CAPTIVE_PORTAL_FEATURE
WebServer.on("/generate_204",HTTP_ANY, handle_web_interface_root);
WebServer.on("/fwlink",HTTP_ANY, handle_web_interface_root);
#endif
#ifdef SSDP_FEATURE
WebServer.on("/description.xml", HTTP_GET, handle_SSDP);
#endif
WebServer.onNotFound( handle_not_found);
#ifdef TEMP_MONITORING_FEATURE
answer4M105="T:0 /0 ";
last_temp = millis();
#endif
#ifdef POS_MONITORING_FEATURE
answer4M114="X:0.0 Y:0.0 Z:0.000";
#endif
#ifdef SPEED_MONITORING_FEATURE
answer4M220="100";
#endif
#ifdef FLOW_MONITORING_FEATURE
answer4M221="100";
#endif
blockserial = false;
restartmodule=false;
//rolling list of 4entries with a maximum of 50 char for each entry
#ifdef ERROR_MSG_FEATURE
error_msg.setsize(4);
error_msg.setlength(50);
#endif
#ifdef INFO_MSG_FEATURE
info_msg.setsize(4);
info_msg.setlength(50);
#endif
#ifdef STATUS_MSG_FEATURE
status_msg.setsize(4);
status_msg.setlength(50);
#endif
fileslist.setlength(100);//12 for filename + space + size
fileslist.setsize(70); // 70 files to limite to 2K
fsUploadFile=(FSFILE)0;
_head=NULL;
_nb_ip=0;
_upload_status=UPLOAD_STATUS_NONE;
}
//Destructor
WEBINTERFACE_CLASS::~WEBINTERFACE_CLASS()
{
#ifdef INFO_MSG_FEATURE
info_msg.clear();
#endif
#ifdef ERROR_MSG_FEATURE
error_msg.clear();
#endif
#ifdef STATUS_MSG_FEATURE
status_msg.clear();
#endif
fileslist.clear();
while (_head) {
auth_ip * current = _head;
_head=_head->_next;
delete current;
}
_nb_ip=0;
}
//check authentification
level_authenticate_type WEBINTERFACE_CLASS::is_authenticated()
{
#ifdef AUTHENTICATION_FEATURE
if (WebServer.hasHeader("Cookie")) {
String cookie = WebServer.header("Cookie");
int pos = cookie.indexOf("ESPSESSIONID=");
if (pos!= -1) {
int pos2 = cookie.indexOf(";",pos);
String sessionID = cookie.substring(pos+strlen("ESPSESSIONID="),pos2);
IPAddress ip = WebServer.client().remoteIP();
//check if cookie can be reset and clean table in same time
return ResetAuthIP(ip,sessionID.c_str());
}
}
return LEVEL_GUEST;
#else
return LEVEL_ADMIN;
#endif
}
//add the information in the linked list if possible
bool WEBINTERFACE_CLASS::AddAuthIP(auth_ip * item)
{
if (_nb_ip>MAX_AUTH_IP) {
return false;
}
item->_next=_head;
_head=item;
_nb_ip++;
return true;
}
#ifdef AUTHENTICATION_FEATURE
//Session ID based on IP and time using 16 char
char * WEBINTERFACE_CLASS::create_session_ID()
{
static char sessionID[17];
//reset SESSIONID
for (int i=0; i<17; i++) {
sessionID[i]='\0';
}
//get time
uint32_t now = millis();
//get remote IP
IPAddress remoteIP=WebServer.client().remoteIP();
//generate SESSIONID
if (0>sprintf(sessionID,"%02X%02X%02X%02X%02X%02X%02X%02X",remoteIP[0],remoteIP[1],remoteIP[2],remoteIP[3],(uint8_t) ((now >> 0) & 0xff),(uint8_t) ((now >> 8) & 0xff),(uint8_t) ((now >> 16) & 0xff),(uint8_t) ((now >> 24) & 0xff))) {
strcpy(sessionID,"NONE");
}
return sessionID;
}
level_authenticate_type WEBINTERFACE_CLASS::ResetAuthIP(IPAddress ip,const char * sessionID)
{
auth_ip * current = _head;
auth_ip * previous = NULL;
//get time
//uint32_t now = millis();
while (current) {
if ((millis()-current->last_time)>180000) {
//remove
if (current==_head) {
_head=current->_next;
_nb_ip--;
delete current;
current=_head;
} else {
previous->_next=current->_next;
_nb_ip--;
delete current;
current=previous->_next;
}
} else {
if (ip==current->ip) {
if (strcmp(sessionID,current->sessionID)==0) {
//reset time
current->last_time=millis();
return current->level;
}
}
previous = current;
current=current->_next;
}
}
return LEVEL_GUEST;
}
#endif
String WEBINTERFACE_CLASS::getContentType(String filename)
{
if(filename.endsWith(".htm")) {
return "text/html";
} else if(filename.endsWith(".html")) {
return "text/html";
} else if(filename.endsWith(".css")) {
return "text/css";
} else if(filename.endsWith(".js")) {
return "application/javascript";
} else if(filename.endsWith(".png")) {
return "image/png";
} else if(filename.endsWith(".gif")) {
return "image/gif";
} else if(filename.endsWith(".jpg")) {
return "image/jpeg";
} else if(filename.endsWith(".ico")) {
return "image/x-icon";
} else if(filename.endsWith(".xml")) {
return "text/xml";
} else if(filename.endsWith(".pdf")) {
return "application/x-pdf";
} else if(filename.endsWith(".zip")) {
return "application/x-zip";
} else if(filename.endsWith(".gz")) {
return "application/x-gzip";
} else if(filename.endsWith(".tpl")) {
return "text/plain";
} else if(filename.endsWith(".inc")) {
return "text/plain";
} else if(filename.endsWith(".txt")) {
return "text/plain";
}
return "application/octet-stream";
}
WEBINTERFACE_CLASS * web_interface;