FlipperHTTP.h 32 KB

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