Use your Raspberry Pi and an (old) monitor to create a smart wall clock

If you happen to have a spare Raspberry Pi lying around, you might know that they're quite fun to tinker with.

I wanted to create a smart wall clock powered by my Raspberry Pi using PHP and HTML for the logic and the interface. As an extra challenge, I only wanted the monitor to be powered on when my Raspberry Pi senses motion using a USB Logitech webcam!
 It's really easy to set up a PHP web server on the Raspberry Pi so I'm not going to explain that in this blog post, as there are lots of tutorials for it.

Using PHP and HTML I created a webpage that automatically requested my upcoming homework, the current weather and of course the current time and date. Using JavaScript I dynamically request updates to the information on the webpage and of course the date and time are automatically updated. Now, how would I show this on the monitor connected to my Raspberry Pi? Well, it's easy and both complicated at the same time. It's easy to open webpages on your Raspberry Pi – The Midori webbrowser has a built-in kiosk mode which allows for fullscreen display of webpages, and there's software named 'Unclutter' to automatically hide the mouse cursor when it's not in use; Perfect for dedicating the complete screen to the webpage! Unfortunately, there is also the complicated part of my problem: Showing this all on the monitor, when you're controlling the Pi via your computer (using an SSH connection)! Due to security measures, it is not default by possible to open applications on the desktop, even when explicitly stating the monitor's number in the commands, when you are sending these commands from a different 'session'. Your SSH session is different from the session that is used to display the desktop on your monitor.

Here's how my dashboard, as I call it, looks:

How it looks is completely up to you! That's what I find so cool about the project, you can completely customise and brand it to your own needs. I added my homework and the weather to the page, and set up the background to change every day (using Bing's image of the day). You probably won't have the ability or need to display this information, or maybe it isn't even a clock in your case!

After a few Google searches on the errors that I got when trying to open Midori from my terminal on my Mac, I managed to find out that the session with the desktop visible has to execute the following command to allow access to its desktop, from any other logged in user: xhost +. Yep, that little command is the solution to the problem!
But how would I be able to execute this command from the desktop session every time the Raspberry Pi boots, without me actually having to execute it? I found out that by placing it in the ~/.config/lxsession/LXDE-pi/autostart file it automatically gets executed by the current user when the desktop environment is loaded.
My ~/.config/lxsession/LXDE-pi/autostart file looks like this now:
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@point-rpi
@xhost +
@xset -display :0 s off
@xset -display :0 -dpms
@xset -display :0 s noblank
The 3 lines all beginning with 'xset' are used to tell the desktop application to stop the display from sleeping automatically. Raspbian has a built-in screensaver which blanks the screen, but this is not what I wanted for my project.

Perfect. Now I can finally open the Midori browser at the right URL and hide the cursor using the following commands:
sudo midori -e Fullscreen --display :0 -a http://localhost/dashboard &>/dev/null &
sudo unclutter -display :0
I put these commands in a script named 'start-motion.sh' in ~/Documents/scripts/start-motion.sh:
#!/bin/bash
DISPLAY=:0.0 ; export DISPLAY
sudo midori -e Fullscreen --display :0 -a http://localhost/dashboard &>/dev/null &
sudo unclutter -display :0
sleep 0.3
/opt/vc/bin/tvservice -p ; chvt 6; chvt 7
sudo chvt 9 && sudo chvt 7
sudo fbset -accel true
As you can see, this script actually contains more than just the command to open Midori and to hide the mouse cursor! In the beginning of the blog post, I mentioned that I did not want the monitor to be on when there's no motion detected by a connected USB webcam. Using these commands, the monitor gets enabled after it's been disabled.
In order to close the browser and disable the monitor again, I used the following script, conveniently named 'stop-motion.sh':
#!/bin/bash
/opt/vc/bin/tvservice -p ; /opt/vc/bin/tvservice -o
sudo killall midori
Good, we now have 2 scripts that allow us to:
  • Open the Midori browser in kiosk mode, hide the mouse cursor and turn on the monitor (signal)
  • Close the Midori browser and turn off the monitor
If this is all working correctly, we can finally set up the Motion detecting software. Typically enough, the software is called 'Motion'. Using the Pi's package manager you can install it using the following command:
sudo apt-get install motion

After that's been installed, it's time to configure motion. Due to there being a lot of webcams on the market, I am only going to discuss a few options in the configuration file that I am using (please do look up the documentation for Motion so that it works best in your case).

Here's a few options from my Motion configuration file, with comments added by me – Do not copy these settings directly, but locate them in the config file on your system and change them accordingly:

#I do not need a higher framerate for motion sensing. Higher framerates cost more processing power.
framerate 10 
#I have changed my noise level to 40 since my webcam has a bit of a noise issue when it's dark
noise_level 40
#The event_gap: I recommend you to not set this value too low! This is the amount of time the application will keep the script active after motion has been detected. If it senses motion again within this gap, the script keeps being active and the timer resets. I have set mine to 15 seconds, but I recommend that you use 30, 60 or more.
event_gap 15
#I am not using this for surveillance, but rather for detecting motion, so I have disabled that it saves pictures when motion has been detected.
output_pictures off
#This is important for our use-case! on_event_start and on_event_end can be used to start scripts on specific events. This is what we will need to start and stop the webbrowser script when motion has been detected, and when no motion has been detected after the event_gap has passed. I have entered the paths to where I have stored my scripts, you might need to change this to your own ones.
on_event_start /home/pi/Documents/scripts/start-motion.sh >/tmp/motion.log 2>&1
on_event_end /home/pi/Documents/scripts/stop-motion.sh >/tmp/motion.log 2>&1

Good. If the motion software detects motion, it executes the start-motion.sh script. When there is no motion for the entire duration of the event gap, the stop-motion.sh script is executed, which is exactly what we want! Now, there is a new problem (they don't stop coming!): Both of these scripts contain 'sudo' commands, which means that usually a password has got to be entered. Normal applications do not even have the rights to use these commands, so if you would already have restarted the Motion service you can see in /tmp/motion.log that it's not allowed to start the web browser or enable the monitor at all!

Luckily, this can be resolved by allowing the users of the 'Motion' group on your Pi to execute any command. The motion software is an user in this group, so its permissions get changed accordingly. You can do this by opening the sudoers file using the following command: sudo visudo. Add the following 2 lines to the end of the file and save it:

motion ALL = NOPASSWD: ALL
Defaults:motion !requiretty

Now the Motion software may execute these scripts and automatically enable or disable your monitor, with the webbrowser displaying your own webpage in fullscreen! Restart the motion service and try to see if this works for you!

This is roughly what I have done on my own Pi, but it could be possible that I forgot any crucial steps in getting this to work – permissions to do specific things were quite a hassle to deal with.

Thanks for reading!

2017-01-17 16:15