Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

8 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

ESP8266 OLED REST Display

This project contains:

  • ESP8266 firmware in modern C++20 using the Arduino framework
  • a small HTTP API for text and raw framebuffer updates
  • a local Python helper client for text, image, and Pillow-based rendering workflows

The target device is an ESP8266 with a 128x64 SSD1306 OLED over I2C.

Overview

The firmware exposes a simple REST API on port 80.

  • Text mode: send lines or plain text to the display
  • Title mode: large centered title with optional scrolling
  • Frame mode: upload a full 1024-byte monochrome framebuffer
  • Status mode: query Wi-Fi state, display mode, and current text lines

The current implementation is intentionally conservative about memory use:

  • fixed-size request and response buffers
  • fixed-size JSON document for /api/display
  • no repeated app-level heap allocation in normal request handling
  • one expected display-buffer allocation at OLED driver startup

Repository Layout

  • src/, include/: ESP8266 firmware
  • platformio.ini: PlatformIO build configuration
  • scripts/load_wifi_secrets.py: injects Wi-Fi credentials into the firmware build
  • oled_client.py: local helper CLI for API access and image/text rendering
  • PSK.txt: optional local Wi-Fi password file used at build time

Hardware Assumptions

The default firmware configuration is in include/app_config.h:

  • OLED width: 128
  • OLED height: 64
  • OLED I2C address: 0x3C
  • SDA pin: 12
  • SCL pin: 14
  • HTTP port: 80

The default PlatformIO board is esp12e in platformio.ini.

Prerequisites

  • Python 3
  • PlatformIO installed in your environment or project venv
  • USB serial access to the ESP8266 board
  • local Wi-Fi credentials for the target network

For the Python helper client:

  • Pillow
  • fonts available to Pillow/fontconfig if you use the render command

Wi-Fi Configuration

Wi-Fi credentials are injected at build time by scripts/load_wifi_secrets.py.

The script uses:

  1. OLED_WIFI_SSID environment variable, defaulting to astro
  2. OLED_WIFI_PSK environment variable
  3. PSK.txt in the project root if OLED_WIFI_PSK is not set

Both SSID and PSK are compiled into the firmware at build time via preprocessor defines.

Examples:

export OLED_WIFI_SSID="my-wifi"
export OLED_WIFI_PSK="my-password"
./.venv/bin/pio run

Or with a local password file:

printf '%s\n' 'my-password' > PSK.txt
./.venv/bin/pio run

If no password is found, the firmware falls back to change-me.

Build

Build the firmware with:

./.venv/bin/pio run

The compiled firmware is written to:

.pio/build/esp8266/firmware.bin

Flashing

The current default serial port in platformio.ini is /dev/ttyUSB1.

Flash with:

./.venv/bin/pio run -t upload

Or override the port explicitly:

./.venv/bin/pio run -t upload --upload-port /dev/ttyUSB1

Serial Monitor

Open the serial monitor with:

./.venv/bin/pio device monitor

Or:

./.venv/bin/pio device monitor --port /dev/ttyUSB1 --baud 115200

On successful boot, the firmware will attempt Wi-Fi connection and then print the HTTP listener address.

Python Helper Client

The local helper app is oled_client.py.

Global options:

python3 oled_client.py --host 192.168.1.124 --port 80 --timeout 5 status

Available commands:

  • status
  • clear
  • demo
  • api-help
  • display
  • frame
  • render
  • checkerboard

Basic Examples

Show current status:

python3 oled_client.py status

Display small text lines:

python3 oled_client.py display --mode small "Hello" "from ESP8266"

Display a scrolling title:

python3 oled_client.py display --mode title --scroll fast "Very Long Title"

Send plain text from stdin:

printf 'stdin text example\n' | python3 oled_client.py display --stdin

Upload an image as a framebuffer:

python3 oled_client.py frame ./image.png --fit contain --dither floyd

Render UTF-8 text locally with Pillow, then upload the result:

python3 oled_client.py render --preserve-header "Hello" "๐Ÿ™‚"

Restore the firmware demo screen:

python3 oled_client.py demo

HTTP API

The board listens on:

http://<board-ip>:80

GET /

Returns plain-text API help.

Example:

curl http://192.168.1.124/

GET /api/status

Returns JSON status.

Example:

curl http://192.168.1.124/api/status

Typical response:

{
  "ssid": "<configured-ssid>",
  "ip": "192.168.1.124",
  "mode": "small",
  "scroll": false,
  "header": ["wifi <ssid>", "192.168.1.124"],
  "lines": ["Display ready", "Send text via", "POST /api/", "display", "", "curl works well"],
  "uptime_s": 123
}

POST /api/display

Accepts either:

  • application/json
  • text/plain

JSON mode

Supported JSON fields:

  • mode: small, large, double, title, frame
  • text: string
  • lines: array of strings
  • scroll: true, false, or one of slow, normal, fast
  • scroll_speed: one of slow, normal, fast

Notes:

  • If lines is present, it is used instead of text
  • frame is not meaningful for /api/display; it is normalized back to text mode
  • title plus scroll enables the title-scrolling behavior

Example:

curl -X POST http://192.168.1.124/api/display \
  -H 'Content-Type: application/json' \
  -d '{"mode":"title","text":"Hello world","scroll":"normal"}'

Multi-line example:

curl -X POST http://192.168.1.124/api/display \
  -H 'Content-Type: application/json' \
  -d '{"mode":"small","lines":["line 1","line 2","line 3"]}'

Plain-text mode

Plain text is accepted as text/plain and displayed in small mode.

Example:

curl -X POST http://192.168.1.124/api/display \
  -H 'Content-Type: text/plain' \
  --data-binary 'plain text body'

POST /api/frame

Accepts a raw 1024-byte monochrome framebuffer.

  • preferred content type: application/octet-stream
  • text/plain is also accepted
  • payload must be exactly 1024 bytes

Example:

curl -X POST http://192.168.1.124/api/frame \
  -H 'Content-Type: application/octet-stream' \
  --data-binary @frame.bin

Framebuffer layout matches the SSD1306 page layout used by the firmware:

  • 128 columns
  • 64 rows
  • 8 pages of 128 bytes each
  • total 1024 bytes

POST /api/clear

Clears the main display area and returns:

ok

Example:

curl -X POST http://192.168.1.124/api/clear

POST /api/demo

Restores the built-in demo text and returns:

ok

Example:

curl -X POST http://192.168.1.124/api/demo

Display Modes

Supported display modes are implemented in include/display_ui.h.

  • small: up to 6 small text lines
  • large: up to 3 larger lines
  • double: up to 2 centered larger lines
  • title: single large title, optionally scrolling
  • frame: raw framebuffer mode

The OLED header area is always two small lines at the top, separated from the main content area by a horizontal line.

Request Size Limits

Important firmware limits from include/app_config.h:

  • max total request bytes: 1600
  • max header bytes: 512
  • max body bytes: 1088
  • max plain text characters: 192
  • raw frame size: 1024

Requests larger than these limits are rejected with HTTP 400.

Failure Modes and Notes

  • The firmware handles one client at a time. Under heavy concurrent request bursts, some requests may time out on the client side.
  • Normal single-client and low-concurrency usage is stable.
  • The SSD1306 library allocates its framebuffer once at startup.
  • The app code avoids repeated heap churn during normal request handling.
  • If the display shows a broken pattern after frame testing, switch back to text mode with:
python3 oled_client.py clear
python3 oled_client.py display --mode small "OLED OK"

Development Notes

  • C++ standard: gnu++2a
  • Framework: Arduino for ESP8266
  • Board target: esp12e
  • Main entry point: src/main.cpp

Quick Start

  1. Set Wi-Fi credentials via environment variables or PSK.txt.
  2. Build with ./.venv/bin/pio run.
  3. Flash with ./.venv/bin/pio run -t upload.
  4. Open serial monitor to find the board IP.
  5. Query python3 oled_client.py status.
  6. Send text with python3 oled_client.py display --mode small "hello".

About

ESP8266 with rest api for displaying content on a small OLED screen.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages