Raspberry Pi WebCam with 3G (Solarcam): Difference between revisions

From Wurst-Wasser.net
Jump to navigation Jump to search
Line 27: Line 27:
  for x in 2323 4242; do nmap -Pn --host_timeout 201 --max-retries 0 -p $x my_fqdn; done
  for x in 2323 4242; do nmap -Pn --host_timeout 201 --max-retries 0 -p $x my_fqdn; done


==== Script: Take picture every minute ====
==== Scripts ====
Add this to crontab:
Add this to crontab:
  # DS18B20
  # DS18B20

Revision as of 23:36, 24 April 2018

The Idea

  • Use solar panel to harvest energy
  • Store the energy in a left over car battery
  • Power a Pi, camera and 3G-Stick Mobile HotSpot[1]
  • Make a nice webcam out of it :)

Shopping List

  • A Pi with camera :)
  • A mobile Hotspot (I used a Huawei E1750C). Because getting an UMTS-Stick getting to work with an Pi sucks. Additionally you can easily join the WiFi network for maintenance)
  • SIM Card
  • (used) Car battery, in my case an 74Ah battery with one dead cell
  • Solar panel (12V, 30W eBay around 40€) NOTE: Might be to small!
  • Solar charger (f.e. "10A 12V/24V PWM solar panel regler solarpanel" @ ebay for around 15€)
  • more to come…

How To

Update your Pi to the latest Linux version

See https://www.datenreise.de/raspberry-pi-raspbian-linux-wheezy-jessie-upgrade/

Scripts

Scripts running on the Pi

knock.sh
#!/bin/bash

# knock on -heavens- servers door...(bad joke. sorry)

for x in 2323 4242; do nmap -Pn --host_timeout 201 --max-retries 0 -p $x my_fqdn; done

Scripts

Add this to crontab:

# DS18B20
*/15 * * * *	/home/pi/Development/temperature/readTemperature.sh > /dev/null 2>&1
#
# PiCam - Take Snapshot(s)
*/15 * * * *	/home/pi/Development/webcam/takePicture.sh > /dev/null 2>&1
takePicture.sh
#!/bin/bash
#set -x
#
# http://www.wurst-wasser.net/wiki/index.php/Raspberry_Pi_WebCam_with_3G
#
# Globals
#
GFOLDERTARGET="/var/www/html/webcam-archive"
GFILELOCK="${GFOLDERTARGET}/takePicture.lck"
GFILELOCKAGEMAX="60"
GTIMESTAMP="`date +'%Y-%m-%d_%H-%M-%S'`" 
GTIMESTAMPDATE="`date +'%Y-%m-%d'`" # Human readable
GTIMESTAMPTIME="`date +'%H:%M:%S'`" # Human readable
GTIMESTAMPMINUTES="`date +'%M'`"
GTIMESTAMPHOURS="`date +'%H'`"
#GTIMESTAMPHOURS="16"
#GTIMESTAMPMINUTES="00"
GFILETARGET="${GFOLDERTARGET}/${GTIMESTAMP}.jpg"
GFILELASTSNAP="/var/www/html/webcam/lastsnap.jpg"
GUPLOADEVERYTIME=0
GBASENAME="${0}"
function log
{
   logger "${GBASENAME}: $1"
   echo $1
} 
if [ "${1}" = "-f" ]; then
  log "Forcing upload."
  GUPLOADEVERYTIME=1
fi
#
#
#
# Main
#
#
# Check locking
if [ -f "${GFILELOCK}" ]; then 
  LOCKFILEAGE="`stat --format=\"%Z\" \"${GFILELOCK}\"`"
  NOW="`date +'%s'`"
  AGE="`expr ${NOW} - ${LOCKFILEAGE}`"
  if [ "${AGE}" -gt "${GFILELOCKAGEMAX}" ]; then
     log "Lockfile is ${AGE} seconds old, removing it."
     rm "${GFILELOCK}"
  else
     log "Lockfile is ${AGE} seconds old, exiting."
     exit 1
  fi
fi
#
#
# Lock
echo $$ > "${GFILELOCK}"
#
# timeout should not be 0, since images will be to dark and are noisy
#raspistill --nopreview -t 1 -w 1024 -h 768 -o -
# 
# Since my cam is mounted wrong, I prefer to flip it :) (and flop it)
#raspistill --nopreview -t 2 -w 1024 -h 768 -o - | convert - -flip -flop -
#raspistill --nopreview -w 1024 -h 768 -o - | convert - -flip -flop -
raspistill --nopreview -w 1024 -h 768 -o - | convert - -flip -flop - > "${GFOLDERTARGET}/lastsnap.tmp"
#
# Bild verkleinern...
mogrify -quality "80%" -interlace Plane "${GFOLDERTARGET}/lastsnap.tmp"
#mogrify -stroke white -pointsize 10 -gravity SouthEast -draw "text 0,0 '${GTIMESTAMPHR}'" "${GFOLDERTARGET}/lastsnap.tmp"
#mogrify -stroke white -pointsize 10 -gravity SouthWest -draw "text 0,0 '${GTIMESTAMPDATE}'" "${GFOLDERTARGET}/lastsnap.tmp" 
#mogrify -stroke white -pointsize 10 -gravity SouthEast -draw "text 0,0 '${GTIMESTAMPTIME}'" "${GFOLDERTARGET}/lastsnap.tmp"
mogrify -stroke black -pointsize 10 -gravity NorthWest -draw "text 0,0 '${GTIMESTAMPDATE}'" "${GFOLDERTARGET}/lastsnap.tmp"
mogrify -stroke black -pointsize 10 -gravity NorthEast -draw "text 0,0 '${GTIMESTAMPTIME}'" "${GFOLDERTARGET}/lastsnap.tmp"
#
# Save the taken picture to the archive, give the file a nice timestamped name
mv "${GFOLDERTARGET}/lastsnap.tmp" "${GFILETARGET}"
#
# Copy the latest image to the "current view" - folder
cp "${GFILETARGET}" "${GFILELASTSNAP}"
#
#raspistill -t 0 -w 1024 -h 768 -o -
#
# Make a upload to our webserver
if [ "${GTIMESTAMPHOURS}" -ge 0 -a "${GTIMESTAMPHOURS}" -le 23 -o "${GUPLOADEVERYTIME}" -eq 1 ]; then # Between 0 and 0 o'clock
  if [ "${GTIMESTAMPMINUTES}" -eq 0 -o "${GTIMESTAMPMINUTES}" -eq 15 -o "${GTIMESTAMPMINUTES}" -eq 30  -o "${GTIMESTAMPMINUTES}" -eq 45 -o "${GUPLOADEVERYTIME}" -eq 1 ]; then
     log "Uploading picture..."
     ~/Development/webcam/knock.sh 
     #   scp "${GFILETARGET}" dt:tmp/
     sftp dt:tmp/ <<< "put ${GFILETARGET}"
  fi
fi
#
# Cleanup: Delete all files older than n*24 hours
find "${GFOLDERTARGET}" -ctime +1 -delete
#
# Unlock
rm "${GFILELOCK}"
#
# Exit
exit 0

Scripts running on the web server

cronjobs
# m h  dom mon dow   command
02,17,32,47 * * * *	~/bin/movePictures.sh >> /dev/null 2>&1
#
# Create a daily time-lapse
50 23 * * *    ~/bin/mergeAllPicturesInOneAnimatedGIF.sh >> /dev/null 2>&1
Scripts
movePictures.sh

(called by crond)

#!/bin/bash
#set -x

# movePictures.sh
# Author: Heiko
# Purpose: Move files into place (Webserver), set lastsnap and delete old files... 

# Globals
GFOLDERWWW="/var/www/html/solarcam"
GFOLDERWWWIMAGES="${GFOLDERWWW}/webcam-archive"
GFILEWWWLASTSNAP="${GFOLDERWWW}/webcam/lastsnap.jpg"
GFILEWWWLASTGRAPH="${GFOLDERWWW}/webcam/lastgraph.svg"
GHOME="/home/solarcam" 

# Move the image in place
mv "${GHOME}/tmp/"*.jpg "${GFOLDERWWWIMAGES}/"
mv "${GHOME}/tmp/"*.svg "${GFOLDERWWWIMAGES}/"

# Make the newest "lastsnap"
FILENEWEST="`ls -Art \"${GFOLDERWWWIMAGES}\" | grep jpg | tail -1`"
cp -p "${GFOLDERWWWIMAGES}/${FILENEWEST}" "${GFILEWWWLASTSNAP}"
FILENEWEST="`ls -Art \"${GFOLDERWWWIMAGES}\" | grep svg |  tail -1`"
cp -p "${GFOLDERWWWIMAGES}/${FILENEWEST}" "${GFILEWWWLASTGRAPH}"

# Cleanup: Delete all files older than n*24hrs
find "${GFOLDERWWWIMAGES}" -ctime +30 -delete

# EOF
mergeAllPicturesInOneAnimatedGIF.sh

(called by crond)

#!/bin/bash
set -x
# 
# Script: mergeAllPicturesInOneAnimatedGIF.sh
# Author: Heiko Kretschmer
# Purpose: Merge all .jpg into one animated .gif
#
# History:
# 2014-03-30,	09:52, h:	Creation. Note. default ticks in -delay is n/100 of a second
# 2018-03-31,   08:11, h:	Moved to dt. Make daily GIF.
# 

# Globals
#
GFOLDERSOURCE="/var/www/html/solarcam/webcam-archive"
GSUFFIXSOURCE="jpg"
GTIMESTAMP="`date +'%Y-%m-%d'`"
#GTIMESTAMP="2018-03-29"
#echo "${GTIMESTAMP}"
#exit 0
GFILETARGET="/var/www/html/solarcam/webcam-archive/${GTIMESTAMP}.gif"

# (Un)Main
#
convert -limit area 0 -delay 25 -loop 1 "${GFOLDERSOURCE}/${GTIMESTAMP}*.${GSUFFIXSOURCE}" "${GFILETARGET}"
index.php

(place in your web server directory)

<?php
?>
<!doctype html public "-//W3C//DTD HTML 4.0 //EN"> 
<html> 
 <head> 
       <title>Webcam History</title> 
       <META HTTP-EQUIV="refresh" CONTENT="3600">
 </head> 
 <body style="background-color:#EEEEEE">
 
       <H1>Webcam Live Image</H1> 
       <img src="./webcam/lastsnap.jpg" />        
       <img src="./webcam/lastgraph.svg" />        
 
       <H1>Webcam History</H1> 
 	 
 <?php 

	$imagepath = "./webcam-archive"; 
	$images = scandir($imagepath); 
	$images = array_reverse($images); // newest on top
	foreach($images as $curimg)
	{ 
		if (substr($curimg, 0, 1)!="." && filesize("$imagepath/$curimg")>10000 &&
                    ( strstr($curimg, ".swf") || strstr($curimg, ".avi") || strstr($curimg, ".mpg") || strstr($curimg, ".jpg") || strstr($curimg, ".gif")  ) )
		{
			/* Link to Viewing-Page */
			$curimgencoded=urlencode($curimg);
	  		echo "<a href='./imageviewer.php?filename=$curimgencoded' alt='Show $curimg'  />$curimg<br>\n";

			/* Direct Link to Image File */
 			if (0)
			{
  				#echo "<H2>$curimg</H2>\n";
	  			#echo "<img src='$imagepath/$curimg' alt='$curimg' /><br>$curimg<br>\n";
	  			echo "<a href='$imagepath/$curimg' alt='$curimg' />$curimg<br>\n";
				#echo "<hr>\n";
			}
		}
	}; 

 ?> 
 
	<hr>
	<br/>
	<a href='./index.php'>Back!</a>

 </body> 
 </html>
 
imageviewer.php

(place in your web server directory)

<?php
 ?>
 <!doctype html public "-//W3C//DTD HTML 4.0 //EN"> 
 <html> 
 <head> 
       <title>Webcam History</title> 
       <META HTTP-EQUIV="refresh" CONTENT="60">
 </head> 
 <body style="background-color:#EEEEEE">
 	 
 <?php 

	/* Chosen Image */
    $filename=htmlspecialchars($_GET["filename"]);
    echo("<H1>Webcam Archive Image: $filename</H1>\n"); 
	//echo("<H2>Showing " . $filename . "</H2><br/>\n");
	$imagepath = "./webcam-archive"; 

	/* Alle Bilder im Archiv finden (Non-Bilder wegfiltern) */
	$images = scandir($imagepath); // Alle Bilder im Ordner
    #echo("images:\n");
    #print_r($images);
    #echo("---\n");
	$imagesfiltered=array();
	foreach($images as $curimg) // filter alles weg, was kein Bild ist!
	{ 
		#echo("Checking: $curimg<br/>\n");
		if (substr($curimg, 0, 1)!="." && filesize("$imagepath/$curimg")>10000 &&
                    ( strstr($curimg, ".swf") || strstr($curimg, ".avi") || strstr($curimg, ".mpg") || strstr($curimg, ".jpg") ) )
		{
			array_push($imagesfiltered, $curimg);
		}
	}
    #echo("imagesfiltered:\n");
	#print_r($imagesfiltered);
	#echo("---\n");

	/* Finde das vorherige und das nachfolgende Bild */
	$idx=array_search($filename, $imagesfiltered);
	#echo("idx: $idx<br/>\n");

	/* Previous Image-Link erzeugen */
	$previouslink="";
	if ($idx>0)
	{
		$previousimage=$imagesfiltered[$idx-1];
		$previousimageencoded=urlencode($previousimage);
		$previouslink="<a href='./imageviewer.php?filename=$previousimageencoded' alt='Show previous image'>< Previous Image <</a>\n";
	}
	
	/* Next Image-Link erzeugen */
	$nextlink="";
    if ($idx<count($imagesfiltered)-1)
	{
		$nextimage=$imagesfiltered[$idx+1];
		$nextimageencoded=urlencode($nextimage);
		$nextlink="<a href='./imageviewer.php?filename=$nextimageencoded' alt='Show next image'>> Next Image ></a>\n";
	}
	
	/* Obere Navigation */
	echo("<p align='center'>\n");
		//echo("$previouslink");
		//if (strlen($previouslink) > 1) { echo($previouslink); }
		if (strlen($previouslink) > 1 ) { echo($previouslink); } 
		echo("     "); // http://de.wikihow.com/Leerzeichen-in-HTML-einfügen
		if (strlen($nextlink) > 1) { echo($nextlink); }
	echo("</p>\n");	

	/* Das Bild */
	echo("<p align='center'>\n");
	echo("<img src='" . $imagepath . "/" . $filename . "' alt='$filename' />\n");
	echo("</p>\n");

	/* Untere Navigation */
	echo("<p align='center'>\n");
		if (strlen($previouslink) > 1 ) { echo($previouslink); } 
		echo("     "); // http://de.wikihow.com/Leerzeichen-in-HTML-einfügen
		if (strlen($nextlink) > 1) { echo($nextlink); }
	echo("</p>\n");	

	if (0)
	foreach($images as $curimg)
	{ 
		if (substr($curimg, 0, 1)!="." && filesize("$imagepath/$curimg")>10000 &&
                    ( strstr($curimg, ".swf") || strstr($curimg, ".avi") || strstr($curimg, ".mpg") || strstr($curimg, ".jpg") ) )
		{
			#echo "<H2>$curimg</H2>\n";
	  		#echo "<img src='$imagepath/$curimg' alt='$curimg' /><br>$curimg<br>\n";
	  		echo "<a href='$imagepath/$curimg' alt='$curimg' />$curimg<br>\n";
			#echo "<hr>\n";
		}
	}; 

 ?> 
 
	<hr>
	<br/>
	<a href='./index.php'>Back!</a>
 
 </body> 
 </html>

Tips

  • Remember that this Pi is in the wild and easily stolen or all the data read
  • Don't use your usual passwords for this project
  • Don't store keys on the Pi
  • Let your master server fetch the data (so no private keys are stored on the Pi) or use a chroot environment
  • Create a special user to access the data from remote, or even better, get it per HTTP and use .htaccess for privacy (and less 3G-traffic ;) )
  • If your WiFi connection breaks regularly, see Raspberry Pi WiFi issue (Solarcam)

?


  1. Since setting up the 3G-Stick was a pain in...