/* * configFS.h * File-class for config * for configuration of user-data * * author Creator P.Rebesky * Copyright (©): 2023 by Peter Rebesky * This code can use in private cases only. Every business or companies using of this codes or codes parts is required an approval of us (me) * Every private use can exchange some parts of code or modify some code-lines. This code can change for private use only. * This software is basicly owned by Peter Rebesky and any comercial using is forbidden without approval of us (me). * Version 1.00 * 10.02.2023 */ #ifndef CONFIG_FS_H_ #define CONFIG_FS_H_ // class for manage config-data into and from file "config.ini" #include "global.h" #include // LittleFS is declared #define __TARGET_SERVER "t_url" #define __NAME_IoT "n_iot" #define __SWITCH_TEMP "s_temp" #define __AUTOMATIC "a_enab" #define __CONTENT_TYPE "c_type" #define __PUSH_PULL "c_push" #define __HTTP "http://" #define __HTTPS "https://" #define __SENSOR1 "n_sens1" #define __SENSOR2 "n_sens2" #define __SENSOR3 "n_sens3" #define __SENSOR4 "n_sens4" /***** class for save data intern into ESP8266 *****/ class configFS { private: String TARGET_URL="http://yourServer/temperature.php"; String NAME_IoT="Temp-Control"; String Sensor1="Sensor 1"; String Sensor2="Sensor 2"; String Sensor3="Sensor 3"; String Sensor4="Sensor 4"; bool MOUNTED = false; bool CONFIG_LOAD = false; void loadConfig(String s); int calculateFreeSpaceFS(); unsigned char h2int(char c); String getTargetWithout(); bool checkHTTPadjustTime(); public: int SwitchOnTemp=4; int SwitchOffTemp=2; int FREESPACE=0; bool sendPUSH=true; // true: sending POST data to server, false: no sending only answer per get bool sendJSON=true; // true: send as JSON, false: send as URL-encoded int SendSSL=0; // 0 = send over http, send over https bool begin(); // start to get data from file String getTargetURL(); String getTargetURLclean(); String getTargetServer(); String getName(); bool readconfigFS(); bool saveconfigFS(); int getFreeSpace(); bool savePostValues(String saveValues); String decodeOnValue(String s); String getOnePostValue(String post,String ident); String getOneFileValue(String file,String ident); String urldecode(String str); String urlencode(String str); void saveValues(String str); String readSavedValues(int pointer); String getSensorName(int sensor); void end(); // debug functions bool getMounted(); }; /**** mount the file-object ****/ bool configFS::begin(){ if(LittleFS.begin()){ this->MOUNTED = true; this->CONFIG_LOAD=this->readconfigFS(); this->calculateFreeSpaceFS(); } return this->MOUNTED; } /**** read values from file or create new default-values ****/ bool configFS::readconfigFS(){ bool r=false; File Fconfig = LittleFS.open("/config.ini","r"); if (Fconfig){ String s=Fconfig.readString(); this->loadConfig(s); Fconfig.close(); r = true; } return r; } /****** for compatibility ******/ void configFS::end(){ // do nothing, it's for compatibility only } /****** debug function *****/ bool configFS::getMounted(){ return this->MOUNTED; } /******** handle target URL ******/ String configFS::getName(){ return this->NAME_IoT; } /******** get sensor name *********/ String configFS::getSensorName(int sensor){ switch(sensor){ case 1: return this->Sensor1; break; case 2: return this->Sensor2; break; case 3: return this->Sensor3; break; case 4: return this->Sensor4; break; default: return "not defined"; break; } } /******** handle target URL clean******/ String configFS::getTargetURLclean(){ return getTargetWithout(); } /******** handle target URL ******/ String configFS::getTargetURL(){ return this->TARGET_URL; } /****** handle update server ******/ String configFS::getTargetServer(){ String url = getTargetWithout(); int urlEnd = url.indexOf("/",0); return url.substring(0,urlEnd); } //*** get return without http r https ******/ String configFS::getTargetWithout(){ String url; int httpString = this->TARGET_URL.indexOf(__HTTP,0); int httpsString = this->TARGET_URL.indexOf(__HTTPS,0); if(httpString != -1){ url=TARGET_URL.substring(httpString+7); SendSSL=0; }else if(httpsString != -1){ url=TARGET_URL.substring(httpsString+8); SendSSL=1; }else{ url=this->TARGET_URL; SendSSL=0; } return url; } /*** end ***/ bool configFS::checkHTTPadjustTime(){ if(this->TARGET_URL.indexOf(__HTTPS,0) >= 0) SendSSL=1; else SendSSL =0; if(SendSSL==1) _secAdjust=_ADJUST_HTTPS; else _secAdjust=_ADJUST_HTTP; return true; } /**** save actuelle config-data ****/ bool configFS::saveconfigFS(){ bool r = false; String s = "{\n"; s += "Config: \""; s += 1; s += "\",\n"; s += "Name_IoT: \""; s += this->NAME_IoT; s += "\",\n"; s += "Name_Sens1: \""; s += this->Sensor1; s += "\",\n"; s += "Name_Sens2: \""; s += this->Sensor2; s += "\",\n"; s += "Name_Sens3: \""; s += this->Sensor3; s += "\",\n"; s += "Name_Sens4: \""; s += this->Sensor4; s += "\",\n"; s += "Target_URL: \""; s += this->TARGET_URL; s += "\",\n"; s += "Switch_Temp: \""; s += this->SwitchOnTemp; s += "\",\n"; s += "Cont_Type: \""; s += this->sendJSON; s += "\",\n"; s += "Push_Pull: \""; s += this->sendPUSH; s += "\"\n"; s += "}"; // Serial.println(s); if(this->MOUNTED){ File Fconfig = LittleFS.open("/config.ini","w"); if (Fconfig){ int w=Fconfig.print(s); Fconfig.close(); if (w > 1) r = true; // write file was successful } } return r; } //******************* load one value from saved config ***************** String configFS::getOneFileValue(String file,String ident){ String ret; int argBegin = file.indexOf(ident); if(argBegin>0){ int argEnd = file.indexOf(",",argBegin+2); ret = this->decodeOnValue(file.substring(argBegin, argEnd)); } return ret; } //******************* decode post-values ******************************* String configFS::getOnePostValue(String post,String ident){ String returnValue=""; if(post.length()>0){ int identBegin = post.indexOf(ident); if(identBegin >= 0){ int argEnd = post.indexOf("&",identBegin); if (argEnd == -1) argEnd = post.length(); returnValue = post.substring(post.indexOf("=",identBegin)+1,argEnd); } } return this->urldecode(returnValue); } /**** decode file-data and save into class ****/ void configFS::loadConfig(String s){ if(getOneFileValue(s,"Config:").toInt()!=0){ // check if config-data is available. If not, then save default values at once this->NAME_IoT = getOneFileValue(s,"Name_IoT:"); this->Sensor1 = getOneFileValue(s,"Name_Sens1:"); this->Sensor2 = getOneFileValue(s,"Name_Sens2:"); this->Sensor3 = getOneFileValue(s,"Name_Sens3:"); this->Sensor4 = getOneFileValue(s,"Name_Sens4:"); this->TARGET_URL = getOneFileValue(s,"Target_URL:"); this->SwitchOnTemp = getOneFileValue(s,"Switch_Temp:").toInt(); this->sendJSON = getOneFileValue(s,"Cont_Type:").toInt(); this->sendPUSH = getOneFileValue(s,"Push_Pull:").toInt(); } else this->saveconfigFS(); // save for the first time all default data } /**** extract one value from string ****/ String configFS::decodeOnValue(String s){ int valueBegin = s.indexOf("\""); int valueLength = s.length(); if(valueLength >0){ if(valueBegin > 0){ s = s.substring(valueBegin+1,valueLength-1); } else { valueBegin = s.indexOf(":"); s = s.substring(valueBegin+1,valueLength); } } else s = ""; return s; } /****** get free space from file-system ******/ int configFS::calculateFreeSpaceFS(){ if(MOUNTED){ FSInfo fsinfo; LittleFS.info(fsinfo); FREESPACE = fsinfo.totalBytes - fsinfo.usedBytes; } else FREESPACE = 0; return FREESPACE; } int configFS::getFreeSpace(){ return this->FREESPACE; } /***** decode values from html-post-arguments *****/ bool configFS::savePostValues(String saveValues){ bool r=false; if(saveValues.length()>0){ // _debugString=saveValues; this->NAME_IoT = getOnePostValue(saveValues,__NAME_IoT); this->Sensor1 = getOnePostValue(saveValues,__SENSOR1); this->Sensor2 = getOnePostValue(saveValues,__SENSOR2); this->Sensor3 = getOnePostValue(saveValues,__SENSOR3); this->Sensor4 = getOnePostValue(saveValues,__SENSOR4); this->TARGET_URL = getOnePostValue(saveValues,__TARGET_SERVER); this->SwitchOnTemp = getOnePostValue(saveValues,__SWITCH_TEMP).toInt(); this->sendJSON = getOnePostValue(saveValues,__CONTENT_TYPE).toInt(); this->sendPUSH = getOnePostValue(saveValues,__PUSH_PULL).toInt(); } // Serial.println(saveValues); return this->saveconfigFS(); } /***** url decoding part *****/ unsigned char configFS::h2int(char c){ if (c >= '0' && c <='9') return((unsigned char)c - '0'); if (c >= 'a' && c <='f') return((unsigned char)c - 'a' + 10); if (c >= 'A' && c <='F') return((unsigned char)c - 'A' + 10); return(0); } /***** url decoding function ******/ String configFS::urldecode(String str){ String encodedString=""; char c; char code0; char code1; for (int i =0; i < str.length(); i++){ c=str.charAt(i); if (c == '+') encodedString+=' '; else if (c == '%') { i++; code0=str.charAt(i); i++; code1=str.charAt(i); c = (h2int(code0) << 4) | h2int(code1); encodedString+=c; } else encodedString+=c; yield(); } return encodedString; } /***** url encoding function ******/ String configFS::urlencode(String str){ String encodedString=""; char c; char code0; char code1; char code2; for (int i =0; i < str.length(); i++){ c=str.charAt(i); if (c == ' ') encodedString+= '+'; else if (isalnum(c)) encodedString+=c; else{ code1=(c & 0xf)+'0'; if ((c & 0xf) >9) code1=(c & 0xf) - 10 + 'A'; c=(c>>4)&0xf; code0=c+'0'; if (c > 9) code0=c - 10 + 'A'; code2='\0'; encodedString+='%'; encodedString+=code0; encodedString+=code1; //encodedString+=code2; } yield(); } return encodedString; } #endif //*** CONFIG_FS_H_