26.02.2017ESP8266 - ESPBasics Library

ESPBasics


Knihovna starající se o základní služby. Přijímá příkazy přes serial, umožňuje nastavit více AP, mezi kterýma pak zařízení přepíná, nastavuje FTP a webserver. Config ukládá na filesystem. Umožňuje rozšířit handlované Serial commandy.

Jako první po nastartování napište do serialu "<help>" pro zobrazení dostupných příkazů.

Ke stažení:
espbasicsdemo.zip
espbasicslibrary.zip

Použití:

espbasicsdemo.ino

/// ESP Basics module ///
#include "ESPBasics.h"
using namespace ESPBasics;
//////

namespace Webserver
{
  void Root() {
    server.send(200, "text/plain", "Non default handle");
  }
}

void serialCommandHandler(String command, String value) {
  if(command == "whatever"){
      Serial.println("Whatever command called with value: " + value);
  }
}

void setup(void){
  /* Uncomment if you want to define your own 404 page
  WifiBasics::Settings::noDefault404 = true;
  */
  /* Uncomment if you dont't want to init FTP server
  WifiBasics::Settings::noFTP = true;
  */
  /* Uncomment if you dont't want to init HTTP server
  WifiBasics::Settings::noHTTP = true;
  */
  // You can set custom Serial Command handler.
  ESPBasics::setSerialCommandHandler(serialCommandHandler);
  
  ESPBasics::setupStart();
  
  // your setup code
  Serial.println("- Define URI listeners -");
  server.on("/", Webserver::Root);
  // end of your setup code
  
  ESPBasics::setupEnd();
}

void loop(void){
  ESPBasics::loop();
  // your loop code
  // end of your loop code
}


Knihovna:

espbasics.h

/*
 * WifiBasics Library
 * ------------------
 * version 1.1
 * 
 * FTP server
 * HTTP server
 * Multiple APs
 * Configurable over Serial or over FTP (config files are saved in filesystem)
 * 
 * Use <help> in serial to get information about available commands
*/

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include "ESP8266FtpServer.h"

namespace ESPBasics {
  namespace Settings {
    String ftpConfig = "/.ftpconf";
    String wifiConfig = "/.wificonf";
    bool noDefault404 = false;
    bool noFTP = false;
    bool noHTTP = false;
  }
  
  namespace Tools {
    void fileCreate(String name) {
      File f = SPIFFS.open(name, "a");
      if (!f) {
        Serial.print("File creation/opening failed: ");
        Serial.println(name);
        return;
      }
      f.close();
    }
    
    void fileAppend(String name, String str) {
      File f = SPIFFS.open(name, "a");
      if (!f) {
        Serial.print("File creation/opening failed: ");
        Serial.println(name);
        return;
      }
    
      f.println(str);
      f.close();
    }

    void fileWrite(String name, String str) {
      File f = SPIFFS.open(name, "w");
      if (!f) {
        Serial.print("File creation/opening failed: ");
        Serial.println(name);
        return;
      }
    
      f.println(str);
      f.close();
    }

    String readFirstLine(String filename) {
      File f = SPIFFS.open(filename, "r");
      if (!f) {
        Serial.print("File opening failed: ");
        Serial.println(filename);
        return "";
      }

      while (f.available()) {
        String line = f.readStringUntil('\n');
        line.replace('\r', '\0');
        return line;
      }
      
      f.close();
    }
    
    String getNthPart(String str, int n, char separator = ';') {
      int len = str.length();
      int count = 0;
      int state = (n == 0 ? 1 : 0);
      char c;
      String result = "";
    
      for (int i = 0; i < len; i++) {
        c = str[i];
        switch (state) {
          case 0:
            if (c == separator) {
              count++;
              if (count == n) {
                state = 1;
              }
            }
            break;
          case 1:
            if (c == separator || c == 13 || c == 10) {
              return result;
            } else {
              result += c;
            }
            break;
        }
      }
    
      return result;
    }
  }
  namespace Command {
    void removeWifi(String ssid, bool silent = false) {
      if(!silent) Serial.println("- Remove Wifi -");

      File f = SPIFFS.open(Settings::wifiConfig, "r");
      if (f) {
         File tmp = SPIFFS.open(Settings::wifiConfig + ".tmp", "w");
         if (tmp) {
            while (f.available()) {
              String line = f.readStringUntil('\n');
              line.trim();
              if(Tools::getNthPart(line, 0) != ssid){
                  tmp.println(line);
              } else if(silent)  {
                Serial.println("- AP config will be replaced");
              }
            }
            tmp.close();
            f.close();
            SPIFFS.remove(Settings::wifiConfig);
            SPIFFS.rename(Settings::wifiConfig + ".tmp", Settings::wifiConfig);

            if(!silent) Serial.println("- Wifi AP removed");
         } else {
            Serial.println("! Cannot create temp file !");
         }
         if(f){
          f.close();
         }
      } else {
        Serial.println("! Cannot read config file !");
      }

      if(!silent) {
        Serial.println("-- Done");
        Serial.println();
      }
    }
  
    void addWifi(String value) {
      Serial.println("- Add Wifi -");
      String line = "";

      removeWifi(Tools::getNthPart(value, 0), true);
      
      line += Tools::getNthPart(value, 0);
      line += ";";
      line += Tools::getNthPart(value, 1);
      line += ";";
    
      Tools::fileAppend(Settings::wifiConfig, line);

      Serial.println("-- Done");
      Serial.println();
    }

    void wifiList() {
      Serial.println("- List of wifi APs -");
      Tools::fileCreate(Settings::wifiConfig);
    
      File f = SPIFFS.open(Settings::wifiConfig, "r");
      if (f) {
        while (f.available()) {
          String line = f.readStringUntil('\n');
          const char * ssid;
          const char * password;
          String str_ssid = Tools::getNthPart(line, 0);
          String str_password = Tools::getNthPart(line, 1);
    
          ssid = str_ssid.c_str();
          password = str_password.c_str();
    
          Serial.print("SSID: ");
          Serial.print(ssid);
          Serial.print(" / Password: ");
          Serial.println(password);
        }
        f.close();
      } else {
        Serial.println("! Cannot read config file !");
      }

      Serial.println("-- Done");
      Serial.println();
    }

    void setFTP(String value) {
      Serial.println("- Set FTP -");
      String line = "";
    
      line += Tools::getNthPart(value, 0);
      line += ";";
      line += Tools::getNthPart(value, 1);
      line += ";";
    
      Tools::fileWrite(Settings::ftpConfig, line);
   
      Serial.println("-- Done");
      Serial.println();
    }

    void activeConnection() {
      Serial.println("- Active Connection -");
      Serial.print("IP: ");
      Serial.println(WiFi.localIP());
      Serial.print("SSID: ");
      Serial.println(WiFi.SSID());
      Serial.println();
    }
  }
  
  /////////////////
  /////////////////
  /////////////////
  
  FtpServer ftpSrv;
  ESP8266WebServer server(80);
  ESP8266WiFiMulti wifiMulti;
  void (*serialCommandCallback)(String, String);
  
  const char* ssid = "Airlive";
  const char* password = "abecedaabcd";

  void setSerialCommandHandler(void (*cb)(String, String)) {
    serialCommandCallback = cb;
  }

  void defaultHandleNotFound() {
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(404, "text/plain", message);
  }
  
  void handleSerialCommand(String command, String value) {
    Serial.println();

    if(serialCommandCallback){
      Serial.println("- Custom serial command handler prepared -");
      serialCommandCallback(command, value);
    }
    
    if (command == "addwifi") {
      Command::addWifi(value);
      wifiMulti.addAP(Tools::getNthPart(value, 0).c_str(), Tools::getNthPart(value, 1).c_str());
    } else if (command == "wifilist") {
      Command::wifiList();
    } else if (command == "removewifi") {
      Command::removeWifi(value);
    } else if(command == "connection") {
      Command::activeConnection();
    } else if (command == "setftp") {
      if(!Settings::noFTP) {
        Command::setFTP(value);
        Serial.println("- Init FTP -");
        ftpSrv.begin(Tools::getNthPart(value, 0), Tools::getNthPart(value, 1));
      } else {
        Serial.println("! FTP is turned off in firmware !");
      }
    } else if (command == "help") {
      Serial.println();
      Serial.println("- Help -");
      Serial.println("--------");
      Serial.println("<help> - This help");
      Serial.println("<addwifi:SSID;PASSWORD> - Add Wifi AP. Device will connect to the more powerfull AP available. If the AP was defined, it's password is rewritten.");
      Serial.println("<removewifi:SSID> - Removes wifi AP if found in config file.");
      Serial.println("<wifilist> - Prints list of all APs device have defined.");
      if(!Settings::noFTP) {
        Serial.println("<setftp:USERNAME;PASSWORD> - Set username and password for FTP. Only one user can be defined. Set will overwrite previous setting.");
      }
      Serial.println("--------");
      Serial.println();
    }
  }
  
  int state = 0;
  String command = "";
  String value = "";
  
  void readCommandFromSerial() {
    if (Serial.available() > 0) {
      while (Serial.available() > 0) {
        char c = Serial.read();  //gets one byte from serial buffer
        switch (state) {
          case 0:
            if (c == '<') {
              state = 1;
            }
            break;
          case 1:
            if (c == ':' || c == '>' || c == 10) {
              if (c == '>' || c == 10) {
                handleSerialCommand(command, value);
                state = 0;
              } else {
                state = 2;
              }
            } else {
              command += c;
            }
            break;
          case 2:
            if (c == '>' || c == 10) {
              state = 0;
              handleSerialCommand(command, value);
            } else {
              value += c;
            }
            break;
        }
  
        if (state == 0) {
          command = "";
          value = "";
        }
      }
    }
  }
  
  void reconnect() {
    Serial.println("");
    Serial.println("- Connecting -");
  
    int i = 0;
    while (wifiMulti.run() != WL_CONNECTED) {
      if (i == 40) {
        Serial.println();
        i = 0;
      }
      i++;
  
      Serial.print(".");
      delay(500);
  
      // Handle Serial commands
      readCommandFromSerial();
    }
  
    Serial.println("");
    Serial.println("");
    Serial.println("- WiFi connected -");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.print("SSID: ");
    Serial.println(WiFi.SSID());
    Serial.println("");
  
    delay(100);
  }
  
  char* string2char(String command){
      if(command.length()!=0){
          char *p = const_cast<char*>(command.c_str());
          return p;
      }
  }
  
  void addAPs() {
    Serial.println("- Add Wifi APs from config -");
    
    int count = 0;
    Tools::fileCreate(Settings::wifiConfig);
    File f = SPIFFS.open(Settings::wifiConfig, "r");
    if (f) {
      while (f.available()) {
        count++;
        String line = f.readStringUntil('\n');
        const char * ssid;
        const char * password;
        String str_ssid = Tools::getNthPart(line, 0);
        String str_password = Tools::getNthPart(line, 1);
  
        ssid = str_ssid.c_str();
        password = str_password.c_str();
  
        Serial.print("SSID: ");
        Serial.println(ssid);
        
        wifiMulti.addAP(ssid, password);
      }
  
      if(count == 0) {
        Serial.println("! Config empty. No APs used. !");
        Serial.println("Add AP to connect to and reboot the device.");
        Serial.println("Use command: <addwifi:SSID;PASSWORD>");
      }

      f.close();
    } else {
      Serial.println("! Cannot read config file !");
    }
  
    Serial.println();
  }
  
  void setupStart() {
    // Init serial
    Serial.begin(115200);
    delay(10);
    Serial.println();
    Serial.println();
    Serial.println("-------------------------------");
    Serial.println("-- Initialize basic services --");
    Serial.println("-------------------------------");
    Serial.println();
  
    if (SPIFFS.begin()) {
      Serial.println("- Filesystem ready -");
    }
  
    addAPs();
    reconnect();
  
    // Init HTTP server
    if(!Settings::noDefault404 && !Settings::noHTTP) server.onNotFound(defaultHandleNotFound);
  }
  
  void setupEnd() {
    if(!Settings::noHTTP) {
      server.begin();
      Serial.println("- HTTP server started -");
    }
    // Init FTP server
    if(!Settings::noFTP) {
      String ftpCredentials = Tools::readFirstLine(Settings::ftpConfig);
      ftpSrv.begin(Tools::getNthPart(ftpCredentials, 0), Tools::getNthPart(ftpCredentials, 1));
      Serial.println("- FTP server started -");
    }
  
    Serial.println();
    Serial.println("---------------------------------");
    Serial.println("---- Initialization finished ----");
    Serial.println("---------------------------------");
    Serial.println();
  }
  
  void loop() {
    // Handle Serial commands
    readCommandFromSerial();
    // Handle FTP server
    if(!Settings::noFTP) {
      ftpSrv.handleFTP();
    }
    // Handle webserver
    server.handleClient();
    // Hancle Wifi connection
    if (wifiMulti.run() != WL_CONNECTED) {
      Serial.println("WiFi disconnected!");
      reconnect();
    }
  }
}




comments powered by Disqus