The esp8266 portion of the project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

929 lines
31 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. #include <ESP8266WiFi.h>
  2. #include <ESP8266WiFiMulti.h>
  3. #include <ArduinoOTA.h>
  4. #include <ESP8266WebServer.h>
  5. #include <ESP8266mDNS.h>
  6. #include <FS.h>
  7. #include <WebSocketsServer.h>
  8. #include <ArduinoJson.h>
  9. #include <SoftwareSerial.h>
  10. #include <Streaming.h>
  11. #include <OneWire.h>
  12. #include <DallasTemperature.h>
  13. #include <GDBStub.h>
  14. #include <ArduinoLog.h>
  15. #define ONE_WIRE_BUS D1
  16. // char wifiMultiSSID[30];
  17. #include <main.hpp>
  18. using namespace std;
  19. SoftwareSerial s(D3, D2); //RX.TX
  20. static char temperaturesJson[200];
  21. static char rtcDate[10];
  22. OneWire oneWire(ONE_WIRE_BUS);
  23. DallasTemperature sensors(&oneWire);
  24. const int SENSOR_RESOLUTION = 12;
  25. unsigned long lastTempRequest = 0;
  26. const unsigned int delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
  27. ESP8266WiFiMulti wifiMulti; // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
  28. ESP8266WebServer server(300); // create a web server on port 80
  29. WebSocketsServer webSocket(301); // create a websocket server on port 81
  30. File fsUploadFile; // a File variable to temporarily store the received file
  31. const char *ssid = "ESP8266 Access Point"; // The name of the Wi-Fi network that will be created
  32. const char *password = "thereisnospoon"; // The password required to connect to it, leave blank for an open network
  33. const char *OTAName = "ESP8266"; // A name and a password for the OTA service
  34. const char *OTAPassword = "esp8266";
  35. const size_t JSON_BUFFER_SIZE = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(2) + 3 * JSON_OBJECT_SIZE(5) + 180;
  36. // #define LED_RED 15 // specify the pins with an RGB LED connected
  37. // #define LED_GREEN 12
  38. // #define LED_BLUE 13
  39. #define ARDUINO_TO_ESP_PIN D0
  40. // #define ESP_TO_ARDUINO_PIN D2
  41. byte currentArduinoState;
  42. byte previousArduinoState;
  43. const char *mdnsName = "esp8266"; // Domain name for the mDNS responder
  44. /*__________________________________________________________SETUP__________________________________________________________*/
  45. void setup()
  46. {
  47. // pinMode(LED_RED, OUTPUT); // the pins with LEDs connected are outputs
  48. // pinMode(LED_GREEN, OUTPUT);
  49. // pinMode(LED_BLUE, OUTPUT);
  50. Serial.begin(115200);
  51. Log.begin(LOG_LEVEL_VERBOSE, &Serial);
  52. Log.setPrefix(printTimestamp); // Uncomment to get timestamps as prefix
  53. Log.setSuffix(printNewline); // Uncomment to get newline as suffix
  54. // Serial << "Starting up ESP light controller with log level = " << Log.getLevel();
  55. // gdbstub_init();
  56. Serial << "Hello" << endl;
  57. pinMode(ARDUINO_TO_ESP_PIN, INPUT);
  58. // pinMode(ESP_TO_ARDUINO_PIN, OUTPUT);
  59. // digitalWrite(ESP_TO_ARDUINO_PIN, 1);
  60. s.begin(9600); // Start the Serial communication to send messages to the computer
  61. delay(10);
  62. Serial.println("\r\n");
  63. startWiFi(); // Start a Wi-Fi access point, and try to connect to some given access points. Then wait for either an AP or STA connection
  64. startOTA(); // Start the OTA service
  65. startSPIFFS(); // Start the SPIFFS and list all contents
  66. startWebSocket(); // Start a WebSocket server
  67. startMDNS(); // Start the mDNS responder
  68. startServer(); // Start a HTTP server with a file read handler and an upload handler
  69. Serial.println();
  70. sensors.begin();
  71. sensors.setWaitForConversion(false);
  72. sensors.requestTemperatures();
  73. // delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
  74. // delayInMillisSensors = 1000;
  75. lastTempRequest = millis();
  76. }
  77. /*__________________________________________________________LOOP__________________________________________________________*/
  78. bool rainbow = false; // The rainbow effect is turned off on startup
  79. //bool arduinoON = false;
  80. unsigned long prevMillis = millis();
  81. int hue = 0;
  82. void loop()
  83. {
  84. // // digitalWrite(ESP_TO_ARDUINO_PIN, 0);
  85. // webSocket.loop(); // constantly check for websocket events
  86. server.handleClient(); // run the server
  87. ArduinoOTA.handle(); // listen for OTA events
  88. previousArduinoState = currentArduinoState;
  89. currentArduinoState = digitalRead(ARDUINO_TO_ESP_PIN);
  90. if (previousArduinoState == LOW && currentArduinoState == HIGH)
  91. {
  92. // Serial.println("Arduino turned on");
  93. Log.notice("Arduino turned on");
  94. //arduinoON = true;
  95. //combineSettings();
  96. displayCombinedSettings();
  97. Log.notice("Settings sent to arduino");
  98. }
  99. // if (rainbow)
  100. // { // if the rainbow effect is turned on
  101. // if (millis() > prevMillis + 32)
  102. // {
  103. // if (++hue == 360) // Cycle through the color wheel (increment by one degree every 32 ms)
  104. // hue = 0;
  105. // setHue(hue); // Set the RGB LED to the right color
  106. // prevMillis = millis();
  107. // }
  108. // }
  109. if (s.available() > 0)
  110. {
  111. // Serial << F("Received JSON from arduino") << endl;
  112. // Serial << F("Inside second if ") << endl;
  113. // StaticJsonBuffer<100> jsonBuffer;
  114. // Log.notice(F("Received JSON from arduino"));
  115. DynamicJsonBuffer jsonBuffer(100);
  116. // Serial << "S available = " << s.available();
  117. JsonObject &root = jsonBuffer.parseObject(s);
  118. JsonArray &lcd_data = root["lcdData"];
  119. // lcd_data[0];
  120. // char a[10];
  121. sprintf(rtcDate, lcd_data[1] | "N/A");
  122. // root.printTo(Serial);
  123. // Serial << s.available() << endl;
  124. // s.flush();
  125. // Serial << (char)s.read() << endl;
  126. // sensors.requestTemperatures();
  127. // char str_temp[6];
  128. // dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
  129. // sprintf(a, "%s", str_temp);
  130. // tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
  131. // Serial.println(sensors.getTempCByIndex(0));
  132. delay(50);
  133. }
  134. // sensors.requestTemperatures();
  135. // Serial.println(sensors.getTempCByIndex(0));
  136. // delay(1000);
  137. // Serial << F("Serial available = ") << s.available() << endl;
  138. // delay(50);
  139. // if (sensors.isConversionAvailable(0))
  140. // {
  141. // // tft.drawString("25.5C", coordinates.x[3], coordinates.y[3], 2);
  142. // Serial << "Reading avaialable" << endl;
  143. // char b[10];
  144. // char str_temp[6];
  145. // dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
  146. // sprintf(b, "%s", str_temp);
  147. // tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
  148. // Serial.println(sensors.getTempCByIndex(0));
  149. // sensors.requestTemperatures();
  150. // }
  151. if (millis() - lastTempRequest >= delayInMillisSensors)
  152. {
  153. // char b[10];
  154. // char str_temp[6];
  155. // saveTemperatureJson();
  156. // StaticJsonBuffer<200> jsonBuffer;
  157. DynamicJsonBuffer jsonBuffer(100);
  158. JsonObject &root = jsonBuffer.createObject();
  159. if (!root.success())
  160. {
  161. Log.error("Error creating temperature json");
  162. }
  163. JsonArray &temperatures = root.createNestedArray("temperatures");
  164. // temperatures.add(sensors.getTempCByIndex(0));
  165. // Serial << "Sensor" << endl;
  166. float temp1 = sensors.getTempCByIndex(0);
  167. // Serial << "Sensor" << endl;
  168. float temp2 = sensors.getTempCByIndex(1);
  169. temperatures.add(temp1);
  170. temperatures.add(temp2);
  171. // root.prettyPrintTo(Serial);
  172. root.prettyPrintTo(temperaturesJson);
  173. // dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
  174. // sprintf(b, "%s", str_temp);
  175. // tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
  176. // Serial.println(sensors.getTempCByIndex(0));
  177. // Serial << "Delay: " << delayInMillisSensors << endl;
  178. // Serial << "Requesting temperatures" << endl;
  179. sensors.requestTemperatures();
  180. // delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
  181. lastTempRequest = millis();
  182. }
  183. }
  184. /*__________________________________________________________SETUP_FUNCTIONS__________________________________________________________*/
  185. void startWiFi()
  186. { // Start a Wi-Fi access point, and try to connect to some given access points. Then wait for either an AP or STA connection
  187. WiFi.softAP(ssid, password); // Start the access point
  188. Serial.print("Access Point \"");
  189. Serial.print(ssid);
  190. Serial.println("\" started\r\n");
  191. // wifiMulti.addAP(wifiMultiSSID, wifiMultiPassword);
  192. // #ifdef WIFI_SSID
  193. // const char *wifiMultiSSID = WIFI_SSID;
  194. // Serial << "Macro " << WIFI_SSID;
  195. // // wifiMulti.addAP(LC_WIFI_SSID, "");
  196. // #else
  197. // const char *wifiMultiSSID = "ssid";
  198. // #endif
  199. // #ifdef WIFI_PASS
  200. // const char *wifiMultiPassword = WIFI_PASS;
  201. // #else
  202. // const char *wifiMultiPassword = "password";
  203. // #endif
  204. // wifiMulti.addAP(wifiMultiSSID, wifiMultiPassword);
  205. Serial.print(F("MAC: "));
  206. Serial.println(WiFi.macAddress());
  207. Serial.println("Connecting");
  208. while (wifiMulti.run() != WL_CONNECTED && WiFi.softAPgetStationNum() < 1)
  209. { // Wait for the Wi-Fi to connect
  210. delay(250);
  211. Serial.print('.');
  212. }
  213. Serial.println("\r\n");
  214. if (WiFi.softAPgetStationNum() == 0)
  215. { // If the ESP is connected to an AP
  216. Serial.print("Connected to ");
  217. Serial.println(WiFi.SSID()); // Tell us what network we're connected to
  218. Serial.print("IP address:\t");
  219. Serial.print(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer
  220. }
  221. else
  222. { // If a station is connected to the ESP SoftAP
  223. Serial.print("Station connected to ESP8266 AP");
  224. }
  225. Serial.println("\r\n");
  226. }
  227. void startOTA()
  228. { // Start the OTA service
  229. ArduinoOTA.setHostname(OTAName);
  230. ArduinoOTA.setPassword(OTAPassword);
  231. ArduinoOTA.onStart([]() {
  232. Serial.println("Start");
  233. // digitalWrite(LED_RED, 0); // turn off the LEDs
  234. // digitalWrite(LED_GREEN, 0);
  235. // digitalWrite(LED_BLUE, 0);
  236. });
  237. ArduinoOTA.onEnd([]() {
  238. Serial.println("\r\nEnd");
  239. });
  240. ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
  241. Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  242. });
  243. ArduinoOTA.onError([](ota_error_t error) {
  244. Serial.printf("Error[%u]: ", error);
  245. if (error == OTA_AUTH_ERROR)
  246. Serial.println("Auth Failed");
  247. else if (error == OTA_BEGIN_ERROR)
  248. Serial.println("Begin Failed");
  249. else if (error == OTA_CONNECT_ERROR)
  250. Serial.println("Connect Failed");
  251. else if (error == OTA_RECEIVE_ERROR)
  252. Serial.println("Receive Failed");
  253. else if (error == OTA_END_ERROR)
  254. Serial.println("End Failed");
  255. });
  256. ArduinoOTA.begin();
  257. Serial.println("OTA ready\r\n");
  258. }
  259. void startSPIFFS()
  260. { // Start the SPIFFS and list all contents
  261. SPIFFS.begin(); // Start the SPI Flash File System (SPIFFS)
  262. Serial.println("SPIFFS started. Contents:");
  263. {
  264. Dir dir = SPIFFS.openDir("/");
  265. while (dir.next())
  266. { // List the file system contents
  267. String fileName = dir.fileName();
  268. size_t fileSize = dir.fileSize();
  269. Serial.printf("\tFS File: %s, size: %s\r\n", fileName.c_str(), formatBytes(fileSize).c_str());
  270. }
  271. Serial.printf("\n");
  272. }
  273. }
  274. void startWebSocket()
  275. { // Start a WebSocket server
  276. webSocket.begin(); // start the websocket server
  277. webSocket.onEvent(webSocketEvent); // if there's an incomming websocket message, go to function 'webSocketEvent'
  278. Serial.println("WebSocket server started.");
  279. }
  280. void startMDNS()
  281. { // Start the mDNS responder
  282. MDNS.begin(mdnsName); // start the multicast domain name server
  283. Serial.print("mDNS responder started: http://");
  284. Serial.print(mdnsName);
  285. Serial.println(".local");
  286. }
  287. void startServer()
  288. { // Start a HTTP server with a file read handler and an upload handler
  289. server.on(
  290. "/edit.html", HTTP_POST, []() { // If a POST request is sent to the /edit.html address,
  291. // server.send(200, "text/plain", "");
  292. server.send(200);
  293. },
  294. handleFileUpload); // go to 'handleFileUpload'
  295. server.onNotFound(handleNotFound); // if someone requests any other file or page, go to function 'handleNotFound'
  296. // and check if the file exists
  297. server.on("/settings.html", HTTP_POST, handleSettings);
  298. server.on("/manualMode.html", HTTP_POST, handleManual);
  299. server.on("/api/get/temperatures", HTTP_GET, []() {
  300. sendCors();
  301. server.send(200, "application/json", temperaturesJson);
  302. });
  303. server.on("/api/get/date", HTTP_GET, []() {
  304. sendCors();
  305. server.send(200, "text/plain", rtcDate);
  306. });
  307. server.serveStatic("/", SPIFFS, "www", "no-cache");
  308. server.begin(); // start the HTTP server
  309. Serial.println("HTTP server started.");
  310. }
  311. /*__________________________________________________________SERVER_HANDLERS__________________________________________________________*/
  312. void handleNotFound()
  313. { // if the requested file or page doesn't exist, return a 404 not found error
  314. server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
  315. server.sendHeader("Pragma", "no-cache");
  316. server.sendHeader("Expires", "-1");
  317. if (!handleFileRead(server.uri()))
  318. { // check if the file exists in the flash memory (SPIFFS), if so, send it
  319. server.send(404, "application/json", "{\"status\":\"failed\",\"message\":\"Resource not found\"}");
  320. }
  321. }
  322. bool handleFileRead(String path)
  323. { // send the right file to the client (if it exists)
  324. Serial.println("handleFileRead: " + path);
  325. if (path.endsWith("/"))
  326. path += "index.html"; // If a folder is requested, send the index file
  327. String contentType = getContentType(path); // Get the MIME type
  328. String pathWithGz = path + ".gz";
  329. if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path))
  330. { // If the file exists, either as a compressed archive, or normal
  331. if (SPIFFS.exists(pathWithGz)) // If there's a compressed version available
  332. path += ".gz"; // Use the compressed verion
  333. File file = SPIFFS.open(path, "r"); // Open the file
  334. size_t sent = server.streamFile(file, contentType); // Send it to the client
  335. file.close(); // Close the file again
  336. Serial.println(String("\tSent file: ") + path);
  337. return true;
  338. }
  339. Serial.println(String("\tFile Not Found: ") + path); // If the file doesn't exist, return false
  340. return false;
  341. }
  342. void sendCors()
  343. {
  344. server.sendHeader("Access-Control-Allow-Origin", "*");
  345. server.sendHeader("Access-Control-Max-Age", "10000");
  346. server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
  347. server.sendHeader("Access-Control-Allow-Headers", "*");
  348. }
  349. void saveTemperatureJson(DallasTemperature &sensors)
  350. {
  351. StaticJsonBuffer<200> jsonBuffer;
  352. JsonObject &root = jsonBuffer.createObject();
  353. if (!root.success())
  354. {
  355. Log.error("Error creating temperature json object");
  356. }
  357. // JsonArray &data = root.createNestedArray("data");
  358. // data.add(48);
  359. // data.add(2);
  360. JsonArray &temperatures = root.createNestedArray("temperatures");
  361. float temp1 = sensors.getTempCByIndex(0);
  362. float temp2 = sensors.getTempCByIndex(1);
  363. temperatures.add(temp1);
  364. temperatures.add(temp2);
  365. temperatures.add(1);
  366. root.prettyPrintTo(Serial);
  367. root.prettyPrintTo(temperaturesJson);
  368. // if (SPIFFS.exists("/temperatures.txt"))
  369. // {
  370. // SPIFFS.remove("/temperatures.txt");
  371. // Serial.println("Old settings file removed");
  372. // }
  373. // File settingsFile = SPIFFS.open("/temperatures.txt", "w");
  374. // if (!settingsFile)
  375. // Log.error("Error wriing json to file");
  376. // root.prettyPrintTo(settingsFile); //Export and save JSON object to SPIFFS area
  377. // Serial.println("Json written to file");
  378. // settingsFile.close();
  379. }
  380. void saveSettings(ESP8266WebServer &server, int num)
  381. {
  382. Log.notice("Ballast num = %d", num);
  383. const int shour = server.arg("shour").toInt();
  384. const int smin = server.arg("smin").toInt();
  385. const int fadePeriod = server.arg("fadePeriod").toInt();
  386. const int ehour = server.arg("ehour").toInt();
  387. const int emin = server.arg("emin").toInt();
  388. StaticJsonBuffer<200> jsonBuffer;
  389. JsonObject &root = jsonBuffer.createObject();
  390. if (!root.success())
  391. {
  392. Log.error("Error creating json");
  393. return;
  394. }
  395. root["shour"] = shour;
  396. root["fadePeriod"] = fadePeriod;
  397. root["smin"] = smin;
  398. root["ehour"] = ehour;
  399. root["emin"] = emin;
  400. root.prettyPrintTo(Serial);
  401. char buf[40] = "";
  402. sprintf(buf, "/settingsFile%d.txt", num);
  403. Log.verbose("Settings file chosen = %s", buf);
  404. if (SPIFFS.exists(buf))
  405. {
  406. SPIFFS.remove(buf);
  407. Log.notice("Old settings file removed");
  408. }
  409. File settingsFile = SPIFFS.open(buf, "w");
  410. if (!settingsFile)
  411. Log.error("Error opening settings file - %d", num);
  412. root.prettyPrintTo(settingsFile); //Export and save JSON object to SPIFFS area
  413. Log.notice("Json written to file");
  414. settingsFile.close();
  415. // delete server;
  416. }
  417. void combineSettings()
  418. {
  419. File file1 = SPIFFS.open("/settingsFile1.txt", "r");
  420. File file2 = SPIFFS.open("/settingsFile2.txt", "r");
  421. File file3 = SPIFFS.open("/settingsFile3.txt", "r");
  422. File file5 = SPIFFS.open("/manualMode.txt", "r");
  423. // Serial.println("2");
  424. if (SPIFFS.exists("/combinedSettingsFile.txt"))
  425. {
  426. SPIFFS.remove("/combinedSettingsFile.txt");
  427. }
  428. File file4 = SPIFFS.open("/combinedSettingsFile.txt", "w");
  429. size_t size1 = file1.size(), size2 = file2.size(), size3 = file3.size(), size5 = file5.size();
  430. ;
  431. std::unique_ptr<char[]> buf1(new char[size1]);
  432. std::unique_ptr<char[]> buf2(new char[size2]);
  433. std::unique_ptr<char[]> buf3(new char[size3]);
  434. std::unique_ptr<char[]> buf5(new char[size5]);
  435. file1.readBytes(buf1.get(), size1);
  436. file2.readBytes(buf2.get(), size2);
  437. file3.readBytes(buf3.get(), size3);
  438. file5.readBytes(buf5.get(), size5);
  439. StaticJsonBuffer<100> jsonBuffer10;
  440. JsonObject &root1 = jsonBuffer10.parseObject(buf1.get());
  441. if (!root1.success())
  442. {
  443. Log.error("Error parsing JSON");
  444. return;
  445. }
  446. StaticJsonBuffer<100> jsonBuffer11;
  447. JsonObject &root2 = jsonBuffer11.parseObject(buf2.get());
  448. if (!root2.success())
  449. {
  450. Log.error("Error parsing JSON");
  451. return;
  452. }
  453. StaticJsonBuffer<100> jsonBuffer12;
  454. JsonObject &root3 = jsonBuffer12.parseObject(buf3.get());
  455. if (!root3.success())
  456. {
  457. Log.error("Error parsing JSON");
  458. return;
  459. }
  460. StaticJsonBuffer<50> jsonBuffer16;
  461. JsonObject &root5 = jsonBuffer16.parseObject(buf5.get());
  462. /*StaticJsonBuffer<300> jsonBuffer13;
  463. JsonObject& root4 = jsonBuffer13.createObject();
  464. JsonObject& ballast1 = root4.createNestedObject();
  465. root4["shour1"]=root1["shour1"];
  466. root4["smin1"]=root1["smin1"];
  467. root4["fadePeriod1"]=root1["fadePeriod1"];
  468. root4["shour2"]=root2["shour2"];
  469. root4["smin2"]=root2["smin2"];
  470. root4["fadePeriod2"]=root2["fadePeriod2"];
  471. root4["shour3"]=root3["shour3"];
  472. root4["smin3"]=root3["smin3"];
  473. root4["fadePeriod3"]=root3["fadePeriod3"];*/
  474. DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);
  475. JsonObject &root = jsonBuffer.createObject();
  476. JsonArray &settings = root.createNestedArray("settings");
  477. JsonObject &settings_0 = settings.createNestedObject();
  478. settings_0["shour"] = root1["shour"];
  479. settings_0["fadePeriod"] = root1["fadePeriod"];
  480. settings_0["smin"] = root1["smin"];
  481. settings_0["ehour"] = root1["ehour"];
  482. settings_0["emin"] = root1["emin"];
  483. JsonObject &settings_1 = settings.createNestedObject();
  484. settings_1["shour"] = root2["shour"];
  485. settings_1["fadePeriod"] = root2["fadePeriod"];
  486. settings_1["smin"] = root2["smin"];
  487. settings_1["ehour"] = root2["ehour"];
  488. settings_1["emin"] = root2["emin"];
  489. JsonObject &settings_2 = settings.createNestedObject();
  490. settings_2["shour"] = root3["shour"];
  491. settings_2["fadePeriod"] = root3["fadePeriod"];
  492. settings_2["smin"] = root3["smin"];
  493. settings_2["ehour"] = root3["ehour"];
  494. settings_2["emin"] = root3["emin"];
  495. root["manual"] = root5["manual"];
  496. /*root1.printTo(file4);
  497. root1.printTo(Serial);
  498. root2.printTo(file4);
  499. root2.printTo(Serial);
  500. root3.printTo(file4);
  501. root3.printTo(Serial);*/
  502. root.prettyPrintTo(Serial);
  503. root.prettyPrintTo(file4);
  504. // Serial.println("3");
  505. file1.close();
  506. file2.close();
  507. file3.close();
  508. file4.close();
  509. file5.close();
  510. }
  511. //FIXME borked - has strange/undefined behaviour
  512. void combineSettings_new()
  513. {
  514. const File file1 = SPIFFS.open("/settingsFile1.txt", "r");
  515. const File file2 = SPIFFS.open("/settingsFile2.txt", "r");
  516. const File file3 = SPIFFS.open("/settingsFile3.txt", "r");
  517. File file5 = SPIFFS.open("/manualMode.txt", "r");
  518. if (SPIFFS.exists("/combinedSettingsFile.txt"))
  519. {
  520. SPIFFS.remove("/combinedSettingsFile.txt");
  521. }
  522. File file_arr[] = {file1, file2, file3};
  523. File file4 = SPIFFS.open("/combinedSettingsFile.txt", "w");
  524. StaticJsonBuffer<JSON_BUFFER_SIZE> jsonBuffer;
  525. JsonObject &root = jsonBuffer.createObject();
  526. JsonArray &settings = root.createNestedArray("settings");
  527. StaticJsonBuffer<50> jsonBufferManual;
  528. size_t size_manual = file5.size();
  529. unique_ptr<char[]> buf_manual(new char[size_manual]);
  530. file5.readBytes(buf_manual.get(), size_manual);
  531. JsonObject &root_manual = jsonBufferManual.parseObject(buf_manual.get());
  532. for (int i = 0; i < 3; i++)
  533. {
  534. const size_t file_size = file_arr[i].size();
  535. const unique_ptr<char[]> buf(new char[file_size]);
  536. file_arr[i].readBytes(buf.get(), file_size);
  537. StaticJsonBuffer<(JSON_BUFFER_SIZE / 3) + 50> jsonBuffer;
  538. JsonObject &root_i = jsonBuffer.parseObject(buf.get());
  539. if (!root_i.success())
  540. {
  541. Log.error(F("Error creating json for file %d"), i + 1);
  542. }
  543. else
  544. {
  545. JsonObject &settings_i = settings.createNestedObject();
  546. settings_i["shour"] = root_i["shour"];
  547. settings_i["fadePeriod"] = root_i["fadePeriod"];
  548. settings_i["smin"] = root_i["smin"];
  549. settings_i["ehour"] = root_i["ehour"];
  550. settings_i["emin"] = root_i["emin"];
  551. // Log.notice("inside array temp");
  552. // char buf[JSON_BUFFER_SIZE / 3];
  553. // root_i.prettyPrintTo(buf);
  554. // Log.trace("%s", buf);
  555. Log.trace("Printing settings %d", i + 1);
  556. // settings_i.prettyPrintTo(Serial);
  557. // root.prettyPrintTo(Serial);
  558. // settings.prettyPrintTo(Serial);
  559. file_arr[i].close();
  560. }
  561. }
  562. root["manual"] = root_manual["manual"];
  563. Log.trace("Printing final root");
  564. root.prettyPrintTo(Serial);
  565. root.prettyPrintTo(file4);
  566. file4.close();
  567. file5.close();
  568. }
  569. /*void displaySettings()
  570. {
  571. File file = SPIFFS.open("/settingsFile.txt", "r");
  572. if (!file){
  573. Log.error("Error reading settings file or file does not exist");
  574. } else {
  575. size_t size = file.size();
  576. if ( size == 0 ) {
  577. Serial.println("Settings file is empty");
  578. } else {
  579. std::unique_ptr<char[]> buf (new char[size]);
  580. file.readBytes(buf.get(), size);
  581. StaticJsonBuffer<200> jsonBuffer2;
  582. JsonObject& root = jsonBuffer2.parseObject(buf.get());
  583. if (!root.success()) {
  584. Log.error("Error reading settings file");
  585. } else {
  586. Serial.println("Settings file loaded");
  587. root.prettyPrintTo(Serial);
  588. root.printTo(s);
  589. Serial.println("Settings sent to arduino");
  590. }
  591. }
  592. file.close();
  593. }
  594. }*/
  595. void displayCombinedSettings()
  596. {
  597. File file = SPIFFS.open("/combinedSettingsFile.txt", "r");
  598. if (!file)
  599. {
  600. Log.error("Error reading combined settings file or file does not exist");
  601. }
  602. else
  603. {
  604. Log.notice("Settings file exists");
  605. size_t size = file.size();
  606. if (size == 0)
  607. {
  608. Log.notice("Settings file is empty");
  609. }
  610. else
  611. {
  612. std::unique_ptr<char[]> buf5(new char[size]);
  613. file.readBytes(buf5.get(), size);
  614. // StaticJsonBuffer<300> jsonBuffer;
  615. DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);
  616. JsonObject &root5 = jsonBuffer.parseObject(buf5.get());
  617. if (!root5.success())
  618. {
  619. Log.error("Error reading combined settings file");
  620. }
  621. else
  622. {
  623. Log.notice("Settings file loaded");
  624. root5.prettyPrintTo(Serial);
  625. // digitalWrite(ESP_TO_ARDUINO_PIN,0);
  626. // analogWrite(ESP_TO_ARDUINO_PIN,255);
  627. root5.printTo(s);
  628. // digitalWrite(ESP_TO_ARDUINO_PIN,1);
  629. }
  630. }
  631. file.close();
  632. }
  633. }
  634. void handleManual()
  635. {
  636. File file = SPIFFS.open("/manualMode.txt", "w");
  637. StaticJsonBuffer<50> jsonBufferManual;
  638. JsonObject &root = jsonBufferManual.createObject();
  639. if (server.arg("manual") == "True")
  640. {
  641. root["manual"] = "True";
  642. }
  643. else
  644. {
  645. root["manual"] = "False";
  646. }
  647. root.prettyPrintTo(file);
  648. file.close();
  649. combineSettings();
  650. // digitalWrite(ESP_TO_ARDUINO_PIN, 1);
  651. displayCombinedSettings();
  652. // digitalWrite(ESP_TO_ARDUINO_PIN,1);
  653. // server.sendHeader("Location", "/manualMode.html"); // Redirect the client to the success page
  654. // server.send(303);
  655. server.send(200);
  656. }
  657. void handleSettings()
  658. {
  659. // if (server.arg("ballast").toInt() == 1)
  660. // handleSettings1();
  661. // else if (server.arg("ballast").toInt() == 2)
  662. // handleSettings2();
  663. // else if (server.arg("ballast").toInt() == 3)
  664. // handleSettings3();
  665. // displayCombinedSettings();
  666. // server.sendHeader("Location", "/settings.html"); // Redirect the client to the success page
  667. const int ballast_num = server.arg("ballast").toInt();
  668. Log.notice("Chosen num = %d", ballast_num);
  669. saveSettings(server, ballast_num);
  670. combineSettings();
  671. displayCombinedSettings();
  672. server.send(200);
  673. }
  674. void handleFileUpload()
  675. { // upload a new file to the SPIFFS
  676. HTTPUpload &upload = server.upload();
  677. String path;
  678. if (upload.status == UPLOAD_FILE_START)
  679. {
  680. path = upload.filename;
  681. if (!path.startsWith("/"))
  682. path = "/" + path;
  683. if (!path.endsWith(".gz"))
  684. { // The file server always prefers a compressed version of a file
  685. String pathWithGz = path + ".gz"; // So if an uploaded file is not compressed, the existing compressed
  686. if (SPIFFS.exists(pathWithGz)) // version of that file must be deleted (if it exists)
  687. SPIFFS.remove(pathWithGz);
  688. }
  689. Serial.print("handleFileUpload Name: ");
  690. Serial.println(path);
  691. fsUploadFile = SPIFFS.open(path, "w"); // Open the file for writing in SPIFFS (create if it doesn't exist)
  692. path = String();
  693. }
  694. else if (upload.status == UPLOAD_FILE_WRITE)
  695. {
  696. if (fsUploadFile)
  697. fsUploadFile.write(upload.buf, upload.currentSize); // Write the received bytes to the file
  698. }
  699. else if (upload.status == UPLOAD_FILE_END)
  700. {
  701. if (fsUploadFile)
  702. { // If the file was successfully created
  703. fsUploadFile.close(); // Close the file again
  704. Serial.print("handleFileUpload Size: ");
  705. Serial.println(upload.totalSize);
  706. // server.sendHeader("Location", "/success.html"); // Redirect the client to the success page
  707. server.send(201, "application/json", "{\"status\":\"success\",\"message\":\"File created successfully\"}");
  708. }
  709. else
  710. {
  711. server.send(500, "application/json", "{\"status\":\"failed\",\"message\":\"Could not create file\"}");
  712. }
  713. }
  714. }
  715. // const char *text = R"(
  716. // { " "
  717. // ;''
  718. // }
  719. // qegqeg
  720. // qegq
  721. // )";
  722. void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t lenght)
  723. { // When a WebSocket message is received
  724. switch (type)
  725. {
  726. case WStype_DISCONNECTED: // if the websocket is disconnected
  727. Serial.printf("[%u] Disconnected!\n", num);
  728. break;
  729. case WStype_CONNECTED:
  730. { // if a new websocket connection is established
  731. IPAddress ip = webSocket.remoteIP(num);
  732. Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
  733. rainbow = false; // Turn rainbow off when a new connection is established
  734. }
  735. break;
  736. case WStype_TEXT: // if new text data is received
  737. Serial.printf("[%u] get Text: %s\n", num, payload);
  738. if (payload[0] == '#')
  739. { // we get RGB data
  740. uint32_t rgb = (uint32_t)strtol((const char *)&payload[1], NULL, 16); // decode rgb data
  741. int r = ((rgb >> 20) & 0x3FF); // 10 bits per color, so R: bits 20-29
  742. int g = ((rgb >> 10) & 0x3FF); // G: bits 10-19
  743. int b = rgb & 0x3FF; // B: bits 0-9
  744. // analogWrite(LED_RED, r); // write it to the LED output pins
  745. // analogWrite(LED_GREEN, g);
  746. // analogWrite(LED_BLUE, b);
  747. }
  748. else if (payload[0] == 'R')
  749. { // the browser sends an R when the rainbow effect is enabled
  750. rainbow = true;
  751. }
  752. else if (payload[0] == 'N')
  753. { // the browser sends an N when the rainbow effect is disabled
  754. rainbow = false;
  755. }
  756. break;
  757. default:
  758. {
  759. Log.error("Unsupported operation - number %d", type);
  760. }
  761. }
  762. }
  763. /*__________________________________________________________HELPER_FUNCTIONS__________________________________________________________*/
  764. String formatBytes(size_t bytes)
  765. { // convert sizes in bytes to KB and MB
  766. if (bytes < 1024)
  767. {
  768. return String(bytes) + "B";
  769. }
  770. else if (bytes < (1024 * 1024))
  771. {
  772. return String(bytes / 1024.0) + "KB";
  773. }
  774. else if (bytes < (1024 * 1024 * 1024))
  775. {
  776. return String(bytes / 1024.0 / 1024.0) + "MB";
  777. }
  778. else
  779. return "";
  780. }
  781. String getContentType(String filename)
  782. { // determine the filetype of a given filename, based on the extension
  783. if (filename.endsWith(".html"))
  784. return "text/html";
  785. else if (filename.endsWith(".css"))
  786. return "text/css";
  787. else if (filename.endsWith(".js"))
  788. return "application/javascript";
  789. else if (filename.endsWith(".ico"))
  790. return "image/x-icon";
  791. else if (filename.endsWith(".gz"))
  792. return "application/x-gzip";
  793. return "text/plain";
  794. }
  795. void setHue(int hue)
  796. { // Set the RGB LED to a given hue (color) (0° = Red, 120° = Green, 240° = Blue)
  797. hue %= 360; // hue is an angle between 0 and 359°
  798. float radH = hue * 3.142 / 180; // Convert degrees to radians
  799. float rf, gf, bf;
  800. if (hue >= 0 && hue < 120)
  801. { // Convert from HSI color space to RGB
  802. rf = cos(radH * 3 / 4);
  803. gf = sin(radH * 3 / 4);
  804. bf = 0;
  805. }
  806. else if (hue >= 120 && hue < 240)
  807. {
  808. radH -= 2.09439;
  809. gf = cos(radH * 3 / 4);
  810. bf = sin(radH * 3 / 4);
  811. rf = 0;
  812. }
  813. else if (hue >= 240 && hue < 360)
  814. {
  815. radH -= 4.188787;
  816. bf = cos(radH * 3 / 4);
  817. rf = sin(radH * 3 / 4);
  818. gf = 0;
  819. }
  820. int r = rf * rf * 1023;
  821. int g = gf * gf * 1023;
  822. int b = bf * bf * 1023;
  823. // analogWrite(LED_RED, r); // Write the right color to the LED output pins
  824. // analogWrite(LED_GREEN, g);
  825. // analogWrite(LED_BLUE, b);
  826. }
  827. void printTimestamp(Print *_logOutput)
  828. {
  829. char c[12];
  830. int m = sprintf(c, "%10lu ", millis());
  831. _logOutput->print(c);
  832. }
  833. void printNewline(Print *_logOutput)
  834. {
  835. _logOutput->print('\n');
  836. }