1# Modified on Jun 19 2016 by PP 2# Changes made 3# - modified command to work properly and pick up credentials from Control Device 4# - the old script did not stop moving- added autostop 5# (note that mjpeg cameras have onestep but that is too granular) 6# - You need to set "user=xxx&pwd=yyy" in the ControlDevice field (NOT usr like in Foscam HD) 7 8# ========================================================================== 9# 10# ZoneMinder Foscam FI8918W IP Control Protocol Module, $Date: 2009-11-25 09:20:00 +0000 (Wed, 04 Nov 2009) $, $Revision: 0001 $ 11# Copyright (C) 2001-2008 Philip Coombes 12# Modified for use with Foscam FI8918W IP Camera by Dave Harris 13# Modified Feb 2011 by Howard Durdle (http://durdl.es/x) to: 14# fix horizontal panning, add presets and IR on/off 15# use Control Device field to pass username and password 16# Modified May 2014 by Arun Horne (http://arunhorne.co.uk) to: 17# use HTTP basic auth as required by firmware 11.37.x.x upward 18# 19# This program is free software; you can redistribute it and/or 20# modify it under the terms of the GNU General Public License 21# as published by the Free Software Foundation; either version 2 22# of the License, or (at your option) any later version. 23# 24# This program is distributed in the hope that it will be useful, 25# but WITHOUT ANY WARRANTY; without even the implied warranty of 26# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27# GNU General Public License for more details. 28# 29# You should have received a copy of the GNU General Public License 30# along with this program; if not, write to the Free Software 31# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 32# 33# ========================================================================== 34# 35# This module contains the implementation of the Foscam FI8918W IP camera control 36# protocol 37# 38 39package MyAgent; 40 41use base 'LWP::UserAgent'; 42 43 44package ZoneMinder::Control::FI8918W; 45 46use 5.006; 47use strict; 48use warnings; 49 50require ZoneMinder::Base; 51require ZoneMinder::Control; 52 53our @ISA = qw(ZoneMinder::Control); 54 55our $VERSION = $ZoneMinder::Base::VERSION; 56 57# ========================================================================== 58# 59# Foscam FI8918W IP Control Protocol 60# 61# ========================================================================== 62 63use ZoneMinder::Logger qw(:all); 64use ZoneMinder::Config qw(:all); 65 66use Time::HiRes qw( usleep ); 67 68our $stop_command; 69 70sub open 71{ 72 my $self = shift; 73 74 $self->loadMonitor(); 75 76 $self->{ua} = MyAgent->new; 77 $self->{ua}->agent( "ZoneMinder Control Agent/" ); 78 79 $self->{state} = 'open'; 80} 81 82sub close 83{ 84 my $self = shift; 85 $self->{state} = 'closed'; 86} 87 88sub printMsg 89{ 90 my $self = shift; 91 my $msg = shift; 92 my $msg_len = length($msg); 93 94 Debug( $msg."[".$msg_len."]" ); 95} 96 97sub sendCmd 98{ 99 my $self = shift; 100 my $cmd = shift; 101 my $result = undef; 102 printMsg( $cmd, "Tx" ); 103 104 # PP Old cameras also support onstep=1 but it is too granular. Instead using moveCon and stop after interval 105 # PP - cleaned up URL to take it properly from Control device 106 # Control device needs to be of format user=xxx&pwd=yyy 107 my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd"."&".$self->{Monitor}->{ControlDevice}); 108 print ("Sending $req\n"); 109 my $res = $self->{ua}->request($req); 110 111 if ( $res->is_success ) 112 { 113 $result = !undef; 114 } 115 else 116 { 117 Error( "Error REALLY check failed:'".$res->status_line()."'" ); 118 Error ("Cmd:".$req); 119 } 120 121 return( $result ); 122} 123 124sub reset 125{ 126 my $self = shift; 127 Debug( "Camera Reset" ); 128 my $cmd = "reboot.cgi?"; 129 $self->sendCmd( $cmd ); 130} 131 132# PP - in all move operations, added auto stop after timeout 133 134#Up Arrow 135sub moveConUp 136{ 137 my $self = shift; 138 Debug( "Move Up" ); 139 my $cmd = "decoder_control.cgi?command=0"; 140 $self->sendCmd( $cmd ); 141 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 142} 143 144#Down Arrow 145sub moveConDown 146{ 147 my $self = shift; 148 Debug( "Move Down" ); 149 my $cmd = "decoder_control.cgi?command=2"; 150 $self->sendCmd( $cmd ); 151 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 152} 153 154#Left Arrow 155sub moveConLeft 156{ 157 my $self = shift; 158 Debug( "Move Left" ); 159 my $cmd = "decoder_control.cgi?command=6"; 160 $self->sendCmd( $cmd ); 161 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 162} 163 164#Right Arrow 165sub moveConRight 166{ 167 my $self = shift; 168 Debug( "Move Right" ); 169 my $cmd = "decoder_control.cgi?command=4"; 170 $self->sendCmd( $cmd ); 171 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 172} 173 174#Diagonally Up Right Arrow 175sub moveConUpRight 176{ 177 my $self = shift; 178 Debug( "Move Diagonally Up Right" ); 179 my $cmd = "decoder_control.cgi?command=90"; 180 $self->sendCmd( $cmd ); 181 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 182 183} 184 185#Diagonally Down Right Arrow 186sub moveConDownRight 187{ 188 my $self = shift; 189 Debug( "Move Diagonally Down Right" ); 190 my $cmd = "decoder_control.cgi?command=92"; 191 $self->sendCmd( $cmd ); 192 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 193} 194 195#Diagonally Up Left Arrow 196sub moveConUpLeft 197{ 198 my $self = shift; 199 Debug( "Move Diagonally Up Left" ); 200 my $cmd = "decoder_control.cgi?command=91"; 201 $self->sendCmd( $cmd ); 202 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 203} 204 205#Diagonally Down Left Arrow 206sub moveConDownLeft 207{ 208 my $self = shift; 209 Debug( "Move Diagonally Down Left" ); 210 my $cmd = "decoder_control.cgi?command=93"; 211 $self->sendCmd( $cmd ); 212 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 213} 214 215#Stop 216sub moveStop 217{ 218 my $self = shift; 219 Debug( "Move Stop" ); 220 my $cmd = "decoder_control.cgi?command=1"; 221 $self->sendCmd( $cmd ); 222} 223 224# PP - imported from 9831 - autostop after usleep 225sub autoStop 226{ 227 my $self = shift; 228 my $autostop = shift; 229 if( $autostop ) 230 { 231 Debug( "Auto Stop" ); 232 usleep( $autostop ); 233 my $cmd = "decoder_control.cgi?command=1"; 234 $self->sendCmd( $cmd ); 235 } 236} 237 238#Move Camera to Home Position 239sub presetHome 240{ 241 my $self = shift; 242 Debug( "Home Preset" ); 243 my $cmd = "decoder_control.cgi?command=25"; 244 $self->sendCmd( $cmd ); 245} 246 247#Set preset 248sub presetSet 249{ 250 my $self = shift; 251 my $params = shift; 252 my $preset = $self->getParam( $params, 'preset' ); 253 my $presetCmd = 30 + ($preset*2); 254 Debug( "Set Preset $preset with cmd $presetCmd" ); 255 my $cmd = "decoder_control.cgi?command=$presetCmd"; 256 $self->sendCmd( $cmd ); 257} 258 259#Goto preset 260sub presetGoto 261{ 262 my $self = shift; 263 my $params = shift; 264 my $preset = $self->getParam( $params, 'preset' ); 265 my $presetCmd = 31 + ($preset*2); 266 Debug( "Goto Preset $preset with cmd $presetCmd" ); 267 my $cmd = "decoder_control.cgi?command=$presetCmd"; 268 $self->sendCmd( $cmd ); 269} 270 271#Turn IR on 272sub wake 273{ 274 my $self = shift; 275 Debug( "Wake - IR on" ); 276 my $cmd = "decoder_control.cgi?command=95"; 277 $self->sendCmd( $cmd ); 278} 279 280#Turn IR off 281sub sleep 282{ 283 my $self = shift; 284 Debug( "Sleep - IR off" ); 285 my $cmd = "decoder_control.cgi?command=94"; 286 $self->sendCmd( $cmd ); 287} 288 2891; 290__END__ 291 292=head1 FI8918W 293 294ZoneMinder::Database - Perl extension for FOSCAM FI8918W 295 296=head1 SYNOPSIS 297 298Control script for Foscam MJPEG 8918W cameras. 299 300=head1 DESCRIPTION 301 302You need to set "user=xxx&pwd=yyy" in the ControlDevice field 303of the control tab for that monitor. 304Auto TimeOut should be 1. Don't set it to less - processes 305start crashing :) 306NOTE: unlike HD foscam cameras, this one uses "user" not "usr" 307in the control device 308 309=head2 EXPORT 310 311None by default. 312 313 314 315=head1 SEE ALSO 316 317=head1 AUTHOR 318 319Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt> 320 321=head1 COPYRIGHT AND LICENSE 322 323Copyright (C) 2001-2008 Philip Coombes 324 325This library is free software; you can redistribute it and/or modify 326it under the same terms as Perl itself, either Perl version 5.8.3 or, 327at your option, any later version of Perl 5 you may have available. 328 329 330=cut 331 332