ESP8266 SmartClock with GeekMagic API compatibility. Works with: https://github.com/adrienbrault/geekmagic-hacs
This firmware is made for the GeekMagic SmallTV Smart Weather Clock as can be found in online stores.
The Smalltv and Smalltv-Ultra are based on an ESP8266, while the Smalltv-Pro uses an ESP32 with more memory and processing power. This code has only been tested on the Smalltv Ultra (ESP8266) and may require modifications for other variants.
Users have reported the first install does not work via OTA, coming from another firmware like the stock firmware or ESPHome. Please erase the device completely and install via UART, e.g. with ESPHome Flasher. See FLASHING.md for a detailed step-by-step guide.
Updating images frequently will wear out flash fast. Think about your update settings. The reserved space for the filesystem is 1MB.
- ✅ Web-based User Interface (UI) for settings and control
- ✅ ST7789V 240x240 display
- ✅ WiFi configuration via captive portal
- ✅ mDNS discovery (smartclock.local)
- ✅ ArduinoOTA updates
- ✅ Web-based OTA updates (/update)
- ✅ LittleFS filesystem
- ✅ Persistent settings (Brightness, Timezone Offset)
- ✅ NTP time synchronization with configurable GMT offset
- ✅ Live update API
- ✅ Simplified clock display (time and date only)
- ✅ Temporary image upload and rendering (images cleared on boot)
The firmware implements a three-layer validation system to prevent corruption from affecting operations:
- Magic Number Check (
0xCAFE): Quick validation that settings exist - Firmware Version Check: Ensures settings structure matches current firmware version
- CRC32 Checksum: Validates data integrity of all settings
When any validation fails, the system automatically:
- Logs the specific failure reason
- Resets settings to factory defaults
- Saves validated defaults back to EEPROM
- Continues boot with safe defaults
The firmware tracks consecutive boot failures to detect crash loops:
- Boot Counter: Incremented at start of each boot attempt
- Reset on Success: Counter cleared when boot completes successfully
- Failsafe Threshold: After 5 consecutive failed boots, triggers emergency recovery
- Emergency Recovery: Performs complete EEPROM reset and restarts device
This prevents infinite crash loops after problematic OTA updates.
The firmware provides a manual factory reset mechanism that users can trigger without needing the web interface or serial console:
How it works:
- Power cycle the device 5 times in quick succession (within ~10 seconds total)
- On the 5th boot, the device automatically performs a complete factory reset
- All settings, WiFi credentials, and filesystem data are erased
- Device restarts in AP mode ready for initial setup
Reset Process:
- Power Cycle Counter: Tracked in EEPROM, increments on each boot
- Timeout Window: Counter resets to 0 after 10 seconds of successful uptime
- Factory Reset Trigger: When counter reaches 5, performs full factory reset
- Reset Actions: Erases WiFi config, resets EEPROM settings, formats filesystem, restarts device
When to use this:
- Device is stuck in a boot loop and web interface is inaccessible
- Forgot WiFi credentials and can't access AP mode
- Need to completely reset device to factory defaults
- Preparing device for a new owner or network
Usage Example:
- Unplug device from power
- Wait 2 seconds
- Plug in device, wait for it to start booting (3-5 seconds)
- Unplug device again
- Repeat steps 2-4 until you've done this 5 times total
- On the 5th boot, device will display "Factory Reset" message and restart in AP mode
Serial Console Output:
========================================
USER RESET: 5 quick power cycles detected!
Performing factory reset...
========================================
Factory reset complete. System will restart in 5 seconds...
Enhanced WiFi connection handling with multiple fallback levels:
- Attempt 1: Immediate connection try (30s timeout)
- Attempt 2: Retry after 2 seconds
- Attempt 3: Retry after 4 seconds
- Attempt 4: Retry after 8 seconds
- Attempt 5: Retry after 16 seconds
If all connection attempts fail:
- Starts WiFiManager captive portal (3 minute timeout)
- If user doesn't configure: enters Failsafe AP Mode
When in failsafe mode:
- Device runs as Access Point (SSID:
SmartClock-Setup) - AP credentials displayed on device screen (SSID, password, and IP address)
- Random password generated for security (8-digit numeric)
- Web interface remains accessible via AP IP (typically 192.168.4.1)
- Retries WiFi connection every 5 minutes automatically
- If connection succeeds: restarts to restore full functionality
- mDNS and OTA temporarily disabled to conserve resources
During normal operation:
- Checks connection status every 60 seconds
- If connection lost: 3 quick reconnection attempts
- If reconnection fails: switches to Failsafe AP Mode
Key settings in src/config.h and src/settings.cpp:
#define WIFI_RETRY_ATTEMPTS 5 // Initial connection attempts
#define WIFI_RETRY_DELAY_MS 2000 // Base delay for exponential backoff
#define WIFI_CONNECTION_TIMEOUT 30000 // 30s timeout per attempt
#define WIFI_MONITOR_INTERVAL 60000 // Check WiFi every 60s
#define WIFI_RECONNECT_INTERVAL 300000 // Retry in AP mode every 5min
#define BOOT_FAILURE_THRESHOLD 5 // Emergency reset after 5 failures
#define POWER_CYCLE_THRESHOLD 5 // Factory reset after 5 quick power cycles
#define FIRMWARE_VERSION 2 // Increment when Settings struct changes- Always test new firmware on a development device first
- Increment
FIRMWARE_VERSIONwhen changing theSettingsstruct - Monitor serial output during first boot after OTA update
- Keep credentials to your WiFi network accessible
- Document any EEPROM layout changes in release notes
| Scenario | Automatic Recovery | Manual Recovery |
|---|---|---|
| Corrupted EEPROM data | ✅ Automatic reset to defaults | Not needed |
| Invalid firmware version | ✅ Automatic reset to defaults | Not needed |
| WiFi network unavailable | ✅ Fallback to AP mode, periodic retry | Connect to AP and reconfigure |
| 5+ consecutive boot failures | ✅ Emergency EEPROM reset + restart | Not needed |
| Need factory reset | ❌ Not automatic | ✅ 5 quick power cycles |
| Forgot WiFi credentials | ✅ Fallback to AP mode | ✅ 5 quick power cycles or connect to AP |
| Complete crash/brick | ❌ Not possible | Flash via USB/UART |
- ESP8266 NodeMCU v2
- ST7789V 240x240 TFT display
- Pins:
- MOSI: GPIO13
- SCLK: GPIO14
- DC: GPIO0
- RST: GPIO2
- Backlight: GPIO5 (PWM)
cd smartclock-arduino
pio run -t upload
pio device monitor- Device starts in AP mode "SmartClock-Setup"
- Look at the device display to see the randomly generated AP password
- Alternatively, connect via serial console (115200 baud) to see the password
- Connect to the "SmartClock-Setup" WiFi network using the displayed password
- Captive portal opens automatically
- Configure WiFi credentials
- Device reboots and connects to the network
- The device display will now show the IP address at the top of the clock screen
Access the comprehensive web-based control panel by navigating to http://smartclock.local/ (or your device's IP address) in a web browser.
Main Sections:
- Status & Info: View device status, storage information, current brightness, and system logs.
- Settings:
- Brightness: Adjust display brightness from 0% to 100%.
- Timezone: Configure the GMT offset (in seconds). Note: Daylight Saving Time (DST) must be manually accounted for by adjusting this offset when changes occur.
- Reconfigure WiFi: Trigger the WiFiManager captive portal to reconnect to a new network or update credentials.
- Image Upload:
- Upload JPEG: Upload new JPEG images directly to the device. These images are temporary and will be cleared on the next reboot.
- Display Image Path: Manually specify a path to an uploaded image to display it.
- Advanced:
- Factory Reset: Erase all saved settings (including WiFi credentials and timezone) and format the LittleFS filesystem, then restart the device. Use with caution.
# Upload image (temporary, cleared on reboot)
curl -F "file=@image.jpg" http://smartclock.local/doUpload?dir=/image/
# Show image (e.g., after upload, will be cleared on reboot)
curl http://smartclock.local/set?img=/image/image.jpg
# Set brightness (0-100)
curl http://smartclock.local/set?brt=50
# Set GMT Offset (e.g., for +1 hour)
curl http://smartclock.local/set?gmt=3600
# Live update (JSON - e.g., for custom text lines)
curl -X POST http://smartclock.local/api/update \
-H "Content-Type: application/json" \
-d '{"line1":"Custom","line2":"Text","bar":0.7}'
# Device status
curl http://smartclock.local/app.json- Tools → Port → smartclock (network)
- Upload firmware
- Open
http://smartclock.local/update(or your device's IP) - Select
firmware.bin - Upload
Device advertises as:
- Hostname:
smartclock.local - HTTP service on port 80
- Metadata: model=SmartClock, api=geekmagic
Stored in EEPROM:
- Brightness level
- GMT Offset (in seconds)
- Last displayed image (temporary, cleared on boot)
- Time Display: Large, centered time (HH:MM) from NTP synchronization
- Date Display: Below time, shows DD-MM-YYYY format
- IP Address: Small text at top of screen showing current IP address (allows easy access without serial monitor)
- Auto-Updates: Display refreshes every 5 seconds
When the device is in AP/failsafe mode, the display automatically shows:
- "AP Mode Active" message
- SSID: The access point name (SmartClock-Setup)
- Password: The randomly generated 8-digit password
- IP Address: The AP IP address (typically 192.168.4.1) shown at top
This ensures you can always see the connection credentials on the device screen without needing serial access.
- JPEG rendering (240x240)
- Images are uploaded via
/doUploadand are temporary (cleared on reboot)
For enhanced security, the device generates a unique random 8-digit numeric password on each boot when AP mode is activated. This prevents unauthorized access to your device's configuration portal.
Password Characteristics:
- Length: 8 digits
- Character set: 0-9 (numbers only)
- Generated using hardware random number generator (ESP.getCycleCount() ^ micros() ^ ESP.getChipId())
- Displayed on device screen in AP mode
- Logged to serial console at boot
How to find your AP password:
- On the device display: When in AP mode, the password is shown on screen
- Via serial console: Connect to serial port (115200 baud) and look for "Generated AP Password: ..."
- After first boot: The password persists for the session but changes after reboot
- Check pin connections
- Verify TFT_eSPI build flags in platformio.ini
- Check the device display for the current AP password (randomly generated)
- Use the "Reconfigure WiFi" option in the Web Control Panel
- Check WiFi credentials
- If in AP mode, the SSID, password, and IP address are shown on the display
- Look at the device display: The IP address is shown at the top of the clock screen in small text
- Alternatively, use mDNS:
smartclock.local - Check your router's DHCP client list
- Verify device on network:
ping smartclock.local - Check firewall settings.
- Ensure the image is a valid JPEG (240x240 resolution, relatively small file size < 100KB).
- Use the "Factory Reset" option in the Web Control Panel, then re-upload firmware and image.
- Check serial monitor for error messages during upload or display.
- Ensure the device is connected to WiFi.
- Check the GMT Offset setting in the Web Control Panel.
- Quick Solution: Power cycle the device 5 times in quick succession (within ~10 seconds total)
- On the 5th boot, the device will automatically perform a complete factory reset
- This will erase all settings, WiFi credentials, and filesystem data
- Device will restart in AP mode ready for initial setup
- See "User-Initiated Factory Reset (Power Cycle Method)" section for detailed instructions
# Build
pio run
# Upload via serial
pio run -t upload
# Monitor serial
pio device monitor
# Clean
pio run -t clean
# Upload filesystem
pio run -t uploadfs| Endpoint | Method | Parameters | Description |
|---|---|---|---|
/ |
GET | - | Web-based User Interface (new) |
/app.json |
GET | - | Device status JSON (now includes gmtOffset) |
/space.json |
GET | - | Storage info JSON |
/brt.json |
GET | - | Brightness info JSON |
/set |
GET | brt=<0-100>, gmt=<seconds>, img=<path> |
Control brightness, GMT offset, display image |
/doUpload |
POST | dir=<path>, file (multipart) |
Upload file to LittleFS (/image/ recommended) |
/delete |
GET | file=<path> |
Delete a file from LittleFS |
/log |
GET | - | View system logs |
/reconfigurewifi |
GET | - | Trigger WiFi configuration portal (new) |
/factoryreset |
GET | - | Perform a factory reset (new) |
/api/update |
POST | JSON body | Live update display content (lines, bar) |
/update |
GET | - | OTA HTML form |
/update |
POST | firmware file | OTA firmware upload |
- WiFi AP SSID: SmartClock-Setup
- WiFi AP Password: Random 8-digit numeric (see device display or serial console)
- OTA Password: admin
- mDNS Hostname: smartclock.local
Note: The AP password is randomly generated on each boot for security. Always check the device display when connecting in AP mode.
MIT