Convert your Raspberry Pi into a smart Bedside Clock.
UPDATE: I no longer have the patience for JavaScript, so moving the implementation over to python, which should hopefully have better long term maintainability than Node.js did. (Famous last words)
UPDATE: bedside-pi has been updated to use Node.js with
Socket.io rather than Apache with long polling. However, you can still
access the Apache Version
BedSide Pi provides information at a glance.
- Time (Who would've thunk?)
- Current Weather (Optional)
BedSide Pi requires a bare minimum of
- Raspberry Pi (Tested on RPi 3b and RPi 4b, your mileage may vary) running Raspbian.
- A screen to display the information
- Technically, does not have to be the Raspberry PI. Any browser that can access the Raspberry Pi's IP will do..
- [Optional] API Key from PirateWeather
Direct Execution
Note: This process assumes you have a Raspberry Pi 4. If you have some other model, or are on a different machine, you might have to change a few things.
-
Install Python
Python comes built in with Raspbian distribution. Just make sure you have a reasonably new version of Python 3.
Python version can be checked by running
$ python --versionFor some dependencies (namely fastapi) you might need CPython symbols, which can be installed with
$ sudo apt install python3.11-devwhere
3.11should be replaced with the specific version of python you have installed.For reference, these are the versions I have on my RPi 4b:
$ python --version Python 3.11.2 $ pip --version pip 23.0.1 from /home/pi/projects/bedside-pi/env/lib/python3.11/site-packages/pip (python 3.11)
-
Set up virtual environment (Optional, but recommended)
It is generally recommended to have virtual environments for different Python projects. This allows various python projects to use their own dependency versions without interfering with each other.
One no-frills virtual environment is
venv, which can be installed using:$ sudo apt install python3.11-venvOnce again, replace
3.11with whatever python version you have installed on your system.
-
Download this project:
Either clone repo using git CLI or download the entire project as a zip, your wish!
For this example, I'll assume the project lives in
~/projects/bedside-pi. -
Create a virtual environment (Optional, but recommended):
Use your favorite virtual environment tool to create a virtual environment for
bedside-pi.If you chose
venvfrom above, the virtual environment can be created as:$ cd ~/projects/bedside-pi $ python -m venv env # creates an env/ directory containing the virtual environment.
This needs only be done once.
Once the virtual environment is created, you can activate the environment by running:
$ cd ~/projects/bedside-pi $ . env/bin/activate # activates the virtual environment for this terminal session only.
This would need to be done for every new terminal session.
You can check that your virtual environment is active by looking at the beginning of your terminal prompt, which will look something like this if it is activated:
(env) user@hostname:~/projects/bedside-pi$Or, you can run
which pythonand check if it points to your environment:pi@bedsidepi:~/projects/bedside-pi $ which python # environment NOT active /usr/bin/python # system Python pi@bedsidepi:~/projects/bedside-pi $ . env/bin/activate # activate environment (env) pi@bedsidepi:~/projects/bedside-pi $ which python # environment active /home/pi/projects/bedside-pi/env/bin/python # environment Python
-
Install dependencies:
With the virtual environment activated, you can now install the dependencies with:
$ pip install -r requirements.txt
-
Setting up weather:
- Sign up and get an API key from PirateWeather
- Open
user_prefs.yaml - Copy the API key from PirateWeather to
apiKey - Update
latitudeandlongitudewith your location. - (Optional) Set
refreshIntervalwhich is how frequently the weather will be updated (in minutes).- NOTE: It might seem obvious, but weather does not change very frequently, so there is little need to refresh it every other minute.
-
Removing weather:
- Open
user_prefs.yaml - Set
enabledunderweatherPrefstoFalse
- Open
To run bedside-pi, use the following commands:
$ cd ~/projects/bedside-pi
$ . env/bin/activate # (optional) for venv users. Use whatever your virtual environment command is.
$ fastapi run server.py --user-prefs ./user_prefs.yamlNote: The path to user_prefs.yaml can be provided either via the --user-prefs CLI argument or the USER_PREFS_PATH environment variable. The CLI argument takes precedence over the environment variable.
This will start the server on port 8000.
You can now access the bedside-pi UI by navigating to http://localhost:8000 in any web browser.
If you're like me you probably want to run bedside-pi automatically when your Raspberry Pi boots.
Thankfully that is easy enough to do with crontab.
-
First create a script to run
bedside-pi, for example~/run_bedside_pi.sh.It could look something like:
#!/bin/bash cd ${HOME}/projects/bedside-pi . ./env/bin/activate fastapi run server.py
Make sure to give it execute permissions with
chmod +x ~/run_bedside_pi.sh. -
Add
crontabentry to startbedside-pion boot$ crontab -eThis will open the crontab file in your default text editor.
Add the following line:
@reboot /home/pi/run_bedside_pi.sh >> /home/pi/bedside_pi.logThis will run the script on boot and log output to
~/bedside_pi.log. -
(Optional) Run chrome in kiosk mode on boot:
Add the following line to the crontab file:
@reboot sleep 20 && chromium-browser --display=:0 --kiosk http://localhost:8000 >> /home/pi/chromium.logThis will start Chromium in kiosk mode on boot, pointing to your local BedSide Pi instance. The
sleep 20lets the bedside-pi script start before Chromium tries to connect. -
Reboot the Raspberry Pi and wait for
bedside-pito start automatically!
Docker Execution
To run bedside-pi using Docker, where the image is built directly from the GitHub repository, follow these steps:
-
Docker and Docker Compose installed on your system.
curl -sSL https://get.docker.com | sh
You can build the Docker image directly from the GitHub repository without cloning it locally. Simply run:
docker build -t bedside-pi:latest https://github.com/avirakesh/bedside-pi.gitThis command will fetch the repository, find the Dockerfile at the root, and build the image.
The user_prefs.yaml file, which contains your API keys and location settings, needs to be mounted into the Docker container at runtime. Ensure you have your desired user_prefs.yaml file in a known location on your host system.
Start by copying the user_prefs.yaml to a known location.
-
Setting up weather:
- Sign up and get an API key from PirateWeather
- Open
user_prefs.yaml - Copy the API key from PirateWeather to
apiKey - Update
latitudeandlongitudewith your location. - (Optional) Set
refreshIntervalwhich is how frequently the weather will be updated (in minutes).- NOTE: It might seem obvious, but weather does not change very frequently, so there is little need to refresh it every other minute.
-
Removing weather:
- Open
user_prefs.yaml - Set
enabledunderweatherPrefstoFalse
- Open
-
Create a
docker-compose.ymlfile in a directory of your choice (e.g.,/home/pi/bedside-pi-docker) with the following content.services: bedside-pi: image: bedside-pi container_name: bedside-pi-app ports: - "8000:8000" volumes: - "./user_prefs.yaml:/config/user_prefs.yaml" environment: USER_PREFS_PATH: /config/user_prefs.yaml restart: unless-stopped
-
Make sure your
user_prefs.yamlis in the same directory as yourdocker-compose.ymlor provide the correct path in thevolumessection. -
Then, navigate to the directory containing your
docker-compose.ymlanduser_prefs.yamland run:docker compose up -dThis will start the
bedside-picontainer in detached mode. -
To stop the container:
docker compose down
If you prefer not to use Docker Compose, you can run the container directly with the following:
docker run -p 8000:8000 \
--name bedside-pi-app -d \
-v "$(pwd)/user_prefs.yaml:/config/user_prefs.yaml" \
-e USER_PREFS_PATH=/config/user_prefs.yaml bedside-pi:latest- Replace
$(pwd)/user_prefs.yamlwith the absolute path to youruser_prefs.yamlfile if it's not in the current directory. - The
-e USER_PREFS_PATH=/app/user_prefs.yamlflag tells the application inside the container where to find the mounted configuration file.
To stop and remove the container:
docker stop bedside-pi-app && docker rm bedside-pi-appOnce the container is running (either via Docker Compose or direct Docker run), you can access the bedside-pi UI by navigating to http://localhost:8000 in any web browser.
-
Stop the container if it's currently running:
docker compose down # when using docker compose docker stop bedside-pi-app && docker rm bedside-pi-app # when running directly with docker
-
Rebuild docker image using Build the Docker Image from GitHub
-
Restart the container, either using Docker Compose or directly.
-
Ensure
docker.serviceis enabled in systemdsystemctl enable docker -
Start container on boot:
-
Create
/etc/systemd/system/bedside-pi-docker.service:[Unit] Description=Bedside Pi Docker Container Requires=docker.service After=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=/home/pi/bedside-pi-docker # skip if using 'docker run ...' ExecStart=docker compose up -d # or 'docker run ...' ExecStop=docker compose down # or 'docker stop ...' TimeoutStartSec=0 [Install] WantedBy=multi-user.target
-
Reload systemd daemon:
systemctl daemon-reload -
Enable the service:
systemctl enable bedside-pi-docker
-
-
Start frontend on boot:
-
Create
~/.config/systemd/user/bedside-pi-frontend.service:[Unit] Description=Bedside Pi Frontend [Service] Type=oneshot RemainAfterExit=yes ExecStartPre=/bin/sleep 60 # wait 60s for docker service and container # to boot ExecStart=chromium --display=:0 --kiosk http://localhost:8000 TimeoutStartSec=120 [Install] WantedBy=default.target
-
Reload systemd daemon:
systemctl --user daemon-reload -
Enable the service:
systemctl --user enable bedside-pi-frontend
-
There are a few options to customize bedside-pi in user_prefs.yaml:
use24HrClock: Use 24-hour format instead of AM/PM.showSeconds: Show seconds on the clock display.showLightsToggle: Show button to toggle lights on/off.days: List of days to be used. Change to whatever word/language you want displayed.months: List of months to be used. Change to whatever word/language you want displayed.
Once bedside-pi is running, using it is simple: Use your eyeballs to look at it!
However, there are a few interaction in the UI:
- Tapping the weather will fetch new data and update the display with latest weather information.
- Tapping the lights toggle on the bottom right will toggle lights out mode,
which dims the screen (while keeping the clock barely visible).
- This will only show up if
showLightsToggleis set toTrue. - Note that for most LCD monitors, this won't turn off the backlight, but it should significantly reduce the the light produced by the screen.
- This will only show up if
All images in this repo were generated using Nano Banana. The images were generated using the prompt of the following pattern:
Create a watercolor painting of a cityscape on a [clear|cloudy|etc...] [day|night]
"THE BEER-WARE LICENSE" (Revision 42):
Avichal Rakesh wrote this project. As long as you retain this notice you can do
whatever you want with this stuff. If we meet some day, and you think this stuff
is worth it, you can buy me a beer in return. Avichal Rakesh
