Skip to content

Commit

Permalink
ESP32 webserver with simple input form which input text is updated to…
Browse files Browse the repository at this point in the history
… an e-paper display
  • Loading branch information
BramNH committed Nov 15, 2024
0 parents commit f9477ec
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.pio
.vscode/*
39 changes: 39 additions & 0 deletions include/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

This directory is intended for project header files.

A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.

```src/main.c

#include "header.h"

int main (void)
{
...
}
```

Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.

In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.

Read more about using header files in official GCC documentation:

* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes

https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
28 changes: 28 additions & 0 deletions include/html.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const char html_input_page[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
<title>ESP Input Form</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head><body>
<form action="" method="GET">
<p>
Naam: <input type="text" id="name" name="name"/><br><br>
Datum: <input type="date" id="date" name="date"/> <br><br>
Reden: <input type="text" id="reason" name="reason"/><br><br>
<button type="submit">Submit</button>
</p>
</form>
<br>
</body></html>)rawliteral";

const char html_confirm_page[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<body>
<h1>Updating E-Paper display, redirecting afterwards...</h1>
<p>If you are not redirected after E-Paper update, <a href='/'>click here</a>.</p>
<script>
setTimeout(function(){ window.location.href = '/'; }, 5000);
</script>
</body>
</html>)rawliteral";


46 changes: 46 additions & 0 deletions lib/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.

The source code of each library should be placed in an own separate directory
("lib/your_library_name/[here are source files]").

For example, see a structure of the following two libraries `Foo` and `Bar`:

|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c

and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>

int main (void)
{
...
}

```

PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.

More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
16 changes: 16 additions & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
monitor_speed = 115200
lib_deps = zinggjm/GxEPD2@^1.6.0
120 changes: 120 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
#include <Arduino.h>
#include <WiFi.h>
#include <html.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>

// 2.13'' EPD Module
// GxEPD2_BW<GxEPD2_213_BN, GxEPD2_213_BN::HEIGHT> display(GxEPD2_213_BN(/*CS=5*/ 5, /*DC=*/ 0, /*RES=*/ 2, /*BUSY=*/ 15)); // DEPG0213BN 122x250, SSD1680
GxEPD2_3C<GxEPD2_213_Z98c, GxEPD2_213_Z98c::HEIGHT> display(GxEPD2_213_Z98c(/*CS=5*/ 5, /*DC=*/17, /*RES=*/16, /*BUSY=*/4)); // GDEY0213Z98 122x250, SSD1680

const char *ssid = "ESP32-Access-Point";
const char *password = "test1234";
WiFiServer server(80);

void drawNameDateReason(const char name[], const char reason[], const char date[])
{
display.setRotation(1); // set rotation to 1 (rotate right 90 degrees) to have enough space on small displays (landscape)
display.setFont(&FreeMonoBold9pt7b);
display.setTextColor(GxEPD_RED);
int16_t tbx, tby;
uint16_t tbw, tbh;

display.setFullWindow();
// here we use paged drawing, even if the processor has enough RAM for full buffer
// so this can be used with any supported processor board.
// the cost in code overhead and execution time penalty is marginal
// tell the graphics class to use paged drawing mode
display.firstPage();
do
{
// this part of code is executed multiple times, as many as needed,
// in case of full buffer it is executed once
// IMPORTANT: each iteration needs to draw the same, to avoid strange effects
// use a copy of values that might change, don't read e.g. from analog or pins in the loop!
display.fillScreen(GxEPD_WHITE);
display.setCursor(0, 20);
// display.setCursor(x, y - tbh);
display.print(name);
display.setTextColor(GxEPD_BLACK);
display.print(reason);

display.getTextBounds(date, 0, 0, &tbx, &tby, &tbw, &tbh);
display.setCursor(0, display.height() - tbh);
display.setTextColor(GxEPD_RED);
display.print(date);

// tell the graphics class to transfer the buffer content (page) to the controller buffer
// the graphics class will command the controller to refresh to the screen when the last page has been transferred
// returns true if more pages need be drawn and transferred
// returns false if the last page has been transferred and the screen refreshed for panels without fast partial update
// returns false for panels with fast partial update when the controller buffer has been written once more, to make the differential buffers equal
// (for full buffered with fast partial update the (full) buffer is just transferred again, and false returned)
} while (display.nextPage());
}

// Function to extract parameters from the GET request
String getParameterFromRequest(String request, String param)
{
String paramPattern = param + "=";
int paramStart = request.indexOf(paramPattern);
if (paramStart == -1)
{
return ""; // Parameter not found
}
paramStart += paramPattern.length();
int paramEnd = request.indexOf("&", paramStart);
if (paramEnd == -1)
{
paramEnd = request.indexOf(" ", paramStart); // Look for the end of the request line
}
String p = request.substring(paramStart, paramEnd);
p.replace('+', ' ');
return p;
}

void setup()
{
// Connect to Wi-Fi network with SSID and password
WiFi.softAP(ssid, password);
IPAddress IP = WiFi.softAPIP();
server.begin();

display.init(115200);
}

void loop()
{
WiFiClient client = server.accept(); // Listen for incoming clients
if (client)
{
// Give the client time to send the data
while (client.connected() && !client.available())
{
delay(1);
}
String request = client.readStringUntil('\r');

// Parse the GET request and extract parameters
String name = getParameterFromRequest(request, "name") + "\n";
String date = getParameterFromRequest(request, "date");
String reason = getParameterFromRequest(request, "reason");

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();

if (name.length() != 0 && date.length() != 0)
{
client.println(html_confirm_page);
drawNameDateReason(name.c_str(), reason.c_str(), date.c_str());
}
else
{
client.println(html_input_page);
client.println();
}
// Close the connection
client.stop();
}
}
11 changes: 11 additions & 0 deletions test/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

This directory is intended for PlatformIO Test Runner and project tests.

Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.

More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html

0 comments on commit f9477ec

Please sign in to comment.