Foscam FI8918W control script for ZoneMinder
Based on origional article by Howard at Durdle.com.
Updated for Fedora 19
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,
To install the Foscam control script: 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/
or CentOS
/usr/share/perl5/ZoneMinder/Control/PanasonicIP.pm
or Fedora 19
/usr/share/perl5/vendor_perl/ZoneMinder/Control/PanasonicIP.pm
If you’re not sure where to look, run the command:
locate PanasonicIP.pm
or
find / -name PanasonicIP.pm -print
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. The username and password are 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.
Now back on the main console click the 'Add New Monitor' button to add a new monitor camera.
Select the Control tab, and click Edit next to Control Type. Click the Add New Control button, then enter the following settings.
Click the 'Add New Control' button and ender the camera details.
Back on the main console add a new monitor and enter all the monitor tabs as shown
Now save the new monitor, then go back and edit the newly created monitor and on the control tab you should be able to pick the Foscam camera.
Now to get the camera to show in the drop down list is a trick. You must create a new monitor with all the data except the control tab, save the camera and then when you edit the camera again you will see the drop down list for the Control Type expanded (this is a zoneminder bug). 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.
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:
Getting ZoneMinder working with my Foscam 8918W IP camera
http://192.168.1.19:85/videostream.asf?user=admin&pwd=pass
Turn off the blinking green LED:
http://192.168.1.19:85/set_misc.cgi?led_mode=2?user=admin&pwd=pass
Other Commands
http://[ipcam]/get_misc.cgi ->Returns all the current values for the functions.
http://[ipcam]/get_log.cgi -> Displays the visits log
http://[ipcam]/get_params.cgi ->Returns the complete configuration of the camera.
# ========================================================================== # # 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;