Foscam FI9821W control script

If you've made a patch to quick fix a bug or to add a new feature not yet in the main tree then post it here so others can try it out.
Post Reply
gmar_87
Posts: 72
Joined: Sat Aug 13, 2011 11:38 pm
Location: Melbourne, Australia

Foscam FI9821W control script

Post by gmar_87 »

Hi all,

I have created a control script for the Foscam FI9821W IP camera.
The script is based on the FI8918W script and has been modified to use the new CGI SDK for the FI9821W.

Working controls
Added 15/04/2013:
- Up, down, left, right & diagonal movements
- Stop movement
- Reset PTZ position (home button)
- Wake and sleep IR LEDs (wake and sleep buttons)
- Reboot camera (reset button)

Added 20/04/2013:
- Set presets
- Move to presets

Limitations:
- Preset cannot be overridden if the preset number has already been set. Preset needs to be deleted from the Foscam FI9821W camera web interface first.

Control Capability Config:
Main tab:
Name - Foscam FI9821W
Type - Remote
Protocol - FoscamFI9821W
Can Wake - ticked
Can Sleep - ticked
Can Reset - ticked

Move tab:
Can Move - ticked
Can Move Diagonally - ticked
Can Move Relative - ticked
Can Move Continuous - ticked

Pan tab:
Can Pan - ticked

Tilt tab:
Can Tilt - ticked

Presets tab:
Has Presets - ticked
Num Presets - 16
Has Home Preset - ticked
Can Set Presets - ticked

Monitor - Control tab
Controllable - ticked
Control type - Foscam FI9821W
Control device - usr=admin&pwd=password
Control address - Camera IP address


Filename = FoscamFI9821W.pm

Code: Select all

# ==========================================================================
#
# ZoneMinder Foscam FI9821W IP Control Protocol Module
# 
# Created from Dave Harris Foscam FI8918W control script - Feb 2011
# Modified by John Marzella on 15/04/2013 to work with Foscam FI9821W
# 
# 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.
#
# ==========================================================================

# Enter username and password in the "Control Device" field
# E.g. usr=admin&pwd=password


package ZoneMinder::Control::FoscamFI9821W;
 
use 5.006; use strict; use warnings;
 
require ZoneMinder::Base; require ZoneMinder::Control;
 
our @ISA = qw(ZoneMinder::Control);
 
our $VERSION = $ZoneMinder::Base::VERSION;
 
# ==========================================================================
#
# Foscam FI9821W IP Control Protocol
#
# ==========================================================================

#Commented out to work with ZoneMinder 1.25
#use ZoneMinder::Debug qw(:all); use ZoneMinder::Config qw(:all);

use ZoneMinder::Logger 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 );
}

#Reboot camera
sub reset {
	my $self = shift;
	Debug( "Camera Reset" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=rebootSystem&";
	$self->sendCmd( $cmd );
}

#Up Arrow
sub moveConUp {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Up" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveUp&";
	$self->sendCmd( $cmd );
}
 
#Down Arrow
sub moveConDown {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Down" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveDown&";
	$self->sendCmd( $cmd );
}
 
#Left Arrow
sub moveConLeft {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Left" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveLeft&";
	$self->sendCmd( $cmd );
}
 
#Right Arrow
sub moveConRight {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Right" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveRight&";
	$self->sendCmd( $cmd );
}
 
#Diagonally Up Right Arrow
sub moveConUpRight {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Diagonally Up Right" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveTopRight&";
	$self->sendCmd( $cmd );
}
 
#Diagonally Down Right Arrow
sub moveConDownRight {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Diagonally Down Right" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveBottomRight&";
	$self->sendCmd( $cmd );
}
 
#Diagonally Up Left Arrow
sub moveConUpLeft {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Diagonally Up Left" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveTopLeft&";
	$self->sendCmd( $cmd );
}
 
#Diagonally Down Left Arrow
sub moveConDownLeft {
	my $self = shift;
	$stop_command = "ptzStopRun";
	Debug( "Move Diagonally Down Left" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzMoveBottomLeft&";
	$self->sendCmd( $cmd );
}
 
#Stop
sub moveStop {
	my $self = shift;
	Debug( "Move Stop" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzStopRun&";
	$self->sendCmd( $cmd );
}
 
#Move Camera to Home Position
sub presetHome {
	my $self = shift;
	Debug( "Home Preset" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzReset&";
	$self->sendCmd( $cmd );
}
 
#Set preset
# Basic preset functionality
# Uses zoneminder preset number as preset name in Foscam FI9821W.
# If preset name already exists it will not override... Old preset needs to be removed from Foscam FI9821W web interface first!
sub presetSet {
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Set Preset $preset" );
    my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzAddPresetPoint&name=$preset&";
    $self->sendCmd( $cmd );
}
 
#Goto preset
# Goes to present name that matches zoneminder preset number
sub presetGoto {
    my $self = shift;
    my $params = shift;
    $stop_command = "ptzStopRun";
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Goto Preset $preset" );
    my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=ptzGotoPresetPoint&name=$preset&";
    $self->sendCmd( $cmd );
}
 
#Turn IR on
sub wake {
	my $self = shift;
	Debug( "Wake - IR on" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=openInfraLed&";
	$self->sendCmd( $cmd );
}
 
#Turn IR off
sub sleep {
	my $self = shift;
	Debug( "Sleep - IR off" );
	my $cmd = "cgi-bin/CGIProxy.fcgi?cmd=closeInfraLed&";
	$self->sendCmd( $cmd );
}
 
1;
Cheers,
John
Last edited by gmar_87 on Thu Apr 25, 2013 6:40 am, edited 1 time in total.
chaoticmachinery
Posts: 8
Joined: Sat Apr 20, 2013 9:59 pm

Re: Foscam FI9821W control script

Post by chaoticmachinery »

Hey John,

Thanks for the control script. I was just getting ready to write my own. I would be happy to give you a hand with it if you want it.

I got one question for you. I keep getting a "Can't connect: No such file or directory" error. Any ideas on how to fix that? OR could you post your configurations for the foscam?

I've narrowed it down to zmcontrol.pl and the socket file doesn't exist. I am not sure why at this point.

Thanks,
CM
gmar_87
Posts: 72
Joined: Sat Aug 13, 2011 11:38 pm
Location: Melbourne, Australia

Re: Foscam FI9821W control script

Post by gmar_87 »

chaoticmachinery wrote:Hey John,

Thanks for the control script. I was just getting ready to write my own. I would be happy to give you a hand with it if you want it.

I got one question for you. I keep getting a "Can't connect: No such file or directory" error. Any ideas on how to fix that? OR could you post your configurations for the foscam?

I've narrowed it down to zmcontrol.pl and the socket file doesn't exist. I am not sure why at this point.

Thanks,
CM
Hi chaoticmachinery,

I'm open to improvements to the script :)

I'm not sure what's causing your issue, but here is my config for your reference..

My control scripts are located in "/usr/local/share/perl/5.10.1/ZoneMinder/Control".
The filename of the control script is "FoscamFI9821W.pm".
Control protocol = FoscamFI9821W
Control device = usr=admin&pwd=password
Control address = camera IP address

Cheers,
John
gmar_87
Posts: 72
Joined: Sat Aug 13, 2011 11:38 pm
Location: Melbourne, Australia

Re: Foscam FI9821W control script

Post by gmar_87 »

chaoticmachinery wrote:Hey John,

Thanks for the control script. I was just getting ready to write my own. I would be happy to give you a hand with it if you want it.

I got one question for you. I keep getting a "Can't connect: No such file or directory" error. Any ideas on how to fix that? OR could you post your configurations for the foscam?

I've narrowed it down to zmcontrol.pl and the socket file doesn't exist. I am not sure why at this point.

Thanks,
CM
Hi CM,

Did you ever solve this problem?
I am currently building a fresh ZM 1.26.4 server running on Ubuntu 12.04 and experiencing the same problem with all my control scripts.

Code: Select all

zmcontrol[5524]: FAT [Can't connect: No such file or directory]
web_php[2792]: ERR [/usr/local/bin/zmcontrol.pl --tiltspeed=2 --autostop --command=moveConUp --id=1=>]
gmar_87
Posts: 72
Joined: Sat Aug 13, 2011 11:38 pm
Location: Melbourne, Australia

Re: Foscam FI9821W control script

Post by gmar_87 »

Executed the control script using perl with the "enable all warnings" switch and discovered the following compilation error:

Code: Select all

john@ZONEMINDER1:/usr/local/share/perl/5.14.2/ZoneMinder/Control$ sudo perl -W FoscamFI9821W.pm
Use of uninitialized value in join or string at /usr/lib/perl5/DBI.pm line 1690.
Bareword "ZM_VERSION" not allowed while "strict subs" in use at FoscamFI9821W.pm line 72.
Execution of FoscamFI9821W.pm aborted due to compilation errors.
Removed the Bareword "ZM_VERSION" in the control script and it's now working :)

Changed

Code: Select all

$self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION );
To

Code: Select all

$self->{ua}->agent( "ZoneMinder Control Agent/");
px03afk
Posts: 77
Joined: Wed Nov 30, 2011 4:53 pm

Re: Foscam FI9821W control script

Post by px03afk »

Thank you for this - I've just spent most of today trying to sort out what was wrong with my Foscam control and this was the problem.
Post Reply