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