Subversion Repositories ESP32_P1_Meter

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include <ArduinoOTA.h>
#include <EEPROM.h>
#include <Ticker.h>
#include <MQTTRemote.h>

#include <FS.h>
#include <LittleFS.h>
#include <AsyncFsWebServer.h>  //https://github.com/cotestatnt/async-esp-fs-webserver


// * Include settings
#include "settings.h"

// * Initiate led blinker library
Ticker ticker;

#define FILESYSTEM LittleFS
bool captiveRun = false;

// AsyncFsWebServer server(80, FILESYSTEM, "esphost");
AsyncFsWebServer server(80, FILESYSTEM);

#ifndef Default_MQTT_Port
#define Default_MQTT_Port 1883
#endif

#define BTN_SAVE  5

// Test "options" values
uint16_t MQTT_Port = Default_MQTT_Port;
bool MQTT_Enabled = false;
String MQTT_Client = "ESP32_P1_Meter";
String MQTT_Server = "";
String MQTT_User = "";
String MQTT_Password = "";
String MQTT_Prefix = "";

// Var labels (in /setup webpage)
#define MQTT_ENABLED_LABEL "MQTT Enabled"
#define MQTT_CLIENT_LABEL "MQTT Client"
#define MQTT_SERVER_LABEL "MQTT Server"
#define MQTT_PORT_LABEL "MQTT Server Port"
#define MQTT_USER_LABEL "MQTT User"
#define MQTT_PASSWORD_LABEL "MQTT Password"
#define MQTT_PREFIX_LABEL "MQTT Prefix"

// Timezone definition to get properly time from NTP server
#define MYTZ "CET-1CEST,M3.5.0,M10.5.0/3"
struct tm Time;

static const char save_btn_htm[] PROGMEM = R"EOF(
<div class="btn-bar">
  <a class="btn" id="reload-btn">Reload options</a>
</div>
)EOF";

static const char button_script[] PROGMEM = R"EOF(
/* Add click listener to button */
document.getElementById('reload-btn').addEventListener('click', reload);
function reload() {
  console.log('Reload configuration options');
  fetch('/reload')
  .then((response) => {
    if (response.ok) {
      openModalMessage('Options loaded', 'Options was reloaded from configuration file');
      return;
    }
    throw new Error('Something goes wrong with fetch');
  })
  .catch((error) => {
    openModalMessage('Error', 'Something goes wrong with your request');
  });
}
)EOF";


////////////////////////////////  Filesystem  /////////////////////////////////////////
bool startFilesystem() {
  if (FILESYSTEM.begin()){
    server.printFileList(FILESYSTEM, "/", 2);
    return true;
  }
  else {
    Serial.println("ERROR on mounting filesystem. It will be reformatted!");
    FILESYSTEM.format();
    ESP.restart();
  }
  return false;
}

/*
* Getting FS info (total and free bytes) is strictly related to
* filesystem library used (LittleFS, FFat, SPIFFS etc etc) and ESP framework
*/
#ifdef ESP32
void getFsInfo(fsInfo_t* fsInfo) {
        fsInfo->fsName = "LittleFS";
        fsInfo->totalBytes = LittleFS.totalBytes();
        fsInfo->usedBytes = LittleFS.usedBytes();
}
#endif

////////////////////  Load application options from filesystem  ////////////////////
bool loadOptions() {
  if (FILESYSTEM.exists(server.getConfiFileName())) {
    server.getOptionValue(MQTT_ENABLED_LABEL, MQTT_Enabled);
    server.getOptionValue(MQTT_CLIENT_LABEL, MQTT_Client);
    server.getOptionValue(MQTT_SERVER_LABEL, MQTT_Server);
    server.getOptionValue(MQTT_PORT_LABEL, MQTT_Port);
    server.getOptionValue(MQTT_USER_LABEL, MQTT_User);
    server.getOptionValue(MQTT_PASSWORD_LABEL, MQTT_Password);
    server.getOptionValue(MQTT_PREFIX_LABEL, MQTT_Prefix);

    Serial.println("\nThis are the current values stored: \n");
    Serial.printf("MQTT Enabled: %s\n", MQTT_Enabled ? "true" : "false");
    Serial.printf("MQTT Client: %s\n", MQTT_Client.c_str());
    Serial.printf("MQTT Server: %s\n", MQTT_Server.c_str());
    Serial.printf("MQTT Server Port: %d\n", MQTT_Port);
    Serial.printf("MQTT User: %s\n", MQTT_User.c_str());
    Serial.printf("MQTT password: %s\n", MQTT_Password.c_str());
    Serial.printf("MQTT Prefix: %s\n", MQTT_Prefix.c_str());
    return true;
  }
  else
    Serial.println(F("Config file not exist"));
  return false;
}

MQTTRemote _mqtt_remote(MQTT_Client.c_str(), MQTT_Server.c_str(), MQTT_Port.c_str(), MQTT_User.c_str(), MQTT_Password.c_str(),
                        {.rx_buffer_size = 2048, .tx_buffer_size = 2048, .keep_alive_s = 10});

bool _was_connected = false;
void saveOptions() {
  // server.saveOptionValue(LED_LABEL, ledPin);
  // server.saveOptionValue(BOOL_LABEL, boolVar);
  // server.saveOptionValue(LONG_LABEL, longVar);
  // server.saveOptionValue(FLOAT_LABEL, floatVar);
  // server.saveOptionValue(STRING_LABEL, stringVar);
  // server.saveOptionValue(DROPDOWN_LABEL, dropdownSelected);
  Serial.println(F("Application options saved."));
}

////////////////////////////  HTTP Request Handlers  ////////////////////////////////////
void handleLoadOptions(AsyncWebServerRequest *request) {
  request->send(200, "text/plain", "Options loaded");
  loadOptions();
  Serial.println("Application option loaded after web request");
}


void setup() {
  Serial.begin(115200);
  pinMode(BTN_SAVE, INPUT_PULLUP);

  // FILESYSTEM INIT
  if (startFilesystem()){
    // Load configuration (if not present, default will be created when webserver will start)
    if (loadOptions())
      Serial.println(F("Application option loaded"));
    else
      Serial.println(F("Application options NOT loaded!"));
  }

  // Try to connect to stored SSID, start AP with captive portal if fails after timeout
  IPAddress myIP = server.startWiFi(15000);
  if (!myIP) {
    Serial.println("\n\nNo WiFi connection, start AP and Captive Portal\n");
    server.startCaptivePortal("ESP_AP", "123456789", "/setup");
    myIP = WiFi.softAPIP();
    captiveRun = true;
  }

  // Add custom page handlers to webserver
  server.on("/reload", HTTP_GET, handleLoadOptions);

  // Configure /setup page and start Web Server
  server.addOptionBox("MQTT");

  server.addOption(MQTT_ENABLED_LABEL, MQTT_Enabled);
  server.addOption(MQTT_SERVER_LABEL, MQTT_Server);
  server.addOption(MQTT_PORT_LABEL, MQTT_Port);
  server.addOption(MQTT_USER_LABEL, MQTT_User);
  server.addOption(MQTT_PASSWORD_LABEL, MQTT_Password);
  server.addOption(MQTT_PREFIX_LABEL, MQTT_Prefix);
  server.addOptionBox(const char *title);

  server.addHTML(save_btn_htm, "buttons", /*overwrite*/ false);
  server.addJavascript(button_script, "js", /*overwrite*/ false);

  // Enable ACE FS file web editor and add FS info callback function
  server.enableFsCodeEditor();
  #ifdef ESP32
  server.setFsInfoCallback(getFsInfo);
  #endif

  // set /setup and /edit page authentication
  server.setAuthentication("admin", "admin");

  // Start server
  server.init();
  Serial.print(F("ESP Web Server started on IP Address: "));
  Serial.println(myIP);
  Serial.println(F(
      "This is \"customOptions.ino\" example.\n"
      "Open /setup page to configure optional parameters.\n"
      "Open /edit page to view, edit or upload example or your custom webserver source files."
  ));

  if (MQTT_Enabled) {
    _mqtt_remote.start([](bool connected) {
    if (connected) {
      _mqtt_remote.subscribe(
            _mqtt_remote.publishMessageVerbose(_mqtt_remote.clientId() + "/initial_message", "oh hello!");
          });
    }
  });
  };
}

void loop() {
  if (captiveRun)
    server.updateDNS();

  // Savew options also on button click
  if (! digitalRead(BTN_SAVE)) {
    saveOptions();
    delay(1000);
  }
}