configFS.h


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_