The tutorial may look a bit intimidating at first, but all you basically have to do is create five files and copy content to them from this tutorial (if you already have a web server running).
Disclaimer: I'm not your typical Linux wizard so improvements are possible and any comments are highly appreciated.
Prerequisites
You need to install the Apache web server (or the like), PHP (and a Wifi dongle configured as access point if you want to use a mobile device; see http://elinux.org/RPI-Wireless-Hotspot). Plus a working PiCamera of course.
Make sure to be able to access '/var/www' and '/dev/vchiq'
To start off showing my ignorance about Linux, I always have a problem with the permissions. As long as you do not open your Pi to others, like me, the easy (but basically unsafe!) way is to make the web directory '/var/www' (created during the install of the webserver, owned by the group 'www-data') and the file '/dev/vchiq' (owned by the group 'video') accessible to anyone with the commands:
Code: Select all
sudo chmod 777 /var/www
sudo chmod 777 /dev/vchiq
Create the '/var/www/img' directory
Shot images and videos will be saved in '/var/www/img' so create this directory with:
Code: Select all
sudo mkdir /var/www/img
In the directory '/var/www' create the file 'shootpi.html' (watch upper- and lower case!) and copy the contents of the next code block to it:
Code: Select all
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ShootPi</title>
<link rel="stylesheet" href="shootpi.css" type="text/css" />
<script>
var hold='';
function loadXMLDoc(){
var xmlhttp;
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
//Put the most recent image name in the variable 'hold'
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
hold=xmlhttp.responseText;
}
}
//Get the latest info from 'ajax_info.txt'
xmlhttp.open("GET","ajax_info.txt",true);
xmlhttp.send();
//Refresh the image only if it has a new name
if(document.getElementById("myDiv").innerHTML!=hold){
document.getElementById("myDiv2").innerHTML="<img src="+hold+">";
document.getElementById("myDiv").innerHTML=hold;
}
}
function shootStill(){
var xmlhttp;
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//Do something
}
}
//Take a still image
xmlhttp.open("GET","shootStill.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();
}
function shootTimelapse(){
var xmlhttp;
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//Do something
}
}
//Take a timelapse sequence
xmlhttp.open("GET","shootTimelapse.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();
}
function shootVideo(){
var xmlhttp;
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200){
//Do something
}
}
//Take a video
xmlhttp.open("GET","shootVideo.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();
}
function timedRefresh(timeoutPeriod) {
loadXMLDoc();
setTimeout("timedRefresh(1000);",timeoutPeriod);
}
</script>
</head>
<!-- Set the refresh interval in miliseconds, default=1000 (1 second) -->
<body onload="JavaScript:timedRefresh(1000);">
<div id="myDiv2"></div>
<div id="myDiv"></div>
<input type="button" value="Shoot Still" onClick='shootStill();'><br><br>
<input type="button" value="Shoot Timelapse" onClick='shootTimelapse();'><br><br>
<input type="button" value="Shoot Video" onClick='shootVideo();'><br><br>
</body>
</html>
Next create the file 'shootpi.css' (watch upper- and lower case!) in '/var/www' and copy the next content to it:
Code: Select all
body
{
/* background-image:
url('bigg.gif');
*/
background-color: #000000;
background-repeat: no-repeat;
background-attachment: fixed;
font-family: "Verdana";
font-size: 8pt;
color: #dddddd;
}
img {
max-width: 100%;
max-height: 97%;
/*height: auto;*/
width: auto\9; /* ie8 */
}
Create the PHP files for still, timelapse and video capture
In '/var/www' create the files (watch upper- and lower case!):
shootStill.php
Code: Select all
<?
//get the last used number for naming file
$lastImgNum = file_get_contents('/var/www/lastImgNum.txt');
echo "lastImgNum read for this use is ".$lastImgNum."<br>";
//up the number by one
$lastImgNum+=1;
//write the new last used number
file_put_contents('/var/www/lastImgNum.txt', $lastImgNum);
echo "lastImgNum written for next use is ".$lastImgNum."<br>";
//construct file name with leading zeros
$imgName=str_pad($lastImgNum,6,"0",STR_PAD_LEFT);
echo "imgName for this use is ".$imgName."<br>";
//take still image with PiCamera and store it in '/var/www/img' directory
//edit the raspistill command here to taste but make sure not to remove the double quotes!
shell_exec("raspistill -t 1000 -o /var/www/img/".$imgName.".jpg");
echo "Shot image ".$imgName.".jpg<br>";
//write the filename to 'ajax_info.txt' so it will be shown in the browser using Ajax
$imgName="/img/".$imgName;
file_put_contents('/var/www/ajax_info.txt', $imgName);
echo "Saved ".imgName." to /var/www/ajax_info.txt <br>";
?>
Code: Select all
<?
//get the last used number for naming file
$lastImgNum = file_get_contents('/var/www/lastImgNum.txt');
echo "lastImgNum read for this use is ".$lastImgNum."<br>";
//up the number by one
$lastImgNum+=1;
//write the new last used number
file_put_contents('/var/www/lastImgNum.txt', $lastImgNum);
echo "lastImgNum written for next use is ".$lastImgNum."<br>";
//construct file name with leading zeros
$imgName=str_pad($lastImgNum,6,"0",STR_PAD_LEFT);
echo "imgName for this use is ".$imgName."<br>";
//take timelapse images with PiCamera and store it in '/var/www/img' directory
//edit the raspistill command here to taste but make sure not to remove the double quotes!
shell_exec("raspistill -t 20000 -tl 2000 -o /var/www/img/".$imgName."_%d.jpg");
echo "Shot timelapse ".$imgName."<br>";
/* DISABLED SHOWING IMAGE THROUGH AJAX!!!
//write the filename to 'ajax_info.txt' so it will be shown in the browser using Ajax
$imgName="/img/".$imgName;
file_put_contents('/var/www/ajax_info.txt', $imgName);
echo "Saved ".imgName." to /var/www/ajax_info.txt <br>";
*/
?>
Code: Select all
<?
//get the last used number for naming file
$lastImgNum = file_get_contents('/var/www/lastImgNum.txt');
echo "lastImgNum read for this use is ".$lastImgNum."<br>";
//up the number by one
$lastImgNum+=1;
//write the new last used number
file_put_contents('/var/www/lastImgNum.txt', $lastImgNum);
echo "lastImgNum written for next use is ".$lastImgNum."<br>";
//construct file name with leading zeros
$imgName=str_pad($lastImgNum,6,"0",STR_PAD_LEFT);
echo "imgName for this use is ".$imgName."<br>";
//take video with PiCamera and store it in '/var/www/img' directory
//edit the raspivid command here to taste but make sure not to remove the double quotes!
shell_exec("raspivid -t 10000 -o /var/www/img/".$imgName.".264");
echo "Shot video ".$imgName.".264<br>";
/* DISABLED SHOWING IMAGE THROUGH AJAX!!!
//write the filename to 'ajax_info.txt' so it will be shown in the browser using Ajax
$imgName="/img/".$imgName;
file_put_contents('/var/www/ajax_info.txt', $imgName);
echo "Saved ".imgName." to /var/www/ajax_info.txt <br>";
*/
?>
So what happens?
Browse to 'Pi_IP_address/shootpi.html' (in my case, using a wired connection, that is 'http://192.168.1.123/shootpi.html'). You'll see a black page with three buttons. Click the 'Shoot Still' button.
The page will launch the 'shootStill()' function that uses Ajax to launch 'shootStill.php' in turn. If all goes well this program gets the last used number from '/var/www/lastImgNum.txt', ups this number by one to create an unused image name, saves the new number for future use (aka the next image), takes an image using raspistill and finally saves the name of the shot image to '/var/www/ajax_info.txt'. This file is read by the 'loadXMLDoc()' function every second and if there's a new image name in the file it changes the image in the 'myDiv2' container to the new one.
The Timelapse and Video functions do not show images or video in the browser window; My use at this moment is to get a good image using still images and then use the other buttons to record timelapse or video.
To change the raspistill and raspivid parameters look in the .php files.
Troubleshooting (edited as problems arise in the thread)
- You can launch the three .php files by themselves in the browser (i.e. 'http://192.168.1.123/shootStill.php') to see error output and check if an image or video is saved.
- Doesn't seem to work with Internet Explorer 10 on Windows 7 64-bit with the present code (but it does work in Chrome and on my Android Nexus S phone).
Good luck, hope this is useful.