Back to my Raspberry Pi page

Raspberry Pi Webcam

(Note: The old version (for Raspbian Wheezy and Jessie) ist still available here.)

In 2014 I purchased a camera module for the Pi.

With the camera module I built a webcam, documenting the growth of our tomatoes on the balcony like a flip-book. ;-).

A demo of the webcam page can be seen here.

Since the webcam software I found online didn't fit my needs and it's fun to do it by oneself, I created my own.
It only consists of two small bash scripts combined with a bit of HTML and Javascript code,
served by an HTTP server on the Pi (lighttpd in my case).

The webserver lighttpd only needs a simple configuration change to work for this task:
It should serve user-created data (in the user directory ~/public_html) additionally to the root data.


sudo apt-get install lighttpd
cd /etc/lighttpd/conf-enabled
sudo ln -s ../conf-available/10-userdir.conf
sudo systemctl restart lighttpd

The user website will be available at address http://servername/~username/ then,
in my case it's http://pi1/~pi/

The main website is stored in the file /var/www/html/index.html

Initially that one doesn't exist, but a placeholder named index.lighttpd.html in the same directory.

I'm using the following in index.html.


<!doctype html>
<html>
<head>
<meta type="text/html" charset="utf-8">
<meta http-equiv="refresh" content="3; url=~pi/">
<title>pi1's webcam root page</title>
</head>
<body>
<h1>Test - Website</h1>
<p> Automatic redirection to the page of user 'pi' in 3 seconds...  </p>
</body>
</html>

You might want to use the editor nano to create it:


sudo nano /var/www/html/index.html

Then create the needed directories:


mkdir -p ~/public_html/images
mkdir -p ~/public_html/templates
mkdir -p ~/bin

The following two scripts should be stored in a directory being in the PATH, e.g. your ~/bin.

First the script klick which takes the picture(s) and stores them in a directory accessible by the webserver:


#!/bin/bash

targetdir=~/public_html/images
filename=p_$(date +"%Y-%m-%d_%H-%M").jpg
lastfilename=p-last.jpg

raspistill -w 800 -h 600 -t 10 -o ${targetdir}/${filename} -l ${targetdir}/${lastfilename}

So there are a few (or many) picture files with timestamp in their names and the most recent picture named p-last.jpg additionally.

The following script makenavi creates a navigation document in HTML (~/public_html/navigation.html) from the collected pictures,
using a template file ~/public_html/templates/navigation.template shown further down.


#!/bin/bash

cd ~/public_html

if [ ! -f templates/navigation.template ] ; then
  echo ""
  echo "Error: No navigation.template file found in ~/public_html/templates/"
  exit 1
fi

(
sed -e '/@IMAGES@/,$d' templates/navigation.template

echo "<ul>"

ls -1t images/p_* | awk '{printf "  <li onmouseover=\"showpic('\''%s'\'')\"> %s &nbsp;%s:%s </li>\n", substr($0,8,22), substr($0,10,10), substr($0,21,2), substr($0,24,2)}'

echo "</ul>"

sed -e '1,/@IMAGES@/d' templates/navigation.template

) > navigation.html

The above created HTML file ~/public_html/navigation.html gets embedded in the main html file ~/public_html/index.html:


<!doctype html>
<html id="htmlindex">
<head>
<meta type="text/html" charset="utf-8">
<meta http-equiv="refresh" content="300">
<title>pi1's webcam page</title>
<noscript>
  <b>Scripting needs to be allowed for a proper function!</b>
</noscript>
</head>

<body id="indexbody">

<h1>My garden-webcam</h1>

<p>
  A new picture will be taken every hour.
  If this window is active it should be refreshed every 5 minutes (300 seconds) with the most current picture automatically - if the browser supports this ... <br>
  To browse through the pictures simply hover over the filenames.
</p>

<div id="navdiv" style="width: 20em ; float: left;">
  <nav id="nav">
  <iframe id="obj" src="navigation.html" style="width: 18em; height:600px; border:0;">
  Here the navigation should appear...
  </iframe>
  </nav>
</div>

<div id="picture" style="width:850px; height: 650px; float: right;">
  <img src="images/p-last.jpg" style="width:800px; height: 600px; "> <br>
  most current picture
</div>

</body>
</html>

Here the above mentioned template file ~/public_html/templates/navigation.template:


<!doctype html>
<html>
<head>
<meta type="text/html" charset="utf-8">
<base target="picture">
<title>Navigation</title>
<script>

function showpic(p) {
  parent.document.getElementById('picture').innerHTML =
    '<img src="images/' + p +'" title="' + p + '" style="width:800px; height: 600px;"> <br>' + p;
}

function dofilter() {
  var ft1 = document.getElementById("filtertext").value;

  for (var i = 0; i < document.getElementsByTagName("li").length; i++)
  {
    var ob1 = document.getElementsByTagName("li")[i];
    var at1 = ob1.attributes[0];
    var va1 = ob1.firstChild.nodeValue;
    /*
     * // simple string search
     * if ( va1.indexOf(ft1) == -1 ) {
     */

    // regular expression search
    // see http://www.hunlock.com/blogs/The_Complete_Javascript_Strings_Reference for details
    if ( va1.search(ft1) == -1 ) {
      ob1.hidden= "hidden";
    } else {
      ob1.hidden= "";
    }
  }
}
</script>

<style>
  ul { list-style-type: none;
       font-size: 0.5em;
       line-height: 110%;
     }
  ul li { cursor: pointer; }
</style>
</head>

<body>

<p>The pictures, sorted by date/time:
</p>

<!-- The ENTER key needs to be handled separately here too. -->
<input type="text" name="filtertext" id="filtertext" value="" size="16em"
       title="normal text or a regular expression to filter by"
       onkeypress="if (event.keyCode == 13) {dofilter(); return false;} else {return true;}">
<input type="button" name="filter" value="filter" onclick="dofilter()">
<input type="button" name="clearfilter" value="all"
       onclick="document.getElementById('filtertext').value = '';dofilter()">

@IMAGES@

</body>
</html>

The webcam is operated by a crontab entry every hour between 05:00 and 22:00 o'clock:

# m h  dom mon dow   command
00 5-22 * * * /home/pi/bin/klick && /home/pi/bin/makenavi

The crontab entry/entries can be created/edited with:

 
crontab -e