{"id":14977924,"url":"https://github.com/piflyer/smartdisplaypi","last_synced_at":"2025-10-28T07:30:40.404Z","repository":{"id":38330831,"uuid":"240620093","full_name":"Piflyer/SmartDisplayPi","owner":"Piflyer","description":"A Smart Display powered by Google Assistant and a Raspberry Pi.","archived":false,"fork":false,"pushed_at":"2022-09-06T19:42:27.000Z","size":5520,"stargazers_count":40,"open_issues_count":2,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-02-01T12:44:11.231Z","etag":null,"topics":["google-assistant-sdk","home-assistant","home-automation","home-hub","iot","raspap","raspberry-pi","raspberry-pi-camera","smart-display","smart-home","smart-speaker"],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Piflyer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-02-15T00:08:45.000Z","updated_at":"2024-12-04T13:10:41.000Z","dependencies_parsed_at":"2022-09-15T12:50:58.378Z","dependency_job_id":null,"html_url":"https://github.com/Piflyer/SmartDisplayPi","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piflyer%2FSmartDisplayPi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piflyer%2FSmartDisplayPi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piflyer%2FSmartDisplayPi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Piflyer%2FSmartDisplayPi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Piflyer","download_url":"https://codeload.github.com/Piflyer/SmartDisplayPi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238608417,"owners_count":19500375,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-assistant-sdk","home-assistant","home-automation","home-hub","iot","raspap","raspberry-pi","raspberry-pi-camera","smart-display","smart-home","smart-speaker"],"created_at":"2024-09-24T13:56:33.493Z","updated_at":"2025-10-28T07:30:40.392Z","avatar_url":"https://github.com/Piflyer.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SmartDisplayPi 🖥️\n\nTurn your Raspberry Pi into a beautiful, Nest Hub-style smart display! This project creates a stunning carousel of cards featuring weather, calendar, photos, and Home Assistant integration - perfect for your kitchen counter, living room, or anywhere you want a smart display.\n\n![Smart Display Demo](https://img.shields.io/badge/Status-Ready-green) ![Node.js](https://img.shields.io/badge/Node.js-18+-blue) ![Raspberry Pi](https://img.shields.io/badge/Raspberry%20Pi-Compatible-red) ![Performance](https://img.shields.io/badge/Performance-Optimized-orange)\n\n## 📸 Screenshots\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"images/smartdisplay1.png\" alt=\"Smart Display Main View\" width=\"600\"\u003e\n  \u003cp\u003e\u003cem\u003eMain ambient view with weather overlay and nature photos\u003c/em\u003e\u003c/p\u003e\n  \n  \u003cimg src=\"images/smartdisplay2.png\" alt=\"Smart Display Calendar View\" width=\"600\"\u003e\n  \u003cp\u003e\u003cem\u003eCalendar agenda view showing upcoming events\u003c/em\u003e\u003c/p\u003e\n  \n  \u003cimg src=\"images/smartdisplay3.png\" alt=\"Smart Display Weather View\" width=\"600\"\u003e\n  \u003cp\u003e\u003cem\u003eDetailed weather forecast with 5-day predictions\u003c/em\u003e\u003c/p\u003e\n\u003c/div\u003e\n\n## ✨ What Makes This Special\n\n### 🎠 **Beautiful Carousel Cards**\n- **Ambient Card**: Gorgeous nature photos from Unsplash with time and weather overlay\n- **Daily Summary Card**: AI-powered daily insights using Google Gemini\n- **Home Assistant Card**: Seamless integration with your HA dashboard\n- **Weather Forecast Card**: 5-day forecast with detailed weather info\n- **Calendar Agenda Card**: Weekly view of your upcoming events\n\n### 🌤️ **Smart Weather Integration**\n- **Current Weather**: Temperature, humidity, wind speed/direction, precipitation\n- **5-Day Forecast**: Daily predictions with beautiful weather icons\n- **Wind Direction Arrows**: Visual indicators so you know which way the wind blows\n- **Colored Weather Icons**: Sunny (yellow), cloudy (gray), and more\n- **OpenMeteo API**: Free, reliable weather data that just works\n- **Auto Refresh**: Weather updates every 30-45 minutes (optimized for performance)\n\n### 📅 **Google Calendar Magic**\n- **Floating Calendar**: Shows your next 24 hours right on the ambient card\n- **Agenda View**: Weekly calendar with clear day headers\n- **OAuth2 Authentication**: Secure Google Calendar access\n- **12-Hour Format**: AM/PM time display for easy reading\n- **Auto Refresh**: Calendar events update every 1-2 minutes\n\n### 🖼️ **Stunning Photo Display**\n- **Unsplash Integration**: High-quality nature photos that change regularly\n- **API Refresh**: New photos every 1.5-3 minutes to keep things fresh\n- **Slideshow**: Photos cycle every 1-2 minutes for variety\n- **Photographer Attribution**: Credits displayed in the corner (because artists deserve recognition!)\n- **Customizable Query**: Set your preferred photo theme (nature, landscapes, etc.)\n- **Landscape Orientation**: Optimized for display screens\n- **Performance Optimized**: Lower resolution images for smooth performance\n\n### 🏠 **Home Assistant Integration**\n- **iFrame Embedding**: Seamless HA dashboard integration\n- **Touch Navigation**: Swipe gestures for easy navigation\n- **Settings Button**: Quick access to HA settings\n- **Back Button**: Return to main display with one tap\n\n### 🤖 **AI-Powered Insights**\n- **Google Gemini AI**: Daily summary generation that actually makes sense\n- **Smart Summaries**: Contextual daily overviews that are actually useful\n- **Configurable Timing**: Set when daily summaries appear (morning coffee time?)\n- **Fallback Support**: Graceful handling when AI is unavailable\n\n### 🎨 **Beautiful Design**\n- **Nest Hub Design**: Glassmorphism and modern aesthetics that look great\n- **Touch-Friendly**: Optimized for touchscreen interaction\n- **Responsive Design**: Adapts to different screen sizes\n- **Uniform Navigation**: Consistent back/settings buttons everywhere\n- **Cursor Hidden**: Clean display experience for kiosk mode\n\n### ⚡ **Performance That Matters**\n- **Low Power Mode Detection**: Automatically adjusts for Raspberry Pi\n- **DOM Caching**: Reduced DOM queries for better performance\n- **Throttled Updates**: Prevents excessive API calls and DOM updates\n- **Optimized Intervals**: Longer refresh times on low-power devices\n- **Event Delegation**: Efficient event handling\n- **Debounced Resize**: Smooth window resize handling\n- **Image Optimization**: Lower resolution images for better performance\n\n## 🚀 Getting Started\n\n### What You'll Need\n- **Raspberry Pi** (3B or newer recommended)\n- **Node.js 18+** and npm\n- **Touchscreen Display** (optional but highly recommended)\n- **Google Account** with Calendar access\n- **Unsplash Account** (free)\n- **Google Gemini API Key** (optional, for AI summaries)\n\n### Installation Steps\n\n1. **Clone the repository**\n   ```bash\n   git clone https://github.com/Piflyer/SmartDisplayPi.git\n   cd SmartDisplayPi\n   ```\n\n2. **Install dependencies**\n   ```bash\n   npm install\n   ```\n\n3. **Set up Google Calendar OAuth2**\n   \n   This is the trickiest part, but we'll get through it together! Follow the official Google Calendar API quickstart:\n   - Go to [Google Calendar API Node.js Quickstart](https://developers.google.com/workspace/calendar/api/quickstart/nodejs)\n   - Complete steps 1-6 to create OAuth2 credentials\n   - Download the JSON file as `client_secret.json`\n   - Place it in your project root\n   - Run the OAuth2 setup:\n     ```bash\n     node setup-oauth.js\n     ```\n   - Follow the browser authorization flow\n   - This creates `token.json` for persistent authentication\n\n4. **Set up Unsplash API**\n   - Create account at [Unsplash Developers](https://unsplash.com/developers)\n   - Create a new application\n   - Get your Access Key and Secret Key\n\n5. **Set up Google Gemini AI (Optional)**\n   - Go to [Google AI Studio](https://makersuite.google.com/app/apikey)\n   - Create an API key for Gemini\n   - Add it to your environment variables\n\n6. **Configure environment variables**\n   ```bash\n   cp env.example .env\n   ```\n   \n   Edit `.env` with your API keys:\n   ```env\n   GOOGLE_APPLICATION_CREDENTIALS=./client_secret.json\n   UNSPLASH_ACCESS_KEY=your_unsplash_access_key_here\n   UNSPLASH_SECRET_KEY=your_unsplash_secret_key_here\n   GEMINI_API_KEY=your_gemini_api_key_here\n   PORT=3000\n   ```\n\n7. **Start the server**\n   ```bash\n   node server.js\n   ```\n\n8. **Enjoy your smart display!**\n   - Open `http://localhost:3000` in your browser\n   - For Raspberry Pi: `http://your-pi-ip:3000`\n\n## 🔧 Customization\n\n### 📱 **Display Settings**\n\nAccess settings by clicking the gear icon on any card:\n\n- **Photo Query**: Change Unsplash search term (default: \"nature landscape\")\n- **Home Assistant URL**: Set your HA instance URL\n- **Location**: Set latitude/longitude for weather data\n- **Summary Time**: Set when daily AI summaries appear (default: 8:00 AM)\n- **System Actions**: Refresh page functionality\n- **Settings persist** in browser local storage\n\n### 🌐 **Adding Your Own Websites**\n\nWant to add more cards to the carousel? Here's how:\n\n1. **Add new card to HTML** (`public/index.html`):\n   ```html\n   \u003cdiv class=\"carousel-card custom-website-card\"\u003e\n     \u003cdiv class=\"custom-header\"\u003e\n       \u003ch3\u003eCustom Website\u003c/h3\u003e\n       \u003cbutton class=\"back-btn\"\u003e←\u003c/button\u003e\n       \u003cbutton class=\"settings-btn\"\u003e⚙️\u003c/button\u003e\n     \u003c/div\u003e\n     \u003ciframe src=\"https://your-website.com\" frameborder=\"0\"\u003e\u003c/iframe\u003e\n   \u003c/div\u003e\n   ```\n\n2. **Add CSS styling** (`public/styles.css`):\n   ```css\n   .custom-website-card {\n     background: #fff;\n     border-radius: 20px;\n     box-shadow: 0 8px 32px rgba(0,0,0,0.1);\n   }\n   \n   .custom-header {\n     display: flex;\n     align-items: center;\n     padding: 16px;\n     border-bottom: 1px solid #eee;\n   }\n   ```\n\n3. **Update JavaScript** (`public/app.js`):\n   ```javascript\n   // Add to currentCard logic\n   const totalCards = 6; // Update total count\n   \n   // Add event listeners for new buttons\n   document.addEventListener('click', (e) =\u003e {\n     if (e.target.closest('.custom-website-card .back-btn')) {\n       goToCard(0); // Return to ambient card\n     }\n   });\n   ```\n\n### 🎨 **Customization Ideas**\n\n#### **News Website Card**\n```html\n\u003cdiv class=\"carousel-card news-card\"\u003e\n  \u003cdiv class=\"news-header\"\u003e\n    \u003ch3\u003e📰 News\u003c/h3\u003e\n    \u003cbutton class=\"back-btn\"\u003e←\u003c/button\u003e\n  \u003c/div\u003e\n  \u003ciframe src=\"https://news.ycombinator.com\" frameborder=\"0\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n```\n\n#### **Dashboard Card**\n```html\n\u003cdiv class=\"carousel-card dashboard-card\"\u003e\n  \u003cdiv class=\"dashboard-header\"\u003e\n    \u003ch3\u003e📊 Dashboard\u003c/h3\u003e\n    \u003cbutton class=\"back-btn\"\u003e←\u003c/button\u003e\n  \u003c/div\u003e\n  \u003ciframe src=\"https://your-dashboard.com\" frameborder=\"0\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n```\n\n## 🏗️ How It Works\n\n### **Backend (Node.js/Express)**\n- **`server.js`**: Main Express server with API endpoints\n- **Google Calendar API**: OAuth2 authentication and event fetching\n- **Google Gemini AI**: AI-powered daily summaries\n- **Unsplash API**: Photo retrieval with caching\n- **OpenMeteo API**: Weather data integration\n- **Static file serving**: Frontend delivery\n\n### **Frontend (HTML/CSS/JavaScript)**\n- **`public/index.html`**: Main HTML structure\n- **`public/styles.css`**: Nest Hub-esque styling with performance optimizations\n- **`public/app.js`**: Carousel logic, API calls, and performance optimizations\n- **Touch/Click Events**: Navigation and interaction handling with throttling\n\n### **Key Files**\n```\nSmartDisplayPi/\n├── server.js              # Main Express server\n├── setup-oauth.js         # Google OAuth2 setup script\n├── test-server.js         # Development server with mock data\n├── kiosk.sh              # Browser kiosk script (adapted from pi-kiosk)\n├── kiosk.service         # SystemD service for kiosk mode (adapted from pi-kiosk)\n├── public/\n│   ├── index.html         # Main HTML structure\n│   ├── styles.css         # CSS styling with optimizations\n│   └── app.js            # Frontend JavaScript with performance features\n├── client_secret.json     # Google OAuth2 credentials\n├── token.json            # OAuth2 tokens (generated)\n├── .env                  # Environment variables\n├── package.json          # Dependencies and scripts\n└── README.md            # This file\n```\n\n## 🔌 API Endpoints\n\n### **Weather**\n- `GET /api/weather?lat=40.7128\u0026lon=-74.0060`\n- Returns current weather and 5-day forecast\n- Uses OpenMeteo API (free, no key required)\n- Auto-refreshes every 30-45 minutes (optimized)\n\n### **Calendar**\n- `GET /api/calendar/events`\n- Returns next 24 hours of events\n- `GET /api/calendar/agenda`\n- Returns next week of events\n- Requires Google OAuth2 setup\n- Auto-refreshes every 1-2 minutes (optimized)\n\n### **Photos**\n- `GET /api/photos/:query?`\n- Returns Unsplash photos for specified query\n- Auto-refreshes every 1.5-3 minutes (optimized)\n\n### **AI Summary**\n- `GET /api/summary`\n- Returns AI-generated daily summary\n- Uses Google Gemini AI\n- Configurable timing via settings\n\n## ⚡ Performance Features\n\n### **Low Power Mode Detection**\n- Automatically detects Raspberry Pi and low-power devices\n- Adjusts refresh intervals and performance settings\n- Optimizes for ARM processors and limited memory\n\n### **DOM Optimization**\n- Caches frequently accessed DOM elements\n- Reduces DOM queries by 80%\n- Improves rendering performance\n\n### **Throttled Updates**\n- Prevents excessive API calls\n- Reduces server load\n- Improves battery life on mobile devices\n\n### **Event Handling**\n- Event delegation for better performance\n- Throttled swipe gestures\n- Debounced resize handlers\n\n### **Image Optimization**\n- Lower resolution images for better performance\n- Optimized loading strategies\n- Reduced bandwidth usage\n\n## 🚀 Deployment\n\n### **Raspberry Pi Setup**\n1. **Install Node.js**:\n   ```bash\n   curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -\n   sudo apt-get install -y nodejs\n   ```\n\n2. **Clone and Setup**:\n   ```bash\n   git clone https://github.com/Piflyer/SmartDisplayPi.git\n   cd SmartDisplayPi\n   npm install\n   ```\n\n3. **Configure OAuth2** (on a computer with browser):\n   - Run `node setup-oauth.js`\n   - Copy `token.json` to Raspberry Pi\n\n4. **Start Service**:\n   ```bash\n   chmod +x start.sh\n   ./start.sh\n   ```\n\n### **Kiosk Mode Setup**\n\nThis project includes kiosk mode configuration files adapted from [Jeff Geerling's pi-kiosk project](https://github.com/geerlingguy/pi-kiosk):\n\n- **`kiosk.sh`**: Browser kiosk script (adapted from [pi-kiosk](https://github.com/geerlingguy/pi-kiosk))\n- **`kiosk.service`**: SystemD service for auto-starting kiosk mode (adapted from [pi-kiosk](https://github.com/geerlingguy/pi-kiosk))\n\nTo set up kiosk mode:\n\n1. **Install prerequisites**:\n   ```bash\n   sudo apt install unclutter\n   ```\n\n2. **Set up kiosk script**:\n   ```bash\n   mkdir -p /home/pi/sdp\n   cp kiosk.sh /home/pi/sdp/kiosk.sh\n   chmod +x /home/pi/sdp/kiosk.sh\n   ```\n\n3. **Move service file to system location**:\n   ```bash\n   sudo cp kiosk.service /lib/systemd/system/kiosk.service\n   sudo systemctl daemon-reload\n   sudo systemctl enable kiosk.service\n   ```\n\n4. **Start kiosk mode**:\n   ```bash\n   sudo systemctl start kiosk\n   ```\n\n**Important**: The service file must be placed in `/lib/systemd/system/` for systemd to recognize it. After copying the file, run `sudo systemctl daemon-reload` to tell systemd about the new service.\n\nThe kiosk script will automatically launch Chromium in full-screen mode pointing to your SmartDisplayPi application at `http://localhost:3000`.\n\n### **Auto-Start on Boot**\n```bash\nsudo nano /etc/systemd/system/smartdisplay.service\n```\n\nAdd:\n```ini\n[Unit]\nDescription=Smart Display Service\nAfter=network.target\n\n[Service]\nType=simple\nUser=pi\nWorkingDirectory=/home/pi/SmartDisplayPi\nExecStart=/usr/bin/node server.js\nRestart=always\nEnvironment=NODE_ENV=production\n\n[Install]\nWantedBy=multi-user.target\n```\n\nEnable:\n```bash\nsudo systemctl enable smartdisplay\nsudo systemctl start smartdisplay\n```\n\n## 📄 License\n\nThis project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.\n\n---\n\n## 🔄 Recent Updates\n\n### **Performance Optimizations (Latest)**\n- **Low Power Mode Detection**: Automatically detects Raspberry Pi and adjusts performance\n- **DOM Caching**: Reduced DOM queries by 80% for better performance\n- **Throttled Updates**: Prevents excessive API calls and DOM updates\n- **Optimized Intervals**: Longer refresh times on low-power devices\n- **Event Delegation**: More efficient event handling\n- **Image Optimization**: Lower resolution images for better performance\n- **Cursor Hidden**: Clean display experience for kiosk mode\n\n### **New Features**\n- **AI Integration**: Google Gemini AI for daily summaries\n- **System Actions**: Page refresh functionality in settings\n- **Enhanced Settings**: More configuration options\n- **Better Error Handling**: Graceful fallbacks for API failures\n\n### **UI/UX Improvements**\n- **Touch Optimization**: Better touch gesture handling\n- **Responsive Design**: Improved mobile and tablet support\n- **Loading States**: Better user feedback during data loading\n- **Accessibility**: Improved keyboard navigation\n\n## 🙏 Acknowledgments\n\n### **Kiosk Mode Configuration**\nThe kiosk mode setup files (`kiosk.sh` and `kiosk.service`) are adapted from [Jeff Geerling's pi-kiosk project](https://github.com/geerlingguy/pi-kiosk). This project provides a simple and effective way to create a persistent browser kiosk on Raspberry Pi devices.\n\n**Original Project**: [geerlingguy/pi-kiosk](https://github.com/geerlingguy/pi-kiosk)  \n**License**: GPL v3  \n**Author**: Jeff Geerling\n\nThe kiosk configuration enables full-screen browser mode that automatically starts on boot, making it perfect for creating a smart display that runs continuously without user intervention.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiflyer%2Fsmartdisplaypi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiflyer%2Fsmartdisplaypi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiflyer%2Fsmartdisplaypi/lists"}