Skip to content

Commit

Permalink
Graph example (#7299)
Browse files Browse the repository at this point in the history
* New Graph Example

* Now using isFlashInterfacePin() no define default GPIO mask.

* Added info about zooming.

* Adressed requested changes (boolean > bool,
using esp8266::polledTimeout::periodicMs, reducing complexity)
  • Loading branch information
vdeconinck committed Jun 3, 2020
1 parent 8ee67ab commit c3796a4
Show file tree
Hide file tree
Showing 3 changed files with 907 additions and 0 deletions.
332 changes: 332 additions & 0 deletions libraries/ESP8266WebServer/examples/Graph/Graph.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
/*
Graph - A web-based Graph display of ESP8266 data
This file is part of the ESP8266WebServer library for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
See readme.md for more information.
*/

////////////////////////////////

// Select the FileSystem by uncommenting one of the lines below

//#define USE_SPIFFS
#define USE_LITTLEFS
//#define USE_SDFS

////////////////////////////////

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <SPI.h>

#if defined USE_SPIFFS
#include <FS.h>
FS* fileSystem = &SPIFFS;
SPIFFSConfig fileSystemConfig = SPIFFSConfig();
#elif defined USE_LITTLEFS
#include <LittleFS.h>
FS* fileSystem = &LittleFS;
LittleFSConfig fileSystemConfig = LittleFSConfig();
#elif defined USE_SDFS
#include <SDFS.h>
FS* fileSystem = &SDFS;
SDFSConfig fileSystemConfig = SDFSConfig();
// fileSystemConfig.setCSPin(chipSelectPin);
#else
#error Please select a filesystem first by uncommenting one of the "#define USE_xxx" lines at the beginning of the sketch.
#endif


#define DBG_OUTPUT_PORT Serial

#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif

// Indicate which digital I/Os should be displayed on the chart.
// From GPIO16 to GPIO0, a '1' means the corresponding GPIO will be shown
// e.g. 0b11111000000111111
unsigned int gpioMask;

const char* ssid = STASSID;
const char* password = STAPSK;
const char* host = "graph";

ESP8266WebServer server(80);

static const char TEXT_PLAIN[] PROGMEM = "text/plain";
static const char FS_INIT_ERROR[] PROGMEM = "FS INIT ERROR";
static const char FILE_NOT_FOUND[] PROGMEM = "FileNotFound";

////////////////////////////////
// Utils to return HTTP codes

void replyOK() {
server.send(200, FPSTR(TEXT_PLAIN), "");
}

void replyOKWithMsg(String msg) {
server.send(200, FPSTR(TEXT_PLAIN), msg);
}

void replyNotFound(String msg) {
server.send(404, FPSTR(TEXT_PLAIN), msg);
}

void replyBadRequest(String msg) {
DBG_OUTPUT_PORT.println(msg);
server.send(400, FPSTR(TEXT_PLAIN), msg + "\r\n");
}

void replyServerError(String msg) {
DBG_OUTPUT_PORT.println(msg);
server.send(500, FPSTR(TEXT_PLAIN), msg + "\r\n");
}

////////////////////////////////
// Request handlers

/*
Read the given file from the filesystem and stream it back to the client
*/
bool handleFileRead(String path) {
DBG_OUTPUT_PORT.println(String("handleFileRead: ") + path);

if (path.endsWith("/")) {
path += "index.htm";
}

String contentType = mime::getContentType(path);

if (!fileSystem->exists(path)) {
// File not found, try gzip version
path = path + ".gz";
}
if (fileSystem->exists(path)) {
File file = fileSystem->open(path, "r");
if (server.streamFile(file, contentType) != file.size()) {
DBG_OUTPUT_PORT.println("Sent less data than expected!");
}
file.close();
return true;
}

return false;
}


/*
The "Not Found" handler catches all URI not explicitely declared in code
First try to find and return the requested file from the filesystem,
and if it fails, return a 404 page with debug information
*/
void handleNotFound() {
String uri = ESP8266WebServer::urlDecode(server.uri()); // required to read paths with blanks

if (handleFileRead(uri)) {
return;
}

// Dump debug data
String message;
message.reserve(100);
message = F("Error: File not found\n\nURI: ");
message += uri;
message += F("\nMethod: ");
message += (server.method() == HTTP_GET) ? "GET" : "POST";
message += F("\nArguments: ");
message += server.args();
message += '\n';
for (uint8_t i = 0; i < server.args(); i++) {
message += F(" NAME:");
message += server.argName(i);
message += F("\n VALUE:");
message += server.arg(i);
message += '\n';
}
message += "path=";
message += server.arg("path");
message += '\n';
DBG_OUTPUT_PORT.print(message);

return replyNotFound(message);
}

void setup(void) {
////////////////////////////////
// SERIAL INIT
DBG_OUTPUT_PORT.begin(115200);
DBG_OUTPUT_PORT.setDebugOutput(true);
DBG_OUTPUT_PORT.print('\n');

////////////////////////////////
// FILESYSTEM INIT

fileSystemConfig.setAutoFormat(false);
fileSystem->setConfig(fileSystemConfig);
bool fsOK = fileSystem->begin();
DBG_OUTPUT_PORT.println(fsOK ? F("Filesystem initialized.") : F("Filesystem init failed!"));

////////////////////////////////
// PIN INIT
pinMode(4, INPUT);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
pinMode(15, OUTPUT);

////////////////////////////////
// WI-FI INIT
DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
DBG_OUTPUT_PORT.print(".");
}
DBG_OUTPUT_PORT.println("");
DBG_OUTPUT_PORT.print(F("Connected! IP address: "));
DBG_OUTPUT_PORT.println(WiFi.localIP());

////////////////////////////////
// MDNS INIT
if (MDNS.begin(host)) {
MDNS.addService("http", "tcp", 80);
DBG_OUTPUT_PORT.print(F("Open http://"));
DBG_OUTPUT_PORT.print(host);
DBG_OUTPUT_PORT.println(F(".local to open the graph page"));
}

////////////////////////////////
// WEB SERVER INIT

//get heap status, analog input value and all GPIO statuses in one json call
server.on("/espData", HTTP_GET, []() {
String json;
json.reserve(88);
json = "{\"time\":";
json += millis();
json += ", \"heap\":";
json += ESP.getFreeHeap();
json += ", \"analog\":";
json += analogRead(A0);
json += ", \"gpioMask\":";
json += gpioMask;
json += ", \"gpioData\":";
json += (uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16));
json += "}";
server.send(200, "text/json", json);
});

// Default handler for all URIs not defined above
// Use it to read files from filesystem
server.onNotFound(handleNotFound);


// Start server
server.begin();
DBG_OUTPUT_PORT.println("HTTP server started");

DBG_OUTPUT_PORT.println("Please pull GPIO4 low (e.g. press button) to switch output mode:");
DBG_OUTPUT_PORT.println(" 0 (OFF): outputs are off and hidden from chart");
DBG_OUTPUT_PORT.println(" 1 (AUTO): outputs are rotated automatically every second");
DBG_OUTPUT_PORT.println(" 2 (MANUAL): outputs can be toggled from the web page");

}

// Return default GPIO mask, that is all I/Os except SD card ones
unsigned int defaultMask() {
unsigned int mask = 0b11111111111111111;
for (auto pin = 0; pin <= 16; pin++) {
if (isFlashInterfacePin(pin)) {
mask &= ~(1 << pin);
}
}
return mask;
}

int rgbMode = 1; // 0=off - 1=auto - 2=manual
int rgbValue = 0;
esp8266::polledTimeout::periodicMs timeToChange(1000);
bool modeChangeRequested = false;

void loop(void) {
server.handleClient();
MDNS.update();

if (digitalRead(4) == 0) {
// button pressed
modeChangeRequested = true;
}

// see if one second has passed since last change, otherwise stop here
if (!timeToChange) {
return;
}

// see if a mode change was requested
if (modeChangeRequested) {
// increment mode (reset after 2)
rgbMode++;
if (rgbMode > 2) {
rgbMode = 0;
}

modeChangeRequested = false;
}

// act according to mode
switch (rgbMode) {
case 0: // off
gpioMask = defaultMask();
gpioMask &= ~(1 << 12); // Hide GPIO 12
gpioMask &= ~(1 << 13); // Hide GPIO 13
gpioMask &= ~(1 << 15); // Hide GPIO 15

// reset outputs
digitalWrite(12, 0);
digitalWrite(13, 0);
digitalWrite(15, 0);
break;

case 1: // auto
gpioMask = defaultMask();

// increment value (reset after 7)
rgbValue++;
if (rgbValue > 7) {
rgbValue = 0;
}

// output new values
digitalWrite(12, rgbValue & 0b001);
digitalWrite(13, rgbValue & 0b010);
digitalWrite(15, rgbValue & 0b100);
break;

case 2: // manual
gpioMask = defaultMask();

// keep outputs unchanged
break;
}
}

Loading

0 comments on commit c3796a4

Please sign in to comment.