Skip to content

KirinDenis/ViewOwl_ESP32

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🦉 ViewOwl

Turn any API data source into a live ESP32 display — without writing firmware

Platform Server License

Part of the OWLOS open-source IoT family (ESP32 / ESP8266 firmware & tools) — ViewOwl is its next step, not a from-scratch experiment.

Try it live → view.owlos.sk — explore the dashboard and the template gallery right in your browser. (Public demo — beta, not for production; see the on-site notice.)


In one sentence

You write a regular HTML page that pulls data from any API. ViewOwl takes a screenshot of it and streams the image to a cheap ESP32 display over Wi-Fi. That's it.


What problem does this solve?

Without ViewOwl

Say you want to show your weather station temperature on a small screen in the hallway. Here's what you'd have to do:

  • Write C/C++ firmware for ESP32 that talks to your specific API
  • Handle JSON parsing on a microcontroller
  • Draw the UI pixel-by-pixel using a graphics library
  • Re-flash the device every time you change the design
  • Repeat all of this for each new data source or display type

This is hard, slow, and requires deep embedded development knowledge.

With ViewOwl

  1. Take any data available over HTTP/API (weather, stock prices, smart home, telemetry — anything)
  2. Build an HTML page as you normally would — with CSS, animations, whatever design you like
  3. Host it on a server (or locally)
  4. ViewOwl automatically takes screenshots and streams them to the ESP32

The ESP32 just receives the image and shows it. No custom firmware per use case.


Who is this for?

You are... ViewOwl helps you...
Building a home weather station Display a beautiful dashboard from Open-Meteo API without any ESP32 code
Monitoring servers or equipment Put Grafana / Prometheus status on a physical screen
Running a café or office Hang an info board with a menu, schedule, or announcements
Working with smart home systems Visualize Home Assistant data on a wall-mounted display
Trading crypto Show live prices on a bedside screen
A maker / hobbyist Build something cool without learning embedded GUI frameworks

Real-world examples

Weather station

API: open-meteo.com (free, no key required)
Shows: temperature, humidity, pressure, forecast
Updates: every 5 minutes automatically

Write an HTML page that does a fetch() to Open-Meteo on load — and you get a beautiful live widget. ViewOwl renders it and sends it to the screen. A ready-made template is already included in the repo.


Server monitoring

API: your Prometheus, Grafana, Zabbix, or any monitoring tool
Shows: CPU, RAM, uptime, alerts
Updates: in real time

Already have a dashboard in your browser? Just give ViewOwl its URL — and it will appear on a physical screen in your server room.


Stock & crypto prices

API: CoinGecko, Yahoo Finance, any broker API
Shows: prices, charts, daily changes
Updates: every minute

Smart home

API: Home Assistant REST API, MQTT-to-HTTP bridge
Shows: room temperatures, device states, energy usage
Updates: on state change

Info board / announcements

Source: Google Sheets, Notion API, or plain static HTML
Shows: café menu, class schedule, office announcements
Updates: you edit the spreadsheet — the screen updates itself

How it works

flowchart TD
    A["Your HTML page<br/>CSS · JavaScript · fetch() any API"]
    B["Grabber — server<br/>renders the page in a real browser,<br/>screenshots it, converts to the display's format"]
    C["UDP Server<br/>sends the frame to each device,<br/>and skips it when nothing has changed"]
    D["ESP32 + display<br/>receives the frame and draws it"]
    A --> B --> C -->|UDP / Wi-Fi| D
Loading

As a user, only the first and last parts matter:

  • You write HTML → take an ESP32 with a display → connect to the network → done.

Smarter than it sounds — not just screenshots

ViewOwl doesn't blast raw images over the air. Each frame is compressed before it's sent, and a frame that hasn't changed isn't sent at all — the device tells the server what it already has, and the server skips it. Animations are pre-rendered once on the server, stored in the device's flash, and play back locally even with no network. That's how a wall of screens stays light on a small server and an ordinary Wi-Fi connection.


Why a custom protocol — and what it taught us

ViewOwl streams full-screen frames to microcontrollers with only a few hundred kilobytes of RAM. That workload breaks the usual IoT answers:

  • MQTT is built for small pub/sub telemetry, not bulk binary frames — a broker hop, payload and buffering limits, and ESP32 MQTT clients that get flaky over multi-day uptimes.
  • WebSocket / TCP carry connection state and socket buffers the device can't spare; head-of-line blocking costs RAM a frame-pusher doesn't have.

So the transport is small and purpose-built: a stop-and-wait flow over UDP (HELLO / AUTH / DATA / ACK / DONE) with retransmit and session recovery. Stop-and-wait is the point — the device never holds more than one packet, so memory stays bounded. It's closer to "reliable file copy, one packet at a time" than to a TCP reimplementation. Devices run for weeks without watchdog reboots.

The non-obvious details are scar tissue from real failures, not preference:

  • The frame checksum must match byte-for-byte across server and firmware. One mismatched CRC variant silently disables "skip unchanged frames" and makes every device re-download its identical frame forever — a freeze every few minutes until it's found.
  • Every frame is rendered at the device's exact resolution. A 480×320 frame on a 320×240 panel crops; it doesn't scale.
  • Animated templates must be deterministic — frame N must always produce identical pixels (no Math.random() / clock), or the dedup checksum never matches and the device re-downloads endlessly.

In practice the transport is the stable part; the hard, evolving engineering is the rendering side.


Built as a platform — run lean on purpose

ViewOwl is more than a renderer for one screen. User accounts and roles already work today, alongside a real-time management dashboard, guest devices, and built-in security (rate limiting, IP auto-blocking). That's why the server does more than a lone weather clock strictly needs — it's designed to host many people's devices, not one.

We deliberately run the live instance on modest hardware. It's a standing stress test: pushing a small box on purpose surfaces limits early and keeps the system honest about what it can take. The heavier stack pays off the moment you run a fleet, let several people manage their own screens, or change content as often as you edit a web page. For a single static screen it's more than you need — but it still runs on a small VPS or single-board computer.


Quick start

What you need

Hardware:

  • ESP32 with an LCD display (ST7796 or ILI9341, 480×320 or 320×240), or a 240×240 round GC9A01 panel (integrated ESP32-C3)
  • 5V power supply
  • Wi-Fi network

Software:

  • .NET 8 SDK
  • ESP-IDF (to flash the ESP32)

Step 1 — Prepare your HTML page

Create a regular HTML page that fetches data from your API.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body {
      width: 480px; height: 320px; /* match your display resolution */
      background: #0a0a1a;
      color: #00ff88;
      font-family: monospace;
      display: flex; align-items: center; justify-content: center;
    }
    .temp { font-size: 72px; font-weight: bold; }
  </style>
</head>
<body>
  <div class="temp" id="temp">--°C</div>
  <script>
    async function update() {
      const r = await fetch('https://api.open-meteo.com/v1/forecast?latitude=50.45&longitude=30.52&current=temperature_2m');
      const d = await r.json();
      document.getElementById('temp').textContent = d.current.temperature_2m + '°C';
    }
    update();
    setInterval(update, 60000); // refresh every minute
  </script>
</body>
</html>

The page dimensions must match your display resolution. The standard is 480×320 px.


Step 2 — Start the server

# Clone the repository
git clone https://github.com/KirinDenis/ViewOwl.git
cd ViewOwl

# Start the Grabber (renders your HTML to PNG)
dotnet run --project ViewOwl.Grabber.WebAPI

# In another terminal, start the UDP Server
dotnet run --project ViewOwl.UDP.Server

UDP Server listens on port 11000 by default.


Step 3 — Configure the ESP32

Open ViewOwl.ESP32.Client/main/config.h and fill in your settings:

#define WIFI_SSID     "YourWiFi"
#define WIFI_PASS     "YourPassword"
#define SERVER_IP     "192.168.1.100"   // IP of the machine running UDP Server
#define SERVER_PORT   11000

Flash the firmware via ESP-IDF:

cd ViewOwl.ESP32.Client
idf.py build flash monitor

Step 4 — Done!

Power on the ESP32. It will connect to Wi-Fi, receive the first frame from the server, and show your HTML page on the display.


Project structure

ViewOwl/
├── ViewOwl.UDP.Server/          # UDP server — receives PNG, broadcasts frames
├── ViewOwl.UDP.Client.WPF/      # WPF client for Windows (debug / simulation)
├── ViewOwl.Grabber.WebAPI/      # Grabber — renders HTML to PNG via headless browser
├── ViewOwl.Grabber.Engine/      # Rendering engine (PuppeteerSharp / Chromium)
├── ViewOwl.ESP32.Client/        # ESP32 firmware — rectangular SPI panels (ESP-IDF, C)
├── ViewOwl.ESP32_C3.Client/     # ESP32-C3 firmware — 240×240 round GC9A01 display
├── ViewOwl.Config/              # Shared configuration
├── ViewOwl.UDP.Utils/           # UDP protocol utilities
└── ExchangeFolder/
    └── SitesTemplates/             # Ready-made HTML templates (weather, dashboards)

Ready-made templates

The ExchangeFolder/SitesTemplates/ folder includes templates you can use right away:

Template Description API
scifi_weather.html Sci-fi weather widget Open-Meteo (free)
scifi_weather_dashboard.html 3-city weather dashboard Open-Meteo (free)
scifi_weather_dashboard2.html Extended weather dashboard Open-Meteo (free)
scifi_weather_3.html Full sensor dashboard: pressure, air quality, forecast Open-Meteo (free)

All templates work without API keys and are ready to use out of the box.


Technical specs

Parameter Value
Transport protocol UDP
Pixel format BGR565 (16-bit color)
Recommended resolution 480×320 px
Supported displays ST7796, ILI9341, ILI9486 (rectangular) · GC9A01 240×240 round (ESP32-C3)
Server platform .NET 8, Linux ARM64 / x64
Client platform ESP32 (ESP-IDF)
UDP Server port 11000
Grabber API port 80

Limitations & things to know

  • JavaScript is fully supported — the page is rendered by a real browser (Chromium)
  • Page size must match the display resolution
  • Refresh rate is controlled by the server configuration
  • Network — ESP32 and server must be on the same network, or the server must be publicly accessible
  • Colors may look slightly different from a monitor due to the BGR565 color depth of TFT displays

Part of OWLOS

ViewOwl is the latest project in the OWLOS open-source IoT line, developed with its maker community — not a one-off experiment.

  • OWLOS — the parent project: open-source IoT firmware & toolset for ESP32 / ESP8266 (47 stars, 14 forks)
  • OWLOSAirQuality — air-quality monitoring built on OWLOS
  • CommunityOWLOS group on Facebook (360+ members)

ViewOwl carries those lessons forward into a server-rendered display platform.


Contributing

Templates, display drivers, bug fixes — all contributions are welcome!

  1. Fork the repository
  2. Create a branch: git checkout -b feature/my-template
  3. Commit: git commit -m 'Add: my weather template'
  4. Push: git push origin feature/my-template
  5. Open a Pull Request

License

MIT — see License.md


Made with by humans and AI · ViewOwl — your data deserves a beautiful screen

About

Turn any API data source into a live ESP32 display — without writing firmware

Topics

Resources

License

Contributing

Stars

11 stars

Watchers

0 watching

Forks

Releases

No releases published

Contributors