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 /etc/init.d/lighttpd restart
The user website is available at address http://servername/~username/ then,
in my case it's http://pi1/~pi/
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 %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 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"> <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 + '"> <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
That crontab entry/entries can be created/edited with:
crontab -e