#include "SPIFFS.h" #include #include #include #include #include #include "AsyncJson.h" #include #include #include #include "INA226.h" #include "INA233.h" #include "global_data/defines.h" #include "networking/networking.h" #include "external_interfacing/leds.h" #include "sensor/sensor.h" #include "telemetry/telemetry.h" #include "tools/tools.h" #include #include "networking/json_builder.h" #include "networking/responses.h" Preferences prefs; extern WaterData water_data; extern DeviceTelemetry telemetry; extern NetworkData wifi_data; extern NetworkData ethernet_data; extern SensorData shunt_data; extern "C" int rom_phy_get_vdd33(); AsyncWebServer server(80); #define FORMAT_LITTLEFS_IF_FAILED true void setup() { prefs.begin("waterlevel", false); Serial.begin(115200); Log.begin(LOG_LEVEL_VERBOSE, &Serial); Log.setSuffix(printSuffix); Log.setPrefix(print_prefix); Log.verbose("Init LEDs"); pinMode(LED_1, OUTPUT); pinMode(LED_2, OUTPUT); pinMode(LED_3, OUTPUT); pinMode(LED_4, OUTPUT); pinMode(LED_5, OUTPUT); pinMode(LED_RED, OUTPUT); display_error_code(31); delay(500); display_error_code(17); init_sensor(); Log.verbose("Beginning SPIFFS"); SPIFFS.begin(true); Log.verbose("SPIFFS initialized"); display_error_code(19); Log.verbose("Begin INA"); display_error_code(22); /////////////////////////////// ROUTES /////////////////////////////// Log.verbose("Route Setup"); // Normal HTML stuff server.on("/", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/status.html", "text/html", false, processor); }); server.on("/settings", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/settings.html", "text/html", false, processor); }); server.on("/export", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/data_export.html", "text/html", false); }); server.on("/logic.js", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/logic.js", "application/javascript", false, processor); }); // API stuff - internal server.on("/update_wifi_credentials", HTTP_POST, [](AsyncWebServerRequest* request) { int params = request->params(); // For settings SSID if (request->hasParam(ssid_key, true) && request->hasParam(wifi_password_key, true)) { Log.verbose("Updating SSID config"); AsyncWebParameter* ssid_param = request->getParam(ssid_key, true); AsyncWebParameter* password_param = request->getParam(wifi_password_key, true); prefs.putString(ssid_key, ssid_param->value().c_str()); prefs.putString(wifi_password_key, password_param->value().c_str()); } else { request->send(400, "text/plain", "Missing parameters"); // TODO add proper error messages } request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating }); server.on("/update_sensor_settings", HTTP_POST, [](AsyncWebServerRequest* request) { int params = request->params(); if (request->hasParam(level_sensor_range_key, true) && request->hasParam(water_level_min_key, true) && request->hasParam(water_level_max_key, true) && request->hasParam(water_volume_key, true)) { Log.verbose("Updating Sensor config"); AsyncWebParameter* range_param = request->getParam(level_sensor_range_key, true); AsyncWebParameter* level_min_param = request->getParam(water_level_min_key, true); AsyncWebParameter* level_max_param = request->getParam(water_level_max_key, true); AsyncWebParameter* liters_param = request->getParam(water_volume_key, true); String range_str = range_param->value(); String level_min_str = level_min_param->value(); String level_max_str = level_max_param->value(); String liters_str = liters_param->value(); float range_float = range_str.toFloat(); float level_min_float = level_min_str.toFloat(); float level_max_float = level_max_str.toFloat(); float liters_float = liters_str.toFloat(); const char* paramCStr = range_str.c_str(); char* endPtr; // Convert the C string to a float using strtod float value = strtod(paramCStr, &endPtr); Log.verbose("range_float:%D:", range_float); prefs.putFloat(level_sensor_range_key, range_float); prefs.putFloat(water_level_min_key, level_min_float); prefs.putFloat(water_level_max_key, level_max_float); prefs.putFloat(water_volume_key, liters_float); Log.verbose("range_float_after:%D:", prefs.getFloat(level_sensor_range_key, -1.0)); } else { Log.verbose("!!!! FAIL lo"); for (int i = 0; i < params; i++) { AsyncWebParameter* p = request->getParam(i); if (p->isFile()) { // p->isPost() is also true Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); } else if (p->isPost()) { Log.verbose("POST[%s]: %s\n", p->name().c_str(), p->value().c_str()); } else { Log.verbose("GET[%s]: %s\n", p->name().c_str(), p->value().c_str()); } } request->send(400, "text/plain", "Missing parameters"); // TODO add proper error messages } request->send(SPIFFS, "/settings.html", "text/html", false); // TODO add proper return templating }); setup_api_endpoints(); server.on("/chota.css", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/chota.css", "text/css", false); }); server.on("/gauge.js", HTTP_GET, [](AsyncWebServerRequest* request) { request->send(SPIFFS, "/gauge.js", "application/javascript", false); }); display_error_code(23); display_error_code(24); Log.verbose("OTA Setup"); ArduinoOTA .onStart([]() { String type; if (ArduinoOTA.getCommand() == U_FLASH) type = "sketch"; else // U_SPIFFS type = "filesystem"; // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end() Log.verbose("Start updating %s", type); }) .onEnd([]() { Log.verbose("\nEnd"); }) .onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }) .onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Log.verbose("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Log.verbose("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Log.verbose("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Log.verbose("Receive Failed"); else if (error == OTA_END_ERROR) Log.verbose("End Failed"); }); display_error_code(26); digitalWrite(LED_RED, 0); xTaskCreate(ethernet_task, "EthernetTask", 4096, NULL, 1, NULL); xTaskCreate(wifi_task, "WiFiTask", 10000, NULL, 1, NULL); delay(250); Log.verbose("Starting webserver"); server.begin(); ArduinoOTA.begin(); display_error_code(25); xTaskCreate(display_task, "DisplayTask", 10000, NULL, 1, NULL); xTaskCreate(read_sensor_task, "ReadSensorTask", 2048, NULL, 1, NULL); xTaskCreate(collect_internal_telemetry_task, "InternalTelemetryTask", 2048, NULL, 1, NULL); } void loop() { ArduinoOTA.handle(); delay(1000); }