Helper.cpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794
  1. #include "defines.h"
  2. #include "freertos/FreeRTOS.h"
  3. #include "freertos/task.h"
  4. #include "Helper.h"
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <iomanip>
  8. #include <sstream>
  9. #include <fstream>
  10. #include <iostream>
  11. #include <math.h>
  12. #include <dirent.h>
  13. #include <string.h>
  14. #include <esp_log.h>
  15. #include <esp_mac.h>
  16. #include <esp_timer.h>
  17. #include "ClassLogFile.h"
  18. #include <esp_vfs_fat.h>
  19. #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0))
  20. #include <esp_private/sdmmc_common.h>
  21. #else
  22. #include <../sdmmc_common.h>
  23. #endif
  24. static const char *TAG = "HELPER";
  25. using namespace std;
  26. unsigned int systemStatus = 0;
  27. bool all_pw_were_encrypted = false;
  28. sdmmc_cid_t sd_card_cid;
  29. sdmmc_csd_t sd_card_csd;
  30. bool is_sd_card_mmc;
  31. #if CONFIG_SOC_TEMP_SENSOR_SUPPORTED
  32. // The ESP32-S2/C3/S3/C2 has a built-in temperature sensor.
  33. // The temperature sensor module contains an 8-bit Sigma-Delta ADC and a temperature offset DAC.
  34. // https://github.com/espressif/esp-idf/blob/master/examples/peripherals/temperature_sensor/
  35. temperature_sensor_handle_t temp_handle = NULL;
  36. temperature_sensor_config_t temp_sensor = {
  37. .range_min = -10,
  38. .range_max = 80,
  39. .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT,
  40. };
  41. void init_tempsensor(void)
  42. {
  43. ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor, &temp_handle));
  44. xTaskCreate(
  45. [](void *pvParameters)
  46. {
  47. while (1)
  48. {
  49. // Get converted sensor data
  50. float tsens_out;
  51. // Enable temperature sensor
  52. ESP_ERROR_CHECK(temperature_sensor_enable(temp_handle));
  53. ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_handle, &tsens_out));
  54. temp_sens_value = tsens_out;
  55. // Disable the temperature sensor if it is not needed and save the power
  56. ESP_ERROR_CHECK(temperature_sensor_disable(temp_handle));
  57. vTaskDelay(pdMS_TO_TICKS(5000));
  58. }
  59. },
  60. "tempsensor_task", 2048, NULL, 5, NULL);
  61. }
  62. float read_tempsensor(void)
  63. {
  64. return temp_sens_value;
  65. }
  66. #elif CONFIG_IDF_TARGET_ESP32
  67. extern "C" uint8_t temprature_sens_read(void);
  68. float read_tempsensor(void)
  69. {
  70. // convert Fahrenheit to Celsius (F-32) * (5/9) = degree Celsius
  71. temp_sens_value = (temprature_sens_read() - 32) / 1.8;
  72. return temp_sens_value;
  73. }
  74. #endif
  75. void string_to_ip4(const char *ip, int &a, int &b, int &c, int &d)
  76. {
  77. std::string zw = std::string(ip);
  78. std::stringstream s(zw);
  79. char ch; // to temporarily store the '.'
  80. s >> a >> ch >> b >> ch >> c >> ch >> d;
  81. }
  82. std::string bssid_to_string(const char *c)
  83. {
  84. char cBssid[25];
  85. sprintf(cBssid, "%02x:%02x:%02x:%02x:%02x:%02x", c[0], c[1], c[2], c[3], c[4], c[5]);
  86. return std::string(cBssid);
  87. }
  88. string to_upper(string in)
  89. {
  90. for (int i = 0; i < in.length(); ++i)
  91. {
  92. in[i] = toupper(in[i]);
  93. }
  94. return in;
  95. }
  96. string to_lower(string in)
  97. {
  98. for (int i = 0; i < in.length(); ++i)
  99. {
  100. in[i] = tolower(in[i]);
  101. }
  102. return in;
  103. }
  104. std::vector<std::string> split_string(const std::string &str)
  105. {
  106. std::vector<std::string> tokens;
  107. std::stringstream ss(str);
  108. std::string token;
  109. while (std::getline(ss, token, '\n'))
  110. {
  111. tokens.push_back(token);
  112. }
  113. return tokens;
  114. }
  115. std::vector<std::string> split_line(std::string input, std::string _delimiter)
  116. {
  117. std::vector<std::string> Output;
  118. // wenn input nicht leer ist
  119. if (input.length() > 1)
  120. {
  121. if ((to_upper(input).find("PASSWORD") != std::string::npos) || (input.find("SSID") != std::string::npos) || (to_upper(input).find("TOKEN") != std::string::npos) || (to_upper(input).find("APIKEY") != std::string::npos) ||
  122. (input.find("**##**") != std::string::npos))
  123. {
  124. size_t pos1 = input.find(_delimiter);
  125. size_t pos2 = input.find(" ");
  126. // wenn _delimiter im string gefunden wird
  127. if (pos1 != std::string::npos)
  128. {
  129. Output.push_back(trim_string_left_right(input.substr(0, pos1), ""));
  130. // wenn der string einen Wert enthält
  131. if ((input.size() - 1) > pos1)
  132. {
  133. // überprüfe die erste Stelle
  134. std::string value = input.substr(pos1, std::string::npos);
  135. value.erase(0, 1);
  136. value = trim_string_left_right(value, "");
  137. if ((value.substr(0, 1) == "\"") && (value.substr(value.size() - 1, std::string::npos) == "\""))
  138. {
  139. value = value.substr(1, value.size() - 2);
  140. }
  141. std::string is_pw_encrypted = value.substr(0, 6);
  142. if (is_pw_encrypted == "**##**")
  143. {
  144. Output.push_back(encrypt_decrypt_string(value.substr(6, std::string::npos)));
  145. }
  146. else
  147. {
  148. Output.push_back(value.substr(0, std::string::npos));
  149. }
  150. }
  151. else
  152. {
  153. Output.push_back("");
  154. }
  155. }
  156. // wenn Leerzeichen im string gefunden wird
  157. else if (pos2 != std::string::npos)
  158. {
  159. Output.push_back(trim_string_left_right(input.substr(0, pos2), ""));
  160. // wenn der string einen Wert enthält
  161. if ((input.size() - 1) > pos2)
  162. {
  163. // überprüfe die erste Stelle
  164. std::string value = input.substr(pos2, std::string::npos);
  165. value.erase(0, 1);
  166. value = trim_string_left_right(value, "");
  167. if ((value.substr(0, 1) == "\"") && (value.substr(value.size() - 1, std::string::npos) == "\""))
  168. {
  169. value = value.substr(1, value.size() - 2);
  170. }
  171. std::string is_pw_encrypted = value.substr(0, 6);
  172. if (is_pw_encrypted == "**##**")
  173. {
  174. Output.push_back(encrypt_decrypt_string(value.substr(6, std::string::npos)));
  175. }
  176. else
  177. {
  178. Output.push_back(value.substr(0, std::string::npos));
  179. }
  180. }
  181. else
  182. {
  183. Output.push_back("");
  184. }
  185. }
  186. else
  187. {
  188. Output.push_back(input);
  189. }
  190. }
  191. else
  192. {
  193. // Legacy Mode
  194. std::string token;
  195. size_t pos1 = std::string::npos;
  196. if (find_delimiter_pos(input, _delimiter) != std::string::npos)
  197. {
  198. pos1 = find_delimiter_pos(input, _delimiter);
  199. }
  200. else
  201. {
  202. pos1 = find_delimiter_pos(input, " ");
  203. }
  204. if (pos1 != std::string::npos)
  205. {
  206. Output.push_back(trim_string_left_right(input.substr(0, pos1), " "));
  207. if ((input.size() - 1) > pos1)
  208. {
  209. // überprüfe die erste Stelle
  210. std::string value = input.substr(pos1, std::string::npos);
  211. value.erase(0, 1);
  212. value = trim_string_left_right(value, " ");
  213. if (find_delimiter_pos(value, _delimiter) != std::string::npos)
  214. {
  215. pos1 = find_delimiter_pos(value, _delimiter);
  216. }
  217. else
  218. {
  219. pos1 = find_delimiter_pos(value, " ");
  220. }
  221. if ((value.substr(0, 1) == "\"") && (value.substr(value.size() - 1, std::string::npos) == "\""))
  222. {
  223. value = value.substr(1, value.size() - 2);
  224. }
  225. while (pos1 != std::string::npos)
  226. {
  227. token = value.substr(0, pos1);
  228. token = trim_string_left_right(token, " ");
  229. if ((token.substr(0, 1) == "\"") && (token.substr(token.size() - 1, std::string::npos) == "\""))
  230. {
  231. token = token.substr(1, token.size() - 2);
  232. }
  233. Output.push_back(token);
  234. value.erase(0, pos1 + 1);
  235. value = trim_string_left_right(value, " ");
  236. if (find_delimiter_pos(value, _delimiter) != std::string::npos)
  237. {
  238. pos1 = find_delimiter_pos(value, _delimiter);
  239. }
  240. else
  241. {
  242. pos1 = find_delimiter_pos(value, " ");
  243. }
  244. }
  245. if ((value.substr(0, 1) == "\"") && (value.substr(value.size() - 1, std::string::npos) == "\""))
  246. {
  247. value = value.substr(1, value.size() - 2);
  248. }
  249. Output.push_back(value);
  250. }
  251. else
  252. {
  253. Output.push_back("");
  254. }
  255. }
  256. else
  257. {
  258. Output.push_back(input);
  259. }
  260. }
  261. }
  262. else
  263. {
  264. Output.push_back(input);
  265. }
  266. return Output;
  267. }
  268. // Encrypt/Decrypt a string
  269. std::string encrypt_decrypt_string(std::string toEncrypt)
  270. {
  271. char key[3] = {'K', 'C', 'Q'}; // Any chars will work, in an array of any size
  272. std::string output = toEncrypt;
  273. for (int i = 0; i < toEncrypt.size(); i++)
  274. {
  275. output[i] = toEncrypt[i] ^ key[i % (sizeof(key) / sizeof(char))];
  276. }
  277. return output;
  278. }
  279. // Checks whether a password is decrypted
  280. std::string encrypt_pw_string(std::string toEncrypt)
  281. {
  282. std::string string_result = "";
  283. if (is_in_string(toEncrypt, (std::string)STRING_ENCRYPTED_LABEL))
  284. {
  285. string_result = toEncrypt;
  286. all_pw_were_encrypted = true;
  287. }
  288. else
  289. {
  290. string_result = (std::string)STRING_ENCRYPTED_LABEL + encrypt_decrypt_string(toEncrypt);
  291. all_pw_were_encrypted = false;
  292. }
  293. return string_result;
  294. }
  295. std::string decrypt_pw_string(std::string toDecrypt)
  296. {
  297. std::string string_result = "";
  298. if (is_in_string(toDecrypt, (std::string)STRING_ENCRYPTED_LABEL))
  299. {
  300. replace_string(toDecrypt, (std::string)STRING_ENCRYPTED_LABEL, "", false);
  301. string_result = encrypt_decrypt_string(toDecrypt);
  302. all_pw_were_encrypted = true;
  303. }
  304. else
  305. {
  306. string_result = toDecrypt;
  307. all_pw_were_encrypted = false;
  308. }
  309. return string_result;
  310. }
  311. // Checks if all passwords on the SD are encrypted and if they are not encrypted, it encrypts them.
  312. esp_err_t encrypt_decrypt_pw_on_sd(bool _encrypt, std::string filename)
  313. {
  314. std::string line = "";
  315. std::vector<std::string> splitted;
  316. std::vector<std::string> temp_file;
  317. all_pw_were_encrypted = false;
  318. std::string fn = format_filename(filename);
  319. FILE *pFile = fopen(fn.c_str(), "r");
  320. if (pFile == NULL)
  321. {
  322. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "EncryptDecryptConfigPwOnSD: Unable to open file config.ini (read)");
  323. fclose(pFile);
  324. return ESP_FAIL;
  325. }
  326. ESP_LOGD(TAG, "EncryptDecryptConfigPwOnSD: config.ini opened");
  327. char temp_line[256];
  328. if (fgets(temp_line, sizeof(temp_line), pFile) == NULL)
  329. {
  330. line = "";
  331. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "EncryptDecryptConfigPwOnSD: File opened, but empty or content not readable");
  332. fclose(pFile);
  333. return ESP_FAIL;
  334. }
  335. else
  336. {
  337. line = std::string(temp_line);
  338. }
  339. if (_encrypt)
  340. {
  341. while ((line.size() > 0) || !(feof(pFile)))
  342. {
  343. splitted = split_line(line);
  344. std::string _param = to_upper(splitted[0]);
  345. if (splitted.size() > 1)
  346. {
  347. if (filename == CONFIG_FILE)
  348. {
  349. if (_param == "PASSWORD")
  350. {
  351. line = "password = " + encrypt_pw_string(splitted[1]) + "\n";
  352. }
  353. else if (_param == "TOKEN")
  354. {
  355. line = "Token = " + encrypt_pw_string(splitted[1]) + "\n";
  356. }
  357. else if (_param == "APIKEY")
  358. {
  359. line = "apikey = " + encrypt_pw_string(splitted[1]) + "\n";
  360. }
  361. }
  362. else if (filename == NETWORK_CONFIG_FILE)
  363. {
  364. if (_param == "PASSWORD")
  365. {
  366. line = "password = \"" + encrypt_pw_string(splitted[1]) + "\"\n";
  367. }
  368. else if (_param == "HTTP_PASSWORD")
  369. {
  370. line = "http_password = \"" + encrypt_pw_string(splitted[1]) + "\"\n";
  371. }
  372. }
  373. }
  374. temp_file.push_back(line);
  375. if (fgets(temp_line, sizeof(temp_line), pFile) == NULL)
  376. {
  377. line = "";
  378. }
  379. else
  380. {
  381. line = std::string(temp_line);
  382. }
  383. }
  384. }
  385. else
  386. {
  387. while ((line.size() > 0) || !(feof(pFile)))
  388. {
  389. splitted = split_line(line);
  390. std::string _param = to_upper(splitted[0]);
  391. if (splitted.size() > 1)
  392. {
  393. if (filename == CONFIG_FILE)
  394. {
  395. if (_param == "PASSWORD")
  396. {
  397. line = "password = " + decrypt_pw_string(splitted[1]) + "\n";
  398. }
  399. else if (_param == "TOKEN")
  400. {
  401. line = "Token = " + decrypt_pw_string(splitted[1]) + "\n";
  402. }
  403. else if (_param == "APIKEY")
  404. {
  405. line = "apikey = " + decrypt_pw_string(splitted[1]) + "\n";
  406. }
  407. }
  408. else if (filename == NETWORK_CONFIG_FILE)
  409. {
  410. if (_param == "PASSWORD")
  411. {
  412. line = "password = \"" + decrypt_pw_string(splitted[1]) + "\"\n";
  413. }
  414. else if (_param == "HTTP_PASSWORD")
  415. {
  416. line = "http_password = \"" + decrypt_pw_string(splitted[1]) + "\"\n";
  417. }
  418. }
  419. }
  420. temp_file.push_back(line);
  421. if (fgets(temp_line, sizeof(temp_line), pFile) == NULL)
  422. {
  423. line = "";
  424. }
  425. else
  426. {
  427. line = std::string(temp_line);
  428. }
  429. }
  430. }
  431. fclose(pFile);
  432. // Only write to the SD if not all passwords are encrypted
  433. if ((all_pw_were_encrypted == false && _encrypt == true) || (all_pw_were_encrypted == true && _encrypt == false))
  434. {
  435. pFile = fopen(fn.c_str(), "w+");
  436. if (pFile == NULL)
  437. {
  438. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "EncryptDecryptConfigPwOnSD: Unable to open file config.ini (write)");
  439. fclose(pFile);
  440. return ESP_FAIL;
  441. }
  442. for (int i = 0; i < temp_file.size(); ++i)
  443. {
  444. fputs(temp_file[i].c_str(), pFile);
  445. }
  446. fclose(pFile);
  447. }
  448. ESP_LOGD(TAG, "EncryptDecryptConfigPwOnSD done");
  449. return ESP_OK;
  450. }
  451. string get_heapinfo()
  452. {
  453. string espInfoResultStr = "";
  454. char aMsgBuf[80];
  455. size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
  456. size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  457. size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
  458. size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  459. size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
  460. size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
  461. size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
  462. sprintf(aMsgBuf, "Heap Total: %ld", (long)aFreeHeapSize);
  463. espInfoResultStr += string(aMsgBuf);
  464. sprintf(aMsgBuf, " | SPI Free: %ld", (long)aFreeSPIHeapSize);
  465. espInfoResultStr += string(aMsgBuf);
  466. sprintf(aMsgBuf, " | SPI Large Block: %ld", (long)aHeapLargestFreeBlockSize);
  467. espInfoResultStr += string(aMsgBuf);
  468. sprintf(aMsgBuf, " | SPI Min Free: %ld", (long)aMinFreeHeapSize);
  469. espInfoResultStr += string(aMsgBuf);
  470. sprintf(aMsgBuf, " | Int Free: %ld", (long)(aFreeInternalHeapSize));
  471. espInfoResultStr += string(aMsgBuf);
  472. sprintf(aMsgBuf, " | Int Large Block: %ld", (long)aHeapIntLargestFreeBlockSize);
  473. espInfoResultStr += string(aMsgBuf);
  474. sprintf(aMsgBuf, " | Int Min Free: %ld", (long)(aMinFreeInternalHeapSize));
  475. espInfoResultStr += string(aMsgBuf);
  476. return espInfoResultStr;
  477. }
  478. size_t get_heapsize()
  479. {
  480. return heap_caps_get_free_size(MALLOC_CAP_8BIT);
  481. }
  482. size_t get_internal_heapsize()
  483. {
  484. return heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
  485. }
  486. ///////////////////////////////////////////////////////////////////////////////////////////////
  487. /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
  488. /* SD Card Manufacturer Database */
  489. struct SDCard_Manufacturer_database
  490. {
  491. string type;
  492. int id;
  493. string manufacturer;
  494. };
  495. /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
  496. /* SD Card Manufacturer Database */
  497. struct SDCard_Manufacturer_database sd_database[] = {
  498. {
  499. .type = "sd",
  500. .id = 0x01,
  501. .manufacturer = "Panasonic",
  502. },
  503. {
  504. .type = "sd",
  505. .id = 0x02,
  506. .manufacturer = "Toshiba/Kingston/Viking",
  507. },
  508. {
  509. .type = "sd",
  510. .id = 0x03,
  511. .manufacturer = "SanDisk",
  512. },
  513. {
  514. .type = "sd",
  515. .id = 0x05,
  516. .manufacturer = "Lenovo",
  517. },
  518. {
  519. .type = "sd",
  520. .id = 0x08,
  521. .manufacturer = "Silicon Power",
  522. },
  523. {
  524. .type = "sd",
  525. .id = 0x09,
  526. .manufacturer = "ATP",
  527. },
  528. {
  529. .type = "sd",
  530. .id = 0x18,
  531. .manufacturer = "Infineon",
  532. },
  533. {
  534. .type = "sd",
  535. .id = 0x1b,
  536. .manufacturer = "Transcend/Samsung",
  537. },
  538. {
  539. .type = "sd",
  540. .id = 0x1c,
  541. .manufacturer = "Transcend",
  542. },
  543. {
  544. .type = "sd",
  545. .id = 0x1d,
  546. .manufacturer = "Corsair/AData",
  547. },
  548. {
  549. .type = "sd",
  550. .id = 0x1e,
  551. .manufacturer = "Transcend",
  552. },
  553. {
  554. .type = "sd",
  555. .id = 0x1f,
  556. .manufacturer = "Kingston",
  557. },
  558. {
  559. .type = "sd",
  560. .id = 0x27,
  561. .manufacturer = "Delkin/Phison",
  562. },
  563. {
  564. .type = "sd",
  565. .id = 0x28,
  566. .manufacturer = "Lexar",
  567. },
  568. {
  569. .type = "sd",
  570. .id = 0x30,
  571. .manufacturer = "SanDisk",
  572. },
  573. {
  574. .type = "sd",
  575. .id = 0x31,
  576. .manufacturer = "Silicon Power",
  577. },
  578. {
  579. .type = "sd",
  580. .id = 0x33,
  581. .manufacturer = "STMicroelectronics",
  582. },
  583. {
  584. .type = "sd",
  585. .id = 0x41,
  586. .manufacturer = "Kingston",
  587. },
  588. {
  589. .type = "sd",
  590. .id = 0x6f,
  591. .manufacturer = "STMicroelectronics",
  592. },
  593. {
  594. .type = "sd",
  595. .id = 0x74,
  596. .manufacturer = "Transcend",
  597. },
  598. {
  599. .type = "sd",
  600. .id = 0x76,
  601. .manufacturer = "Patriot",
  602. },
  603. {
  604. .type = "sd",
  605. .id = 0x82,
  606. .manufacturer = "Gobe/Sony",
  607. },
  608. {
  609. .type = "sd",
  610. .id = 0x89,
  611. .manufacturer = "Netac",
  612. },
  613. {
  614. .type = "sd",
  615. .id = 0x9f,
  616. .manufacturer = "Kingston/Kodak/Silicon Power",
  617. },
  618. {
  619. .type = "sd",
  620. .id = 0xad,
  621. .manufacturer = "Amazon Basics/Lexar/OV",
  622. },
  623. {
  624. .type = "sd",
  625. .id = 0xdf,
  626. .manufacturer = "Lenovo",
  627. },
  628. {
  629. .type = "sd",
  630. .id = 0xfe,
  631. .manufacturer = "Bekit/Cloudisk/HP/Reletech",
  632. },
  633. };
  634. struct SDCard_Manufacturer_database mmc_database[] = {
  635. {
  636. .type = "mmc",
  637. .id = 0x00,
  638. .manufacturer = "SanDisk",
  639. },
  640. {
  641. .type = "mmc",
  642. .id = 0x02,
  643. .manufacturer = "Kingston/SanDisk",
  644. },
  645. {
  646. .type = "mmc",
  647. .id = 0x03,
  648. .manufacturer = "Toshiba",
  649. },
  650. {
  651. .type = "mmc",
  652. .id = 0x05,
  653. .manufacturer = "Unknown",
  654. },
  655. {
  656. .type = "mmc",
  657. .id = 0x06,
  658. .manufacturer = "Unknown",
  659. },
  660. {
  661. .type = "mmc",
  662. .id = 0x11,
  663. .manufacturer = "Toshiba",
  664. },
  665. {
  666. .type = "mmc",
  667. .id = 0x13,
  668. .manufacturer = "Micron",
  669. },
  670. {
  671. .type = "mmc",
  672. .id = 0x15,
  673. .manufacturer = "Samsung/SanDisk/LG",
  674. },
  675. {
  676. .type = "mmc",
  677. .id = 0x37,
  678. .manufacturer = "KingMax",
  679. },
  680. {
  681. .type = "mmc",
  682. .id = 0x44,
  683. .manufacturer = "ATP",
  684. },
  685. {
  686. .type = "mmc",
  687. .id = 0x45,
  688. .manufacturer = "SanDisk Corporation",
  689. },
  690. {
  691. .type = "mmc",
  692. .id = 0x2c,
  693. .manufacturer = "Kingston",
  694. },
  695. {
  696. .type = "mmc",
  697. .id = 0x70,
  698. .manufacturer = "Kingston",
  699. },
  700. {
  701. .type = "mmc",
  702. .id = 0xfe,
  703. .manufacturer = "Micron",
  704. },
  705. };
  706. /* Parse SD Card Manufacturer Database */
  707. string sd_card_parse_manufacturer_ids(int id)
  708. {
  709. if (is_sd_card_mmc)
  710. {
  711. unsigned int id_cnt = sizeof(mmc_database) / sizeof(struct SDCard_Manufacturer_database);
  712. string ret_val = "";
  713. for (int i = 0; i < id_cnt; i++)
  714. {
  715. if (mmc_database[i].id == id)
  716. {
  717. return mmc_database[i].manufacturer;
  718. }
  719. else
  720. {
  721. ret_val = "ID unknown (not in DB)";
  722. }
  723. }
  724. return ret_val;
  725. }
  726. else
  727. {
  728. unsigned int id_cnt = sizeof(sd_database) / sizeof(struct SDCard_Manufacturer_database);
  729. string ret_val = "";
  730. for (int i = 0; i < id_cnt; i++)
  731. {
  732. if (sd_database[i].id == id)
  733. {
  734. return sd_database[i].manufacturer;
  735. }
  736. else
  737. {
  738. ret_val = "ID unknown (not in DB)";
  739. }
  740. }
  741. return ret_val;
  742. }
  743. }
  744. string get_sd_card_partition_size()
  745. {
  746. FATFS *fs;
  747. uint32_t fre_clust, tot_sect;
  748. /* Get volume information and free clusters of drive 0 */
  749. f_getfree("0:", (DWORD *)&fre_clust, &fs);
  750. tot_sect = ((fs->n_fatent - 2) * fs->csize) / 1024 / (1024 / sd_card_csd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB
  751. return std::to_string(tot_sect);
  752. }
  753. string get_sd_card_free_partition_space()
  754. {
  755. FATFS *fs;
  756. uint32_t fre_clust, fre_sect;
  757. /* Get volume information and free clusters of drive 0 */
  758. f_getfree("0:", (DWORD *)&fre_clust, &fs);
  759. fre_sect = (fre_clust * fs->csize) / 1024 / (1024 / sd_card_csd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB
  760. return std::to_string(fre_sect);
  761. }
  762. string get_sd_card_partition_allocation_size()
  763. {
  764. FATFS *fs;
  765. uint32_t fre_clust, allocation_size;
  766. /* Get volume information and free clusters of drive 0 */
  767. f_getfree("0:", (DWORD *)&fre_clust, &fs);
  768. allocation_size = fs->ssize;
  769. return std::to_string(allocation_size);
  770. }
  771. void save_sd_card_info(sdmmc_card_t *card)
  772. {
  773. sd_card_cid = card->cid;
  774. sd_card_csd = card->csd;
  775. is_sd_card_mmc = card->is_mmc;
  776. }
  777. string get_sd_card_manufacturer()
  778. {
  779. string SDCardManufacturer = sd_card_parse_manufacturer_ids(sd_card_cid.mfg_id);
  780. return (SDCardManufacturer + " (ID: " + std::to_string(sd_card_cid.mfg_id) + ")");
  781. }
  782. string get_sd_card_name()
  783. {
  784. char *SDCardName = sd_card_cid.name;
  785. return std::string(SDCardName);
  786. }
  787. string get_sd_card_capacity()
  788. {
  789. int SDCardCapacity = sd_card_csd.capacity / (1024 / sd_card_csd.sector_size) / 1024; // total sectors * sector size --> Byte to MB (1024*1024)
  790. return std::to_string(SDCardCapacity);
  791. }
  792. string get_sd_card_sector_size()
  793. {
  794. int SDCardSectorSize = sd_card_csd.sector_size;
  795. return std::to_string(SDCardSectorSize);
  796. }
  797. ///////////////////////////////////////////////////////////////////////////////////////////////
  798. void mem_copy_gen(uint8_t *_source, uint8_t *_target, int _size)
  799. {
  800. for (int i = 0; i < _size; ++i)
  801. {
  802. *(_target + i) = *(_source + i);
  803. }
  804. }
  805. std::string format_filename(std::string input)
  806. {
  807. #ifdef ISWINDOWS_TRUE
  808. input.erase(0, 1);
  809. std::string os = "/";
  810. std::string ns = "\\";
  811. find_replace(input, os, ns);
  812. #endif
  813. return input;
  814. }
  815. std::size_t file_size(const std::string &file_name)
  816. {
  817. std::ifstream file(file_name.c_str(), std::ios::in | std::ios::binary);
  818. if (!file)
  819. {
  820. return 0;
  821. }
  822. file.seekg(0, std::ios::end);
  823. return static_cast<std::size_t>(file.tellg());
  824. }
  825. void find_replace(std::string &line, std::string &oldString, std::string &newString)
  826. {
  827. const size_t oldSize = oldString.length();
  828. // do nothing if line is shorter than the string to find
  829. if (oldSize > line.length())
  830. {
  831. return;
  832. }
  833. const size_t newSize = newString.length();
  834. for (size_t pos = 0;; pos += newSize)
  835. {
  836. // Locate the substring to replace
  837. pos = line.find(oldString, pos);
  838. if (pos == std::string::npos)
  839. {
  840. return;
  841. }
  842. if (oldSize == newSize)
  843. {
  844. // if they're same size, use std::string::replace
  845. line.replace(pos, oldSize, newString);
  846. }
  847. else
  848. {
  849. // if not same size, replace by erasing and inserting
  850. line.erase(pos, oldSize);
  851. line.insert(pos, newString);
  852. }
  853. }
  854. }
  855. /**
  856. * Create a folder and its parent folders as needed
  857. */
  858. bool make_dir(std::string path)
  859. {
  860. std::string parent;
  861. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Creating folder " + path + "...");
  862. bool bSuccess = false;
  863. int nRC = ::mkdir(path.c_str(), 0775);
  864. if (nRC == -1)
  865. {
  866. switch (errno)
  867. {
  868. case ENOENT:
  869. // parent didn't exist, try to create it
  870. parent = path.substr(0, path.find_last_of('/'));
  871. LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Need to create parent folder first: " + parent);
  872. if (make_dir(parent))
  873. {
  874. // Now, try to create again.
  875. bSuccess = 0 == ::mkdir(path.c_str(), 0775);
  876. }
  877. else
  878. {
  879. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create parent folder: " + parent);
  880. bSuccess = false;
  881. }
  882. break;
  883. case EEXIST:
  884. // Done!
  885. bSuccess = true;
  886. break;
  887. default:
  888. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")");
  889. bSuccess = false;
  890. break;
  891. }
  892. }
  893. else
  894. {
  895. bSuccess = true;
  896. }
  897. return bSuccess;
  898. }
  899. bool ctype_space(const char c, string adddelimiter)
  900. {
  901. if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11)
  902. {
  903. return true;
  904. }
  905. if (adddelimiter.find(c) != string::npos)
  906. {
  907. return true;
  908. }
  909. return false;
  910. }
  911. std::string trim_string_left_right(std::string istring, std::string adddelimiter)
  912. {
  913. bool trimmed = false;
  914. if (ctype_space(istring[istring.length() - 1], adddelimiter))
  915. {
  916. istring.erase(istring.length() - 1);
  917. trimmed = true;
  918. }
  919. if (ctype_space(istring[0], adddelimiter))
  920. {
  921. istring.erase(0, 1);
  922. trimmed = true;
  923. }
  924. if ((trimmed == false) || (istring.size() == 0))
  925. {
  926. return istring;
  927. }
  928. else
  929. {
  930. return trim_string_left_right(istring, adddelimiter);
  931. }
  932. }
  933. std::string trim_string_left(std::string istring, std::string adddelimiter)
  934. {
  935. bool trimmed = false;
  936. if (ctype_space(istring[0], adddelimiter))
  937. {
  938. istring.erase(0, 1);
  939. trimmed = true;
  940. }
  941. if ((trimmed == false) || (istring.size() == 0))
  942. {
  943. return istring;
  944. }
  945. else
  946. {
  947. return trim_string_left(istring, adddelimiter);
  948. }
  949. }
  950. std::string trim_string_right(std::string istring, std::string adddelimiter)
  951. {
  952. bool trimmed = false;
  953. if (ctype_space(istring[istring.length() - 1], adddelimiter))
  954. {
  955. istring.erase(istring.length() - 1);
  956. trimmed = true;
  957. }
  958. if ((trimmed == false) || (istring.size() == 0))
  959. {
  960. return istring;
  961. }
  962. else
  963. {
  964. return trim_string_right(istring, adddelimiter);
  965. }
  966. }
  967. size_t find_delimiter_pos(string input, string delimiter)
  968. {
  969. size_t pos = std::string::npos;
  970. string akt_del;
  971. for (int anz = 0; anz < delimiter.length(); ++anz)
  972. {
  973. akt_del = delimiter[anz];
  974. size_t zw = input.find(akt_del);
  975. if (zw != std::string::npos)
  976. {
  977. if ((pos != std::string::npos) && (zw < pos))
  978. {
  979. pos = zw;
  980. }
  981. else
  982. {
  983. pos = zw;
  984. }
  985. }
  986. }
  987. return pos;
  988. }
  989. bool rename_file(string from, string to)
  990. {
  991. // ESP_LOGI(logTag, "Renaming File: %s", from.c_str());
  992. FILE *fpSourceFile = fopen(from.c_str(), "rb");
  993. // Sourcefile does not exist otherwise there is a mistake when renaming!
  994. if (!fpSourceFile)
  995. {
  996. ESP_LOGE(TAG, "RenameFile: File %s does not exist!", from.c_str());
  997. return false;
  998. }
  999. fclose(fpSourceFile);
  1000. rename(from.c_str(), to.c_str());
  1001. return true;
  1002. }
  1003. bool rename_folder(string from, string to)
  1004. {
  1005. // ESP_LOGI(logTag, "Renaming Folder: %s", from.c_str());
  1006. DIR *fpSourceFolder = opendir(from.c_str());
  1007. // Sourcefolder does not exist otherwise there is a mistake when renaming!
  1008. if (!fpSourceFolder)
  1009. {
  1010. ESP_LOGE(TAG, "RenameFolder: Folder %s does not exist!", from.c_str());
  1011. return false;
  1012. }
  1013. closedir(fpSourceFolder);
  1014. rename(from.c_str(), to.c_str());
  1015. return true;
  1016. }
  1017. bool file_exists(string filename)
  1018. {
  1019. FILE *fpSourceFile = fopen(filename.c_str(), "rb");
  1020. // Sourcefile does not exist
  1021. if (!fpSourceFile)
  1022. {
  1023. return false;
  1024. }
  1025. fclose(fpSourceFile);
  1026. return true;
  1027. }
  1028. bool folder_exists(string foldername)
  1029. {
  1030. DIR *fpSourceFolder = opendir(foldername.c_str());
  1031. // Sourcefolder does not exist
  1032. if (!fpSourceFolder)
  1033. {
  1034. return false;
  1035. }
  1036. closedir(fpSourceFolder);
  1037. return true;
  1038. }
  1039. bool delete_file(string filename)
  1040. {
  1041. // ESP_LOGI(logTag, "Deleting file: %s", filename.c_str());
  1042. /* Delete file */
  1043. FILE *fpSourceFile = fopen(filename.c_str(), "rb");
  1044. // Sourcefile does not exist otherwise there is a mistake in copying!
  1045. if (!fpSourceFile)
  1046. {
  1047. ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", filename.c_str());
  1048. return false;
  1049. }
  1050. fclose(fpSourceFile);
  1051. unlink(filename.c_str());
  1052. return true;
  1053. }
  1054. bool copy_file(string input, string output)
  1055. {
  1056. input = format_filename(input);
  1057. output = format_filename(output);
  1058. if (to_upper(input).compare(NETWORK_CONFIG_FILE) == 0)
  1059. {
  1060. ESP_LOGD(TAG, "wlan.ini kann nicht kopiert werden!");
  1061. return false;
  1062. }
  1063. char cTemp;
  1064. FILE *fpSourceFile = fopen(input.c_str(), "rb");
  1065. // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
  1066. if (!fpSourceFile)
  1067. {
  1068. ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
  1069. return false;
  1070. }
  1071. FILE *fpTargetFile = fopen(output.c_str(), "wb");
  1072. // Code Section
  1073. // Read From The Source File - "Copy"
  1074. while (fread(&cTemp, 1, 1, fpSourceFile) == 1)
  1075. {
  1076. // Write To The Target File - "Paste"
  1077. fwrite(&cTemp, 1, 1, fpTargetFile);
  1078. }
  1079. // Close The Files
  1080. fclose(fpSourceFile);
  1081. fclose(fpTargetFile);
  1082. ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str());
  1083. return true;
  1084. }
  1085. string get_file_full_filename(string filename)
  1086. {
  1087. size_t lastpos = filename.find_last_of('/');
  1088. if (lastpos == string::npos)
  1089. {
  1090. return "";
  1091. }
  1092. string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
  1093. return zw;
  1094. }
  1095. string get_directory(string filename)
  1096. {
  1097. size_t lastpos = filename.find('/');
  1098. if (lastpos == string::npos)
  1099. {
  1100. lastpos = filename.find('\\');
  1101. }
  1102. if (lastpos == string::npos)
  1103. {
  1104. return "";
  1105. }
  1106. string zw = filename.substr(0, lastpos - 1);
  1107. return zw;
  1108. }
  1109. string get_file_type(string filename)
  1110. {
  1111. size_t lastpos = filename.rfind(".", filename.length());
  1112. size_t neu_pos;
  1113. while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
  1114. {
  1115. lastpos = neu_pos;
  1116. }
  1117. if (lastpos == string::npos)
  1118. {
  1119. return "";
  1120. }
  1121. string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
  1122. zw = to_upper(zw);
  1123. return zw;
  1124. }
  1125. /* recursive mkdir */
  1126. int mkdir_r(const char *dir, const mode_t mode)
  1127. {
  1128. char tmp[FILE_PATH_MAX];
  1129. char *p = NULL;
  1130. struct stat sb;
  1131. size_t len;
  1132. /* copy path */
  1133. len = strnlen(dir, FILE_PATH_MAX);
  1134. if (len == 0 || len == FILE_PATH_MAX)
  1135. {
  1136. return -1;
  1137. }
  1138. memcpy(tmp, dir, len);
  1139. tmp[len] = '\0';
  1140. /* remove trailing slash */
  1141. if (tmp[len - 1] == '/')
  1142. {
  1143. tmp[len - 1] = '\0';
  1144. }
  1145. /* check if path exists and is a directory */
  1146. if (stat(tmp, &sb) == 0)
  1147. {
  1148. if (S_ISDIR(sb.st_mode))
  1149. {
  1150. return 0;
  1151. }
  1152. }
  1153. /* recursive mkdir */
  1154. for (p = tmp + 1; *p; p++)
  1155. {
  1156. if (*p == '/')
  1157. {
  1158. *p = 0;
  1159. /* test path */
  1160. if (stat(tmp, &sb) != 0)
  1161. {
  1162. /* path does not exist - create directory */
  1163. if (mkdir(tmp, mode) < 0)
  1164. {
  1165. return -1;
  1166. }
  1167. }
  1168. else if (!S_ISDIR(sb.st_mode))
  1169. {
  1170. /* not a directory */
  1171. return -1;
  1172. }
  1173. *p = '/';
  1174. }
  1175. }
  1176. /* test path */
  1177. if (stat(tmp, &sb) != 0)
  1178. {
  1179. /* path does not exist - create directory */
  1180. if (mkdir(tmp, mode) < 0)
  1181. {
  1182. return -1;
  1183. }
  1184. }
  1185. else if (!S_ISDIR(sb.st_mode))
  1186. {
  1187. /* not a directory */
  1188. return -1;
  1189. }
  1190. return 0;
  1191. }
  1192. time_t add_days(time_t startTime, int days)
  1193. {
  1194. struct tm *tm = localtime(&startTime);
  1195. tm->tm_mday += days;
  1196. return mktime(tm);
  1197. }
  1198. int remove_folder(const char *folderPath, const char *logTag)
  1199. {
  1200. // ESP_LOGD(logTag, "Delete content in path %s", folderPath);
  1201. DIR *dir = opendir(folderPath);
  1202. if (!dir)
  1203. {
  1204. ESP_LOGE(logTag, "Failed to stat dir: %s", folderPath);
  1205. return -1;
  1206. }
  1207. struct dirent *entry;
  1208. int deleted = 0;
  1209. while ((entry = readdir(dir)) != NULL)
  1210. {
  1211. std::string path = string(folderPath) + "/" + entry->d_name;
  1212. if (entry->d_type == DT_REG)
  1213. {
  1214. // ESP_LOGD(logTag, "Delete file %s", path.c_str());
  1215. if (unlink(path.c_str()) == 0)
  1216. {
  1217. deleted++;
  1218. }
  1219. else
  1220. {
  1221. ESP_LOGE(logTag, "can't delete file: %s", path.c_str());
  1222. }
  1223. }
  1224. else if (entry->d_type == DT_DIR)
  1225. {
  1226. deleted += remove_folder(path.c_str(), logTag);
  1227. }
  1228. }
  1229. closedir(dir);
  1230. if (rmdir(folderPath) != 0)
  1231. {
  1232. ESP_LOGE(logTag, "can't delete folder: %s", folderPath);
  1233. }
  1234. ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
  1235. return deleted;
  1236. }
  1237. std::string replace_string(std::string subject, const std::string &search, const std::string &replace)
  1238. {
  1239. size_t pos = 0;
  1240. while ((pos = subject.find(search, pos)) != std::string::npos)
  1241. {
  1242. subject.replace(pos, search.length(), replace);
  1243. pos += replace.length();
  1244. }
  1245. return subject;
  1246. }
  1247. string round_output(double _in, int _anzNachkomma)
  1248. {
  1249. std::stringstream stream;
  1250. int temp_value = _in;
  1251. // ESP_LOGD(TAG, "AnzNachkomma: %d", _anzNachkomma);
  1252. if (_anzNachkomma > 0)
  1253. {
  1254. stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
  1255. }
  1256. else
  1257. {
  1258. stream << temp_value;
  1259. }
  1260. return stream.str();
  1261. }
  1262. string get_mac(void)
  1263. {
  1264. uint8_t macInt[6];
  1265. char macFormated[6 * 2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
  1266. esp_read_mac(macInt, ESP_MAC_WIFI_STA);
  1267. sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]);
  1268. return macFormated;
  1269. }
  1270. void set_system_statusflag(SystemStatusFlag_t flag)
  1271. {
  1272. systemStatus = systemStatus | flag; // set bit
  1273. char buf[20];
  1274. snprintf(buf, sizeof(buf), "0x%08X", get_system_status());
  1275. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
  1276. }
  1277. void clear_system_statusflag(SystemStatusFlag_t flag)
  1278. {
  1279. systemStatus = systemStatus | ~flag; // clear bit
  1280. char buf[20];
  1281. snprintf(buf, sizeof(buf), "0x%08X", get_system_status());
  1282. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
  1283. }
  1284. int get_system_status(void)
  1285. {
  1286. return systemStatus;
  1287. }
  1288. bool is_set_system_statusflag(SystemStatusFlag_t flag)
  1289. {
  1290. // ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
  1291. if ((systemStatus & flag) == flag)
  1292. {
  1293. return true;
  1294. }
  1295. else
  1296. {
  1297. return false;
  1298. }
  1299. }
  1300. time_t get_uptime(void)
  1301. {
  1302. return (uint32_t)(esp_timer_get_time() / 1000 / 1000); // in seconds
  1303. }
  1304. string get_reset_reason(void)
  1305. {
  1306. std::string reasonText;
  1307. switch (esp_reset_reason())
  1308. {
  1309. case ESP_RST_POWERON:
  1310. reasonText = "Power-on event (or reset button)";
  1311. break; //!< Reset due to power-on event
  1312. case ESP_RST_EXT:
  1313. reasonText = "External pin";
  1314. break; //!< Reset by external pin (not applicable for ESP32)
  1315. case ESP_RST_SW:
  1316. reasonText = "Via esp_restart";
  1317. break; //!< Software reset via esp_restart
  1318. case ESP_RST_PANIC:
  1319. reasonText = "Exception/panic";
  1320. break; //!< Software reset due to exception/panic
  1321. case ESP_RST_INT_WDT:
  1322. reasonText = "Interrupt watchdog";
  1323. break; //!< Reset (software or hardware) due to interrupt watchdog
  1324. case ESP_RST_TASK_WDT:
  1325. reasonText = "Task watchdog";
  1326. break; //!< Reset due to task watchdog
  1327. case ESP_RST_WDT:
  1328. reasonText = "Other watchdogs";
  1329. break; //!< Reset due to other watchdogs
  1330. case ESP_RST_DEEPSLEEP:
  1331. reasonText = "Exiting deep sleep mode";
  1332. break; //!< Reset after exiting deep sleep mode
  1333. case ESP_RST_BROWNOUT:
  1334. reasonText = "Brownout";
  1335. break; //!< Brownout reset (software or hardware)
  1336. case ESP_RST_SDIO:
  1337. reasonText = "SDIO";
  1338. break; //!< Reset over SDIO
  1339. case ESP_RST_UNKNOWN: //!< Reset reason can not be determined
  1340. default:
  1341. reasonText = "Unknown";
  1342. }
  1343. return reasonText;
  1344. }
  1345. /**
  1346. * Returns the current uptime formated ad xxf xxh xxm [xxs]
  1347. */
  1348. std::string get_formated_uptime(bool compact)
  1349. {
  1350. char buf[20];
  1351. #pragma GCC diagnostic ignored "-Wformat-truncation"
  1352. int uptime = get_uptime(); // in seconds
  1353. int days = int(floor(uptime / (3600 * 24)));
  1354. int hours = int(floor((uptime - days * 3600 * 24) / (3600)));
  1355. int minutes = int(floor((uptime - days * 3600 * 24 - hours * 3600) / (60)));
  1356. int seconds = uptime - days * 3600 * 24 - hours * 3600 - minutes * 60;
  1357. if (compact)
  1358. {
  1359. snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds);
  1360. }
  1361. else
  1362. {
  1363. snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds);
  1364. }
  1365. return std::string(buf);
  1366. }
  1367. const char *get404(void)
  1368. {
  1369. return "<pre>\n\n\n\n"
  1370. " _\n"
  1371. " .__(.)< ( oh oh! This page does not exist! )\n"
  1372. " \\___)\n"
  1373. "\n\n"
  1374. " You could try your <a href=index.html target=_parent>luck</a> here!</pre>\n"
  1375. "<script>document.cookie = \"page=overview.html\"</script>"; // Make sure we load the overview page
  1376. }
  1377. std::string url_decode(const std::string &value)
  1378. {
  1379. std::string result;
  1380. result.reserve(value.size());
  1381. for (std::size_t i = 0; i < value.size(); ++i)
  1382. {
  1383. auto ch = value[i];
  1384. if (ch == '%' && (i + 2) < value.size())
  1385. {
  1386. auto hex = value.substr(i + 1, 2);
  1387. auto dec = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
  1388. result.push_back(dec);
  1389. i += 2;
  1390. }
  1391. else if (ch == '+')
  1392. {
  1393. result.push_back(' ');
  1394. }
  1395. else
  1396. {
  1397. result.push_back(ch);
  1398. }
  1399. }
  1400. return result;
  1401. }
  1402. bool replace_string(std::string &s, std::string const &toReplace, std::string const &replaceWith)
  1403. {
  1404. return replace_string(s, toReplace, replaceWith, true);
  1405. }
  1406. bool replace_string(std::string &s, std::string const &toReplace, std::string const &replaceWith, bool logIt)
  1407. {
  1408. std::size_t pos = s.find(toReplace);
  1409. if (pos == std::string::npos)
  1410. {
  1411. // Not found
  1412. return false;
  1413. }
  1414. std::string old = s;
  1415. s.replace(pos, toReplace.length(), replaceWith);
  1416. if (logIt)
  1417. {
  1418. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
  1419. }
  1420. return true;
  1421. }
  1422. // from https://stackoverflow.com/a/14678800
  1423. void replace_all(std::string &s, const std::string &toReplace, const std::string &replaceWith)
  1424. {
  1425. size_t pos = 0;
  1426. while ((pos = s.find(toReplace, pos)) != std::string::npos)
  1427. {
  1428. s.replace(pos, toReplace.length(), replaceWith);
  1429. pos += replaceWith.length();
  1430. }
  1431. }
  1432. bool is_in_string(std::string &s, std::string const &toFind)
  1433. {
  1434. std::size_t pos = s.find(toFind);
  1435. if (pos == std::string::npos)
  1436. {
  1437. // Not found
  1438. return false;
  1439. }
  1440. return true;
  1441. }
  1442. bool is_string_numeric(std::string &input)
  1443. {
  1444. if (input.size() <= 0)
  1445. {
  1446. return false;
  1447. }
  1448. // Replace comma with a dot
  1449. replace_string(input, ",", ".", false);
  1450. int start = 0;
  1451. int punkt_existiert_schon = 0;
  1452. if (input[0] == '-')
  1453. {
  1454. start = 1;
  1455. }
  1456. for (int i = start; i < input.size(); i++)
  1457. {
  1458. if ((input[i] == '.') && (i > 0) && (punkt_existiert_schon == 0))
  1459. {
  1460. punkt_existiert_schon = 1;
  1461. i++;
  1462. }
  1463. else if (!isdigit(input[i]))
  1464. {
  1465. return false;
  1466. }
  1467. }
  1468. return true;
  1469. }
  1470. bool is_string_alphabetic(std::string &input)
  1471. {
  1472. for (int i = 0; i < input.size(); i++)
  1473. {
  1474. if (!isalpha(input[i]))
  1475. {
  1476. return false;
  1477. }
  1478. }
  1479. return true;
  1480. }
  1481. bool is_string_alphanumeric(std::string &input)
  1482. {
  1483. for (int i = 0; i < input.size(); i++)
  1484. {
  1485. if (!isalnum(input[i]))
  1486. {
  1487. return false;
  1488. }
  1489. }
  1490. return true;
  1491. }
  1492. bool alphanumeric_to_boolean(std::string &input)
  1493. {
  1494. if (is_string_alphabetic(input))
  1495. {
  1496. return string_to_boolean(to_upper(input));
  1497. }
  1498. else if (is_string_numeric(input))
  1499. {
  1500. return numeric_str_to_boolean(input);
  1501. }
  1502. return false;
  1503. }
  1504. int clip_int(int input, int high, int low)
  1505. {
  1506. if (input < low)
  1507. {
  1508. input = low;
  1509. }
  1510. else if (input > high)
  1511. {
  1512. input = high;
  1513. }
  1514. return input;
  1515. }
  1516. bool numeric_str_to_boolean(std::string input)
  1517. {
  1518. return (std::stoi(input) != 0);
  1519. }
  1520. bool string_to_boolean(std::string input)
  1521. {
  1522. return (input == "TRUE");
  1523. }