diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 36562fb..7143502 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-slim-bullseye as development +FROM python:3.11-slim-bookworm as development WORKDIR /app RUN apt-get -y update && apt-get install -yqq dos2unix chromium chromium-driver \ libxi6 libgconf-2-4 python3-selenium \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 03b1ec4..1bf5540 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,17 +1,16 @@ // For format details, see https://aka.ms/devcontainer.json. { "name": "Inkycal-dev", - "build": { - "dockerfile": "Dockerfile", - "target": "development" - }, - + "build": { + "dockerfile": "Dockerfile", + "target": "development" + }, // This is the settings.json mount "mounts": ["source=/c/temp/settings_test.json,target=/boot/settings.json,type=bind,consistency=cached"], // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "chmod +x ./.devcontainer/postCreate.sh && ./.devcontainer/postCreate.sh", + "postCreateCommand": "dos2unix ./.devcontainer/postCreate.sh && chmod +x ./.devcontainer/postCreate.sh && ./.devcontainer/postCreate.sh", "customizations": { "vscode": { diff --git a/README.md b/README.md index 4608ede..8a482a2 100644 --- a/README.md +++ b/README.md @@ -1,287 +1,9 @@ -# Welcome to inkycal v2.0.3! +# Inkycal-based full screen weather display (scraper solution) -

- aceinnolab logo -

-

- featured-image -

+This fork of was used to try out a webscraper approach for a openweathermap-based full screen weather display on a 7in5 waveshare v2 colour epd. +It didn't prove particularly robust, so I've decided to not further develop it. +I'll leave it here in case someone wants to try and play around with it a little. -

- - - Version - Licence - GitHub stars - python -

+Since Selenium doesn't run on Pi Zero, I had to run the scraper part as a cron job on my Pi 4 and scp the resulting image to the Pi Zero that's connected to the e-paper display. -Inkycal is a software written in python for selected E-Paper displays. It converts these displays into useful -information dashboards. It's open-source, free for personal use, fully modular and user-friendly. Despite all this, -Inkycal can run well even on the Raspberry Pi Zero. Oh, and it's open for third-party modules! Hooray! - -## ⚠️ Warning: long installation time expected! - -Starting october 2023, Raspberry Pi OS is now based on Debian bookworm and uses python 3.11 instead of 3.9 as the -default version. Inkycal has been updated to work with python3.11, but the installation of numpy can take a very long -time, in some cases even hours. If you do not want to wait this long to install Inkycal, you can also get a -ready-to-flash version of Inkycal called InkycalOS-Lite with everything pre-installed for you by sponsoring -via [Github Sponsors](https://github.com/sponsors/aceisace). This helps keep up maintenance costs, implement new -features and fixing bugs. Please choose the one-time sponsor option and select the one with the plug-and-play version of -Inkycal. Then, send your email-address to which InkycalOS-Lite should be sent. - -## Main features - -Inkycal is fully modular, you can mix and match any modules you like and configure them on the web-ui. For now, these -following built-in modules are supported: - -* Calendar - Monthly Calendar with option to sync events from iCalendars, e.g. Google. -* Agenda - Agenda showing upcoming events from given iCalendar URLs. -* Image - Display an Image from URL or local file path. -* Slideshow - Cycle through images in a given folder and show them on the E-Paper. -* Feeds - Synchronise RSS/ATOM feeds from your favorite providers. -* Stocks - Display stocks using Tickers from Yahoo! Finance. -* Weather - Show current weather, daily or hourly weather forecasts from openweathermap. -* Todoist - Synchronise with Todoist app or website to show todos. -* iCanHazDad - Display a random joke from [iCanHazDad.com](iCanhazdad.com). - -## Quickstart - -Watch the one-minute video on getting started with Inkycal: - -[![Inkycal quickstart](https://img.youtube.com/vi/IiIv_nWE5KI/0.jpg)](https://www.youtube.com/watch?v=IiIv_nWE5KI) - -## Hardware guide - -Before you can start, please ensure you have one of the supported displays and of the supported Raspberry -Pi: `|4|3A|3B|3B+|2B|0W|0WH|02W|`. We personally recommend the Raspberry Pi Zero W as this is relatively cheaper, uses -less power and is perfect to fit in a small photo frame once you have assembled everything. - -**Serial** displays are usually cheaper, but slower. Their main advantage is ease of use, like being able to communicate -via SPI. A single update will cause flickering (fully normal on e-paper displays) ranging from a few seconds to half an -minute. We recommend these for users who want to get started quickly and for more compact setups, e.g. fitting inside a -photo frame. The resolution of these displays ranges from low to medium. Usually, these displays support 2-3 colours, -but no colours in between, e.g. fully black, fully red/yellow and fully-white. - -**Parallel** displays on the other hand do not understand SPI and require their own dedicated driver boards individually -configured for these displays. Flickering also takes place here, but an update only takes about one to a few seconds. -The resolution is much better than serial e-paper displays, but the cost is also higher. These also have 16 different -grayscale levels, which does not compare to the 256 grayscales of LCDs, but far better than serial displays. - -**❗️Important note: e-paper displays cannot be simply connected to the Raspberry Pi, but require a driver board. The -links below may or may not contain the required driver board. Please ensure you get the correct driver board for the -display!** - -| type | vendor | affiliate links to product | -|-------------------------------------------|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 7.5" Inkycal (plug-and-play) | Author of Inkycal |  [Buy on Tindie](https://www.tindie.com/products/aceisace4444/inkycal-build-v1/) Pre-configured version of Inkycal with custom frame and a web-ui. You do not need to buy anything extra. Includes Raspberry Pi Zero W, 7.5" e-paper, microSD card, driver board, custom packaging and 1m of cable. Comes pre-assembled for plug-and-play. | -| Inkycal frame | Author of Inkycal | coming soon (ultraslim frame with custom-made front and backcover inkl. ultraslim driver board). You will need a Raspberry Pi and a 7.5" e-paper display | -| `[serial]` 12.48" (1304×984px) display | waveshare / gooddisplay |  Waveshare 12.48 Inch E-Paper | -| `[serial]` 7.5" (640x384px) -> v1 display | waveshare / gooddisplay | Waveshare 7.5 Inch E-Paper | -| `[serial]` 7.5" (800x400px) -> v2 display | waveshare / gooddisplay | Waveshare 7.5 Inch E-Paper | -| `[serial]` 7.5" (880x528px) -> v3 display | waveshare / gooddisplay | Waveshare 7.5 Inch E-Paper | -| `[serial]` 5.83" (400x300px) display | waveshare / gooddisplay | Waveshare 5.83 Inch E-Paper | -| `[serial]` 4.2" (400x300px)display | waveshare / gooddisplay | Waveshare 4.2 Inch E-Paper | -| `[parallel]` 10.3" (1872×1404px) display | waveshare / gooddisplay |  Waveshare 10.3 Inch E-Paper | -| `[parallel]` 9.7" (1200×825px) display | waveshare / gooddisplay | Waveshare 9.7 Inch E-Paper | -| `[parallel]` 7.8" (1872×1404px) display | waveshare / gooddisplay |  Waveshare 7.8" E-Paper | -| Raspberry Pi Zero W | Raspberry Pi |  Raspberry Pi Zero W | -| MicroSD card | Sandisk |  MicroSD card (8GB) | - -## Configuring the Raspberry Pi - -Flash Raspberry Pi OS on your microSD card (min. 4GB) with [Raspberry Pi Imager](https://rptl.io/imager). Use the -following settings: - -| option | value | -|:--------------------------|:---------------------------:| -| hostname | inkycal | -| enable ssh | yes | -| set username and password | yes | -| username | a username you like | -| password | a password you can remember | -| set Wi-Fi | yes | -| Wi-Fi SSID | your Wi-Fi name | -| Wi-Fi password | your Wi-Fi password | -| set timezone | your local timezone | - -1. Create and download `settings.json` file for Inkycal from - the [WEB-UI](https://aceinnolab.com/inkycal/ui). Add the modules you want with the add - module button. -2. Copy the `settings.json` to the flashed microSD card in the `/boot` folder of microSD card. On Windows, this is the - only visible directory on the SD card. On Linux, copy these files to `/boot` of the microSD card. -3. Eject the microSD card from your computer now, insert it in the Raspberry Pi and power the Raspberry Pi. -4. Once the green LED has stopped blinking after ~3 minutes, you can connect to your Raspberry Pi via SSH using a SSH - Client. We suggest [Termius](https://termius.com/download/windows) - on your smartphone. Use the address: `inkycal.local` with the username and password you set earlier. For more - detailed instructions, check out the page from - the [Raspberry Pi website](https://www.raspberrypi.org/documentation/remote-access/ssh/) -5. After connecting via SSH, run the following commands, line by line: - -```bash -sudo raspi-config --expand-rootfs -sudo sed -i s/#dtparam=spi=on/dtparam=spi=on/ /boot/config.txt -sudo dpkg-reconfigure tzdata - -# If you have the 12.48" display, these steps are also required: -wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.71.tar.gz -tar zxvf bcm2835-1.71.tar.gz -cd bcm2835-1.71/ -sudo ./configure && sudo make && sudo make check && sudo make install -wget https://project-downloads.drogon.net/wiringpi-latest.deb -sudo dpkg -i wiringpi-latest.deb - -# If you are using the Raspberry Pi Zero models, you may need to increase the swapfile size to be able to install Inkycal: -sudo dphys-swapfile swapoff -sudo sed -i -E '/^CONF_SWAPSIZE=/s/=.*/=256/' /etc/dphys-swapfile -sudo dphys-swapfile setup -sudo dphys-swapfile swapon -``` - -These commands expand the filesystem, enable SPI and set up the correct timezone on the Raspberry Pi. When running the -last command, please select the continent you live in, press enter and then select the capital of the country you live -in. Lastly, press enter. - -7. Follow the steps in `Installation` (see below) on how to install Inkycal. - -## Installing Inkycal - -⚠️ Please note that although the developers try to keep the installation as simple as possible, the full installation -can sometimes take hours on the Raspberry Pi Zero W and is not guaranteed to go smoothly each time. This is because -installing dependencies on the zero w takes a long time and is prone to copy-paste-, permission- and configuration -errors. - -ℹ️ **Looking for a shortcut to safe a few hours?** We know about this problem and have spent a signifcant amount of time -to prepare a pre-configured image with the latest version of Inkycal for the Raspberry Pi Zero. It comes with the latest -version of Inkycal, is fully tested and uses the Raspberry Pi OS Lite as it's base image. You only need to copy your -settings.json file, we already took care of the rest, including auto-start at boot, enabling spi and installing all -dependencies in advance. Pretty neat right? Check the [sponsor button](https://github.com/sponsors/aceisace) at the very -top of the repo to get access to Inkycal-OS-Lite. This will help keep this project growing and cover the ongoing -expenses too! Win-win for everyone! 🎊 - -### Manual installation - -Run the following steps to install Inkycal. Do **not** use sudo for this, except where explicitly specified. - -```bash -# the next line is for the Raspberry Pi only -sudo apt-get install zlib1g libjpeg-dev libatlas-base-dev rustc libopenjp2-7 python3-dev scons libssl-dev python3-venv python3-pip git libfreetype6-dev wkhtmltopdf -cd $HOME -git clone --branch main --single-branch https://github.com/aceinnolab/Inkycal -cd Inkycal -python3 -m venv venv -source venv/bin/activate -python -m pip install --upgrade pip -pip install wheel -pip install -e ./ - -# If you are running on the Raspberry Pi, please install the following too to allow rendering on the display -pip install RPi.GPIO==0.7.1 spidev==3.5 -``` - -## Running Inkycal - -To run Inkycal, type in the following command in the terminal: - -```bash -cd $HOME/Inkycal -source venv/bin/activate -python3 inky_run.py -``` - -## Running on each boot - -To make inkycal run on each boot automatically, you can use crontab. Do not use sudo for this - -```bash -(crontab -l ; echo "@reboot sleep 60 && cd $HOME/Inkycal && venv/bin/python inky_run.py &")| crontab - -``` - -## Updating Inkycal - -To update Inkycal to the latest version, navigate to the Inkycal folder, then run: - -```bash -git pull -``` - -Yep. It's actually that simple! -But, if you have made changes to Inkycal, those will be overwritten. -If that is the case, backup your modified files somewhere else if you need them. Then run: - -```bash -git reset --hard -git pull -``` - -## Uninstalling Inkycal - -We'll miss you, but we don't want to make it hard for you to leave. -Just delete the Inkycal folder, and you're good to go! - -Additionally, if you want to reset your crontab file, which runs inkycal at boot, run: - -```bash -crontab -r -``` - -## Modifying Inkycal - -Inkycal now runs in a virtual environment to support more devices than just the Raspberry Pi. Therefore, to make changes -to Inkycal, navigate to Inkycal, then run: - -```bash -cd $HOME/Inkycal && source venv/bin/activate -``` - -Then modify the files as needed and experiment with Inkycal. -To deactivate the virtual environment, simply run: - -```bash -deactivate -``` - -## 3D printed frames - -With your setup being complete at this stage, you may want to 3d-print a case. The following files were shared by our -friendly community: -[3D-printable case](https://github.com/aceinnolab/Inkycal/wiki/3D-printable-files) - -## Contributing - -All sorts of contributions are most welcome and appreciated. To start contributing, please follow -the [Contribution Guidelines](https://github.com/aceisace/Inkycal/blob/main/.github/CONTRIBUTING.md) - -The average response time for issues, PRs and emails is usually 24 hours. In some cases, it might be longer. If you want -to have some faster responses, please use Discord (link below) - -**P.S:** Don't forget to star and/or watch the repo. For those who have done so already, thank you very much! - -## Join us on Discord! - -We're happy to help, to beginners and developers alike. In fact, you are more likely to get faster support on Discord -than on Github. - - - Inkycal chatroom Discord - - -## Sponsoring - -Inkycal relies on sponsors to keep up maintainance, development and bug-fixing. Please consider sponsoring Inkycal via -the sponsor button if you are happy with Inkycal. - -We now offer perks depending on the amount contributed for sponsoring, ranging from pre-configured OS images for -plug-and-play to development of user-suggested modules. Check out the sponsor page to find out more. -If you have been a previous sponsor, please let us know on our Dicord server or by sending an email. We'll send you the -perks after confirming 💯 - -## As featured on - -* [makeuseof - fantastic projects using an eink display](http://makeuseof.com/fantastic-projects-using-an-e-ink-display/) -* [magpi.de](https://www.magpi.de/news/maginkcal-ein-kalender-mit-epaper-display-und-raspberry-pi) -* [reddit - Inkycal](https://www.reddit.com/r/InkyCal/) -* [schuemann.it](https://schuemann.it/2019/09/11/e-ink-calendar-with-a-raspberry-pi/) -* [huernerfuerst.de](https://www.huenerfuerst.de/archives/e-ink-kalender-mit-einem-raspberry-pi-zero-teil-1-was-wird-benoetigt) -* [raspberrypi.com](https://www.raspberrypi.com/news/ashleys-top-five-projects-for-raspberry-pi-first-timers/) -* [canox.net](https://canox.net/2019/06/raspberry-pi-als-e-ink-kalender/) +For further information see the official Inkycal repo. diff --git a/inkycal/modules/inkycal_openweather_scrape.py b/inkycal/modules/inkycal_openweather_scrape.py index 42185d7..45b1ab9 100644 --- a/inkycal/modules/inkycal_openweather_scrape.py +++ b/inkycal/modules/inkycal_openweather_scrape.py @@ -1,29 +1,32 @@ +import sys +import time + from PIL import Image from PIL import ImageEnhance from selenium import webdriver -from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException +from selenium.common.exceptions import ElementClickInterceptedException +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import TimeoutException from selenium.webdriver.chrome.options import Options from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.wait import WebDriverWait -import sys -import time def get_scraped_weatherforecast_image() -> Image: # Set the desired viewport size (width, height) my_width = 480 my_height = 850 mobile_emulation = { - "deviceMetrics": { "width": my_width, "height": my_height, "pixelRatio": 1.0 }, - "userAgent": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19" + "deviceMetrics": {"width": my_width, "height": my_height, "pixelRatio": 1.0}, + "userAgent": "Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19", } # Create an instance of the webdriver with some pre-configured options options = Options() options.add_argument("--no-sandbox") options.add_argument("--headless=new") - #options.add_argument("--disable-gpu") + # options.add_argument("--disable-gpu") options.add_argument("--disable-dev-shm-usage") options.add_experimental_option("mobileEmulation", mobile_emulation) service = Service("/usr/bin/chromedriver") @@ -38,7 +41,7 @@ def get_scraped_weatherforecast_image() -> Image: driver.execute_script("return arguments[0].scrollIntoView();", login_button) # Click the button button_clicked = False - while(button_clicked == False): + while button_clicked == False: try: login_button.click() button_clicked = True @@ -49,9 +52,12 @@ def get_scraped_weatherforecast_image() -> Image: # hacky wait statement for all the page elements to load page_loaded = False - while(page_loaded == False): + while page_loaded == False: try: - WebDriverWait(driver, timeout=45).until(lambda d: d.find_element(By.XPATH, '//*[@id="weather-widget"]/div[2]/div[1]/div[1]/div[1]/h2').text != "") + WebDriverWait(driver, timeout=45).until( + lambda d: d.find_element(By.XPATH, '//*[@id="weather-widget"]/div[2]/div[1]/div[1]/div[1]/h2').text + != "" + ) page_loaded = True except TimeoutException: print("Couldn't get the page to load, retrying...") @@ -66,11 +72,11 @@ def get_scraped_weatherforecast_image() -> Image: driver.execute_script("arguments[0].remove();", map_element) # remove the hourly forecast - #map_element = driver.find_element(By.XPATH, '//*[@id="weather-widget"]/div[2]/div[2]/div[1]') - #driver.execute_script("arguments[0].remove();", map_element) + # map_element = driver.find_element(By.XPATH, '//*[@id="weather-widget"]/div[2]/div[2]/div[1]') + # driver.execute_script("arguments[0].remove();", map_element) # zoom in a little - not now - driver.execute_script("document.body.style.zoom='110%'"); + driver.execute_script("document.body.style.zoom='110%'") html_element = driver.find_element(By.TAG_NAME, "html") driver.execute_script("arguments[0].style.fontSize = '16px';", html_element) @@ -83,18 +89,20 @@ def get_scraped_weatherforecast_image() -> Image: driver.quit() # crop, resize, enhance & rotate the image for inky display - im = Image.open(image_filename, mode='r', formats=None) - im = im.crop((0, 100, (my_width-50), (my_height-50))) + im = Image.open(image_filename, mode="r", formats=None) + im = im.crop((0, 100, (my_width - 50), (my_height - 50))) im = im.resize((480, 800), resample=Image.LANCZOS) - #im = im.rotate(90, Image.NEAREST, expand = 1) + # im = im.rotate(90, Image.NEAREST, expand = 1) im = ImageEnhance.Contrast(im).enhance(1.0) im.save(image_filename) return im, im + def main(): _, _ = get_scraped_weatherforecast_image() -if __name__ == '__main__': + +if __name__ == "__main__": now = time.asctime() print(f"It's {now} - running {__name__} in standalone/debug mode") main() diff --git a/run_weather_scraper.sh b/run_weather_scraper.sh index 84480ed..7da98fd 100755 --- a/run_weather_scraper.sh +++ b/run_weather_scraper.sh @@ -1,3 +1,3 @@ #!/bin/sh -python3 /home/ubuntu/Inkycal/inkycal/modules/inkycal_openweather_scrape.py +python3 /home/ubuntu/Inkycal/inkycal/modules/inkycal_openweather_scrape.py scp -i /home/ubuntu/.ssh/id_rsa /tmp/openweather_scraped.png inky@10.10.9.10:~/Inkycal/