FlipperHTTP.h 33 KB

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