Files
esp8266-weather-clock-opens…/PROJECT_CONTEXT.md
T
Alex Petrochenko 0f2860c25e Add comprehensive project context documentation
Complete context file with:
- Full development history (v1.5 → v1.9.1)
- All technical details and architecture
- Security issues and fixes
- Hardware specifications and pinout
- Current device configuration
- Next steps (Home Assistant integration)
- Key learnings from project
- Quick reference commands

This file serves as complete knowledge base for:
- Resuming work after long breaks
- Onboarding new contributors
- Understanding project evolution
- Reference for future features
2026-01-03 15:59:24 +00:00

22 KiB

ESP8266 Weather Clock - Full Project Context

Last Updated: 2026-01-03 Current Version: v1.9.1 (Production Ready) GitHub: https://github.com/petrochen/esp8266-weather-clock-opensource


Table of Contents

  1. Project Overview
  2. Hardware Details
  3. Development History
  4. Current Status (v1.9.1)
  5. Technical Architecture
  6. Security Issues Fixed
  7. Files & Structure
  8. Git Repository
  9. Next Steps
  10. Key Learnings

Project Overview

What Is This?

Complete reverse engineering and firmware replacement for an ESP8266-based weather clock purchased from AliExpress (model TJ-56-654, €5).

Why?

Original firmware had critical security vulnerabilities:

  • WiFi password displayed in plaintext
  • Persistent open access point running in parallel to home WiFi
  • Dependency on Chinese cloud service (QWeather) requiring API key registration
  • No OTA updates (required physical FTDI access for updates)

Solution: Complete custom firmware with security, performance, and features.

Key Features

  • ✅ Security: No password leaks, WiFiManager captive portal, no hardcoded credentials
  • ✅ Performance: Fully async architecture, <1ms loop time (was 10ms+)
  • ✅ Weather: Open-Meteo API (free, no registration, no API key)
  • ✅ Updates: OTA via web interface + ArduinoOTA
  • ✅ Interface: Web UI, REST API, full configuration
  • ✅ Display: 3 rotating modes (time, weather, sunrise/sunset with daylight duration)
  • ✅ Time: NTP sync with timezone + automatic European DST

Hardware Details

Device Purchased

  • Product: ESP8266 Mini Weather Clock Kit
  • Model: TJ-56-654
  • Source: AliExpress Link
  • Price: €5 EUR (~$5.50 USD)
  • Size: 40mm x 40mm x 43mm (transparent acrylic case)

Components

ESP-01S WiFi Module

  • Chip: ESP8266EX
  • Flash: 1MB (8Mbit)
  • RAM: 80KB total
  • CPU: 80MHz
  • WiFi: 802.11 b/g/n (2.4GHz only)
  • GPIO: Only GPIO0 and GPIO2 available
  • Voltage: 3.3V ⚠️ NOT 5V tolerant

Display Module

  • Model: GM009605v4.3
  • Type: OLED (128x64 pixels, 0.96 inches)
  • Controller: SSD1306/SH1106 compatible
  • Interface: I2C
  • I2C Address: 0x3C (default), 0x3D (fallback)
  • Colors: Monochrome (white on black)

Pin Mapping (CRITICAL!)

Non-standard I2C mapping:

  • SDA: GPIO0 (not GPIO4 as typical)
  • SCL: GPIO2 (not GPIO5 as typical)

This mapping is backwards from standard ESP8266 breakout boards!

Wire.begin(0, 2);  // SDA=GPIO0, SCL=GPIO2

Power Supply

  • Input: 5V via Micro-USB
  • Current: 80-120mA typical
  • Regulator: Onboard 3.3V LDO

Development History

Timeline

2025-12-29: v1.5 (unreleased)

  • Attempted TM1637 7-segment display support
  • ❌ Wrong - device has OLED, not 7-segment LEDs

2025-12-30: v1.6 (unreleased)

  • Attempted TM1650 LED driver support
  • ❌ Wrong - I2C addresses didn't match

2025-12-31: v1.7 ✅

  • ✅ Identified correct display: GM009605v4.3 (SSD1306-compatible OLED)
  • ✅ Discovered swapped pins: SDA=GPIO0, SCL=GPIO2
  • ✅ Switched to Adafruit_SSD1306 library
  • ✅ Basic time display working
  • ✅ WiFiManager integration
  • ✅ First OTA deployment

2026-01-01: v1.8 🔒

  • 🔒 Security fixes:
    • Removed hardcoded WiFi credentials
    • Added config validation (magic number check)
    • Input sanitization (buffer overflow protection)
  • 🛠️ Stability fixes:
    • IRAM crisis fix (94% → 70% via ICACHE_FLASH_ATTR on 26 functions)
    • NTP interval bug (config value was ignored)
    • Boolean parsing errors in JSON import/export
    • Infinite loop protection in display rotation
  • ⚡ Performance:
    • Chunked HTTP responses (eliminated 140+ String concatenations)
    • Peak heap usage reduced by ~8KB
    • Memory leaks fixed

2026-01-02: v1.9.0 ⚡

  • ⚡ Full async refactoring:
    • Async HTTP weather fetch (AsyncHTTPRequest library)
    • Custom async NTP implementation (manual UDP packets)
    • Async WiFi connection (state machine)
    • Removed all delay() calls from loop()
    • Exponential backoff retry logic
  • 📊 Performance results:
    • Loop time: 10ms → <1ms (10x improvement)
    • Weather fetch: 1-10s blocking → 0ms
    • NTP sync: 5-20s blocking → 0ms
    • WiFi reconnect: 15s blocking → 0ms
  • ❌ Problem discovered:
    • Display blank for 10+ seconds on boot
    • "DNS resolution failed" errors

2026-01-03: v1.9.1 (Current) 🎯

  • 🔧 Critical fix: Hybrid WiFi model
    • Synchronous WiFi in setup() (waits up to 10 seconds)
    • Async WiFi reconnect in loop() (non-blocking)
    • Ensures proper initialization order: WiFi → OTA → web → NTP
  • 📺 Display improvements:
    • Fixed sunrise/sunset labels cutoff (removed labels, kept arrows)
    • Superscript degree symbol (°c)
    • Daylight duration display instead of static "Sun Times"
  • ✅ Result: Production ready, tested 24/7

Current Status (v1.9.1)

Version Information

Firmware: v1.9.1 (Production Ready) Released: 2026-01-03 Status: Actively running 24/7, stable

Memory Usage

Resource Used Total Usage Status
Flash 408,844 1,048,576 38% ✅ Plenty
RAM 37,644 80,192 46% ✅ Safe
IRAM 61,987 65,536 94% ⚠️ Critical but stable

IRAM Note: 94% is acceptable because:

  • ICACHE_FLASH_ATTR applied to 26 functions
  • Stable across v1.8 → v1.9.1
  • No growth observed in testing

Performance Metrics

  • Loop time: <1ms (was 10ms+ before async)
  • Boot to time display: ~15 seconds
  • WiFi connection: 5-10 seconds (synchronous in setup)
  • NTP sync interval: Configurable (default 1 hour)
  • Weather update interval: Configurable (default 30 minutes)

Uptime

  • ✅ 24+ hours stable
  • ✅ No memory leaks
  • ✅ No crashes or reboots
  • ✅ OTA updates work during operation

Technical Architecture

Async State Machines

Weather State Machine

enum WeatherState { IDLE, REQUESTING, SUCCESS, FAILED };
  • Library: AsyncHTTPRequest_Generic v1.13.0
  • API: Open-Meteo (free, no API key)
  • Callback: onWeatherResponse()
  • Retry: Exponential backoff (1s → 2s → 4s, max 3 retries)

NTP State Machine

enum NTPState { IDLE, REQUEST_SENT, WAITING, SUCCESS, FAILED };
  • Custom manual UDP packet building/parsing
  • Independent epoch tracking: syncedEpoch, syncedMillis, timeIsSynced
  • Non-blocking UDP checks via parsePacket()
  • Timeout: 5 seconds
  • Why manual? NTPClient library is inherently blocking

WiFi State Machine

enum WiFiConnectionState { IDLE, CONNECTING, CONNECTED, FAILED };

Hybrid model (critical for v1.9.1):

  • Setup phase: Synchronous (waits up to 10 seconds)
    • Why? OTA, web server, NTP all need WiFi ready
    • Prevents "DNS resolution failed" errors
    • Ensures time appears on display immediately after WiFi connects
  • Loop phase: Asynchronous (checks every 5 seconds)
    • Why? Don't freeze device if WiFi drops during operation
    • Graceful reconnection without user impact

Configuration Storage

EEPROM struct (512 bytes, 26 fields):

struct Config {
  char ssid[32];                      // WiFi network name
  char password[64];                  // WiFi password
  int timezone_offset;                // Seconds from UTC
  bool dst_enabled;                   // Auto DST (European rules)
  uint8_t brightness;                 // Display brightness (0-7)
  char ntp_server[64];                // NTP server address
  unsigned long ntp_interval;         // NTP sync interval (seconds)
  bool hour_format_24;                // 24h vs 12h display
  char hostname[32];                  // mDNS hostname
  float latitude;                     // Weather location
  float longitude;                    // Weather location
  char city_name[32];                 // Display in weather mode
  bool weather_enabled;               // Feature toggle
  unsigned long weather_interval;     // Update interval (seconds)
  unsigned long display_rotation_sec; // Mode switch interval
  bool show_weather;                  // Enable weather mode
  bool show_sunrise_sunset;           // Enable sunrise/sunset mode
  uint8_t display_orientation;        // Screen rotation (0-3)
  uint32_t magic;                     // 0xC10CC10C - validation
};

Validation: Magic number check prevents loading corrupted EEPROM data.

Display Modes

Mode 1: Time Mode

  • Large HH:MM display
  • Blinking colon (500ms interval)
  • Day of week + date
  • 24/12 hour format support

Mode 2: Weather Mode

  • Temperature with superscript °c
  • City name at bottom
  • Example: "15.4°c" + "Portimao"

Mode 3: Sunrise/Sunset Mode

  • Sunrise time with ↑ arrow
  • Sunset time with ↓ arrow
  • Daylight duration (e.g., "Day 9h 41m")
  • Calculation: sunset - sunrise = total daylight minutes

Rotation: Configurable interval (default 5 seconds), gracefully skips disabled modes.

Memory Optimization Techniques

1. ICACHE_FLASH_ATTR

Applied to 26 functions to move code from IRAM to Flash:

  • All web handlers (15 functions)
  • Setup functions (5 functions)
  • Utilities (6 functions)

Result: IRAM usage manageable at 94%

2. Chunked HTTP Responses

// ❌ BAD - 140+ concatenations
String html = "";
html += F("<!DOCTYPE html>");
html += F("<head>...");

// ✅ GOOD - Chunked transfer
server.setContentLength(CONTENT_LENGTH_UNKNOWN);
server.send(200, "text/html", "");
server.sendContent_P(HTML_HEADER);
server.sendContent_P(HTML_FOOTER);
server.sendContent("");

Result: ~8KB peak heap reduction

3. Fixed-Size Buffers

No dynamic String allocations in loops:

char buf[150];
snprintf_P(buf, sizeof(buf), PSTR("<div>IP: %s</div>"),
          WiFi.localIP().toString().c_str());

Security Issues Fixed

Original Firmware Vulnerabilities

1. WiFi Password Leak (CRITICAL)

  • Open access point remained active after setup
  • Web interface displayed WiFi password in plaintext
  • Anyone within range could connect and read password
  • Impact: Full network compromise

2. Cloud Dependency

  • Required QWeather API (Chinese service)
  • Needed account registration + API key
  • Unknown data collection practices
  • Impact: Privacy concerns, vendor lock-in

3. No OTA Updates

  • Required physical FTDI connection for updates
  • Difficult for non-technical users
  • Impact: Security vulnerabilities can't be patched remotely

4. Hardcoded Credentials

  • Default WiFi credentials in source code
  • No secure setup flow
  • Impact: Easy attack vector

Custom Firmware Solutions

1. WiFiManager Integration ✅

  • Captive portal for secure first-time setup
  • AP automatically closes after 180 seconds
  • Fallback AP only on connection failure
  • Password-protected fallback (customizable)

2. Open-Meteo API ✅

  • Free weather service
  • No registration required
  • No API key needed
  • European service (GDPR compliant)

3. OTA Updates ✅

  • Web-based upload at /update
  • ArduinoOTA for IDE uploads
  • Password-protected (admin/admin - customizable)
  • Non-blocking during operation

4. No Hardcoded Secrets ✅

  • All credentials stored in EEPROM
  • Magic number validation
  • Factory reset capability
  • Configuration import/export

Files & Structure

Project Directory

Location: /Users/apetrochenko/Library/Mobile Documents/com~apple~CloudDocs/src/arduino/clock/esp8266-weather-clock-opensource

Key Files

Root Level:

  • README.md (26KB) - Main documentation (blog-style)
  • LICENSE - MIT License
  • CHANGELOG.md - Version history
  • CONTRIBUTING.md - Contribution guidelines
  • PROJECT_STRUCTURE.md - Directory layout
  • PROJECT_CONTEXT.md - This file
  • PUBLISH_TO_GITHUB.md - GitHub publishing guide
  • .gitignore - Git exclusions

Source Code:

  • src/clock_ntp_ota_v1.9.ino (65KB, 2,096 lines)

Documentation:

  • docs/INSTALLATION.md (18KB) - Complete installation guide
  • docs/HARDWARE.md (8KB) - Hardware specs + pinout
  • docs/v1.9_RELEASE_NOTES.md (7KB) - v1.9.0 changelog
  • docs/v1.9.1_HYBRID_FIX.md (6KB, Russian) - v1.9.1 fix explanation

Images:

  • images/product/ - 6 AliExpress product photos
    • 01-main-product.webp
    • 02-components.webp
    • 03-weather-forecast.webp
    • 04-temperature-display.webp
    • 05-details.webp
    • 06-size.webp
  • images/build/ - 3 display screenshots
    • display-time.png
    • display-temperature.png
    • display-sunrise-sunset.png

GitHub Config:

  • .github/workflows/build.yml - CI/CD pipeline
  • .github/ISSUE_TEMPLATE/bug_report.md
  • .github/ISSUE_TEMPLATE/feature_request.md

Compiled Artifacts (not in git)

build/
├── clock_ntp_ota_v1.9.ino.bin  (409KB) - Flash this via OTA
├── clock_ntp_ota_v1.9.ino.elf  - Debug symbols
└── clock_ntp_ota_v1.9.ino.map  - Memory map

Git Repository

GitHub Details

Repository Configuration

Enabled Features:

  • ✅ Issues
  • ✅ Discussions
  • ✅ GitHub Actions (CI/CD)
  • ✅ Releases

Topics (Tags):

  • esp8266, arduino, iot, weather-station
  • reverse-engineering, security, oled-display
  • ntp, ota-updates, open-meteo

Badges:

  • Release version (auto-updates)
  • License (MIT)
  • Build status (CI/CD)
  • Open issues count
  • Hardware (ESP-01S)
  • Status (Production Ready)

Current Release

Tag: v1.9.1 URL: https://github.com/petrochen/esp8266-weather-clock-opensource/releases/tag/v1.9.1 Status: Production Ready Created: 2026-01-03

Git Commits

Total: 3 commits

  1. 8f0df02 - Initial commit: v1.9.1 production firmware
  2. f2dc2fb - Add dynamic GitHub badges to README
  3. 2205445 - Update price: $12 → €5

Web Interface URLs


Next Steps

Planned Features (v1.10 or v2.0)

1. Home Assistant Integration (High Priority)

User specifically wants custom display screens pulling data from Home Assistant.

Implementation ideas:

  • Add REST API client to fetch HA sensor data
  • New display modes:
    • Energy usage dashboard
    • Room temperatures (multiple sensors)
    • Air quality / CO2 levels
    • Automation states (alarm, doors, lights)
  • Configuration: HA server URL, access token, entity IDs
  • Update interval: configurable (default 30 seconds)

Technical approach:

  • Use AsyncHTTPRequest for non-blocking HA API calls
  • JSON parsing with ArduinoJson library
  • Store HA config in EEPROM (new fields)
  • New web UI section for HA configuration

2. MQTT Support

  • Publish time/weather data to MQTT broker
  • Subscribe to topics for display content
  • Enable automation triggers
  • Library: PubSubClient (async wrapper needed)

3. WebSocket Live Updates

  • Replace polling with WebSocket
  • Real-time config changes
  • Live display preview in web UI
  • Push notifications for updates

4. Multiple Weather Locations

  • Store 2-3 favorite locations
  • Rotate between them
  • Useful for travelers or multiple homes

5. Display Animations

  • Smooth transitions between modes
  • Weather icons (sunny, cloudy, rainy)
  • Sunrise/sunset animations

Code Quality Improvements

1. Modular Architecture (v2.0)

Split monolith (2,096 lines) into modules:

src/
├── main.ino
├── config.h
├── display.cpp/h
├── network.cpp/h
├── weather.cpp/h
├── webserver.cpp/h
└── home_assistant.cpp/h  (new)

2. ArduinoJson Integration

Replace manual JSON parsing (173 lines) with library:

  • Cleaner code
  • Better error handling
  • Type safety

3. Constants Organization

Eliminate magic numbers:

namespace Hardware {
  constexpr uint8_t I2C_SDA_PIN = 0;
  constexpr uint8_t I2C_SCL_PIN = 2;
}

4. Unit Tests

  • Test state machines
  • Test JSON parsing
  • Test time calculations
  • Mock network calls

Documentation Improvements

1. Video Tutorial

  • YouTube walkthrough
  • FTDI connection demo
  • OTA update demo
  • Web configuration walkthrough

2. Troubleshooting Flow Chart

Visual guide for common issues:

  • Display not working
  • WiFi not connecting
  • Time not syncing
  • Weather not updating

3. Localization

Translate docs to:

  • Russian (v1.9.1_HYBRID_FIX.md already in Russian)
  • Spanish
  • Portuguese

4. Home Assistant Integration Guide

Complete guide when HA support is added.

Community Engagement

1. Reddit Posts

Subreddits to share on:

  • r/esp8266
  • r/arduino
  • r/selfhosted
  • r/homeassistant (after HA integration)
  • r/ReverseEngineering

2. Hackaday

Submit project tip: https://hackaday.com/submit-a-tip/

3. Hackster.io

Create full project page with build guide.

4. Awesome Lists

Add to "awesome ESP8266" and "awesome IoT" lists.


Key Learnings

Hardware

  1. Always verify pinouts - Don't assume standard mappings
  2. FTDI is essential - $2 adapter unlocks any ESP8266 device
  3. Read PCB markings - Model numbers save hours of guessing
  4. Test voltage - ESP8266 is NOT 5V tolerant
  5. Document discoveries - Pin mappings, I2C addresses, display models

Software

  1. Async is hard but worth it - Fully non-blocking eliminates freezes
  2. IRAM is precious - Use ICACHE_FLASH_ATTR liberally on ESP8266
  3. Hybrid approaches work - Don't be dogmatic (sync WiFi in setup() was correct)
  4. State machines scale - Better than callback hell for complex async
  5. Test on real hardware - Emulators miss pin issues and memory constraints

Security

  1. IoT security is often terrible - Always audit before trusting
  2. Open source is safer - Closed firmware is a black box
  3. Defaults matter - Insecure defaults (open AP, plaintext passwords) are vulnerabilities
  4. Defense in depth - Multiple layers catch mistakes
  5. Update mechanism is critical - OTA enables security patches

Development

  1. OTA from day 1 - FTDI flashing gets old fast
  2. Version control - Backups (.bak, .bak2) saved the project multiple times
  3. Document as you go - Release notes prevent "what was I thinking?" moments
  4. Incremental improvements - v1.7 → v1.8 → v1.9.x made debugging manageable
  5. User testing - Photos from user revealed display cutoff issues

Project Management

  1. Understand user needs - User wanted Home Assistant integration (plan for it)
  2. Security first - Privacy/security was main motivation
  3. Performance matters - 10ms loop → <1ms dramatically improves UX
  4. Documentation is product - Good docs = more users = more contributors
  5. Publish early - GitHub repo enables community contributions

Quick Reference

Current Device Configuration

Hardware:

  • Device: TJ-56-654 Weather Clock
  • Location: User's home network
  • IP: 192.168.2.47
  • Hostname: tj56654-clock.local

Software:

  • Firmware: v1.9.1
  • WiFi: SibWings
  • Weather: Portimao, Portugal (37.19°N, 8.54°W)
  • Timezone: UTC+0 (Lisbon) with auto DST
  • NTP: pool.ntp.org (1 hour interval)

Access:

Important Commands

Compile:

arduino-cli compile --fqbn esp8266:esp8266:generic \
  src/clock_ntp_ota_v1.9.ino

Upload OTA:

curl -u admin:admin \
  -F "file=@build/clock_ntp_ota_v1.9.ino.bin" \
  http://192.168.2.47/update

Check status:

curl http://192.168.2.47/api/status | jq

View logs:

# Connect via serial (if FTDI attached)
screen /dev/cu.usbserial* 115200

Library Dependencies

Required libraries (install via Arduino Library Manager):

Library Version Purpose
Adafruit GFX Library 1.11.0+ Graphics primitives
Adafruit SSD1306 2.5.0+ OLED display driver
NTPClient 3.2.0+ NTP time sync (base)
WiFiManager 2.0.0+ Captive portal
AsyncHTTPRequest_Generic 1.13.0+ Async weather fetch
ESPAsyncTCP 1.2.2+ Async TCP layer

External APIs

Open-Meteo:

NTP:

  • Default: pool.ntp.org
  • Protocol: UDP port 123
  • Fallbacks: time.google.com, time.cloudflare.com

Contact & Collaboration

GitHub: https://github.com/petrochen/esp8266-weather-clock-opensource Issues: https://github.com/petrochen/esp8266-weather-clock-opensource/issues Discussions: https://github.com/petrochen/esp8266-weather-clock-opensource/discussions

Contributions welcome! See CONTRIBUTING.md


Summary

This project successfully transformed a €5 AliExpress IoT device with critical security vulnerabilities into a fully secure, high-performance, feature-rich smart clock with open-source firmware.

Key achievements:

  • ✅ Eliminated WiFi password leak vulnerability
  • ✅ Achieved <1ms loop time (10x performance improvement)
  • ✅ Enabled OTA updates (no more FTDI wiring)
  • ✅ Free weather API (no registration)
  • ✅ Full async architecture (zero blocking)
  • ✅ Production-ready stability (24/7 uptime)
  • ✅ Open-source on GitHub (MIT license)
  • ✅ Comprehensive documentation (100KB+ docs)

Next milestone: Home Assistant integration for custom display screens.

Status: Project complete and ready for community contributions! 🚀


Last session work (2026-01-03):

  1. ✅ Compiled v1.9.1 with daylight duration feature
  2. ✅ Uploaded via OTA to device (192.168.2.47)
  3. ✅ Created complete GitHub repository structure
  4. ✅ Published to https://github.com/petrochen/esp8266-weather-clock-opensource
  5. ✅ Created release v1.9.1
  6. ✅ Added badges, topics, documentation
  7. ✅ Fixed price ($12 → €5)
  8. ✅ Saved full project context

Repository ready for sharing on Reddit, Hackaday, and other communities!