1 | /*
|
2 | * configFS.h
|
3 | * File-class for config
|
4 | * for configuration of user-data
|
5 | *
|
6 | * author Creator P.Rebesky
|
7 | * Copyright (©): 2023 by Peter Rebesky
|
8 | * 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)
|
9 | * Every private use can exchange some parts of code or modify some code-lines. This code can change for private use only.
|
10 | * This software is basicly owned by Peter Rebesky and any comercial using is forbidden without approval of us (me).
|
11 | * Version 1.00
|
12 | * 10.02.2023
|
13 | */
|
14 | #ifndef CONFIG_FS_H_
|
15 | #define CONFIG_FS_H_
|
16 |
|
17 | // class for manage config-data into and from file "config.ini"
|
18 | #include "global.h"
|
19 | #include <LittleFS.h> // LittleFS is declared
|
20 |
|
21 | #define __TARGET_SERVER "t_url"
|
22 | #define __NAME_IoT "n_iot"
|
23 | #define __SWITCH_TEMP "s_temp"
|
24 | #define __AUTOMATIC "a_enab"
|
25 | #define __CONTENT_TYPE "c_type"
|
26 | #define __PUSH_PULL "c_push"
|
27 | #define __HTTP "http://"
|
28 | #define __HTTPS "https://"
|
29 | #define __SENSOR1 "n_sens1"
|
30 | #define __SENSOR2 "n_sens2"
|
31 | #define __SENSOR3 "n_sens3"
|
32 | #define __SENSOR4 "n_sens4"
|
33 |
|
34 | /***** class for save data intern into ESP8266 *****/
|
35 | class configFS {
|
36 | private:
|
37 | String TARGET_URL="http://yourServer/temperature.php";
|
38 | String NAME_IoT="Temp-Control";
|
39 | String Sensor1="Sensor 1";
|
40 | String Sensor2="Sensor 2";
|
41 | String Sensor3="Sensor 3";
|
42 | String Sensor4="Sensor 4";
|
43 | bool MOUNTED = false;
|
44 | bool CONFIG_LOAD = false;
|
45 | void loadConfig(String s);
|
46 | int calculateFreeSpaceFS();
|
47 | unsigned char h2int(char c);
|
48 | String getTargetWithout();
|
49 | bool checkHTTPadjustTime();
|
50 |
|
51 | public:
|
52 | int SwitchOnTemp=4;
|
53 | int SwitchOffTemp=2;
|
54 | int FREESPACE=0;
|
55 | bool sendPUSH=true; // true: sending POST data to server, false: no sending only answer per get
|
56 | bool sendJSON=true; // true: send as JSON, false: send as URL-encoded
|
57 | int SendSSL=0; // 0 = send over http, send over https
|
58 | bool begin(); // start to get data from file
|
59 | String getTargetURL();
|
60 | String getTargetURLclean();
|
61 | String getTargetServer();
|
62 | String getName();
|
63 | bool readconfigFS();
|
64 | bool saveconfigFS();
|
65 | int getFreeSpace();
|
66 | bool savePostValues(String saveValues);
|
67 | String decodeOnValue(String s);
|
68 | String getOnePostValue(String post,String ident);
|
69 | String getOneFileValue(String file,String ident);
|
70 | String urldecode(String str);
|
71 | String urlencode(String str);
|
72 | void saveValues(String str);
|
73 | String readSavedValues(int pointer);
|
74 | String getSensorName(int sensor);
|
75 | void end();
|
76 | // debug functions
|
77 | bool getMounted();
|
78 | };
|
79 | /**** mount the file-object ****/
|
80 | bool configFS::begin(){
|
81 | if(LittleFS.begin()){
|
82 | this->MOUNTED = true;
|
83 | this->CONFIG_LOAD=this->readconfigFS();
|
84 | this->calculateFreeSpaceFS();
|
85 | }
|
86 | return this->MOUNTED;
|
87 | }
|
88 | /**** read values from file or create new default-values ****/
|
89 | bool configFS::readconfigFS(){
|
90 | bool r=false;
|
91 | File Fconfig = LittleFS.open("/config.ini","r");
|
92 | if (Fconfig){
|
93 | String s=Fconfig.readString();
|
94 | this->loadConfig(s);
|
95 | Fconfig.close();
|
96 | r = true;
|
97 | }
|
98 | return r;
|
99 | }
|
100 | /****** for compatibility ******/
|
101 | void configFS::end(){
|
102 | // do nothing, it's for compatibility only
|
103 | }
|
104 | /****** debug function *****/
|
105 | bool configFS::getMounted(){
|
106 | return this->MOUNTED;
|
107 | }
|
108 | /******** handle target URL ******/
|
109 | String configFS::getName(){
|
110 | return this->NAME_IoT;
|
111 | }
|
112 | /******** get sensor name *********/
|
113 | String configFS::getSensorName(int sensor){
|
114 | switch(sensor){
|
115 | case 1: return this->Sensor1; break;
|
116 | case 2: return this->Sensor2; break;
|
117 | case 3: return this->Sensor3; break;
|
118 | case 4: return this->Sensor4; break;
|
119 | default: return "not defined"; break;
|
120 | }
|
121 | }
|
122 | /******** handle target URL clean******/
|
123 | String configFS::getTargetURLclean(){
|
124 | return getTargetWithout();
|
125 | }
|
126 | /******** handle target URL ******/
|
127 | String configFS::getTargetURL(){
|
128 | return this->TARGET_URL;
|
129 | }
|
130 | /****** handle update server ******/
|
131 | String configFS::getTargetServer(){
|
132 | String url = getTargetWithout();
|
133 | int urlEnd = url.indexOf("/",0);
|
134 | return url.substring(0,urlEnd);
|
135 | }
|
136 | //*** get return without http r https ******/
|
137 | String configFS::getTargetWithout(){
|
138 | String url;
|
139 | int httpString = this->TARGET_URL.indexOf(__HTTP,0);
|
140 | int httpsString = this->TARGET_URL.indexOf(__HTTPS,0);
|
141 | if(httpString != -1){
|
142 | url=TARGET_URL.substring(httpString+7);
|
143 | SendSSL=0;
|
144 | }else if(httpsString != -1){
|
145 | url=TARGET_URL.substring(httpsString+8);
|
146 | SendSSL=1;
|
147 | }else{
|
148 | url=this->TARGET_URL;
|
149 | SendSSL=0;
|
150 | }
|
151 | return url;
|
152 | }
|
153 | /*** end ***/
|
154 | bool configFS::checkHTTPadjustTime(){
|
155 | if(this->TARGET_URL.indexOf(__HTTPS,0) >= 0) SendSSL=1;
|
156 | else SendSSL =0;
|
157 | if(SendSSL==1) _secAdjust=_ADJUST_HTTPS;
|
158 | else _secAdjust=_ADJUST_HTTP;
|
159 |
|
160 | return true;
|
161 | }
|
162 | /**** save actuelle config-data ****/
|
163 | bool configFS::saveconfigFS(){
|
164 | bool r = false;
|
165 | String s = "{\n";
|
166 | s += "Config: \""; s += 1; s += "\",\n";
|
167 | s += "Name_IoT: \""; s += this->NAME_IoT; s += "\",\n";
|
168 | s += "Name_Sens1: \""; s += this->Sensor1; s += "\",\n";
|
169 | s += "Name_Sens2: \""; s += this->Sensor2; s += "\",\n";
|
170 | s += "Name_Sens3: \""; s += this->Sensor3; s += "\",\n";
|
171 | s += "Name_Sens4: \""; s += this->Sensor4; s += "\",\n";
|
172 | s += "Target_URL: \""; s += this->TARGET_URL; s += "\",\n";
|
173 | s += "Switch_Temp: \""; s += this->SwitchOnTemp; s += "\",\n";
|
174 | s += "Cont_Type: \""; s += this->sendJSON; s += "\",\n";
|
175 | s += "Push_Pull: \""; s += this->sendPUSH; s += "\"\n";
|
176 | s += "}";
|
177 |
|
178 | // Serial.println(s);
|
179 | if(this->MOUNTED){
|
180 | File Fconfig = LittleFS.open("/config.ini","w");
|
181 | if (Fconfig){
|
182 | int w=Fconfig.print(s);
|
183 | Fconfig.close();
|
184 | if (w > 1) r = true; // write file was successful
|
185 | }
|
186 | }
|
187 | return r;
|
188 | }
|
189 | //******************* load one value from saved config *****************
|
190 | String configFS::getOneFileValue(String file,String ident){
|
191 | String ret;
|
192 | int argBegin = file.indexOf(ident);
|
193 | if(argBegin>0){
|
194 | int argEnd = file.indexOf(",",argBegin+2);
|
195 | ret = this->decodeOnValue(file.substring(argBegin, argEnd));
|
196 | }
|
197 | return ret;
|
198 | }
|
199 | //******************* decode post-values *******************************
|
200 | String configFS::getOnePostValue(String post,String ident){
|
201 | String returnValue="";
|
202 | if(post.length()>0){
|
203 | int identBegin = post.indexOf(ident);
|
204 | if(identBegin >= 0){
|
205 | int argEnd = post.indexOf("&",identBegin);
|
206 | if (argEnd == -1) argEnd = post.length();
|
207 | returnValue = post.substring(post.indexOf("=",identBegin)+1,argEnd);
|
208 | }
|
209 | }
|
210 | return this->urldecode(returnValue);
|
211 | }
|
212 | /**** decode file-data and save into class ****/
|
213 | void configFS::loadConfig(String s){
|
214 | if(getOneFileValue(s,"Config:").toInt()!=0){ // check if config-data is available. If not, then save default values at once
|
215 | this->NAME_IoT = getOneFileValue(s,"Name_IoT:");
|
216 | this->Sensor1 = getOneFileValue(s,"Name_Sens1:");
|
217 | this->Sensor2 = getOneFileValue(s,"Name_Sens2:");
|
218 | this->Sensor3 = getOneFileValue(s,"Name_Sens3:");
|
219 | this->Sensor4 = getOneFileValue(s,"Name_Sens4:");
|
220 | this->TARGET_URL = getOneFileValue(s,"Target_URL:");
|
221 | this->SwitchOnTemp = getOneFileValue(s,"Switch_Temp:").toInt();
|
222 | this->sendJSON = getOneFileValue(s,"Cont_Type:").toInt();
|
223 | this->sendPUSH = getOneFileValue(s,"Push_Pull:").toInt();
|
224 | }
|
225 | else this->saveconfigFS(); // save for the first time all default data
|
226 | }
|
227 | /**** extract one value from string ****/
|
228 | String configFS::decodeOnValue(String s){
|
229 | int valueBegin = s.indexOf("\"");
|
230 | int valueLength = s.length();
|
231 | if(valueLength >0){
|
232 | if(valueBegin > 0){
|
233 | s = s.substring(valueBegin+1,valueLength-1);
|
234 | }
|
235 | else {
|
236 | valueBegin = s.indexOf(":");
|
237 | s = s.substring(valueBegin+1,valueLength);
|
238 | }
|
239 | }
|
240 | else s = "";
|
241 | return s;
|
242 | }
|
243 | /****** get free space from file-system ******/
|
244 | int configFS::calculateFreeSpaceFS(){
|
245 | if(MOUNTED){
|
246 | FSInfo fsinfo;
|
247 | LittleFS.info(fsinfo);
|
248 | FREESPACE = fsinfo.totalBytes - fsinfo.usedBytes;
|
249 | }
|
250 | else FREESPACE = 0;
|
251 | return FREESPACE;
|
252 | }
|
253 | int configFS::getFreeSpace(){
|
254 | return this->FREESPACE;
|
255 | }
|
256 | /***** decode values from html-post-arguments *****/
|
257 | bool configFS::savePostValues(String saveValues){
|
258 | bool r=false;
|
259 | if(saveValues.length()>0){
|
260 | // _debugString=saveValues;
|
261 | this->NAME_IoT = getOnePostValue(saveValues,__NAME_IoT);
|
262 | this->Sensor1 = getOnePostValue(saveValues,__SENSOR1);
|
263 | this->Sensor2 = getOnePostValue(saveValues,__SENSOR2);
|
264 | this->Sensor3 = getOnePostValue(saveValues,__SENSOR3);
|
265 | this->Sensor4 = getOnePostValue(saveValues,__SENSOR4);
|
266 | this->TARGET_URL = getOnePostValue(saveValues,__TARGET_SERVER);
|
267 | this->SwitchOnTemp = getOnePostValue(saveValues,__SWITCH_TEMP).toInt();
|
268 | this->sendJSON = getOnePostValue(saveValues,__CONTENT_TYPE).toInt();
|
269 | this->sendPUSH = getOnePostValue(saveValues,__PUSH_PULL).toInt();
|
270 | }
|
271 | // Serial.println(saveValues);
|
272 | return this->saveconfigFS();
|
273 | }
|
274 | /***** url decoding part *****/
|
275 | unsigned char configFS::h2int(char c){
|
276 | if (c >= '0' && c <='9') return((unsigned char)c - '0');
|
277 | if (c >= 'a' && c <='f') return((unsigned char)c - 'a' + 10);
|
278 | if (c >= 'A' && c <='F') return((unsigned char)c - 'A' + 10);
|
279 | return(0);
|
280 | }
|
281 | /***** url decoding function ******/
|
282 | String configFS::urldecode(String str){
|
283 | String encodedString="";
|
284 | char c;
|
285 | char code0;
|
286 | char code1;
|
287 | for (int i =0; i < str.length(); i++){
|
288 | c=str.charAt(i);
|
289 | if (c == '+') encodedString+=' ';
|
290 | else if (c == '%') {
|
291 | i++;
|
292 | code0=str.charAt(i);
|
293 | i++;
|
294 | code1=str.charAt(i);
|
295 | c = (h2int(code0) << 4) | h2int(code1);
|
296 | encodedString+=c;
|
297 | }
|
298 | else encodedString+=c;
|
299 | yield();
|
300 | }
|
301 | return encodedString;
|
302 | }
|
303 | /***** url encoding function ******/
|
304 | String configFS::urlencode(String str){
|
305 | String encodedString="";
|
306 | char c;
|
307 | char code0;
|
308 | char code1;
|
309 | char code2;
|
310 | for (int i =0; i < str.length(); i++){
|
311 | c=str.charAt(i);
|
312 | if (c == ' ') encodedString+= '+';
|
313 | else if (isalnum(c)) encodedString+=c;
|
314 | else{
|
315 | code1=(c & 0xf)+'0';
|
316 | if ((c & 0xf) >9) code1=(c & 0xf) - 10 + 'A';
|
317 | c=(c>>4)&0xf;
|
318 | code0=c+'0';
|
319 | if (c > 9) code0=c - 10 + 'A';
|
320 | code2='\0';
|
321 | encodedString+='%';
|
322 | encodedString+=code0;
|
323 | encodedString+=code1;
|
324 | //encodedString+=code2;
|
325 | }
|
326 | yield();
|
327 | }
|
328 | return encodedString;
|
329 | }
|
330 |
|
331 | #endif //*** CONFIG_FS_H_
|