FlipperHTTP.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  1. // FlipperHTTP.h for flipper-http.ino
  2. #include <WiFi.h>
  3. #include <HTTPClient.h>
  4. #include <WiFiClientSecure.h>
  5. #include "SPIFFS.h"
  6. #include <ArduinoJson.h>
  7. #include <Arduino.h>
  8. #include <ArduinoHttpClient.h>
  9. #define B_PIN 4 // Blue
  10. #define G_PIN 5 // Green
  11. #define R_PIN 6 // Red
  12. #define ON LOW
  13. #define OFF HIGH
  14. class FlipperHTTP
  15. {
  16. public:
  17. // Constructor
  18. FlipperHTTP()
  19. {
  20. }
  21. // Main methods for flipper-http.ino
  22. void setup();
  23. void loop();
  24. // HTTP Methods
  25. String get(String url);
  26. String get(String url, const char *headerKeys[], const char *headerValues[], int headerSize);
  27. String post(String url, String payload);
  28. String post(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
  29. String put(String url, String payload);
  30. String put(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
  31. String delete_request(String url, String payload);
  32. String delete_request(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize);
  33. // stream data as bytes
  34. bool get_bytes_to_file(String url, const char *headerKeys[], const char *headerValues[], int headerSize)
  35. {
  36. WiFiClientSecure client;
  37. client.setInsecure(); // Bypass certificate
  38. HTTPClient http;
  39. File file = SPIFFS.open("/test.fap", FILE_WRITE);
  40. if (!file)
  41. {
  42. Serial.println("[ERROR] Failed to open file for writing.");
  43. return false;
  44. }
  45. http.collectHeaders(headerKeys, headerSize);
  46. if (http.begin(client, url))
  47. {
  48. for (int i = 0; i < headerSize; i++)
  49. {
  50. http.addHeader(headerKeys[i], headerValues[i]);
  51. }
  52. int httpCode = http.GET();
  53. if (httpCode > 0)
  54. {
  55. Serial.println("[GET/SUCCESS] POST request successful.");
  56. http.writeToStream(&file);
  57. file.close();
  58. return true;
  59. }
  60. else
  61. {
  62. Serial.print("[ERROR] GET Request Failed, error: ");
  63. Serial.println(http.errorToString(httpCode).c_str());
  64. }
  65. http.end();
  66. }
  67. else
  68. {
  69. Serial.println("[ERROR] Unable to connect to the server.");
  70. }
  71. return false;
  72. }
  73. bool post_bytes_to_file(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
  74. {
  75. WiFiClientSecure client;
  76. client.setInsecure(); // Bypass certificate
  77. HTTPClient http;
  78. File file = SPIFFS.open("/test.txt", FILE_WRITE);
  79. if (!file)
  80. {
  81. Serial.println("[ERROR] Failed to open file for writing.");
  82. return false;
  83. }
  84. http.collectHeaders(headerKeys, headerSize);
  85. if (http.begin(client, url))
  86. {
  87. for (int i = 0; i < headerSize; i++)
  88. {
  89. http.addHeader(headerKeys[i], headerValues[i]);
  90. }
  91. int httpCode = http.POST(payload);
  92. if (httpCode > 0)
  93. {
  94. Serial.println("[POST/SUCCESS] POST request successful.");
  95. http.writeToStream(&file);
  96. file.close();
  97. return true;
  98. }
  99. else
  100. {
  101. Serial.print("[ERROR] POST Request Failed, error: ");
  102. Serial.println(http.errorToString(httpCode).c_str());
  103. }
  104. http.end();
  105. }
  106. else
  107. {
  108. Serial.println("[ERROR] Unable to connect to the server.");
  109. }
  110. return false;
  111. }
  112. void print_bytes_file()
  113. {
  114. File file = SPIFFS.open("/test.txt", FILE_READ);
  115. if (!file)
  116. {
  117. Serial.println("[ERROR] Failed to open file for reading.");
  118. return;
  119. }
  120. while (file.available())
  121. {
  122. Serial.write(file.read());
  123. }
  124. Serial.flush();
  125. Serial.println();
  126. file.close();
  127. }
  128. // Save and Load settings to and from SPIFFS
  129. bool saveWifiSettings(String data);
  130. bool loadWifiSettings();
  131. // Connect to Wifi using the loaded SSID and Password
  132. bool connectToWifi();
  133. // Check if the Dev Board is connected to Wifi
  134. bool isConnectedToWifi() { return WiFi.status() == WL_CONNECTED; }
  135. // Read serial data until newline character
  136. String readSerialLine();
  137. // Clear serial buffer to avoid any residual data
  138. void clearSerialBuffer()
  139. {
  140. while (Serial.available() > 0)
  141. {
  142. Serial.read();
  143. }
  144. }
  145. // Turn on and off the LED
  146. void ledAction(int pin = G_PIN, int timeout = 250)
  147. {
  148. digitalWrite(pin, ON);
  149. delay(timeout);
  150. digitalWrite(pin, OFF);
  151. delay(timeout);
  152. }
  153. // Display LED sequence when Wifi Board is first connected to the Flipper
  154. void ledStart()
  155. {
  156. pinMode(B_PIN, OUTPUT); // Set Blue Pin mode as output
  157. pinMode(G_PIN, OUTPUT); // Set Green Pin mode as output
  158. pinMode(R_PIN, OUTPUT); // Set Red Pin mode as output
  159. digitalWrite(B_PIN, OFF);
  160. digitalWrite(R_PIN, OFF);
  161. ledAction();
  162. ledAction();
  163. ledAction();
  164. }
  165. // Starting LED (Green only)
  166. void ledStatus()
  167. {
  168. digitalWrite(B_PIN, OFF);
  169. digitalWrite(R_PIN, OFF);
  170. digitalWrite(G_PIN, ON);
  171. }
  172. // Turn off all LEDs
  173. void ledOff()
  174. {
  175. digitalWrite(B_PIN, OFF);
  176. digitalWrite(G_PIN, OFF);
  177. digitalWrite(R_PIN, OFF);
  178. }
  179. private:
  180. const char *settingsFilePath = "/flipper-http.json"; // Path to the settings file in the SPIFFS file system
  181. char loadedSSID[64] = {0}; // Variable to store SSID
  182. char loadedPassword[64] = {0}; // Variable to store password
  183. bool readSerialSettings(String receivedData, bool connectAfterSave);
  184. };
  185. // Connect to Wifi using the loaded SSID and Password
  186. bool FlipperHTTP::connectToWifi()
  187. {
  188. if (String(loadedSSID) == "" || String(loadedPassword) == "")
  189. {
  190. Serial.println("[ERROR] WiFi SSID or Password is empty.");
  191. return false;
  192. }
  193. WiFi.disconnect(true); // Ensure WiFi is disconnected before reconnecting
  194. WiFi.begin(loadedSSID, loadedPassword);
  195. int i = 0;
  196. while (!this->isConnectedToWifi() && i < 20)
  197. {
  198. delay(500);
  199. i++;
  200. Serial.print(".");
  201. }
  202. Serial.println(); // Move to next line after dots
  203. if (this->isConnectedToWifi())
  204. {
  205. Serial.println("[SUCCESS] Successfully connected to Wifi.");
  206. return true;
  207. }
  208. else
  209. {
  210. Serial.println("[ERROR] Failed to connect to Wifi.");
  211. return false;
  212. }
  213. }
  214. // Save Wifi settings to SPIFFS
  215. bool FlipperHTTP::saveWifiSettings(String jsonData)
  216. {
  217. File file = SPIFFS.open(settingsFilePath, FILE_WRITE);
  218. if (!file)
  219. {
  220. Serial.println("[ERROR] Failed to open file for writing.");
  221. return false;
  222. }
  223. file.print(jsonData);
  224. file.close();
  225. Serial.println("[SUCCESS] Settings saved to SPIFFS.");
  226. return true;
  227. }
  228. // Load Wifi settings from SPIFFS
  229. bool FlipperHTTP::loadWifiSettings()
  230. {
  231. File file = SPIFFS.open(settingsFilePath, FILE_READ);
  232. if (!file)
  233. {
  234. Serial.println("[ERROR] Failed to open file for reading.");
  235. return "";
  236. }
  237. // Read the entire file content
  238. String fileContent = file.readString();
  239. file.close();
  240. return fileContent;
  241. }
  242. String FlipperHTTP::readSerialLine()
  243. {
  244. String receivedData = "";
  245. while (Serial.available() > 0)
  246. {
  247. char incomingChar = Serial.read();
  248. if (incomingChar == '\n')
  249. {
  250. break;
  251. }
  252. receivedData += incomingChar;
  253. delay(1); // Minimal delay to allow buffer to fill
  254. }
  255. receivedData.trim(); // Remove any leading/trailing whitespace
  256. return receivedData;
  257. }
  258. bool FlipperHTTP::readSerialSettings(String receivedData, bool connectAfterSave)
  259. {
  260. DynamicJsonDocument doc(1024);
  261. DeserializationError error = deserializeJson(doc, receivedData);
  262. if (error)
  263. {
  264. Serial.print("[ERROR] Failed to parse JSON: ");
  265. Serial.println(error.c_str());
  266. return false;
  267. }
  268. // Extract values from JSON
  269. if (doc.containsKey("ssid") && doc.containsKey("password"))
  270. {
  271. strlcpy(loadedSSID, doc["ssid"], sizeof(loadedSSID));
  272. strlcpy(loadedPassword, doc["password"], sizeof(loadedPassword));
  273. }
  274. else
  275. {
  276. Serial.println("[ERROR] JSON does not contain ssid and password.");
  277. return false;
  278. }
  279. // Save to SPIFFS
  280. if (!this->saveWifiSettings(receivedData))
  281. {
  282. Serial.println("[ERROR] Failed to save settings to file.");
  283. return false;
  284. }
  285. // Attempt to reconnect with new settings
  286. if (connectAfterSave && this->connectToWifi())
  287. {
  288. Serial.println("[SUCCESS] Connected to the new Wifi network.");
  289. }
  290. return true;
  291. }
  292. String FlipperHTTP::get(String url)
  293. {
  294. WiFiClientSecure client;
  295. client.setInsecure(); // Bypass certificate validation
  296. HTTPClient http;
  297. String payload = "";
  298. if (http.begin(client, url))
  299. {
  300. int httpCode = http.GET();
  301. if (httpCode > 0)
  302. {
  303. payload = http.getString();
  304. http.end();
  305. return payload;
  306. }
  307. else
  308. {
  309. Serial.print("[ERROR] GET Request Failed, error: ");
  310. Serial.println(http.errorToString(httpCode).c_str());
  311. }
  312. http.end();
  313. }
  314. else
  315. {
  316. Serial.println("[ERROR] Unable to connect to the server.");
  317. }
  318. // Clear serial buffer to avoid any residual data
  319. this->clearSerialBuffer();
  320. return payload;
  321. }
  322. String FlipperHTTP::get(String url, const char *headerKeys[], const char *headerValues[], int headerSize)
  323. {
  324. WiFiClientSecure client;
  325. client.setInsecure(); // Bypass certificate
  326. HTTPClient http;
  327. String payload = "";
  328. http.collectHeaders(headerKeys, headerSize);
  329. if (http.begin(client, url))
  330. {
  331. for (int i = 0; i < headerSize; i++)
  332. {
  333. http.addHeader(headerKeys[i], headerValues[i]);
  334. }
  335. int httpCode = http.GET();
  336. if (httpCode > 0)
  337. {
  338. payload = http.getString();
  339. http.end();
  340. return payload;
  341. }
  342. else
  343. {
  344. Serial.print("[ERROR] GET Request Failed, error: ");
  345. Serial.println(http.errorToString(httpCode).c_str());
  346. }
  347. http.end();
  348. }
  349. else
  350. {
  351. Serial.println("[ERROR] Unable to connect to the server.");
  352. }
  353. // Clear serial buffer to avoid any residual data
  354. this->clearSerialBuffer();
  355. return payload;
  356. }
  357. String FlipperHTTP::delete_request(String url, String payload)
  358. {
  359. WiFiClientSecure client;
  360. client.setInsecure(); // Bypass certificate
  361. HTTPClient http;
  362. String response = "";
  363. if (http.begin(client, url))
  364. {
  365. int httpCode = http.sendRequest("DELETE", payload);
  366. if (httpCode > 0)
  367. {
  368. response = http.getString();
  369. http.end();
  370. return response;
  371. }
  372. else
  373. {
  374. Serial.print("[ERROR] DELETE Request Failed, error: ");
  375. Serial.println(http.errorToString(httpCode).c_str());
  376. }
  377. http.end();
  378. }
  379. else
  380. {
  381. Serial.println("[ERROR] Unable to connect to the server.");
  382. }
  383. // Clear serial buffer to avoid any residual data
  384. this->clearSerialBuffer();
  385. return response;
  386. }
  387. String FlipperHTTP::delete_request(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
  388. {
  389. WiFiClientSecure client;
  390. client.setInsecure(); // Bypass certificate
  391. HTTPClient http;
  392. String response = "";
  393. http.collectHeaders(headerKeys, headerSize);
  394. if (http.begin(client, url))
  395. {
  396. for (int i = 0; i < headerSize; i++)
  397. {
  398. http.addHeader(headerKeys[i], headerValues[i]);
  399. }
  400. int httpCode = http.sendRequest("DELETE", payload);
  401. if (httpCode > 0)
  402. {
  403. response = http.getString();
  404. http.end();
  405. return response;
  406. }
  407. else
  408. {
  409. Serial.print("[ERROR] DELETE Request Failed, error: ");
  410. Serial.println(http.errorToString(httpCode).c_str());
  411. }
  412. http.end();
  413. }
  414. else
  415. {
  416. Serial.println("[ERROR] Unable to connect to the server.");
  417. }
  418. // Clear serial buffer to avoid any residual data
  419. this->clearSerialBuffer();
  420. return response;
  421. }
  422. String FlipperHTTP::post(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
  423. {
  424. WiFiClientSecure client;
  425. client.setInsecure(); // Bypass certificate
  426. HTTPClient http;
  427. String response = "";
  428. http.collectHeaders(headerKeys, headerSize);
  429. if (http.begin(client, url))
  430. {
  431. for (int i = 0; i < headerSize; i++)
  432. {
  433. http.addHeader(headerKeys[i], headerValues[i]);
  434. }
  435. int httpCode = http.POST(payload);
  436. if (httpCode > 0)
  437. {
  438. response = http.getString();
  439. http.end();
  440. return response;
  441. }
  442. else
  443. {
  444. Serial.print("[ERROR] POST Request Failed, error: ");
  445. Serial.println(http.errorToString(httpCode).c_str());
  446. }
  447. http.end();
  448. }
  449. else
  450. {
  451. Serial.println("[ERROR] Unable to connect to the server.");
  452. }
  453. // Clear serial buffer to avoid any residual data
  454. this->clearSerialBuffer();
  455. return response;
  456. }
  457. String FlipperHTTP::post(String url, String payload)
  458. {
  459. WiFiClientSecure client;
  460. client.setInsecure(); // Bypass certificate
  461. HTTPClient http;
  462. String response = "";
  463. if (http.begin(client, url))
  464. {
  465. int httpCode = http.POST(payload);
  466. if (httpCode > 0)
  467. {
  468. response = http.getString();
  469. http.end();
  470. return response;
  471. }
  472. else
  473. {
  474. Serial.print("[ERROR] POST Request Failed, error: ");
  475. Serial.println(http.errorToString(httpCode).c_str());
  476. }
  477. http.end();
  478. }
  479. else
  480. {
  481. Serial.println("[ERROR] Unable to connect to the server.");
  482. }
  483. // Clear serial buffer to avoid any residual data
  484. this->clearSerialBuffer();
  485. return response;
  486. }
  487. String FlipperHTTP::put(String url, String payload, const char *headerKeys[], const char *headerValues[], int headerSize)
  488. {
  489. WiFiClientSecure client;
  490. client.setInsecure(); // Bypass certificate
  491. HTTPClient http;
  492. String response = "";
  493. http.collectHeaders(headerKeys, headerSize);
  494. if (http.begin(client, url))
  495. {
  496. for (int i = 0; i < headerSize; i++)
  497. {
  498. http.addHeader(headerKeys[i], headerValues[i]);
  499. }
  500. int httpCode = http.PUT(payload);
  501. if (httpCode > 0)
  502. {
  503. response = http.getString();
  504. http.end();
  505. return response;
  506. }
  507. else
  508. {
  509. Serial.print("[ERROR] PUT Request Failed, error: ");
  510. Serial.println(http.errorToString(httpCode).c_str());
  511. }
  512. http.end();
  513. }
  514. else
  515. {
  516. Serial.println("[ERROR] Unable to connect to the server.");
  517. }
  518. // Clear serial buffer to avoid any residual data
  519. this->clearSerialBuffer();
  520. return response;
  521. }
  522. String FlipperHTTP::put(String url, String payload)
  523. {
  524. WiFiClientSecure client;
  525. client.setInsecure(); // Bypass certificate
  526. HTTPClient http;
  527. String response = "";
  528. if (http.begin(client, url))
  529. {
  530. int httpCode = http.PUT(payload);
  531. if (httpCode > 0)
  532. {
  533. response = http.getString();
  534. http.end();
  535. return response;
  536. }
  537. else
  538. {
  539. Serial.print("[ERROR] PUT Request Failed, error: ");
  540. Serial.println(http.errorToString(httpCode).c_str());
  541. }
  542. http.end();
  543. }
  544. else
  545. {
  546. Serial.println("[ERROR] Unable to connect to the server.");
  547. }
  548. // Clear serial buffer to avoid any residual data
  549. this->clearSerialBuffer();
  550. return response;
  551. }
  552. void FlipperHTTP::setup()
  553. {
  554. Serial.begin(115200);
  555. // Initialize SPIFFS
  556. if (!SPIFFS.begin(true))
  557. {
  558. Serial.println("[ERROR] SPIFFS initialization failed.");
  559. ESP.restart();
  560. }
  561. this->ledStart();
  562. Serial.flush();
  563. }
  564. void FlipperHTTP::loop()
  565. {
  566. // Check if there's incoming serial data
  567. if (Serial.available() > 0)
  568. {
  569. // Read the incoming serial data until newline
  570. String _data = this->readSerialLine();
  571. if (_data.length() == 0)
  572. {
  573. // No complete command received
  574. return;
  575. }
  576. this->ledStatus();
  577. // Ping/Pong to see if board/flipper is connected
  578. if (_data.startsWith("[PING]"))
  579. {
  580. Serial.println("[PONG]");
  581. }
  582. // Handle [WIFI/SAVE] command
  583. else if (_data.startsWith("[WIFI/SAVE]"))
  584. {
  585. // Extract JSON data by removing the command part
  586. String jsonData = _data.substring(strlen("[WIFI/SAVE]"));
  587. jsonData.trim(); // Remove any leading/trailing whitespace
  588. // Parse and save the settings
  589. if (this->readSerialSettings(jsonData, true))
  590. {
  591. Serial.println("[SUCCESS] Wifi settings saved.");
  592. }
  593. else
  594. {
  595. Serial.println("[ERROR] Failed to save Wifi settings.");
  596. }
  597. }
  598. // Handle [WIFI/CONNECT] command
  599. else if (_data == "[WIFI/CONNECT]")
  600. {
  601. // Check if WiFi is already connected
  602. if (!this->isConnectedToWifi())
  603. {
  604. // Attempt to connect to Wifi
  605. if (this->connectToWifi())
  606. {
  607. Serial.println("[SUCCESS] Connected to Wifi.");
  608. }
  609. else
  610. {
  611. Serial.println("[ERROR] Failed to connect to Wifi.");
  612. }
  613. }
  614. else
  615. {
  616. Serial.println("[INFO] Already connected to Wifi.");
  617. }
  618. }
  619. // Handle [WIFI/DISCONNECT] command
  620. else if (_data == "[WIFI/DISCONNECT]")
  621. {
  622. WiFi.disconnect(true);
  623. Serial.println("[DISCONNECTED] Wifi has been disconnected.");
  624. }
  625. // Handle [GET] command
  626. else if (_data.startsWith("[GET]"))
  627. {
  628. if (!this->isConnectedToWifi() && !this->connectToWifi())
  629. {
  630. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  631. this->ledOff();
  632. return;
  633. }
  634. // Extract URL by removing the command part
  635. String url = _data.substring(strlen("[GET]"));
  636. url.trim();
  637. // GET request
  638. String getData = this->get(url);
  639. if (getData != "")
  640. {
  641. Serial.println("[GET/SUCCESS] GET request successful.");
  642. Serial.println(getData);
  643. Serial.flush();
  644. Serial.println();
  645. Serial.println("[GET/END]");
  646. }
  647. else
  648. {
  649. Serial.println("[ERROR] GET request failed or returned empty data.");
  650. }
  651. }
  652. // Handle [GET/HTTP] command
  653. else if (_data.startsWith("[GET/HTTP]"))
  654. {
  655. if (!this->isConnectedToWifi() && !this->connectToWifi())
  656. {
  657. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  658. this->ledOff();
  659. return;
  660. }
  661. // Extract the JSON by removing the command part
  662. String jsonData = _data.substring(strlen("[GET/HTTP]"));
  663. jsonData.trim();
  664. DynamicJsonDocument doc(1024);
  665. DeserializationError error = deserializeJson(doc, jsonData);
  666. if (error)
  667. {
  668. Serial.print("[ERROR] Failed to parse JSON.");
  669. this->ledOff();
  670. return;
  671. }
  672. // Extract values from JSON
  673. if (!doc.containsKey("url"))
  674. {
  675. Serial.println("[ERROR] JSON does not contain url.");
  676. this->ledOff();
  677. return;
  678. }
  679. String url = doc["url"];
  680. // Extract headers if available
  681. const char *headerKeys[10];
  682. const char *headerValues[10];
  683. int headerSize = 0;
  684. if (doc.containsKey("headers"))
  685. {
  686. JsonObject headers = doc["headers"];
  687. for (JsonPair header : headers)
  688. {
  689. headerKeys[headerSize] = header.key().c_str();
  690. headerValues[headerSize] = header.value();
  691. headerSize++;
  692. }
  693. }
  694. // GET request
  695. String getData = this->get(url, headerKeys, headerValues, headerSize);
  696. if (getData != "")
  697. {
  698. Serial.println("[GET/SUCCESS] GET request successful.");
  699. Serial.println(getData);
  700. Serial.flush();
  701. Serial.println();
  702. Serial.println("[GET/END]");
  703. }
  704. else
  705. {
  706. Serial.println("[ERROR] GET request failed or returned empty data.");
  707. }
  708. }
  709. // Handle [POST/HTTP] command
  710. else if (_data.startsWith("[POST/HTTP]"))
  711. {
  712. if (!this->isConnectedToWifi() && !this->connectToWifi())
  713. {
  714. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  715. this->ledOff();
  716. return;
  717. }
  718. // Extract the JSON by removing the command part
  719. String jsonData = _data.substring(strlen("[POST/HTTP]"));
  720. jsonData.trim();
  721. DynamicJsonDocument doc(1024);
  722. DeserializationError error = deserializeJson(doc, jsonData);
  723. if (error)
  724. {
  725. Serial.print("[ERROR] Failed to parse JSON.");
  726. this->ledOff();
  727. return;
  728. }
  729. // Extract values from JSON
  730. if (!doc.containsKey("url") || !doc.containsKey("payload"))
  731. {
  732. Serial.println("[ERROR] JSON does not contain url or payload.");
  733. this->ledOff();
  734. return;
  735. }
  736. String url = doc["url"];
  737. String payload = doc["payload"];
  738. // Extract headers if available
  739. const char *headerKeys[10];
  740. const char *headerValues[10];
  741. int headerSize = 0;
  742. if (doc.containsKey("headers"))
  743. {
  744. JsonObject headers = doc["headers"];
  745. for (JsonPair header : headers)
  746. {
  747. headerKeys[headerSize] = header.key().c_str();
  748. headerValues[headerSize] = header.value();
  749. headerSize++;
  750. }
  751. }
  752. // POST request
  753. String postData = this->post(url, payload, headerKeys, headerValues, headerSize);
  754. if (postData != "")
  755. {
  756. Serial.println("[POST/SUCCESS] POST request successful.");
  757. Serial.println(postData);
  758. Serial.flush();
  759. Serial.println();
  760. Serial.println("[POST/END]");
  761. }
  762. else
  763. {
  764. Serial.println("[ERROR] POST request failed or returned empty data.");
  765. }
  766. }
  767. // Handle [PUT/HTTP] command
  768. else if (_data.startsWith("[PUT/HTTP]"))
  769. {
  770. if (!this->isConnectedToWifi() && !this->connectToWifi())
  771. {
  772. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  773. this->ledOff();
  774. return;
  775. }
  776. // Extract the JSON by removing the command part
  777. String jsonData = _data.substring(strlen("[PUT/HTTP]"));
  778. jsonData.trim();
  779. DynamicJsonDocument doc(1024);
  780. DeserializationError error = deserializeJson(doc, jsonData);
  781. if (error)
  782. {
  783. Serial.print("[ERROR] Failed to parse JSON.");
  784. this->ledOff();
  785. return;
  786. }
  787. // Extract values from JSON
  788. if (!doc.containsKey("url") || !doc.containsKey("payload"))
  789. {
  790. Serial.println("[ERROR] JSON does not contain url or payload.");
  791. this->ledOff();
  792. return;
  793. }
  794. String url = doc["url"];
  795. String payload = doc["payload"];
  796. // Extract headers if available
  797. const char *headerKeys[10];
  798. const char *headerValues[10];
  799. int headerSize = 0;
  800. if (doc.containsKey("headers"))
  801. {
  802. JsonObject headers = doc["headers"];
  803. for (JsonPair header : headers)
  804. {
  805. headerKeys[headerSize] = header.key().c_str();
  806. headerValues[headerSize] = header.value();
  807. headerSize++;
  808. }
  809. }
  810. // PUT request
  811. String putData = this->put(url, payload, headerKeys, headerValues, headerSize);
  812. if (putData != "")
  813. {
  814. Serial.println("[PUT/SUCCESS] PUT request successful.");
  815. Serial.println(putData);
  816. Serial.flush();
  817. Serial.println();
  818. Serial.println("[PUT/END]");
  819. }
  820. else
  821. {
  822. Serial.println("[ERROR] PUT request failed or returned empty data.");
  823. }
  824. }
  825. // Handle [DELETE/HTTP] command
  826. else if (_data.startsWith("[DELETE/HTTP]"))
  827. {
  828. if (!this->isConnectedToWifi() && !this->connectToWifi())
  829. {
  830. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  831. this->ledOff();
  832. return;
  833. }
  834. // Extract the JSON by removing the command part
  835. String jsonData = _data.substring(strlen("[DELETE/HTTP]"));
  836. jsonData.trim();
  837. DynamicJsonDocument doc(1024);
  838. DeserializationError error = deserializeJson(doc, jsonData);
  839. if (error)
  840. {
  841. Serial.print("[ERROR] Failed to parse JSON.");
  842. this->ledOff();
  843. return;
  844. }
  845. // Extract values from JSON
  846. if (!doc.containsKey("url") || !doc.containsKey("payload"))
  847. {
  848. Serial.println("[ERROR] JSON does not contain url or payload.");
  849. this->ledOff();
  850. return;
  851. }
  852. String url = doc["url"];
  853. String payload = doc["payload"];
  854. // Extract headers if available
  855. const char *headerKeys[10];
  856. const char *headerValues[10];
  857. int headerSize = 0;
  858. if (doc.containsKey("headers"))
  859. {
  860. JsonObject headers = doc["headers"];
  861. for (JsonPair header : headers)
  862. {
  863. headerKeys[headerSize] = header.key().c_str();
  864. headerValues[headerSize] = header.value();
  865. headerSize++;
  866. }
  867. }
  868. // DELETE request
  869. String deleteData = this->delete_request(url, payload, headerKeys, headerValues, headerSize);
  870. if (deleteData != "")
  871. {
  872. Serial.println("[DELETE/SUCCESS] DELETE request successful.");
  873. Serial.println(deleteData);
  874. Serial.flush();
  875. Serial.println();
  876. Serial.println("[DELETE/END]");
  877. }
  878. else
  879. {
  880. Serial.println("[ERROR] DELETE request failed or returned empty data.");
  881. }
  882. }
  883. // Handle [GET/BYTES]
  884. else if (_data.startsWith("[GET/BYTES]"))
  885. {
  886. if (!this->isConnectedToWifi() && !this->connectToWifi())
  887. {
  888. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  889. this->ledOff();
  890. return;
  891. }
  892. // Extract the JSON by removing the command part
  893. String jsonData = _data.substring(strlen("[GET/BYTES]"));
  894. jsonData.trim();
  895. DynamicJsonDocument doc(1024);
  896. DeserializationError error = deserializeJson(doc, jsonData);
  897. if (error)
  898. {
  899. Serial.print("[ERROR] Failed to parse JSON.");
  900. this->ledOff();
  901. return;
  902. }
  903. // Extract values from JSON
  904. if (!doc.containsKey("url"))
  905. {
  906. Serial.println("[ERROR] JSON does not contain url.");
  907. this->ledOff();
  908. return;
  909. }
  910. String url = doc["url"];
  911. // Extract headers if available
  912. const char *headerKeys[10];
  913. const char *headerValues[10];
  914. int headerSize = 0;
  915. if (doc.containsKey("headers"))
  916. {
  917. JsonObject headers = doc["headers"];
  918. for (JsonPair header : headers)
  919. {
  920. headerKeys[headerSize] = header.key().c_str();
  921. headerValues[headerSize] = header.value();
  922. headerSize++;
  923. }
  924. }
  925. // GET request
  926. if (this->get_bytes_to_file(url, headerKeys, headerValues, headerSize))
  927. {
  928. // Serial.println("[GET/SUCCESS] GET request successful.");
  929. // moved this locally since we're streaming
  930. this->print_bytes_file();
  931. Serial.println("[GET/END]");
  932. }
  933. else
  934. {
  935. Serial.println("[ERROR] GET request failed or returned empty data.");
  936. }
  937. }
  938. // handle [POST/BYTES]
  939. else if (_data.startsWith("[POST/BYTES]"))
  940. {
  941. if (!this->isConnectedToWifi() && !this->connectToWifi())
  942. {
  943. Serial.println("[ERROR] Not connected to Wifi. Failed to reconnect.");
  944. this->ledOff();
  945. return;
  946. }
  947. // Extract the JSON by removing the command part
  948. String jsonData = _data.substring(strlen("[POST/BYTES]"));
  949. jsonData.trim();
  950. DynamicJsonDocument doc(1024);
  951. DeserializationError error = deserializeJson(doc, jsonData);
  952. if (error)
  953. {
  954. Serial.print("[ERROR] Failed to parse JSON.");
  955. this->ledOff();
  956. return;
  957. }
  958. // Extract values from JSON
  959. if (!doc.containsKey("url") || !doc.containsKey("payload"))
  960. {
  961. Serial.println("[ERROR] JSON does not contain url or payload.");
  962. this->ledOff();
  963. return;
  964. }
  965. String url = doc["url"];
  966. String payload = doc["payload"];
  967. // Extract headers if available
  968. const char *headerKeys[10];
  969. const char *headerValues[10];
  970. int headerSize = 0;
  971. if (doc.containsKey("headers"))
  972. {
  973. JsonObject headers = doc["headers"];
  974. for (JsonPair header : headers)
  975. {
  976. headerKeys[headerSize] = header.key().c_str();
  977. headerValues[headerSize] = header.value();
  978. headerSize++;
  979. }
  980. }
  981. // POST request
  982. if (this->post_bytes_to_file(url, payload, headerKeys, headerValues, headerSize))
  983. {
  984. //Serial.println("[POST/SUCCESS] POST request successful.");
  985. // moved the success message locally since it's streaming the data
  986. this->print_bytes_file();
  987. Serial.println("[POST/END]");
  988. }
  989. else
  990. {
  991. Serial.println("[ERROR] POST request failed or returned empty data.");
  992. }
  993. }
  994. this->ledOff();
  995. }
  996. }