Juli 65a391940b insecam desk widget for the LilyGO T-Embed
ESP-IDF 5.5 + LVGL 9 firmware that plays random public cameras from
insecam.org on the T-Embed's 320x170 screen, live MJPEG where available,
a new camera every 20 seconds. Knob steps through cameras, LED ring shows
the countdown. Auto-detects the original vs CC1101 board, reuses Wi-Fi
credentials from NVS and falls back to a captive-portal setup hotspot.
2026-09-17 00:38:09 +02:00

insecam desk widget (LilyGO T-Embed)

A little window onto the world's public webcams. The T-Embed's 320×170 IPS screen shows a random camera from insecam.org — as live MJPEG video where the camera streams it — and moves on to the next one every 20 seconds. The knob steps through cameras, the LED ring drains as the countdown runs. Everything happens on the ESP32-S3; no bridge or PC needed.

insecam lists cameras that are reachable on the public internet without any password. The widget only ever does what a browser on that site does: fetch a listing page, then fetch the camera's own snapshot/stream URL.

Hardware

Either LilyGO T-Embed. The firmware tells them apart at boot by probing the I2C bus (ES7210 on the 2022 board, BQ27220/BQ25896/PN532 on the CC1101 board) and picks the matching pin map from main/board.c. Nothing beyond the board is needed: ESP32-S3R8, 16 MB flash, 8 MB PSRAM, ST7789 170×320, EC11 encoder, APA102 (×7) or WS2812 (×8) ring.

Build and flash

Needs ESP-IDF 5.5 (on this machine: . ~/esp/idf55-env.sh).

idf.py set-target esp32s3
idf.py build
idf.py -p /dev/ttyACM0 flash monitor

The partition table keeps nvs where the ESPHome build that shipped on this unit had it (0xf90000), so stored Wi-Fi credentials survive re-flashing. Options (interval, listing, brightness, forced variant) live under idf.py menuconfig → insecam desk widget.

First boot / Wi-Fi

With no saved network the widget opens the open hotspot insecam-setup; join it with a phone and the captive portal (or http://192.168.4.1) asks for your Wi-Fi. Holding the knob down while the widget starts forces the portal.

Controls

input action
turn clockwise next camera
turn counter-clockwise previous camera (history of 24)
click pause / resume the countdown (the live stream keeps playing)
double-click or hold hide / show the caption

How it works

  • insecam.c fetches one listing page (/en/byrating/ or /en/bynew/, random page) — six cameras per request, so insecam sees one hit every two minutes.
  • httpstream.c is a small raw-socket HTTP client: esp_http_client gives up on bodies without Content-Length, which is exactly what MJPEG cameras send.
  • jpegframe.c pulls complete JPEG files out of the byte stream by walking the marker structure (so an EXIF thumbnail's EOI can't truncate a frame).
  • jpegdec.c decodes with esp_jpeg at the largest power-of-two reduction that still covers the screen, then bilinear-resamples to a full-bleed 320×170.
  • slideshow.c runs the state machine: connect, play frames until the interval elapses or the knob moves, skip dead cameras, keep history for "previous".
  • ui.c is LVGL 9 via esp_lvgl_port: a canvas for the frame, a translucent caption bar, a LIVE/PAUSED badge and a hairline progress bar.
S
Description
an esp slideshow viewer for insecam and opentopia
Readme MIT
380 KiB
0 Stars 1 Watchers 0 Forks
Languages
C 99.6%
CMake 0.4%