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
929 lines
31 KiB
#include <ESP8266WiFi.h>
|
|
#include <ESP8266WiFiMulti.h>
|
|
#include <ArduinoOTA.h>
|
|
#include <ESP8266WebServer.h>
|
|
#include <ESP8266mDNS.h>
|
|
#include <FS.h>
|
|
#include <WebSocketsServer.h>
|
|
#include <ArduinoJson.h>
|
|
#include <SoftwareSerial.h>
|
|
#include <Streaming.h>
|
|
#include <OneWire.h>
|
|
#include <DallasTemperature.h>
|
|
#include <GDBStub.h>
|
|
#include <ArduinoLog.h>
|
|
|
|
#define ONE_WIRE_BUS D1
|
|
|
|
// char wifiMultiSSID[30];
|
|
|
|
#include <main.hpp>
|
|
|
|
using namespace std;
|
|
|
|
SoftwareSerial s(D3, D2); //RX.TX
|
|
|
|
static char temperaturesJson[200];
|
|
static char rtcDate[10];
|
|
|
|
OneWire oneWire(ONE_WIRE_BUS);
|
|
DallasTemperature sensors(&oneWire);
|
|
const int SENSOR_RESOLUTION = 12;
|
|
unsigned long lastTempRequest = 0;
|
|
const unsigned int delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
|
|
|
|
ESP8266WiFiMulti wifiMulti; // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
|
|
|
|
ESP8266WebServer server(300); // create a web server on port 80
|
|
WebSocketsServer webSocket(301); // create a websocket server on port 81
|
|
|
|
File fsUploadFile; // a File variable to temporarily store the received file
|
|
|
|
const char *ssid = "ESP8266 Access Point"; // The name of the Wi-Fi network that will be created
|
|
const char *password = "thereisnospoon"; // The password required to connect to it, leave blank for an open network
|
|
|
|
const char *OTAName = "ESP8266"; // A name and a password for the OTA service
|
|
const char *OTAPassword = "esp8266";
|
|
const size_t JSON_BUFFER_SIZE = JSON_ARRAY_SIZE(3) + JSON_OBJECT_SIZE(2) + 3 * JSON_OBJECT_SIZE(5) + 180;
|
|
// #define LED_RED 15 // specify the pins with an RGB LED connected
|
|
// #define LED_GREEN 12
|
|
// #define LED_BLUE 13
|
|
#define ARDUINO_TO_ESP_PIN D0
|
|
// #define ESP_TO_ARDUINO_PIN D2
|
|
|
|
byte currentArduinoState;
|
|
byte previousArduinoState;
|
|
|
|
const char *mdnsName = "esp8266"; // Domain name for the mDNS responder
|
|
|
|
/*__________________________________________________________SETUP__________________________________________________________*/
|
|
|
|
void setup()
|
|
{
|
|
// pinMode(LED_RED, OUTPUT); // the pins with LEDs connected are outputs
|
|
// pinMode(LED_GREEN, OUTPUT);
|
|
// pinMode(LED_BLUE, OUTPUT);
|
|
Serial.begin(115200);
|
|
Log.begin(LOG_LEVEL_VERBOSE, &Serial);
|
|
Log.setPrefix(printTimestamp); // Uncomment to get timestamps as prefix
|
|
Log.setSuffix(printNewline); // Uncomment to get newline as suffix
|
|
// Serial << "Starting up ESP light controller with log level = " << Log.getLevel();
|
|
// gdbstub_init();
|
|
Serial << "Hello" << endl;
|
|
|
|
pinMode(ARDUINO_TO_ESP_PIN, INPUT);
|
|
// pinMode(ESP_TO_ARDUINO_PIN, OUTPUT);
|
|
// digitalWrite(ESP_TO_ARDUINO_PIN, 1);
|
|
|
|
s.begin(9600); // Start the Serial communication to send messages to the computer
|
|
delay(10);
|
|
Serial.println("\r\n");
|
|
|
|
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
|
|
|
|
startOTA(); // Start the OTA service
|
|
|
|
startSPIFFS(); // Start the SPIFFS and list all contents
|
|
|
|
startWebSocket(); // Start a WebSocket server
|
|
|
|
startMDNS(); // Start the mDNS responder
|
|
|
|
startServer(); // Start a HTTP server with a file read handler and an upload handler
|
|
|
|
Serial.println();
|
|
sensors.begin();
|
|
sensors.setWaitForConversion(false);
|
|
sensors.requestTemperatures();
|
|
// delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
|
|
// delayInMillisSensors = 1000;
|
|
lastTempRequest = millis();
|
|
}
|
|
|
|
/*__________________________________________________________LOOP__________________________________________________________*/
|
|
|
|
bool rainbow = false; // The rainbow effect is turned off on startup
|
|
//bool arduinoON = false;
|
|
unsigned long prevMillis = millis();
|
|
int hue = 0;
|
|
|
|
void loop()
|
|
{
|
|
// // digitalWrite(ESP_TO_ARDUINO_PIN, 0);
|
|
|
|
// webSocket.loop(); // constantly check for websocket events
|
|
server.handleClient(); // run the server
|
|
ArduinoOTA.handle(); // listen for OTA events
|
|
previousArduinoState = currentArduinoState;
|
|
currentArduinoState = digitalRead(ARDUINO_TO_ESP_PIN);
|
|
if (previousArduinoState == LOW && currentArduinoState == HIGH)
|
|
{
|
|
// Serial.println("Arduino turned on");
|
|
Log.notice("Arduino turned on");
|
|
//arduinoON = true;
|
|
//combineSettings();
|
|
displayCombinedSettings();
|
|
Log.notice("Settings sent to arduino");
|
|
}
|
|
|
|
// if (rainbow)
|
|
// { // if the rainbow effect is turned on
|
|
// if (millis() > prevMillis + 32)
|
|
// {
|
|
// if (++hue == 360) // Cycle through the color wheel (increment by one degree every 32 ms)
|
|
// hue = 0;
|
|
// setHue(hue); // Set the RGB LED to the right color
|
|
// prevMillis = millis();
|
|
// }
|
|
// }
|
|
|
|
if (s.available() > 0)
|
|
{
|
|
// Serial << F("Received JSON from arduino") << endl;
|
|
// Serial << F("Inside second if ") << endl;
|
|
// StaticJsonBuffer<100> jsonBuffer;
|
|
// Log.notice(F("Received JSON from arduino"));
|
|
DynamicJsonBuffer jsonBuffer(100);
|
|
// Serial << "S available = " << s.available();
|
|
|
|
JsonObject &root = jsonBuffer.parseObject(s);
|
|
JsonArray &lcd_data = root["lcdData"];
|
|
// lcd_data[0];
|
|
// char a[10];
|
|
sprintf(rtcDate, lcd_data[1] | "N/A");
|
|
|
|
// root.printTo(Serial);
|
|
// Serial << s.available() << endl;
|
|
// s.flush();
|
|
// Serial << (char)s.read() << endl;
|
|
// sensors.requestTemperatures();
|
|
// char str_temp[6];
|
|
// dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
|
|
// sprintf(a, "%s", str_temp);
|
|
// tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
|
|
// Serial.println(sensors.getTempCByIndex(0));
|
|
delay(50);
|
|
}
|
|
// sensors.requestTemperatures();
|
|
// Serial.println(sensors.getTempCByIndex(0));
|
|
// delay(1000);
|
|
|
|
// Serial << F("Serial available = ") << s.available() << endl;
|
|
// delay(50);
|
|
|
|
// if (sensors.isConversionAvailable(0))
|
|
// {
|
|
// // tft.drawString("25.5C", coordinates.x[3], coordinates.y[3], 2);
|
|
// Serial << "Reading avaialable" << endl;
|
|
// char b[10];
|
|
// char str_temp[6];
|
|
// dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
|
|
// sprintf(b, "%s", str_temp);
|
|
// tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
|
|
// Serial.println(sensors.getTempCByIndex(0));
|
|
// sensors.requestTemperatures();
|
|
// }
|
|
if (millis() - lastTempRequest >= delayInMillisSensors)
|
|
{
|
|
// char b[10];
|
|
// char str_temp[6];
|
|
// saveTemperatureJson();
|
|
// StaticJsonBuffer<200> jsonBuffer;
|
|
DynamicJsonBuffer jsonBuffer(100);
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
if (!root.success())
|
|
{
|
|
Log.error("Error creating temperature json");
|
|
}
|
|
JsonArray &temperatures = root.createNestedArray("temperatures");
|
|
// temperatures.add(sensors.getTempCByIndex(0));
|
|
// Serial << "Sensor" << endl;
|
|
float temp1 = sensors.getTempCByIndex(0);
|
|
// Serial << "Sensor" << endl;
|
|
float temp2 = sensors.getTempCByIndex(1);
|
|
temperatures.add(temp1);
|
|
temperatures.add(temp2);
|
|
// root.prettyPrintTo(Serial);
|
|
root.prettyPrintTo(temperaturesJson);
|
|
// dtostrf(sensors.getTempCByIndex(0), 1, 1, str_temp);
|
|
// sprintf(b, "%s", str_temp);
|
|
// tft.drawString(str_temp, coordinates.x[3], coordinates.y[3], 2);
|
|
// Serial.println(sensors.getTempCByIndex(0));
|
|
// Serial << "Delay: " << delayInMillisSensors << endl;
|
|
// Serial << "Requesting temperatures" << endl;
|
|
|
|
sensors.requestTemperatures();
|
|
// delayInMillisSensors = 750 / (1 << (12 - SENSOR_RESOLUTION));
|
|
lastTempRequest = millis();
|
|
}
|
|
}
|
|
|
|
/*__________________________________________________________SETUP_FUNCTIONS__________________________________________________________*/
|
|
|
|
void 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
|
|
WiFi.softAP(ssid, password); // Start the access point
|
|
Serial.print("Access Point \"");
|
|
Serial.print(ssid);
|
|
Serial.println("\" started\r\n");
|
|
|
|
// wifiMulti.addAP(wifiMultiSSID, wifiMultiPassword);
|
|
|
|
// #ifdef WIFI_SSID
|
|
// const char *wifiMultiSSID = WIFI_SSID;
|
|
// Serial << "Macro " << WIFI_SSID;
|
|
// // wifiMulti.addAP(LC_WIFI_SSID, "");
|
|
// #else
|
|
// const char *wifiMultiSSID = "ssid";
|
|
// #endif
|
|
|
|
// #ifdef WIFI_PASS
|
|
// const char *wifiMultiPassword = WIFI_PASS;
|
|
// #else
|
|
// const char *wifiMultiPassword = "password";
|
|
// #endif
|
|
|
|
// wifiMulti.addAP(wifiMultiSSID, wifiMultiPassword);
|
|
Serial.print(F("MAC: "));
|
|
Serial.println(WiFi.macAddress());
|
|
|
|
Serial.println("Connecting");
|
|
while (wifiMulti.run() != WL_CONNECTED && WiFi.softAPgetStationNum() < 1)
|
|
{ // Wait for the Wi-Fi to connect
|
|
delay(250);
|
|
Serial.print('.');
|
|
}
|
|
Serial.println("\r\n");
|
|
if (WiFi.softAPgetStationNum() == 0)
|
|
{ // If the ESP is connected to an AP
|
|
Serial.print("Connected to ");
|
|
Serial.println(WiFi.SSID()); // Tell us what network we're connected to
|
|
Serial.print("IP address:\t");
|
|
Serial.print(WiFi.localIP()); // Send the IP address of the ESP8266 to the computer
|
|
}
|
|
else
|
|
{ // If a station is connected to the ESP SoftAP
|
|
Serial.print("Station connected to ESP8266 AP");
|
|
}
|
|
Serial.println("\r\n");
|
|
}
|
|
|
|
void startOTA()
|
|
{ // Start the OTA service
|
|
ArduinoOTA.setHostname(OTAName);
|
|
ArduinoOTA.setPassword(OTAPassword);
|
|
|
|
ArduinoOTA.onStart([]() {
|
|
Serial.println("Start");
|
|
// digitalWrite(LED_RED, 0); // turn off the LEDs
|
|
// digitalWrite(LED_GREEN, 0);
|
|
// digitalWrite(LED_BLUE, 0);
|
|
});
|
|
ArduinoOTA.onEnd([]() {
|
|
Serial.println("\r\nEnd");
|
|
});
|
|
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
|
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
|
});
|
|
ArduinoOTA.onError([](ota_error_t error) {
|
|
Serial.printf("Error[%u]: ", error);
|
|
if (error == OTA_AUTH_ERROR)
|
|
Serial.println("Auth Failed");
|
|
else if (error == OTA_BEGIN_ERROR)
|
|
Serial.println("Begin Failed");
|
|
else if (error == OTA_CONNECT_ERROR)
|
|
Serial.println("Connect Failed");
|
|
else if (error == OTA_RECEIVE_ERROR)
|
|
Serial.println("Receive Failed");
|
|
else if (error == OTA_END_ERROR)
|
|
Serial.println("End Failed");
|
|
});
|
|
ArduinoOTA.begin();
|
|
Serial.println("OTA ready\r\n");
|
|
}
|
|
|
|
void startSPIFFS()
|
|
{ // Start the SPIFFS and list all contents
|
|
SPIFFS.begin(); // Start the SPI Flash File System (SPIFFS)
|
|
Serial.println("SPIFFS started. Contents:");
|
|
{
|
|
Dir dir = SPIFFS.openDir("/");
|
|
while (dir.next())
|
|
{ // List the file system contents
|
|
String fileName = dir.fileName();
|
|
size_t fileSize = dir.fileSize();
|
|
Serial.printf("\tFS File: %s, size: %s\r\n", fileName.c_str(), formatBytes(fileSize).c_str());
|
|
}
|
|
Serial.printf("\n");
|
|
}
|
|
}
|
|
|
|
void startWebSocket()
|
|
{ // Start a WebSocket server
|
|
webSocket.begin(); // start the websocket server
|
|
webSocket.onEvent(webSocketEvent); // if there's an incomming websocket message, go to function 'webSocketEvent'
|
|
Serial.println("WebSocket server started.");
|
|
}
|
|
|
|
void startMDNS()
|
|
{ // Start the mDNS responder
|
|
MDNS.begin(mdnsName); // start the multicast domain name server
|
|
Serial.print("mDNS responder started: http://");
|
|
Serial.print(mdnsName);
|
|
Serial.println(".local");
|
|
}
|
|
|
|
void startServer()
|
|
{ // Start a HTTP server with a file read handler and an upload handler
|
|
server.on(
|
|
"/edit.html", HTTP_POST, []() { // If a POST request is sent to the /edit.html address,
|
|
// server.send(200, "text/plain", "");
|
|
server.send(200);
|
|
},
|
|
handleFileUpload); // go to 'handleFileUpload'
|
|
|
|
server.onNotFound(handleNotFound); // if someone requests any other file or page, go to function 'handleNotFound'
|
|
// and check if the file exists
|
|
server.on("/settings.html", HTTP_POST, handleSettings);
|
|
|
|
server.on("/manualMode.html", HTTP_POST, handleManual);
|
|
|
|
server.on("/api/get/temperatures", HTTP_GET, []() {
|
|
sendCors();
|
|
server.send(200, "application/json", temperaturesJson);
|
|
});
|
|
|
|
server.on("/api/get/date", HTTP_GET, []() {
|
|
sendCors();
|
|
server.send(200, "text/plain", rtcDate);
|
|
});
|
|
|
|
server.serveStatic("/", SPIFFS, "www", "no-cache");
|
|
|
|
server.begin(); // start the HTTP server
|
|
Serial.println("HTTP server started.");
|
|
}
|
|
|
|
/*__________________________________________________________SERVER_HANDLERS__________________________________________________________*/
|
|
|
|
void handleNotFound()
|
|
{ // if the requested file or page doesn't exist, return a 404 not found error
|
|
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
|
server.sendHeader("Pragma", "no-cache");
|
|
server.sendHeader("Expires", "-1");
|
|
if (!handleFileRead(server.uri()))
|
|
{ // check if the file exists in the flash memory (SPIFFS), if so, send it
|
|
server.send(404, "application/json", "{\"status\":\"failed\",\"message\":\"Resource not found\"}");
|
|
}
|
|
}
|
|
|
|
bool handleFileRead(String path)
|
|
{ // send the right file to the client (if it exists)
|
|
Serial.println("handleFileRead: " + path);
|
|
if (path.endsWith("/"))
|
|
path += "index.html"; // If a folder is requested, send the index file
|
|
String contentType = getContentType(path); // Get the MIME type
|
|
String pathWithGz = path + ".gz";
|
|
if (SPIFFS.exists(pathWithGz) || SPIFFS.exists(path))
|
|
{ // If the file exists, either as a compressed archive, or normal
|
|
if (SPIFFS.exists(pathWithGz)) // If there's a compressed version available
|
|
path += ".gz"; // Use the compressed verion
|
|
File file = SPIFFS.open(path, "r"); // Open the file
|
|
size_t sent = server.streamFile(file, contentType); // Send it to the client
|
|
file.close(); // Close the file again
|
|
Serial.println(String("\tSent file: ") + path);
|
|
return true;
|
|
}
|
|
Serial.println(String("\tFile Not Found: ") + path); // If the file doesn't exist, return false
|
|
return false;
|
|
}
|
|
|
|
void sendCors()
|
|
{
|
|
server.sendHeader("Access-Control-Allow-Origin", "*");
|
|
server.sendHeader("Access-Control-Max-Age", "10000");
|
|
server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
|
|
server.sendHeader("Access-Control-Allow-Headers", "*");
|
|
}
|
|
|
|
void saveTemperatureJson(DallasTemperature &sensors)
|
|
{
|
|
StaticJsonBuffer<200> jsonBuffer;
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
if (!root.success())
|
|
{
|
|
Log.error("Error creating temperature json object");
|
|
}
|
|
|
|
// JsonArray &data = root.createNestedArray("data");
|
|
// data.add(48);
|
|
// data.add(2);
|
|
JsonArray &temperatures = root.createNestedArray("temperatures");
|
|
float temp1 = sensors.getTempCByIndex(0);
|
|
float temp2 = sensors.getTempCByIndex(1);
|
|
temperatures.add(temp1);
|
|
temperatures.add(temp2);
|
|
temperatures.add(1);
|
|
root.prettyPrintTo(Serial);
|
|
root.prettyPrintTo(temperaturesJson);
|
|
// if (SPIFFS.exists("/temperatures.txt"))
|
|
// {
|
|
// SPIFFS.remove("/temperatures.txt");
|
|
// Serial.println("Old settings file removed");
|
|
// }
|
|
// File settingsFile = SPIFFS.open("/temperatures.txt", "w");
|
|
// if (!settingsFile)
|
|
// Log.error("Error wriing json to file");
|
|
// root.prettyPrintTo(settingsFile); //Export and save JSON object to SPIFFS area
|
|
// Serial.println("Json written to file");
|
|
// settingsFile.close();
|
|
}
|
|
|
|
void saveSettings(ESP8266WebServer &server, int num)
|
|
{
|
|
Log.notice("Ballast num = %d", num);
|
|
const int shour = server.arg("shour").toInt();
|
|
const int smin = server.arg("smin").toInt();
|
|
const int fadePeriod = server.arg("fadePeriod").toInt();
|
|
const int ehour = server.arg("ehour").toInt();
|
|
const int emin = server.arg("emin").toInt();
|
|
StaticJsonBuffer<200> jsonBuffer;
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
if (!root.success())
|
|
{
|
|
Log.error("Error creating json");
|
|
return;
|
|
}
|
|
root["shour"] = shour;
|
|
root["fadePeriod"] = fadePeriod;
|
|
root["smin"] = smin;
|
|
root["ehour"] = ehour;
|
|
root["emin"] = emin;
|
|
root.prettyPrintTo(Serial);
|
|
char buf[40] = "";
|
|
sprintf(buf, "/settingsFile%d.txt", num);
|
|
Log.verbose("Settings file chosen = %s", buf);
|
|
if (SPIFFS.exists(buf))
|
|
{
|
|
SPIFFS.remove(buf);
|
|
Log.notice("Old settings file removed");
|
|
}
|
|
File settingsFile = SPIFFS.open(buf, "w");
|
|
if (!settingsFile)
|
|
Log.error("Error opening settings file - %d", num);
|
|
root.prettyPrintTo(settingsFile); //Export and save JSON object to SPIFFS area
|
|
Log.notice("Json written to file");
|
|
settingsFile.close();
|
|
// delete server;
|
|
}
|
|
|
|
void combineSettings()
|
|
{
|
|
File file1 = SPIFFS.open("/settingsFile1.txt", "r");
|
|
File file2 = SPIFFS.open("/settingsFile2.txt", "r");
|
|
File file3 = SPIFFS.open("/settingsFile3.txt", "r");
|
|
File file5 = SPIFFS.open("/manualMode.txt", "r");
|
|
// Serial.println("2");
|
|
if (SPIFFS.exists("/combinedSettingsFile.txt"))
|
|
{
|
|
SPIFFS.remove("/combinedSettingsFile.txt");
|
|
}
|
|
|
|
File file4 = SPIFFS.open("/combinedSettingsFile.txt", "w");
|
|
size_t size1 = file1.size(), size2 = file2.size(), size3 = file3.size(), size5 = file5.size();
|
|
;
|
|
std::unique_ptr<char[]> buf1(new char[size1]);
|
|
std::unique_ptr<char[]> buf2(new char[size2]);
|
|
std::unique_ptr<char[]> buf3(new char[size3]);
|
|
std::unique_ptr<char[]> buf5(new char[size5]);
|
|
file1.readBytes(buf1.get(), size1);
|
|
file2.readBytes(buf2.get(), size2);
|
|
file3.readBytes(buf3.get(), size3);
|
|
file5.readBytes(buf5.get(), size5);
|
|
|
|
StaticJsonBuffer<100> jsonBuffer10;
|
|
JsonObject &root1 = jsonBuffer10.parseObject(buf1.get());
|
|
if (!root1.success())
|
|
{
|
|
Log.error("Error parsing JSON");
|
|
return;
|
|
}
|
|
StaticJsonBuffer<100> jsonBuffer11;
|
|
JsonObject &root2 = jsonBuffer11.parseObject(buf2.get());
|
|
if (!root2.success())
|
|
{
|
|
Log.error("Error parsing JSON");
|
|
return;
|
|
}
|
|
StaticJsonBuffer<100> jsonBuffer12;
|
|
JsonObject &root3 = jsonBuffer12.parseObject(buf3.get());
|
|
if (!root3.success())
|
|
{
|
|
Log.error("Error parsing JSON");
|
|
return;
|
|
}
|
|
StaticJsonBuffer<50> jsonBuffer16;
|
|
JsonObject &root5 = jsonBuffer16.parseObject(buf5.get());
|
|
/*StaticJsonBuffer<300> jsonBuffer13;
|
|
JsonObject& root4 = jsonBuffer13.createObject();
|
|
JsonObject& ballast1 = root4.createNestedObject();
|
|
root4["shour1"]=root1["shour1"];
|
|
root4["smin1"]=root1["smin1"];
|
|
root4["fadePeriod1"]=root1["fadePeriod1"];
|
|
root4["shour2"]=root2["shour2"];
|
|
root4["smin2"]=root2["smin2"];
|
|
root4["fadePeriod2"]=root2["fadePeriod2"];
|
|
root4["shour3"]=root3["shour3"];
|
|
root4["smin3"]=root3["smin3"];
|
|
root4["fadePeriod3"]=root3["fadePeriod3"];*/
|
|
|
|
DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);
|
|
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
|
|
JsonArray &settings = root.createNestedArray("settings");
|
|
|
|
JsonObject &settings_0 = settings.createNestedObject();
|
|
settings_0["shour"] = root1["shour"];
|
|
settings_0["fadePeriod"] = root1["fadePeriod"];
|
|
settings_0["smin"] = root1["smin"];
|
|
settings_0["ehour"] = root1["ehour"];
|
|
settings_0["emin"] = root1["emin"];
|
|
|
|
JsonObject &settings_1 = settings.createNestedObject();
|
|
settings_1["shour"] = root2["shour"];
|
|
settings_1["fadePeriod"] = root2["fadePeriod"];
|
|
settings_1["smin"] = root2["smin"];
|
|
settings_1["ehour"] = root2["ehour"];
|
|
settings_1["emin"] = root2["emin"];
|
|
|
|
JsonObject &settings_2 = settings.createNestedObject();
|
|
settings_2["shour"] = root3["shour"];
|
|
settings_2["fadePeriod"] = root3["fadePeriod"];
|
|
settings_2["smin"] = root3["smin"];
|
|
settings_2["ehour"] = root3["ehour"];
|
|
settings_2["emin"] = root3["emin"];
|
|
|
|
root["manual"] = root5["manual"];
|
|
/*root1.printTo(file4);
|
|
root1.printTo(Serial);
|
|
root2.printTo(file4);
|
|
root2.printTo(Serial);
|
|
root3.printTo(file4);
|
|
root3.printTo(Serial);*/
|
|
root.prettyPrintTo(Serial);
|
|
root.prettyPrintTo(file4);
|
|
// Serial.println("3");
|
|
|
|
file1.close();
|
|
file2.close();
|
|
file3.close();
|
|
file4.close();
|
|
file5.close();
|
|
}
|
|
|
|
//FIXME borked - has strange/undefined behaviour
|
|
void combineSettings_new()
|
|
{
|
|
const File file1 = SPIFFS.open("/settingsFile1.txt", "r");
|
|
const File file2 = SPIFFS.open("/settingsFile2.txt", "r");
|
|
const File file3 = SPIFFS.open("/settingsFile3.txt", "r");
|
|
File file5 = SPIFFS.open("/manualMode.txt", "r");
|
|
if (SPIFFS.exists("/combinedSettingsFile.txt"))
|
|
{
|
|
SPIFFS.remove("/combinedSettingsFile.txt");
|
|
}
|
|
|
|
File file_arr[] = {file1, file2, file3};
|
|
File file4 = SPIFFS.open("/combinedSettingsFile.txt", "w");
|
|
|
|
StaticJsonBuffer<JSON_BUFFER_SIZE> jsonBuffer;
|
|
JsonObject &root = jsonBuffer.createObject();
|
|
JsonArray &settings = root.createNestedArray("settings");
|
|
|
|
StaticJsonBuffer<50> jsonBufferManual;
|
|
size_t size_manual = file5.size();
|
|
unique_ptr<char[]> buf_manual(new char[size_manual]);
|
|
file5.readBytes(buf_manual.get(), size_manual);
|
|
JsonObject &root_manual = jsonBufferManual.parseObject(buf_manual.get());
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
const size_t file_size = file_arr[i].size();
|
|
const unique_ptr<char[]> buf(new char[file_size]);
|
|
file_arr[i].readBytes(buf.get(), file_size);
|
|
StaticJsonBuffer<(JSON_BUFFER_SIZE / 3) + 50> jsonBuffer;
|
|
JsonObject &root_i = jsonBuffer.parseObject(buf.get());
|
|
|
|
if (!root_i.success())
|
|
{
|
|
Log.error(F("Error creating json for file %d"), i + 1);
|
|
}
|
|
else
|
|
{
|
|
JsonObject &settings_i = settings.createNestedObject();
|
|
settings_i["shour"] = root_i["shour"];
|
|
settings_i["fadePeriod"] = root_i["fadePeriod"];
|
|
settings_i["smin"] = root_i["smin"];
|
|
settings_i["ehour"] = root_i["ehour"];
|
|
settings_i["emin"] = root_i["emin"];
|
|
// Log.notice("inside array temp");
|
|
// char buf[JSON_BUFFER_SIZE / 3];
|
|
// root_i.prettyPrintTo(buf);
|
|
// Log.trace("%s", buf);
|
|
Log.trace("Printing settings %d", i + 1);
|
|
// settings_i.prettyPrintTo(Serial);
|
|
// root.prettyPrintTo(Serial);
|
|
// settings.prettyPrintTo(Serial);
|
|
file_arr[i].close();
|
|
}
|
|
}
|
|
|
|
root["manual"] = root_manual["manual"];
|
|
Log.trace("Printing final root");
|
|
root.prettyPrintTo(Serial);
|
|
root.prettyPrintTo(file4);
|
|
|
|
file4.close();
|
|
file5.close();
|
|
}
|
|
/*void displaySettings()
|
|
{
|
|
File file = SPIFFS.open("/settingsFile.txt", "r");
|
|
if (!file){
|
|
Log.error("Error reading settings file or file does not exist");
|
|
} else {
|
|
size_t size = file.size();
|
|
if ( size == 0 ) {
|
|
Serial.println("Settings file is empty");
|
|
} else {
|
|
std::unique_ptr<char[]> buf (new char[size]);
|
|
file.readBytes(buf.get(), size);
|
|
StaticJsonBuffer<200> jsonBuffer2;
|
|
JsonObject& root = jsonBuffer2.parseObject(buf.get());
|
|
if (!root.success()) {
|
|
Log.error("Error reading settings file");
|
|
} else {
|
|
Serial.println("Settings file loaded");
|
|
root.prettyPrintTo(Serial);
|
|
root.printTo(s);
|
|
Serial.println("Settings sent to arduino");
|
|
}
|
|
}
|
|
file.close();
|
|
}
|
|
}*/
|
|
void displayCombinedSettings()
|
|
{
|
|
File file = SPIFFS.open("/combinedSettingsFile.txt", "r");
|
|
if (!file)
|
|
{
|
|
Log.error("Error reading combined settings file or file does not exist");
|
|
}
|
|
else
|
|
{
|
|
Log.notice("Settings file exists");
|
|
size_t size = file.size();
|
|
if (size == 0)
|
|
{
|
|
Log.notice("Settings file is empty");
|
|
}
|
|
else
|
|
{
|
|
std::unique_ptr<char[]> buf5(new char[size]);
|
|
file.readBytes(buf5.get(), size);
|
|
// StaticJsonBuffer<300> jsonBuffer;
|
|
DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);
|
|
JsonObject &root5 = jsonBuffer.parseObject(buf5.get());
|
|
if (!root5.success())
|
|
{
|
|
Log.error("Error reading combined settings file");
|
|
}
|
|
else
|
|
{
|
|
Log.notice("Settings file loaded");
|
|
root5.prettyPrintTo(Serial);
|
|
// digitalWrite(ESP_TO_ARDUINO_PIN,0);
|
|
// analogWrite(ESP_TO_ARDUINO_PIN,255);
|
|
root5.printTo(s);
|
|
// digitalWrite(ESP_TO_ARDUINO_PIN,1);
|
|
}
|
|
}
|
|
file.close();
|
|
}
|
|
}
|
|
void handleManual()
|
|
{
|
|
File file = SPIFFS.open("/manualMode.txt", "w");
|
|
StaticJsonBuffer<50> jsonBufferManual;
|
|
JsonObject &root = jsonBufferManual.createObject();
|
|
if (server.arg("manual") == "True")
|
|
{
|
|
root["manual"] = "True";
|
|
}
|
|
else
|
|
{
|
|
root["manual"] = "False";
|
|
}
|
|
root.prettyPrintTo(file);
|
|
file.close();
|
|
combineSettings();
|
|
// digitalWrite(ESP_TO_ARDUINO_PIN, 1);
|
|
displayCombinedSettings();
|
|
// digitalWrite(ESP_TO_ARDUINO_PIN,1);
|
|
// server.sendHeader("Location", "/manualMode.html"); // Redirect the client to the success page
|
|
// server.send(303);
|
|
server.send(200);
|
|
}
|
|
void handleSettings()
|
|
{
|
|
// if (server.arg("ballast").toInt() == 1)
|
|
// handleSettings1();
|
|
// else if (server.arg("ballast").toInt() == 2)
|
|
// handleSettings2();
|
|
// else if (server.arg("ballast").toInt() == 3)
|
|
// handleSettings3();
|
|
// displayCombinedSettings();
|
|
// server.sendHeader("Location", "/settings.html"); // Redirect the client to the success page
|
|
const int ballast_num = server.arg("ballast").toInt();
|
|
Log.notice("Chosen num = %d", ballast_num);
|
|
saveSettings(server, ballast_num);
|
|
combineSettings();
|
|
displayCombinedSettings();
|
|
server.send(200);
|
|
}
|
|
|
|
void handleFileUpload()
|
|
{ // upload a new file to the SPIFFS
|
|
HTTPUpload &upload = server.upload();
|
|
String path;
|
|
if (upload.status == UPLOAD_FILE_START)
|
|
{
|
|
path = upload.filename;
|
|
if (!path.startsWith("/"))
|
|
path = "/" + path;
|
|
if (!path.endsWith(".gz"))
|
|
{ // The file server always prefers a compressed version of a file
|
|
String pathWithGz = path + ".gz"; // So if an uploaded file is not compressed, the existing compressed
|
|
if (SPIFFS.exists(pathWithGz)) // version of that file must be deleted (if it exists)
|
|
SPIFFS.remove(pathWithGz);
|
|
}
|
|
Serial.print("handleFileUpload Name: ");
|
|
Serial.println(path);
|
|
fsUploadFile = SPIFFS.open(path, "w"); // Open the file for writing in SPIFFS (create if it doesn't exist)
|
|
path = String();
|
|
}
|
|
else if (upload.status == UPLOAD_FILE_WRITE)
|
|
{
|
|
if (fsUploadFile)
|
|
fsUploadFile.write(upload.buf, upload.currentSize); // Write the received bytes to the file
|
|
}
|
|
else if (upload.status == UPLOAD_FILE_END)
|
|
{
|
|
if (fsUploadFile)
|
|
{ // If the file was successfully created
|
|
fsUploadFile.close(); // Close the file again
|
|
Serial.print("handleFileUpload Size: ");
|
|
Serial.println(upload.totalSize);
|
|
// server.sendHeader("Location", "/success.html"); // Redirect the client to the success page
|
|
server.send(201, "application/json", "{\"status\":\"success\",\"message\":\"File created successfully\"}");
|
|
}
|
|
else
|
|
{
|
|
server.send(500, "application/json", "{\"status\":\"failed\",\"message\":\"Could not create file\"}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// const char *text = R"(
|
|
// { " "
|
|
// ;''
|
|
// }
|
|
// qegqeg
|
|
// qegq
|
|
// )";
|
|
|
|
void webSocketEvent(uint8_t num, WStype_t type, uint8_t *payload, size_t lenght)
|
|
{ // When a WebSocket message is received
|
|
switch (type)
|
|
{
|
|
case WStype_DISCONNECTED: // if the websocket is disconnected
|
|
Serial.printf("[%u] Disconnected!\n", num);
|
|
break;
|
|
case WStype_CONNECTED:
|
|
{ // if a new websocket connection is established
|
|
IPAddress ip = webSocket.remoteIP(num);
|
|
Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
|
|
rainbow = false; // Turn rainbow off when a new connection is established
|
|
}
|
|
break;
|
|
case WStype_TEXT: // if new text data is received
|
|
Serial.printf("[%u] get Text: %s\n", num, payload);
|
|
if (payload[0] == '#')
|
|
{ // we get RGB data
|
|
uint32_t rgb = (uint32_t)strtol((const char *)&payload[1], NULL, 16); // decode rgb data
|
|
int r = ((rgb >> 20) & 0x3FF); // 10 bits per color, so R: bits 20-29
|
|
int g = ((rgb >> 10) & 0x3FF); // G: bits 10-19
|
|
int b = rgb & 0x3FF; // B: bits 0-9
|
|
|
|
// analogWrite(LED_RED, r); // write it to the LED output pins
|
|
// analogWrite(LED_GREEN, g);
|
|
// analogWrite(LED_BLUE, b);
|
|
}
|
|
else if (payload[0] == 'R')
|
|
{ // the browser sends an R when the rainbow effect is enabled
|
|
rainbow = true;
|
|
}
|
|
else if (payload[0] == 'N')
|
|
{ // the browser sends an N when the rainbow effect is disabled
|
|
rainbow = false;
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
Log.error("Unsupported operation - number %d", type);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*__________________________________________________________HELPER_FUNCTIONS__________________________________________________________*/
|
|
|
|
String formatBytes(size_t bytes)
|
|
{ // convert sizes in bytes to KB and MB
|
|
if (bytes < 1024)
|
|
{
|
|
return String(bytes) + "B";
|
|
}
|
|
else if (bytes < (1024 * 1024))
|
|
{
|
|
return String(bytes / 1024.0) + "KB";
|
|
}
|
|
else if (bytes < (1024 * 1024 * 1024))
|
|
{
|
|
return String(bytes / 1024.0 / 1024.0) + "MB";
|
|
}
|
|
else
|
|
return "";
|
|
}
|
|
|
|
String getContentType(String filename)
|
|
{ // determine the filetype of a given filename, based on the extension
|
|
if (filename.endsWith(".html"))
|
|
return "text/html";
|
|
else if (filename.endsWith(".css"))
|
|
return "text/css";
|
|
else if (filename.endsWith(".js"))
|
|
return "application/javascript";
|
|
else if (filename.endsWith(".ico"))
|
|
return "image/x-icon";
|
|
else if (filename.endsWith(".gz"))
|
|
return "application/x-gzip";
|
|
return "text/plain";
|
|
}
|
|
|
|
void setHue(int hue)
|
|
{ // Set the RGB LED to a given hue (color) (0° = Red, 120° = Green, 240° = Blue)
|
|
hue %= 360; // hue is an angle between 0 and 359°
|
|
float radH = hue * 3.142 / 180; // Convert degrees to radians
|
|
float rf, gf, bf;
|
|
|
|
if (hue >= 0 && hue < 120)
|
|
{ // Convert from HSI color space to RGB
|
|
rf = cos(radH * 3 / 4);
|
|
gf = sin(radH * 3 / 4);
|
|
bf = 0;
|
|
}
|
|
else if (hue >= 120 && hue < 240)
|
|
{
|
|
radH -= 2.09439;
|
|
gf = cos(radH * 3 / 4);
|
|
bf = sin(radH * 3 / 4);
|
|
rf = 0;
|
|
}
|
|
else if (hue >= 240 && hue < 360)
|
|
{
|
|
radH -= 4.188787;
|
|
bf = cos(radH * 3 / 4);
|
|
rf = sin(radH * 3 / 4);
|
|
gf = 0;
|
|
}
|
|
int r = rf * rf * 1023;
|
|
int g = gf * gf * 1023;
|
|
int b = bf * bf * 1023;
|
|
|
|
// analogWrite(LED_RED, r); // Write the right color to the LED output pins
|
|
// analogWrite(LED_GREEN, g);
|
|
// analogWrite(LED_BLUE, b);
|
|
}
|
|
|
|
void printTimestamp(Print *_logOutput)
|
|
{
|
|
char c[12];
|
|
int m = sprintf(c, "%10lu ", millis());
|
|
_logOutput->print(c);
|
|
}
|
|
|
|
void printNewline(Print *_logOutput)
|
|
{
|
|
_logOutput->print('\n');
|
|
}
|