From 991291ce67e130e8c1e890bd98094083a2ee56ac Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Fri, 19 Jun 2015 14:12:08 -0400 Subject: [PATCH 1/4] declared so perl does not complain of globals --- scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm index ca9cf6b68..4a7bab230 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI9831W.pm @@ -70,6 +70,7 @@ use Time::HiRes qw( usleep ); # it does not reset the name if a command fails. Net result: Your camera gets a name like "Move Left" which # I bet you won't like my $osd = "off"; +my $cmd; sub new { From f8cc27e224b3a6f5d6ce95bd479c86fed825cd8d Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Fri, 19 Jun 2015 15:45:50 -0400 Subject: [PATCH 2/4] Protocol for 8918W --- .../lib/ZoneMinder/Control/FI8918W.pm | 355 ++++++++++++++++++ 1 file changed, 355 insertions(+) create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm new file mode 100644 index 000000000..835f2943b --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/FI8918W.pm @@ -0,0 +1,355 @@ +# Modified on Jun 19 2016 by PP +# Changes made +# - modified command to work properly and pick up credentials from Control Device +# - the old script did not stop moving- added autostop +# (note that mjpeg cameras have onestep but that is too granular) +# - You need to set "user=xxx&pwd=yyy" in the ControlDevice field (NOT usr like in Foscam HD) + +# ========================================================================== +# +# 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 +# Modified May 2014 by Arun Horne (http://arunhorne.co.uk) to: +# use HTTP basic auth as required by firmware 11.37.x.x upward +# +# 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 MyAgent; + +use base 'LWP::UserAgent'; + + +package ZoneMinder::Control::FI8918W; + +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::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(); + + $self->{ua} = MyAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/" ); + + $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" ); + + # PP Old cameras also support onstep=1 but it is too granular. Instead using moveCon and stop after interval + # PP - cleaned up URL to take it properly from Control device + # Control device needs to be of format user=xxx&pwd=yyy + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd"."&".$self->{Monitor}->{ControlDevice}); + print ("Sending $req\n"); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error REALLY check failed:'".$res->status_line()."'" ); + Error ("Cmd:".$req); + } + + return( $result ); +} + +sub reset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "reboot.cgi?"; + $self->sendCmd( $cmd ); +} + +# PP - in all move operations, added auto stop after timeout + +#Up Arrow +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "decoder_control.cgi?command=0"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Down Arrow +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "decoder_control.cgi?command=2"; + $self->sendCmd( $cmd ); +} + +#Left Arrow +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "decoder_control.cgi?command=6"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Right Arrow +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "decoder_control.cgi?command=4"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Diagonally Up Right Arrow +sub moveConUpRight +{ + my $self = shift; + Debug( "Move Diagonally Up Right" ); + my $cmd = "decoder_control.cgi?command=90"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); + +} + +#Diagonally Down Right Arrow +sub moveConDownRight +{ + my $self = shift; + Debug( "Move Diagonally Down Right" ); + my $cmd = "decoder_control.cgi?command=92"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Diagonally Up Left Arrow +sub moveConUpLeft +{ + my $self = shift; + Debug( "Move Diagonally Up Left" ); + my $cmd = "decoder_control.cgi?command=91"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Diagonally Down Left Arrow +sub moveConDownLeft +{ + my $self = shift; + Debug( "Move Diagonally Down Left" ); + my $cmd = "decoder_control.cgi?command=93"; + $self->sendCmd( $cmd ); + $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); +} + +#Stop +sub moveStop +{ + my $self = shift; + Debug( "Move Stop" ); + my $cmd = "decoder_control.cgi?command=1"; + $self->sendCmd( $cmd ); +} + +# PP - imported from 9831 - autostop after usleep +sub autoStop +{ + my $self = shift; + my $autostop = shift; + if( $autostop ) + { + Debug( "Auto Stop" ); + usleep( $autostop ); + 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; + 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; +__END__ + +=head1 FI8918W + +ZoneMinder::Database - Perl extension for FOSCAM FI8918W + +=head1 SYNOPSIS + +Control script for Foscam MJPEG 8918W cameras. + +=head1 DESCRIPTION + +You need to set "user=xxx&pwd=yyy" in the ControlDevice field +of the control tab for that monitor. +Auto TimeOut should be 1. Don't set it to less - processes +start crashing :) +NOTE: unlike HD foscam cameras, this one uses "user" not "usr" +in the control device + +=head2 EXPORT + +None by default. + + + +=head1 SEE ALSO + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2001-2008 Philip Coombes + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.8.3 or, +at your option, any later version of Perl 5 you may have available. + + +=cut + From 67f1914e2609eb22790353ea903ef0a0f5bb9fef Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Fri, 19 Jun 2015 15:48:03 -0400 Subject: [PATCH 3/4] Added definition for Foscam FI8918W --- db/zm_create.sql.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 1c7ee032e..c7d51641c 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -560,6 +560,8 @@ INSERT INTO Controls VALUES (NULL,'WanscamPT','Remote','Wanscam',1,1,1,0,0,0,0,0 INSERT INTO Controls VALUES (NULL,'3S Domo N5071', 'Remote', '3S', 0, 0, 1, 1, 0, 1, 1, 0, 0, 9999, 0, 9999, 0, 0, 0, 1, 1, 1, 1, 0, 0, 9999, 20, 9999, 0, 0, 0, 1, 1, 1, 1, 0, 0, 9999, 1, 9999, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 64, 1, 0, 1, 1, 0, 0, 0, 0, 1, -180, 180, 40, 100, 1, 40, 100, 0, 0, 1, -180, 180, 40, 100, 1, 40, 100, 0, 0, 0, 0); INSERT INTO Controls VALUES (NULL,'ONVIF Camera','Ffmpeg','onvif',0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,255,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,6,1,1,0,0,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0); INSERT INTO `Controls` VALUES (NULL,'Foscam 9831W','Ffmpeg','FI9831W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,16,1,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,0,0,0,0,0,0,0); +INSERT INTO `Controls` VALUES (NULL,'Foscam FI8918W','Ffmpeg','FI8918W',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,8,0,1,1,1,0,0,0,1,1,0,360,0,360,1,0,4,0,0,1,0,90,0,90,1,0,4,0,0,0,0); + From b41538fe6504723415ee63e45dbbaeb9609999bb Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Fri, 19 Jun 2015 15:51:07 -0400 Subject: [PATCH 4/4] Added definition for Foscam FI8918W --- db/zm_update-1.28.99.sql | 106 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/db/zm_update-1.28.99.sql b/db/zm_update-1.28.99.sql index c1d3da87d..3aab54345 100644 --- a/db/zm_update-1.28.99.sql +++ b/db/zm_update-1.28.99.sql @@ -5,6 +5,7 @@ -- -- Add Controls definition for ONVIF -- Add Controls definition for FI9831W +-- Add Controls definition for FI8918W -- INSERT INTO Controls SELECT * FROM (SELECT NULL as Id, @@ -213,6 +214,111 @@ SELECT * FROM (SELECT NULL as Id, WHERE NOT EXISTS ( SELECT Name FROM Controls WHERE name = 'Foscam 9831W' ) LIMIT 1; + +INSERT INTO Controls +SELECT * FROM (SELECT NULL as Id, + 'Foscam FI8918W' as Name, + 'Ffmpeg' as Type, + 'FI8918W' as Protocol, + 0 as CanWake, + 0 as CanSleep, + 1 as CanReset, + 0 as CanZoom, + 0 as CanAutoZoom, + 0 as CanZoomAbs, + 0 as CanZoomRel, + 0 as CanZoomCon, + 0 as MinZoomRange, + 0 as MaxZoomRange, + 0 as MinZoomStep, + 0 as MaxZoomStep, + 0 as HasZoomSpeed, + 0 as MinZoomSpeed, + 0 as MaxZoomSpeed, + 0 as CanFocus, + 0 as CanAutoFocus, + 0 as CanFocusAbs, + 0 as CanFocusRel, + 0 as CanFocusCon, + 0 as MinFocusRange, + 0 as MaxFocusRange, + 0 as MinFocusStep, + 0 as MaxFocusStep, + 0 as HasFocusSpeed, + 0 as MinFocusSpeed, + 0 as MaxFocusSpeed, + 0 as CanIris, + 0 as CanAutoIris, + 0 as CanIrisAbs, + 0 as CanIrisRel, + 0 as CanIrisCon, + 0 as MinIrisRange, + 0 as MaxIrisRange, + 0 as MinIrisStep, + 0 as MaxIrisStep, + 0 as HasIrisSpeed, + 0 as MinIrisSpeed, + 0 as MaxIrisSpeed, + 0 as CanGain, + 0 as CanAutoGain, + 0 as CanGainAbs, + 0 as CanGainRel, + 0 as CanGainCon, + 0 as MinGainRange, + 0 as MaxGainRange, + 0 as MinGainStep, + 0 as MaxGainStep, + 0 as HasGainSpeed, + 0 as MinGainSpeed, + 0 as MaxGainSpeed, + 0 as CanWhite, + 0 as CanAutoWhite, + 0 as CanWhiteAbs, + 0 as CanWhiteRel, + 0 as CanWhiteCon, + 0 as MinWhiteRange, + 0 as MaxWhiteRange, + 0 as MinWhiteStep, + 0 as MaxWhiteStep, + 0 as HasWhiteSpeed, + 0 as MinWhiteSpeed, + 0 as MaxWhiteSpeed, + 0 as HasPresets, + 8 as NumPresets, + 0 as HasHomePreset, + 1 as CanSetPresets, + 1 as CanMove, + 1 as CanMoveDiag, + 0 as CanMoveMap, + 0 as CanMoveAbs, + 0 as CanMoveRel, + 1 as CanMoveCon, + 1 as CanPan, + 0 as MinPanRange, + 360 as MaxPanRange, + 0 as MinPanStep, + 360 as MaxPanStep, + 1 as HasPanSpeed, + 0 as MinPanSpeed, + 4 as MaxPanSpeed, + 0 as HasTurboPan, + 0 as TurboPanSpeed, + 1 as CanTilt, + 0 as MinTiltRange, + 90 as MaxTiltRange, + 0 as MinTiltStep, + 90 as MaxTiltStep, + 0 as HasTiltSpeed, + 0 as MinTiltSpeed, + 0 as MaxTiltSpeed, + 0 as HasTurboTilt, + 0 as TurboTiltSpeed, + 0 as CanAutoScan, + 0 as NumScanPaths) AS tmp +WHERE NOT EXISTS ( + SELECT Name FROM Controls WHERE name = 'Foscam FI8918W' +) LIMIT 1; + -- -- Hide USE_DEEP_STORAGE from user to prevent accidental event loss --