Helper.cpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792
  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 _filename = format_filename(filename);
  315. FILE *pFile = fopen(_filename.c_str(), "r");
  316. if (pFile == NULL)
  317. {
  318. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "EncryptDecryptConfigPwOnSD: Unable to open file config.ini (read)");
  319. fclose(pFile);
  320. return ESP_FAIL;
  321. }
  322. ESP_LOGD(TAG, "EncryptDecryptConfigPwOnSD: config.ini opened");
  323. std::string line = "";
  324. char temp_line[256];
  325. if (fgets(temp_line, sizeof(temp_line), pFile) == NULL)
  326. {
  327. line = "";
  328. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "EncryptDecryptConfigPwOnSD: File opened, but empty or content not readable");
  329. fclose(pFile);
  330. return ESP_FAIL;
  331. }
  332. else
  333. {
  334. line = std::string(temp_line);
  335. }
  336. all_pw_were_encrypted = false;
  337. std::vector<std::string> splitted;
  338. std::vector<std::string> temp_file;
  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 == WLAN_CONFIG_FILE) || (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 == WLAN_CONFIG_FILE) || (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(_filename.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 *pFile = fopen(from.c_str(), "rb");
  993. // Sourcefile does not exist otherwise there is a mistake when renaming!
  994. if (!pFile)
  995. {
  996. ESP_LOGE(TAG, "RenameFile: File %s does not exist!", from.c_str());
  997. return false;
  998. }
  999. fclose(pFile);
  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 *pFile = fopen(filename.c_str(), "rb");
  1020. // Sourcefile does not exist
  1021. if (!pFile)
  1022. {
  1023. return false;
  1024. }
  1025. fclose(pFile);
  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 *pFile = fopen(filename.c_str(), "rb");
  1044. // Sourcefile does not exist otherwise there is a mistake in copying!
  1045. if (!pFile)
  1046. {
  1047. ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", filename.c_str());
  1048. return false;
  1049. }
  1050. fclose(pFile);
  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(WLAN_CONFIG_FILE) == 0) || (to_upper(input).compare(NETWORK_CONFIG_FILE) == 0))
  1059. {
  1060. ESP_LOGD(TAG, "wlan.ini kann nicht kopiert werden!");
  1061. return false;
  1062. }
  1063. FILE *fpSourceFile = fopen(input.c_str(), "rb");
  1064. // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
  1065. if (!fpSourceFile)
  1066. {
  1067. ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
  1068. return false;
  1069. }
  1070. FILE *fpTargetFile = fopen(output.c_str(), "wb");
  1071. char temp_char[1024];
  1072. // Read From The Source File - "Copy"
  1073. while (fread(&temp_char, 1, 1, fpSourceFile) == 1)
  1074. {
  1075. // Write To The Target File - "Paste"
  1076. fwrite(&temp_char, 1, 1, fpTargetFile);
  1077. }
  1078. // Close The Files
  1079. fclose(fpSourceFile);
  1080. fclose(fpTargetFile);
  1081. ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str());
  1082. return true;
  1083. }
  1084. string get_file_full_filename(string filename)
  1085. {
  1086. size_t lastpos = filename.find_last_of('/');
  1087. if (lastpos == string::npos)
  1088. {
  1089. return "";
  1090. }
  1091. string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
  1092. return zw;
  1093. }
  1094. string get_directory(string filename)
  1095. {
  1096. size_t lastpos = filename.find('/');
  1097. if (lastpos == string::npos)
  1098. {
  1099. lastpos = filename.find('\\');
  1100. }
  1101. if (lastpos == string::npos)
  1102. {
  1103. return "";
  1104. }
  1105. string zw = filename.substr(0, lastpos - 1);
  1106. return zw;
  1107. }
  1108. string get_file_type(string filename)
  1109. {
  1110. size_t lastpos = filename.rfind(".", filename.length());
  1111. size_t neu_pos;
  1112. while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
  1113. {
  1114. lastpos = neu_pos;
  1115. }
  1116. if (lastpos == string::npos)
  1117. {
  1118. return "";
  1119. }
  1120. string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
  1121. zw = to_upper(zw);
  1122. return zw;
  1123. }
  1124. /* recursive mkdir */
  1125. int mkdir_r(const char *dir, const mode_t mode)
  1126. {
  1127. char tmp[FILE_PATH_MAX];
  1128. char *p = NULL;
  1129. struct stat sb;
  1130. size_t len;
  1131. /* copy path */
  1132. len = strnlen(dir, FILE_PATH_MAX);
  1133. if (len == 0 || len == FILE_PATH_MAX)
  1134. {
  1135. return -1;
  1136. }
  1137. memcpy(tmp, dir, len);
  1138. tmp[len] = '\0';
  1139. /* remove trailing slash */
  1140. if (tmp[len - 1] == '/')
  1141. {
  1142. tmp[len - 1] = '\0';
  1143. }
  1144. /* check if path exists and is a directory */
  1145. if (stat(tmp, &sb) == 0)
  1146. {
  1147. if (S_ISDIR(sb.st_mode))
  1148. {
  1149. return 0;
  1150. }
  1151. }
  1152. /* recursive mkdir */
  1153. for (p = tmp + 1; *p; p++)
  1154. {
  1155. if (*p == '/')
  1156. {
  1157. *p = 0;
  1158. /* test path */
  1159. if (stat(tmp, &sb) != 0)
  1160. {
  1161. /* path does not exist - create directory */
  1162. if (mkdir(tmp, mode) < 0)
  1163. {
  1164. return -1;
  1165. }
  1166. }
  1167. else if (!S_ISDIR(sb.st_mode))
  1168. {
  1169. /* not a directory */
  1170. return -1;
  1171. }
  1172. *p = '/';
  1173. }
  1174. }
  1175. /* test path */
  1176. if (stat(tmp, &sb) != 0)
  1177. {
  1178. /* path does not exist - create directory */
  1179. if (mkdir(tmp, mode) < 0)
  1180. {
  1181. return -1;
  1182. }
  1183. }
  1184. else if (!S_ISDIR(sb.st_mode))
  1185. {
  1186. /* not a directory */
  1187. return -1;
  1188. }
  1189. return 0;
  1190. }
  1191. time_t add_days(time_t startTime, int days)
  1192. {
  1193. struct tm *tm = localtime(&startTime);
  1194. tm->tm_mday += days;
  1195. return mktime(tm);
  1196. }
  1197. int remove_folder(const char *folderPath, const char *logTag)
  1198. {
  1199. // ESP_LOGD(logTag, "Delete content in path %s", folderPath);
  1200. DIR *dir = opendir(folderPath);
  1201. if (!dir)
  1202. {
  1203. ESP_LOGE(logTag, "Failed to stat dir: %s", folderPath);
  1204. return -1;
  1205. }
  1206. struct dirent *entry;
  1207. int deleted = 0;
  1208. while ((entry = readdir(dir)) != NULL)
  1209. {
  1210. std::string path = string(folderPath) + "/" + entry->d_name;
  1211. if (entry->d_type == DT_REG)
  1212. {
  1213. // ESP_LOGD(logTag, "Delete file %s", path.c_str());
  1214. if (unlink(path.c_str()) == 0)
  1215. {
  1216. deleted++;
  1217. }
  1218. else
  1219. {
  1220. ESP_LOGE(logTag, "can't delete file: %s", path.c_str());
  1221. }
  1222. }
  1223. else if (entry->d_type == DT_DIR)
  1224. {
  1225. deleted += remove_folder(path.c_str(), logTag);
  1226. }
  1227. }
  1228. closedir(dir);
  1229. if (rmdir(folderPath) != 0)
  1230. {
  1231. ESP_LOGE(logTag, "can't delete folder: %s", folderPath);
  1232. }
  1233. ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
  1234. return deleted;
  1235. }
  1236. std::string replace_string(std::string subject, const std::string &search, const std::string &replace)
  1237. {
  1238. size_t pos = 0;
  1239. while ((pos = subject.find(search, pos)) != std::string::npos)
  1240. {
  1241. subject.replace(pos, search.length(), replace);
  1242. pos += replace.length();
  1243. }
  1244. return subject;
  1245. }
  1246. string round_output(double _in, int _anzNachkomma)
  1247. {
  1248. std::stringstream stream;
  1249. int temp_value = _in;
  1250. if (_anzNachkomma > 0)
  1251. {
  1252. stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
  1253. }
  1254. else
  1255. {
  1256. stream << temp_value;
  1257. }
  1258. return stream.str();
  1259. }
  1260. string get_mac(void)
  1261. {
  1262. uint8_t macInt[6];
  1263. char macFormated[6 * 2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
  1264. esp_read_mac(macInt, ESP_MAC_WIFI_STA);
  1265. sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]);
  1266. return macFormated;
  1267. }
  1268. void set_system_statusflag(SystemStatusFlag_t flag)
  1269. {
  1270. systemStatus = systemStatus | flag; // set bit
  1271. char buf[20];
  1272. snprintf(buf, sizeof(buf), "0x%08X", get_system_status());
  1273. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
  1274. }
  1275. void clear_system_statusflag(SystemStatusFlag_t flag)
  1276. {
  1277. systemStatus = systemStatus | ~flag; // clear bit
  1278. char buf[20];
  1279. snprintf(buf, sizeof(buf), "0x%08X", get_system_status());
  1280. LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
  1281. }
  1282. int get_system_status(void)
  1283. {
  1284. return systemStatus;
  1285. }
  1286. bool is_set_system_statusflag(SystemStatusFlag_t flag)
  1287. {
  1288. // ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
  1289. if ((systemStatus & flag) == flag)
  1290. {
  1291. return true;
  1292. }
  1293. else
  1294. {
  1295. return false;
  1296. }
  1297. }
  1298. time_t get_uptime(void)
  1299. {
  1300. return (uint32_t)(esp_timer_get_time() / 1000 / 1000); // in seconds
  1301. }
  1302. string get_reset_reason(void)
  1303. {
  1304. std::string reasonText;
  1305. switch (esp_reset_reason())
  1306. {
  1307. case ESP_RST_POWERON:
  1308. reasonText = "Power-on event (or reset button)";
  1309. break; //!< Reset due to power-on event
  1310. case ESP_RST_EXT:
  1311. reasonText = "External pin";
  1312. break; //!< Reset by external pin (not applicable for ESP32)
  1313. case ESP_RST_SW:
  1314. reasonText = "Via esp_restart";
  1315. break; //!< Software reset via esp_restart
  1316. case ESP_RST_PANIC:
  1317. reasonText = "Exception/panic";
  1318. break; //!< Software reset due to exception/panic
  1319. case ESP_RST_INT_WDT:
  1320. reasonText = "Interrupt watchdog";
  1321. break; //!< Reset (software or hardware) due to interrupt watchdog
  1322. case ESP_RST_TASK_WDT:
  1323. reasonText = "Task watchdog";
  1324. break; //!< Reset due to task watchdog
  1325. case ESP_RST_WDT:
  1326. reasonText = "Other watchdogs";
  1327. break; //!< Reset due to other watchdogs
  1328. case ESP_RST_DEEPSLEEP:
  1329. reasonText = "Exiting deep sleep mode";
  1330. break; //!< Reset after exiting deep sleep mode
  1331. case ESP_RST_BROWNOUT:
  1332. reasonText = "Brownout";
  1333. break; //!< Brownout reset (software or hardware)
  1334. case ESP_RST_SDIO:
  1335. reasonText = "SDIO";
  1336. break; //!< Reset over SDIO
  1337. case ESP_RST_UNKNOWN: //!< Reset reason can not be determined
  1338. default:
  1339. reasonText = "Unknown";
  1340. }
  1341. return reasonText;
  1342. }
  1343. /**
  1344. * Returns the current uptime formated ad xxf xxh xxm [xxs]
  1345. */
  1346. std::string get_formated_uptime(bool compact)
  1347. {
  1348. char buf[20];
  1349. #pragma GCC diagnostic ignored "-Wformat-truncation"
  1350. int uptime = get_uptime(); // in seconds
  1351. int days = int(floor(uptime / (3600 * 24)));
  1352. int hours = int(floor((uptime - days * 3600 * 24) / (3600)));
  1353. int minutes = int(floor((uptime - days * 3600 * 24 - hours * 3600) / (60)));
  1354. int seconds = uptime - days * 3600 * 24 - hours * 3600 - minutes * 60;
  1355. if (compact)
  1356. {
  1357. snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds);
  1358. }
  1359. else
  1360. {
  1361. snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds);
  1362. }
  1363. return std::string(buf);
  1364. }
  1365. const char *get404(void)
  1366. {
  1367. return "<pre>\n\n\n\n"
  1368. " _\n"
  1369. " .__(.)< ( oh oh! This page does not exist! )\n"
  1370. " \\___)\n"
  1371. "\n\n"
  1372. " You could try your <a href=index.html target=_parent>luck</a> here!</pre>\n"
  1373. "<script>document.cookie = \"page=overview.html\"</script>"; // Make sure we load the overview page
  1374. }
  1375. std::string url_decode(const std::string &value)
  1376. {
  1377. std::string result;
  1378. result.reserve(value.size());
  1379. for (std::size_t i = 0; i < value.size(); ++i)
  1380. {
  1381. auto ch = value[i];
  1382. if (ch == '%' && (i + 2) < value.size())
  1383. {
  1384. auto hex = value.substr(i + 1, 2);
  1385. auto dec = static_cast<char>(std::strtol(hex.c_str(), nullptr, 16));
  1386. result.push_back(dec);
  1387. i += 2;
  1388. }
  1389. else if (ch == '+')
  1390. {
  1391. result.push_back(' ');
  1392. }
  1393. else
  1394. {
  1395. result.push_back(ch);
  1396. }
  1397. }
  1398. return result;
  1399. }
  1400. bool replace_string(std::string &s, std::string const &toReplace, std::string const &replaceWith)
  1401. {
  1402. return replace_string(s, toReplace, replaceWith, true);
  1403. }
  1404. bool replace_string(std::string &s, std::string const &toReplace, std::string const &replaceWith, bool logIt)
  1405. {
  1406. std::size_t pos = s.find(toReplace);
  1407. if (pos == std::string::npos)
  1408. {
  1409. // Not found
  1410. return false;
  1411. }
  1412. std::string old = s;
  1413. s.replace(pos, toReplace.length(), replaceWith);
  1414. if (logIt)
  1415. {
  1416. LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
  1417. }
  1418. return true;
  1419. }
  1420. // from https://stackoverflow.com/a/14678800
  1421. void replace_all(std::string &s, const std::string &toReplace, const std::string &replaceWith)
  1422. {
  1423. size_t pos = 0;
  1424. while ((pos = s.find(toReplace, pos)) != std::string::npos)
  1425. {
  1426. s.replace(pos, toReplace.length(), replaceWith);
  1427. pos += replaceWith.length();
  1428. }
  1429. }
  1430. bool is_in_string(std::string &s, std::string const &toFind)
  1431. {
  1432. std::size_t pos = s.find(toFind);
  1433. if (pos == std::string::npos)
  1434. {
  1435. // Not found
  1436. return false;
  1437. }
  1438. return true;
  1439. }
  1440. bool is_string_numeric(std::string &input)
  1441. {
  1442. if (input.size() <= 0)
  1443. {
  1444. return false;
  1445. }
  1446. // Replace comma with a dot
  1447. replace_string(input, ",", ".", false);
  1448. int start = 0;
  1449. int punkt_existiert_schon = 0;
  1450. if (input[0] == '-')
  1451. {
  1452. start = 1;
  1453. }
  1454. for (int i = start; i < input.size(); i++)
  1455. {
  1456. if ((input[i] == '.') && (i > 0) && (punkt_existiert_schon == 0))
  1457. {
  1458. punkt_existiert_schon = 1;
  1459. i++;
  1460. }
  1461. else if (!isdigit(input[i]))
  1462. {
  1463. return false;
  1464. }
  1465. }
  1466. return true;
  1467. }
  1468. bool is_string_alphabetic(std::string &input)
  1469. {
  1470. for (int i = 0; i < input.size(); i++)
  1471. {
  1472. if (!isalpha(input[i]))
  1473. {
  1474. return false;
  1475. }
  1476. }
  1477. return true;
  1478. }
  1479. bool is_string_alphanumeric(std::string &input)
  1480. {
  1481. for (int i = 0; i < input.size(); i++)
  1482. {
  1483. if (!isalnum(input[i]))
  1484. {
  1485. return false;
  1486. }
  1487. }
  1488. return true;
  1489. }
  1490. bool alphanumeric_to_boolean(std::string &input)
  1491. {
  1492. if (is_string_alphabetic(input))
  1493. {
  1494. return string_to_boolean(to_upper(input));
  1495. }
  1496. else if (is_string_numeric(input))
  1497. {
  1498. return numeric_str_to_boolean(input);
  1499. }
  1500. return false;
  1501. }
  1502. int clip_int(int input, int high, int low)
  1503. {
  1504. if (input < low)
  1505. {
  1506. input = low;
  1507. }
  1508. else if (input > high)
  1509. {
  1510. input = high;
  1511. }
  1512. return input;
  1513. }
  1514. bool numeric_str_to_boolean(std::string input)
  1515. {
  1516. return (std::stoi(input) != 0);
  1517. }
  1518. bool string_to_boolean(std::string input)
  1519. {
  1520. return (input == "TRUE");
  1521. }