# 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 (OpenWeatherMap) - 📅 **Google Calendar** - Calendar events display (supports public iCal feeds) - 🖼️ **Rotating Backgrounds** - Beautiful images from local directory - 🎨 **Dynamic Text Color** - Automatically adjusts text color based on background brightness - 😄 **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 ```bash git clone ssh://git@gitea.meyfamily.co.nz:2222/luddie/Calender.git cd Calender ``` ### 2. Install Dependencies ```bash python3 -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -r requirements.txt ``` ### 3. Configure Environment Variables ```bash cp .env.example .env ``` Edit [.env](.env) and add your API keys: ```bash # 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. Get OpenWeatherMap API Key 1. Go to [OpenWeatherMap](https://openweathermap.org/api) 2. Sign up for a free account 3. Navigate to "API keys" section 4. Copy your API key 5. Add it to your `.env` file as `OPENWEATHER_API_KEY` **Find Your Location Coordinates:** 1. Go to [LatLong.net](https://www.latlong.net/) 2. Search for your city 3. Copy the latitude and longitude values 4. Add them to your `.env` file as `WEATHER_LAT` and `WEATHER_LON` ### 5. Set Up Google Calendar **Option 1: Public iCal Feed (Easiest - No Authentication)** 1. Open [Google Calendar](https://calendar.google.com/) 2. Go to Settings (⚙️ gear icon) 3. Select the calendar you want to display 4. Scroll down to "Integrate calendar" 5. Copy the **"Public URL to this calendar"** in iCal format - The URL looks like: `https://calendar.google.com/calendar/ical/...@group.calendar.google.com/public/basic.ics` 6. Add this URL to your `.env` file as `GOOGLE_CALENDAR_ICAL_URL` 7. Also copy the Calendar ID (looks like `abc123...@group.calendar.google.com`) 8. Add it to your `.env` file as `GOOGLE_CALENDAR_ID` **Note:** Your calendar must be set to "Public" for this method to work. **Option 2: Google Calendar API with Credentials (Advanced)** If you prefer to use private calendars with authentication: 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select existing one 3. Enable the Google Calendar API 4. Create credentials (Service Account) 5. Download the credentials JSON file 6. Save it as `credentials/google_calendar_credentials.json` 7. Share your calendar with the service account email ### 6. Add Background Images Place your images in the `static/backgrounds/` directory: ```bash cp /path/to/your/images/*.jpg static/backgrounds/ ``` **Supported formats:** JPG, JPEG, PNG, GIF, WebP **Recommended specifications:** - Resolution: 1920x1080 or higher - Aspect ratio: 16:9 (for full-screen displays) - File size: Keep under 5MB for faster loading **Changing Image Rotation Interval:** Edit `static/js/app.js`: ```javascript const INTERVALS = { BACKGROUND: 3600000, // Milliseconds (3600000 = 60 minutes) ... }; ``` ### 7. Run the Application ```bash python app.py ``` Visit `http://localhost:5000` in your browser. ## Raspberry Pi Deployment ### Auto-start Flask Application Create a systemd service: ```bash sudo nano /etc/systemd/system/calendar-display.service ``` Add the following content: ```ini [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: ```bash sudo systemctl daemon-reload sudo systemctl enable calendar-display.service sudo systemctl start calendar-display.service ``` ### Configure Chromium Kiosk Mode The Pi uses **labwc** (Wayland). Create the autostart entry: ```bash mkdir -p ~/.config/autostart nano ~/.config/autostart/chromium-kiosk.desktop ``` Add the following: ```ini [Desktop Entry] Type=Application Name=Chromium Kiosk Exec=chromium-browser --ozone-platform=wayland --kiosk --noerrdialogs --incognito --disable-infobars --simulate-touch-screen --force-show-cursor http://localhost:5002 X-GNOME-Autostart-enabled=true ``` ### Reboot ```bash sudo reboot ``` The display should now start automatically on boot! ### Restarting Without Rebooting A helper script is included to restart both the Flask service and the Chromium kiosk without rebooting: ```bash bash ~/restart-calendar.sh ``` This will: 1. Restart the `calendar-display` systemd service 2. Kill and relaunch Chromium in the correct Wayland session ## Configuration ### Environment Variables (`.env` file) **Weather Settings:** - `OPENWEATHER_API_KEY` - Your OpenWeatherMap API key - `WEATHER_LOCATION` - City name and country code (e.g., "London,UK") - `WEATHER_LAT` - Latitude of your location - `WEATHER_LON` - Longitude of your location **Calendar Settings:** - `GOOGLE_CALENDAR_ID` - Your calendar ID - `GOOGLE_CALENDAR_ICAL_URL` - Public iCal feed URL (easiest method) - `CALENDAR_DAYS_AHEAD` - Number of days ahead to show events (default: 5) **Update Intervals (in seconds):** - `WEATHER_UPDATE_INTERVAL` - Weather refresh interval (default: 900) - `CALENDAR_UPDATE_INTERVAL` - Calendar refresh interval (default: 300) - `JOKE_UPDATE_INTERVAL` - Dad joke refresh interval (default: 3600) **Other:** - `FLASK_SECRET_KEY` - Flask session secret key ### JavaScript Configuration (`static/js/app.js`) For more precise control over update intervals, edit the `INTERVALS` object: ```javascript const INTERVALS = { TIME: 1000, // 1 second WEATHER: 900000, // 15 minutes CALENDAR: 300000, // 5 minutes BACKGROUND: 3600000, // 60 minutes JOKE: 3600000 // 1 hour }; ``` **To change image rotation time:** 1. Open `static/js/app.js` 2. Find the `INTERVALS` object at the top 3. Change `BACKGROUND` to your desired value in milliseconds - 300000 = 5 minutes - 1800000 = 30 minutes - 3600000 = 60 minutes (default) ## 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/](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: - [Flask](https://flask.palletsprojects.com/) - Web framework - [OpenWeatherMap API](https://openweathermap.org/api) - Weather data - [Google Calendar API](https://developers.google.com/calendar) - Calendar integration - [icanhazdadjoke](https://icanhazdadjoke.com/) - Dad jokes API