Ludwig Mey ced41148ef Add dynamic text color adjustment based on background brightness
Automatically adjusts text color for optimal readability:
- Bright backgrounds: Text switches to dark color (#1a1a1a)
- Dark backgrounds: Text remains white (#ffffff)
- Uses luminance formula (0.299×R + 0.587×G + 0.114×B) for accurate brightness detection
- Analyzes images using canvas to sample 100x100 pixels
- Smooth color transitions (0.5s) between background changes
- Adjusts text shadows for better contrast in each mode
- Event time color adapts (#0066cc for light, #4a9eff for dark)

Technical implementation:
- Added calculateImageBrightness() function in app.js
- Modified updateBackground() to analyze and apply appropriate CSS class
- Added .light-bg and .dark-bg CSS classes for text color themes
- Brightness threshold set at 140 (out of 255)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 22:25:51 +13:00

Family Calendar Display

A smart display application for Raspberry Pi that shows time, weather, calendar events, and rotating background images.

Project created: February 14, 2026

Features

  • 🕐 Real-time Clock - Current time and date display
  • 🌤️ Weather - Current weather and 3-day forecast for Hamilton, New Zealand (OpenWeatherMap)
  • 📅 Google Calendar - Family calendar events display
  • 🖼️ Rotating Backgrounds - Beautiful images from local directory
  • 😄 Dad Jokes - Random jokes to brighten your day (optional)

Requirements

  • Python 3.8+
  • Raspberry Pi (tested on Pi 3/4) or any Linux system
  • Google Calendar API credentials
  • OpenWeatherMap API key (free tier)

Quick Start

1. Clone the Repository

git clone ssh://git@gitea.meyfamily.co.nz:2222/luddie/Calender.git
cd Calender

2. Install Dependencies

python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -r requirements.txt

3. Configure Environment Variables

cp .env.example .env

Edit .env and add your API keys:

# Get your OpenWeatherMap API key from: https://openweathermap.org/api
OPENWEATHER_API_KEY=your_api_key_here

# Your Google Calendar ID (found in Google Calendar settings)
GOOGLE_CALENDAR_ID=your_calendar_id@group.calendar.google.com

# Generate a secret key for Flask
FLASK_SECRET_KEY=your_random_secret_key

4. Set Up Google Calendar API

  1. Go to Google Cloud Console
  2. Create a new project or select existing one
  3. Enable the Google Calendar API
  4. Create credentials (OAuth 2.0 or Service Account)
  5. Download the credentials JSON file
  6. Save it as credentials/google_calendar_credentials.json

5. Add Background Images

Place your images in the static/backgrounds/ directory:

cp /path/to/your/images/*.jpg static/backgrounds/

Supported formats: JPG, PNG, GIF, WebP

6. Run the Application

python app.py

Visit http://localhost:5000 in your browser.

Raspberry Pi Deployment

Auto-start Flask Application

Create a systemd service:

sudo nano /etc/systemd/system/calendar-display.service

Add the following content:

[Unit]
Description=Calendar Display Flask App
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/Calender
ExecStart=/home/pi/Calender/venv/bin/python app.py
Restart=always
Environment="PATH=/home/pi/Calender/venv/bin"

[Install]
WantedBy=multi-user.target

Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable calendar-display.service
sudo systemctl start calendar-display.service

Configure Chromium Kiosk Mode

Edit the autostart file:

mkdir -p ~/.config/lxsession/LXDE-pi
nano ~/.config/lxsession/LXDE-pi/autostart

Add these lines:

@xset s off
@xset -dpms
@xset s noblank
@chromium-browser --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble http://localhost:5000

Disable screensaver and cursor (optional):

sudo apt-get install unclutter
echo "@unclutter -idle 0" >> ~/.config/lxsession/LXDE-pi/autostart

Reboot

sudo reboot

The display should now start automatically on boot!

Configuration

Edit .env to customize:

  • IMAGE_ROTATION_INTERVAL - Seconds between background changes (default: 300)
  • WEATHER_UPDATE_INTERVAL - Seconds between weather updates (default: 900)
  • CALENDAR_UPDATE_INTERVAL - Seconds between calendar updates (default: 300)
  • JOKE_UPDATE_INTERVAL - Seconds between joke updates (default: 3600)
  • CALENDAR_DAYS_AHEAD - Number of days ahead to show events (default: 7)

Project Structure

Calender/
├── app.py                      # Main Flask application
├── config.py                   # Configuration management
├── requirements.txt            # Python dependencies
├── .env                        # Environment variables (create from .env.example)
├── .env.example               # Environment template
├── static/
│   ├── css/style.css          # Styling
│   ├── js/app.js              # Frontend JavaScript
│   └── backgrounds/           # Background images directory
├── templates/
│   └── index.html             # Main display template
└── credentials/
    └── google_calendar_credentials.json  # Google API credentials

API Endpoints

  • GET / - Main display page
  • GET /api/weather - Weather data (cached for 15 min)
  • GET /api/calendar - Calendar events (cached for 5 min)
  • GET /api/background - Random background image
  • GET /api/joke - Dad joke (cached for 1 hour)

Troubleshooting

Weather not loading

  • Check your OpenWeatherMap API key is valid
  • Ensure you're not exceeding the free tier rate limits (60 calls/min)

Calendar not loading

  • Verify Google Calendar API credentials are set up correctly
  • Check the calendar ID is correct
  • Ensure the service account has access to the calendar

Display not starting on boot

  • Check systemd service status: sudo systemctl status calendar-display.service
  • View logs: sudo journalctl -u calendar-display.service -f

Background images not showing

  • Ensure images are in static/backgrounds/
  • Check file permissions: chmod 644 static/backgrounds/*

Contributing

Feel free to submit issues or pull requests!

License

MIT License - Feel free to use and modify for personal use.

Credits

Built with:

Description
Family calender display
Readme 30 MiB
Languages
JavaScript 36.2%
Python 33.3%
CSS 24.4%
HTML 6.1%