Update 27/02/2011: Added IR control and password passthrough.
I’ve recently put together a CCTV solution using a few Foscam FI8918W cameras and the excellent ZoneMinder software. This is all running on a CentOS 5.5 virtual machine under Hyper-V (more on this setup another time). The Foscam cameras have pan, tilt and the ability to set and move to preset locations.
The Foscam control script for ZoneMinder which I found on the ZoneMinder wiki was a good starting point, but seemed to have left and right wired backwards, and didn’t support the presets. So I’ve updated it to fix those issues, the script is below.
To install: find where the control scripts are installed on your distro. In mine I found the files in:
/usr/lib/perl5/site_perl/5.8.8/ZoneMinder/Control/
If you’re not sure where to look, run the command:
locate PanasonicIP.pm
This will return the location of one of the existing control scripts.
Once you’ve found them, create a new file called FoscamFI8918W.pm and paste the code below into it. As with the original script this assumes there is an admin user with no password on your camera. This will have to do until I can work out how to pass through a proper username and password from the ZoneMinder frontend.Update 27/02/2011: the username and password are now passed via the Control Device field. See below.
You’ll need to add the control script to the ZoneMinder interface and attach it to your camera. First make sure that ZoneMinder is configured to support controllable cameras. Open Options from the main console and click OPT_CONTROL in the System tab.
Then open the source options for the camera you want to control. Select the Control tab, and click Edit next to Control Type. Click the Add New Control button, then enter the following settings (Update 27/02/2011, see bottom of post for updated settings for IR control and username/password.):
Now save and close that window, and refresh the one for your camera. You should now see the Foscam FI8918W script in the list. Select it, and enter the IP address of the camera in the Control Address box. Make sure Controllable is ticked, then click Save.
Now if you view the camera you’ll have a Control option near the top. Click it to reveal the Pan/Tilt controls, along with the presets:
That’s it. Enjoy your controllable cameras!�
Download the FoscamFI8918W.pm script. Rename to .pm.
I’ll update this post when I work out the password passthrough and how to turn the IR LED on and off via ZoneMinder. Update 27/02/2011: the script now uses Sleep and Wake to turn the IR off and on and passes the username and password via the Control Device parameter. You’ll need to enable those options on the Main tab of the Control like so:
And put your username and password query string in the Control Device field:
# ========================================================================== # # ZoneMinder Foscam FI8918W IP Control Protocol Module, $Date: 2009-11-25 09:20:00 +0000 (Wed, 04 Nov 2009) $, $Revision: 0001 $ # Copyright (C) 2001-2008 Philip Coombes # Modified for use with Foscam FI8918W IP Camera by Dave Harris # Modified Feb 2011 by Howard Durdle (http://durdl.es/x) to: # fix horizontal panning, add presets and IR on/off # use Control Device field to pass username and password # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ========================================================================== # # This module contains the implementation of the Foscam FI8918W IP camera control # protocol # package ZoneMinder::Control::FoscamFI8918W; use 5.006; use strict; use warnings; require ZoneMinder::Base; require ZoneMinder::Control; our @ISA = qw(ZoneMinder::Control); our $VERSION = $ZoneMinder::Base::VERSION; # ========================================================================== # # Foscam FI8918W IP Control Protocol # # ========================================================================== use ZoneMinder::Debug qw(:all); use ZoneMinder::Config qw(:all); use Time::HiRes qw( usleep ); sub new { my $class = shift; my $id = shift; my $self = ZoneMinder::Control->new( $id ); my $logindetails = ""; bless( $self, $class ); srand( time() ); return $self; } our $AUTOLOAD; sub AUTOLOAD { my $self = shift; my $class = ref($self) || croak( "$self not object" ); my $name = $AUTOLOAD; $name =~ s/.*://; if ( exists($self->{$name}) ) { return( $self->{$name} ); } Fatal( "Can't access $name member of object of class $class" ); } our $stop_command; sub open { my $self = shift; $self->loadMonitor(); use LWP::UserAgent; $self->{ua} = LWP::UserAgent->new; $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); $self->{state} = 'open'; } sub close { my $self = shift; $self->{state} = 'closed'; } sub printMsg { my $self = shift; my $msg = shift; my $msg_len = length($msg); Debug( $msg."[".$msg_len."]" ); } sub sendCmd { my $self = shift; my $cmd = shift; my $result = undef; printMsg( $cmd, "Tx" ); my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd".$self->{Monitor}->{ControlDevice} ); my $res = $self->{ua}->request($req); if ( $res->is_success ) { $result = !undef; } else { Error( "Error check failed:'".$res->status_line()."'" ); } return( $result ); } sub reset { my $self = shift; Debug( "Camera Reset" ); my $cmd = "reboot.cgi?"; $self->sendCmd( $cmd ); } #Up Arrow sub moveConUp { my $self = shift; $stop_command = "1"; Debug( "Move Up" ); my $cmd = "decoder_control.cgi?command=0&"; $self->sendCmd( $cmd ); } #Down Arrow sub moveConDown { my $self = shift; $stop_command = "1"; Debug( "Move Down" ); my $cmd = "decoder_control.cgi?command=2&"; $self->sendCmd( $cmd ); } #Left Arrow sub moveConLeft { my $self = shift; $stop_command = "1"; Debug( "Move Left" ); my $cmd = "decoder_control.cgi?command=6&"; $self->sendCmd( $cmd ); } #Right Arrow sub moveConRight { my $self = shift; $stop_command = "1"; Debug( "Move Right" ); my $cmd = "decoder_control.cgi?command=4&"; $self->sendCmd( $cmd ); } #Diagonally Up Right Arrow sub moveConUpRight { my $self = shift; $stop_command = "1"; Debug( "Move Diagonally Up Right" ); my $cmd = "decoder_control.cgi?command=90&"; $self->sendCmd( $cmd ); } #Diagonally Down Right Arrow sub moveConDownRight { my $self = shift; $stop_command = "1"; Debug( "Move Diagonally Down Right" ); my $cmd = "decoder_control.cgi?command=92&"; $self->sendCmd( $cmd ); } #Diagonally Up Left Arrow sub moveConUpLeft { my $self = shift; $stop_command = "1"; Debug( "Move Diagonally Up Left" ); my $cmd = "decoder_control.cgi?command=91&"; $self->sendCmd( $cmd ); } #Diagonally Down Left Arrow sub moveConDownLeft { my $self = shift; $stop_command = "1"; Debug( "Move Diagonally Down Left" ); my $cmd = "decoder_control.cgi?command=93&"; $self->sendCmd( $cmd ); } #Stop sub moveStop { my $self = shift; Debug( "Move Stop" ); my $cmd = "decoder_control.cgi?command=1&"; $self->sendCmd( $cmd ); } #Move Camera to Home Position sub presetHome { my $self = shift; Debug( "Home Preset" ); my $cmd = "decoder_control.cgi?command=25&"; $self->sendCmd( $cmd ); } #Set preset sub presetSet { my $self = shift; my $params = shift; my $preset = $self->getParam( $params, 'preset' ); my $presetCmd = 30 + ($preset*2); Debug( "Set Preset $preset with cmd $presetCmd" ); my $cmd = "decoder_control.cgi?command=$presetCmd&"; $self->sendCmd( $cmd ); } #Goto preset sub presetGoto { my $self = shift; my $params = shift; $stop_command = "1"; my $preset = $self->getParam( $params, 'preset' ); my $presetCmd = 31 + ($preset*2); Debug( "Goto Preset $preset with cmd $presetCmd" ); my $cmd = "decoder_control.cgi?command=$presetCmd&"; $self->sendCmd( $cmd ); } #Turn IR on sub wake { my $self = shift; Debug( "Wake - IR on" ); my $cmd = "decoder_control.cgi?command=95&"; $self->sendCmd( $cmd ); } #Turn IR off sub sleep { my $self = shift; Debug( "Sleep - IR off" ); my $cmd = "decoder_control.cgi?command=94&"; $self->sendCmd( $cmd ); } 1; |
Many thanks for sharing your script.
It works… almost fully in my case. Only problem I am facing is that it the “stop” command does not seem to work… Once I click on one of the control buttons the camera never stops moving even when I click on Stop. Any idea what I am doing wrong (the pb is not the cam, all controls work fine when I use the native Foscam cgi script).
Just found the problem.
In the perl script, there is a “&” missing in the stop command call. Instead of :
my $cmd = “decoder_control.cgi?&command=1”;
it should be:
my $cmd = “decoder_control.cgi?&command=1&”;
Good spot Lionel – I uploaded an interim version of the script, this was already fixed on my install. I’ve corrected the post now. Note that the line is:
my $cmd = "decoder_control.cgi?command=1&";
with no & after the ?.
You are a lifesaver! i just ordered 4 of these cams without checking zoneminder support but now have my answer! any idea about zoneminder and sound?
thanks for sharing so valuable info…!
I’m with William…any idea when the sound will be working?
im having an issue with this script in zmcontrol.log i get
03/16/11 14:50:47.484996 zmcontrol[7952].FAT [Can’t connect: No such file or directory]
03/16/11 14:52:23.043193 zmcontrol[7988].INF [Starting control server 2/FoscamFI8919W]
03/16/11 14:52:23.057361 zmcontrol[7991].INF [Control server 2/FoscamFI8919W starting at 11/03/16 14:52:23]
03/16/11 14:52:33.060981 zmcontrol[7988].FAT [Can’t connect: No such file or directory]
03/16/11 14:57:31.408380 zmcontrol[8025].INF [Starting control server 1/FoscamFI8919W]
03/16/11 14:57:31.423073 zmcontrol[8028].INF [Control server 1/FoscamFI8919W starting at 11/03/16 14:57:31]
03/16/11 14:57:41.413174 zmcontrol[8025].FAT [Can’t connect: No such file or directory]
03/16/11 14:59:47.334719 zmcontrol[8064].INF [Starting control server 1/FoscamFI8919W]
03/16/11 14:59:47.346186 zmcontrol[8067].INF [Control server 1/FoscamFI8919W starting at 11/03/16 14:59:47]
03/16/11 14:59:57.345374 zmcontrol[8064].FAT [Can’t connect: No such file or directory]
also getting this
Mar 16 15:29:05 blackbox zmcontrol[8229]: INF [Control server 1/FoscamFI8919W starting at 11/03/16 15:29:05]
Mar 16 15:29:06 blackbox zmc_m1[8044]: INF [LivingRoom: 19000 – Capturing at 9.17 fps]
Mar 16 15:29:15 blackbox zmcontrol[8226]: FAT [Can’t connect: No such file or directory]
blackbox Control #
Control is working for me but I can’t seem to get the videostream to display.
This is what I have configured in the camera source:
Remote Protocol: HTTP
Remote Method: Simple
Remote Host Name: 192.168.1.1
Remote Port: 80
Remote Host Path: /videostream.cgi?user=admin&pwd=password
What am I doing wrong?