FOSCAM FI-8620 dome ptz h264 control script on gentoo

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
christophe_y2k
Posts: 102
Joined: Mon Oct 12, 2009 8:47 am
Location: EUROPE-FRANCE-MANDELIEU

FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by christophe_y2k »

Hi all, this is a small tuto to use this FOSCAM FI-8620 only H264 ptz camera.
Sorry for my English but i'm French.

This Tuto is updated at 08 August 2013 00h11 GMT+1 at Version 1.1

You need FOSCAM FI-8620 camera with Firmware version V3.2.2.2.1-20120815 (latest at 04/08/2013)
You need ZoneMinder V1.25 build 159 from the good SVN of Nextime.
You need to tweak some files until all patch are integrated in source code.
You need to compile yourself zoneminder and have a fresh empty MySQL database.
I use only Gentoo Linux distribution and i write this tuto for this distribution.

This camera have a buggy firmware , Foscam camera are buggy, and generally do not work well, and generally never
fully work well...

Gentoo generally require some classic ebuild:
you need to have apache,mysql,perl,ffmpeg,php installed and running

And specific ebuild (package) :

Code: Select all

# emerge dev-perl/DateManip
# emerge dev-perl/libwww-perl
# emerge dev-perl/PHP-Serialization
# emerge dev-perl/Device-SerialPort
# emerge dev-perl/MIME-Lite
# emerge dev-perl/MIME-tools
# emerge virtual/perl-Getopt-Long
# emerge virtual/perl-Module-Load
# emerge perl-Time-HiRes
# emerge media-libs/netpbm
# emerge dev-perl/MD5
# emerge media-libs/libv4l
# emerge SVN-Mirror
MySQL Setup of ZM database:

Code: Select all

# mysql -u root -p mysql
(enter your mysql admin/root password)
mysql> drop database zm ;
mysql> create database zm;
mysql> grant alter,select,insert,update,delete,create on zm.* to 'zmuser'@localhost identified by 'zmpass';
mysql> show databases ;
mysql> quit ;
Add an user "zoneminder" with password "zoneminder" to your linux.

Because when you test ZM PTZ script, you need to be use this user in console,
if you use root console you modify the owner of files and after the ptz control system
do not work, same if you plan to use cron job with ZoneMinder.

Code: Select all

# useradd -m -g users -s /bin/bash zoneminder
# passwd zoneminder
(enter zoneminder or your own password here)
Add zoneminder user to the wheel groups

Code: Select all

# gpasswd -a zoneminder wheel
Activate wheel

Code: Select all

# nano -w /etc/sudoers
(remove the # for have this :)
##
## User privilege specification
##
root ALL=(ALL) ALL

## Uncomment to allow members of group wheel to execute any command
 %wheel ALL=(ALL) ALL
The folder where we install the source code must be empty

Code: Select all

# rm -R /usr/src/zm
or
$ sudo rm -R /usr/src/zm
Now login with zoneminder user and create folder

Code: Select all

# login zoneminder
(enter the zoneminder user password : zoneminder)
$ cd /usr/src
$ sudo mkdir zm
(enter the zoneminder user password : zoneminder for all futur sudo command if the system ask you)
$ sudo chown -R zoneminder:users /usr/src/zm
$ cd zm
Download the source code from NEXTIME SVM, compile and install...

Nextime have an good thread in this forum here http://www.zoneminder.com/forums/viewto ... =9&t=20587
His job come from MasterTheKnife excellent work http://www.zoneminder.com/forums/viewto ... =9&t=17652
Nextime add some patch and release incredible plugin, he also update source for new ffmpeg revision.

Code: Select all

$ svn co https://svn.unixmedia.net/public/zum/trunk/zum/ /usr/src/zm
(REVISION 159 At Tue Aug 06, 2013)
$ sudo  mysql --user=root -p zm < /usr/src/zm/db/zm_create.sql
(enter your mysql admin/root password)
$ cd /usr/src/zm
$ autoreconf

$ ./configure --prefix=/usr --with-webhost=zoneminder.yourdomain.fr --datadir=/usr/src --sysconfdir=/etc --localstatedir=/var/lib --libdir=/usr/lib64 --with-libarch=lib64 --with-mysql=/usr --with-ffmpeg=/usr --with-webdir=/var/www/zoneminder.yourdomain.fr/htdocs --with-cgidir=/var/www/zoneminder.yourdomain.fr/cgi-bin --with-webuser=apache --with-webgroup=apache --enable-debug=no --enable-crashtrace=no --enable-mmap=no ZM_DB_HOST=localhost ZM_DB_NAME=zm ZM_DB_USER=zmuser ZM_DB_PASS=zmpass CXXFLAGS=-D__STDC_CONSTANT_MACROS

$ sudo /etc/init.d/zm stop
$ make
$ sudo make install
$ make clean
$ cd ..
$ sudo zmupdate.pl
$ sudo zmupdate.pl -f
$ sudo rm -R /var/log/zm
$ sudo mkdir /var/log/zm
$ sudo chown -R apache:apache /var/log/zm
$ sudo chmod u+w /var/log/zm
$ sudo rm -R /tmp/zm
$ sudo mkdir /tmp/zm
$ sudo chown -R apache:apache /tmp/zm
$ sudo chmod u+w /tmp/zm
Setup for apache, adapt it for you:

Code: Select all

# nano -w /etc/apache2/vhost.d/10_zoneminder.conf

ScriptAlias /zoneminder/cgi-bin/zms /var/www/zoneminder.yourdomain.fr/cgi-bin/zms
ScriptAlias /zoneminder/cgi-bin/nph-zms /var/www/zoneminder.yourdomain.fr/cgi-bin/nph-zms

<Directory "/var/www/zoneminder.yourdomain.fr/cgi-bin">
  AllowOverride All
  Options ExecCGI
  Order allow,deny
  Allow from all
</Directory> 

Alias /zoneminder "/var/www/zoneminder.yourdomain.fr/htdocs"

<Directory "/var/www/zoneminder.yourdomain.fr/htdocs">
  Options -Indexes MultiViews FollowSymLinks
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory> 

Very important :
Use and tweak zoneminder initscript;
I adapt for Gentoo and integrate the famous zombie process killer.
Because when you debug the control script, when you have some error code in your control script,
zmcontrol process stay zombie, and until you kill it, you can't move anything with cam, you can't send any ptz command.
For that i stop and restart zm with this script /etc/init.d/zm stop ... /etc/init.d/zm start ...
in console mode only (never with zm web interface)
to debug my perl script at every modification .
When you stop zm if the initscript found an zombie process that mean you have a bug in your perl script...
And this init script remove all temp files, pid file, verify right and owner on files you must use it, if not
zoneminder never works weel.

Code: Select all

# nano -w /etc/init.d/zm

Code: Select all

#!/bin/sh
# description: ZoneMinder is the top Linux video camera security and surveillance solution. ZoneMinder is intended for use in single or multi-camera video security applications.Copyright: Philip Coombes, Corey DeLasaux 2003-2008
# chkconfig: 2345 99 00
# processname: zmpkg.pl

# Source function library.
#. /etc/rc.d/init.d/functions
# Adapted for Linux Gentoo and included the Zombie process killer - by Christophe DAPREMONT - christophe_y2k@yahoo.fr at 21/07/2013
# Famous Zombie killer script from Marius Voila - http://www.mariusv.com/automatic-zombie-processes-killing-shell-script/
#
prog=ZoneMinder
ZM_CONFIG="/etc/zm.conf"
pidfile="/var/run/zm"
LOCKFILE=/var/lock/zm
tempfile=/tmp/zm
logfile=/var/log/zm/*

loadconf()
{
	if [ -f $ZM_CONFIG ]; then
		. $ZM_CONFIG
	else
		echo "ERROR: $ZM_CONFIG not found."
		return 1
	fi
}

loadconf
command="$ZM_PATH_BIN/zmpkg.pl"

start()
{
	zmupdate || return $?
	loadconf || return $?
	#Make sure the directory for our PID folder exists or create one.
	[ ! -d $pidfile ] \
		&& mkdir -m 774 $pidfile \
		&& chown $ZM_WEB_USER:$ZM_WEB_GROUP $pidfile
	#Make sure the folder for the socks file exists or create one
	GetPath="select Value from Config where Name='ZM_PATH_SOCKS'"
    dbHost=`echo $ZM_DB_HOST | cut -d: -f1`
    dbPort=`echo $ZM_DB_HOST | cut -d: -s -f2`
    if [ "$dbPort" = "" ]
    then
	    ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$ZM_DB_HOST -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'`
    else
	    ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$dbHost -P$dbPort -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'`
    fi 
	[ ! -d $ZM_PATH_SOCK ] \
		&& mkdir -m 774 $ZM_PATH_SOCK \
		&& chown $ZM_WEB_USER:$ZM_WEB_GROUP $ZM_PATH_SOCK
	echo -n $"Starting $prog: "
	$command start
	RETVAL=$?
#	 [$RETVAL = 0 ] && success || failure
# 	 echo
#	 [ $RETVAL = 0 ] && touch $LOCKFILE
#	 return $RETVAL
        [ $RETVAL = 0 ] && echo success
	[ $RETVAL != 0 ] && echo failure
	echo
	[ $RETVAL = 0 ] && touch /var/lock/zm
	return $RETVAL
}

stop()
{
	loadconf
	echo -n $"Stopping $prog: "
	$command stop
	RETVAL=$?

#	[ $RETVAL = 0 ] && success || failure
#	echo
#	[ $RETVAL = 0 ] && rm -f $LOCKFILE

	[ $RETVAL = 0 ] && echo success
	[ $RETVAL != 0 ] && echo failure
	echo
	rm -r $tempfile
	rm $logfile
        rm -f $LOCKFILE
        
	stat=`ps ax | awk '{print $1}' | grep -v "PID" | xargs -n 1 ps lOp | grep -v "UID" | awk '{print"pid: "$3" *** parent_pid: "$4" *** status: "$10" *** process: "$13}' | grep ": Z"`
            if ((${#stat} > 0));then   
                			echo zombie processes found:
			                echo .
            				ps ax | awk '{print $1}' | grep -v "PID" | xargs -n 1 ps lOp | grep -v "UID" | awk '{print"pid: "$3" *** parent_pid: "$4" *** status: "$10" *** process: "$13}' | grep ": Z"
            				echo killing zombies...
			                ps ax | awk '{print $1}' | grep -v "PID" | xargs -n 1 ps lOp | grep -v "UID" | awk '{print$4" status:"$10}' | grep "status:Z" | awk '{print $1}' | xargs -n 1 kill -9
				       
				else   
				        echo no zombies found!
				fi       
	[ $RETVAL = 0 ] && touch /var/lock/zm
	return $RETVAL
}

zmstatus()
{
	loadconf
	result=`$command status`
	if [ "$result" = "running" ]; then
		echo "ZoneMinder is running"
		$ZM_PATH_BIN/zmu -l
		RETVAL=0
	else
		echo "ZoneMinder is stopped"
		RETVAL=1
	fi
}

zmupdate()
{
	if [ -x $ZM_PATH_BIN/zm_update ]; then
		$ZM_PATH_BIN/zm_update -f
	fi
}


case "$1" in
	'start')
		start
		;;
	'stop')
		stop
		;;
	'restart')
		stop
		start
		;;
	'condrestart')
		loadconf
		result=`$ZM_PATH_BIN/zmdc.pl check`
		if [ "$result" = "running" ]; then
			$ZM_PATH_BIN/zmdc.pl shutdown > /dev/null
			rm -f $LOCKFILE
			start
		fi
		;;
	'status')
		echo "Apache server :"
		/etc/init.d/apache2 status
		echo "MySQL server :"
		/etc/init.d/mysql status
		echo "ZoneMinder status :"
		zmdc.pl check
		;;
	*)
		echo "Usage: $0 { start | stop | restart | condrestart | status }"
		RETVAL=1
		;;
esac
exit $RETVAL
ZM InitScript must be executable:

Code: Select all

# chmod u+x /etc/init.d/zm
The next super tweak come from "Karthu"
in this thread http://www.zoneminder.com/forums/viewto ... +as+a+type

(vital for chose an ffmpeg camera in control tab)

He wrote:
You need to make changes in two places for it to accept Ffmpeg as a type in the Controls creation.
Change this file to add the Ffmpeg option in the classic skin


edit this file /var/www/zoneminder.yourdomain.fr/htdocs/skins/classic/views/controlcap.php
becarefully the same file with "s" at the end (controlcaps.php) exist in the same folder

at line 348 you need have this:

Code: Select all

        $types = array( 'Local'=>$SLANG['Local'], 'Remote'=>$SLANG['Remote'], 'Ffmpeg'=>$SLANG['Ffmpeg'] );


After edit, restore right and owner (apache:apache):

Code: Select all

# chown apache:apache /var/www/zoneminder.yourdomain.fr/htdocs/skins/classic/views/controlcap.php


Add the type to the Controls mysql Type column enum:

Code: Select all

$ mysql -h localhost -u zmuser -pzmpass zm
mysql> alter table Controls modify column Type enum('Local', 'Remote', 'Ffmpeg') not null default 'Local';
mysql> quit	
These changes should then make Ffmpeg type available in the Control edit screen, and then the Ffmpeg Control you have created should subsequently appear in the list of Controls available for the Ffmpeg Monitor you have created.
Ideally these changes would be made available upstream in the Zoneminder github repo so we do not need to hack it to work this way.



And now the script to control the camera must be placed here with this name:
Maybe different on your own distro and perl version, but :
/usr/ ..../..../..../zoneMinder/Control/FI8620_Y2k.pm
do not change.

Code: Select all

/usr/lib64/perl5/site_perl/5.12.4/ZoneMinder/Control/FI8620_Y2k.pm
The owner and group and proper permissions on this file:

Code: Select all

Owner: root
Group: root
-rw-r--r--	100644
For the similar FOSCAM H264 FI-8608W the script is here http://www.zoneminder.com/forums/viewto ... =9&t=21244

The "FI8620_Y2k.pm" control script: (updated at V1.1 at 11 AUGUST 2013)

Code: Select all

# V1.1 ====================================================================================
#
# ZoneMinder FOSCAM version 1.0 API Control Protocol Module, $Date$, $Revision$
# Copyright (C) 2001-2008  Philip Coombes
#
# 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.
#
# V1.1 ====================================================================================
#
# This module FI8620_Y2k.pm contains the implementation of API camera control
# For FOSCAM FI8620 Dome PTZ Camera (This cam support only H264 streaming)
# V0.1b Le 01 JUIN 2013
# V0.2b Le 11 JUILLET 2013
# V0.5b Le 24 JUILLET 2013
# V0.6b Le 01 AOUT 2013 - 
# V1.0  Le 04 AOUT 2013 - production usable if you do not use preset ptz
# V1.1  Le 11 AOUT 2013 - put a cosmetic update source code
# If you wan't to contact me i understand French and English, precise ZoneMinder in subject
# My name is Christophe DAPREMONT my email is christophe_y2k@yahoo.fr
#
# V1.1 ====================================================================================
package ZoneMinder::Control::FI8620_Y2k;

use 5.006;
use strict;
use warnings;

require ZoneMinder::Base;
require ZoneMinder::Control;

our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ===================================================================================================================================
#
# FI8620 FOSCAM Dome PTZ H264 Control Protocol
# with Firmware version V3.2.2.2.1-20120815 (latest at 04/08/2013)
# based with the latest buggy CGI doc from FOSCAM ( http://foscam.us/forum/cgi-api-sdk-for-mjpeg-h-264-camera-t2986.html )
# This IPCAM work under ZoneMinder V1.25 from alternative source of code 
# from this svn at https://svn.unixmedia.net/public/zum/trunk/zum/
# Many Thanks to "MASTERTHEKNIFE" for the excellent speed optimisation ( http://www.zoneminder.com/forums/viewtopic.php?f=9&t=17652 )
# And to "NEXTIME" for the recent source update and incredible plugins ( http://www.zoneminder.com/forums/viewtopic.php?f=9&t=20587 )
# And all people helping ZoneMinder dev.
#
# -FUNCTIONALITIES:
# -Move camera in 8 direction with arrow, the speed of movement is function
#  of the position of your mouse on the arrow.
#  Extremity of arrow equal to fastest speed of movement
#  Close the base of arrow to lowest speed of movement
#  for diagonaly you can click before the begining of the arrow for low speed
#  In round center equal to stop to move
# -You can clic directly on the image that equal to click on arrow (for the left there is a bug in zoneminder speed is inverted)
# -Zoom Tele/Wide with time control to simulate speed because speed value do not work (buggy firmware or not implemented on this cam)
# -Focus Near/Far with time control to simulate speed because speed value do not work (buggy firmware or not implemented on this cam)
# -Autofocus is automatic when you move again or can be setting by autofocus button
# -8 Preset PTZ are implemented but the firmware is buggy and that do not work
#  You Need to configure ZoneMinder PANSPEED & TILTSEPPED & ZOOMSPEED 1 to 63 by 1 step
# -This Script use for login "admin" this hardcoded and your password must setup in "Control Device" section
# -This script is compatible with the basic authentification method used by mostly new camera
# -AutoStop function is active and you must set up value (in sec exemple 0.5) under AutoStop section
#  or you can set up to 0 for disable it but the camera never stop to move and trust me, she can move all the night...
#  (you need to click to the center arrow for stop)
# -"White In" to control Brightness, "auto" for restore the original value of Brightness
# -"White Out" to control Contrast, "man" for restore the original value of Contrast
# -"Iris Open" to control Saturation , "auto" for restore the original value of Saturation
# -"Iris Close" to control Hue , "man" for restore the original value of Hue
# -Another cool stuff i use the OSD function of this cam for printing the command with the value
#  The button of Focus "Man" is for enable or disable OSD but that do not work ( it's my bug... i'm very very new with perl )
# ===================================================================================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );

# Set $osd to "off" if you wan't disabled OSD i need to place this variable in another script because
# this script is reload at every command ,if i want the button on/off (Focus MAN) for OSD works...
my $osd = "on";

sub new
{
    my $class = shift;
    my $id = shift;
    my $self = ZoneMinder::Control->new( $id );
    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" );
}

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" );
    # I solve the authentification problem with recent Foscam
    # I use perl Basic Authentification method
    my $ua = LWP::UserAgent->new();
    my $req = HTTP::Request->new( GET =>"http://".$self->{Monitor}->{ControlAddress}."/web/cgi-bin/hi3510/".$cmd );
    $req->authorization_basic('admin', $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 moveStop
{
	my $self = shift;
	Debug( "Move Stop" );
	my $cmd = "ptzctrl.cgi?-step=0&-act=stop";
	$self->sendCmd( $cmd );
        my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=0&-name=.";
        $self->sendCmd( $cmd );
}

sub autoStop
{
    my $self = shift;
    my $autostop = shift;
    if( $autostop )
    {
       Debug( "Auto Stop" );
       usleep( $autostop );
       my $cmd = "ptzctrl.cgi?-step=0&-act=stop";
       $self->sendCmd( $cmd );
       my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=0&-name=.";
       $self->sendCmd( $cmd );
    }
}

sub moveConUp
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
			    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
			   $tiltspeed = 1;
		          }
    Debug( "Move Up" );	
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Move Up $tiltspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=up&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} ); 
}

sub moveConDown
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
			    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
		  	   $tiltspeed = 1;
		          }
    Debug( "Move Down" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Move Down $tiltspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=down&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConLeft
{
    my $self = shift;
    my $params = shift;
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    # Algorithme pour inverser la table de valeur de la flèche gauche, (for invert the value) 63 ==> 1 et 1 ==> 63 ...
    $panspeed = abs($panspeed - 63) + 1;
    Debug( "Move Left" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Move Left $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=left&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConRight
{
    my $self = shift;
    my $params = shift;
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    Debug( "Move Right" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Move Right $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=right&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConUpLeft
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
			    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
			   $tiltspeed = 1;
		          }
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect value in the database
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    Debug( "Move Con Up Left" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Up $tiltspeed Left $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=up&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    my $cmd = "ptzctrl.cgi?-step=0&-act=left&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConUpRight
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
			    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
			   $tiltspeed = 1;
		          }
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    Debug( "Move Con Up Right" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Up $tiltspeed Right $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=up&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    my $cmd = "ptzctrl.cgi?-step=0&-act=right&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConDownLeft
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
	 		    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
			   $tiltspeed = 1;
		          }
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    Debug( "Move Con Down Left" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Down $tiltspeed Left $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=down&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    my $cmd = "ptzctrl.cgi?-step=0&-act=left&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub moveConDownRight
{
    my $self = shift;
    my $params = shift;
    my $tiltspeed = $self->getParam( $params, 'tiltspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $tiltspeed > 59 ) {
	 		    $tiltspeed = 63;
		           }
    if ( $tiltspeed < 6 ) {
			   $tiltspeed = 1;
		          }
    my $panspeed = $self->getParam( $params, 'panspeed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $panspeed > 59 ) {
			   $panspeed = 63;
		          }
    if ( $panspeed < 6 ) {
			  $panspeed = 1;
		         }
    Debug( "Move Con Down Right" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Down $tiltspeed Right $panspeed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=down&-speed=$tiltspeed";
    $self->sendCmd( $cmd );
    my $cmd = "ptzctrl.cgi?-step=0&-act=right&-speed=$panspeed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub zoomConTele
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 59 ) {
		        $speed = 63;
		       }
    if ( $speed < 6 ) {
		       $speed = 1;
		      }
    Debug( "Zoom-Tele" );
    # I use OSD Function to send the speed used for determining the time before stop the order
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Zoom Tele $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=zoomin";
    $self->sendCmd( $cmd );
    # The variable speed does not work with zoom setting, so I used to set the duration of the order
    # the result is identical
    $self->autoStop( int(10000*$speed) );
}

sub zoomConWide
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 59 ) {
		        $speed = 63;
		       }
    if ( $speed < 6 ) {
		       $speed = 1;
		      }
    Debug( "Zoom-Wide" );
    # I use the feature OSD (OnScreenDisplay). Variable speed as a basis for calculating the duration of the zoom order
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Zoom Wide $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=zoomout";
    $self->sendCmd( $cmd );
    # The variable speed does not work with zoom setting, so I used to set the duration of the order
    # the result is identical
    $self->autoStop( int(10000*$speed) );
}

sub focusConNear
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 59 ) {
		        $speed = 63;
	    	       }
    if ( $speed < 6 ) {
		       $speed = 1;
		      }
    Debug( "Focus Near" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Focus Near $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=focusout&-speed=$speed";
    $self->sendCmd( $cmd );
    # The variable speed does not work with focus setting, so I used to set the duration of the order
    # the result is identical
    $self->autoStop( int(10000*$speed) );
}

sub focusConFar
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 59 ) {
		        $speed = 63;
		       }
    if ( $speed < 6 ) {
		       $speed = 1;
		      }
    Debug( "Focus Far" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Focus Far $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-step=0&-act=focusin&-speed=$speed";
    $self->sendCmd( $cmd );
    # The variable speed does not work with focus setting, so I used to set the duration of the order
    # the result is identical
    $self->autoStop( int(10000*$speed) );
}

sub focusAuto
{
    my $self = shift;
    Debug( "Focus Auto" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Focus Auto";
         $self->sendCmd( $cmd );
        }
    my $cmd = "ptzctrl.cgi?-act=auto&-step=1";
    $self->sendCmd( $cmd );
}

sub focusMan
{
    my $self = shift;
    Debug( "Focus Manu=OSD ON OFF" );
    if ( $osd eq "on" )
	 {
	  $osd = "off";
          my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=OSD $osd";
          $self->sendCmd( $cmd );
          $self->autoStop( int(1000000*0.5) );
	 }
    if ( $osd eq "off" )
         {
          $osd = "on";
          my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=OSD $osd";
          $self->sendCmd( $cmd );
          $self->autoStop( int(1000000*0.5) );
         }
}

sub whiteConIn
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 255 ) {
		         $speed = 255;
		        }
    if ( $speed < 0 ) {
		       $speed = 0;
		      }
    Debug( "White ConIn=brightness" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Brightness $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-brightness=$speed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub whiteConOut
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect possible value in the database, and for realise at low and high speed an more precise moving
    if ( $speed > 255 ) {
		         $speed = 255;
		        }
    if ( $speed < 0 ) {
		       $speed = 0;
		      }
    Debug( "White ConOut=Contrast" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Contrast $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-contrast=$speed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub whiteAuto
{
    my $self = shift;
    Debug( "White Auto=Brightness Reset" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Brightness Reset";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-brightness=120";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub whiteMan
{
    my $self = shift;
    Debug( "White Manuel=Contrast Reset" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Contrast Reset";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-contrast=140";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub irisConOpen
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect value in the database
    if ( $speed > 255 ) {
		         $speed = 255;
		        }
    if ( $speed < 0 ) {
		       $speed = 0;
		      }
    Debug( "Iris ConOpen=Saturation" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Saturation $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-saturation=$speed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub irisConClose
{
    my $self = shift;
    my $params = shift;
    my $speed = $self->getParam( $params, 'speed' );
    # Standardization for incorrect value in the database
    if ( $speed > 255 ) {
		         $speed = 255;
		        }
    if ( $speed < 0 ) {
		       $speed = 0;
		      }
    Debug( "Iris ConClose=Hue" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Hue $speed";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-hue=$speed";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub irisAuto
{
    my $self = shift;
    Debug( "Iris Auto=Saturation Reset" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Saturation Reset";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-saturation=150";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub irisMan
{
    my $self = shift;
    Debug( "Iris Manuel=Hue Reset" );
    if ( $osd eq "on" )
	{
         my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=Hue Reset";
         $self->sendCmd( $cmd );
        }
    my $cmd = "param.cgi?cmd=setimageattr&-hue=255";
    $self->sendCmd( $cmd );
    $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
}

sub presetSet
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    if ( ( $preset >= 1 ) && ( $preset <= 8 ) ) {
    						 Debug( "Clear Preset $preset" );
    						 my $cmd = "preset.cgi?-act=set&-status=0&-number=$preset";
		      			         $self->sendCmd( $cmd );
                                                 Debug( "Set Preset $preset" );
					         if ( $osd eq "on" )
							{
   					                 my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=PresetSet $preset";
		      			                 $self->sendCmd( $cmd );
							}
                                                 my $cmd = "preset.cgi?-act=set&-status=1&-number=$preset";
                                                 $self->sendCmd( $cmd );
						 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
					        }
}

sub presetGoto
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    if ( ( $preset >= 1 ) && ( $preset <= 8 ) ) {
					         Debug( "Goto Preset $preset" );
					         if ( $osd eq "on" )
							{
					       		 my $cmd = "param.cgi?cmd=setoverlayattr&-region=1&-show=1&-name=PresetGoto $preset";
		      			                 $self->sendCmd( $cmd );
							}
					         my $cmd = "preset.cgi?-act=goto&-number=$preset";
					         $self->sendCmd( $cmd );
						 $self->autoStop( $self->{Monitor}->{AutoStopTimeout} );
					        }
}

1;
__END__
# Below is stub documentation for your module. You'd better edit it!

=head1 FI8620

ZoneMinder::Database - Perl extension for FOSCAM FI8620

=head1 SYNOPSIS

  use ZoneMinder::Database;
  blah blah blah

=head1 DESCRIPTION

Stub documentation for ZoneMinder, created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub
unedited.

Blah blah blah.

=head2 EXPORT

None by default.



=head1 SEE ALSO

Mention other useful documentation such as the documentation of
related modules or operating system documentation (such as man pages
in UNIX), or any relevant external documentation such as RFCs or
standards.

If you have a mailing list set up for your module, mention it here.

If you have a web site set up for your module, mention it here.

=head1 AUTHOR

Philip Coombes, E<lt>philip.coombes@zoneminder.comE<gt>

=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
White In => set brightness value 0 from 255
White "auto" button => restore default value of brightness

White Out => set contrast value 0 from 255
White "man" button => restore default value of contrast

Iris open => set Saturation value 0 from 255
Iris "auto" button => restore default value of Saturation

Iris Close => set Hue value from 0 to 255
Iris "man" button => restore default value of Hue

For move slowly click on the base of arrow
For move fast click on the etremity of arrow

For move slowly in diagonaly click betwen the round stop center and the base of arrow...

If you change autostop value you need to stop and start ZoneMinder for that take effect.

Many thanks for all, next time the control script for FI9821W

Christophe_y2k.
Last edited by christophe_y2k on Sun Mar 22, 2015 11:58 am, edited 14 times in total.
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by knight-of-ni »

Nice work.

Do you happen to know what exactly was modified in the latest firmware for this camera?
Looking at how the control script handles authentication, the camera still appears to want to authenticate using a separate password challenge.

Can you check the camera setup screenshots? They don't appear for me.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
christophe_y2k
Posts: 102
Joined: Mon Oct 12, 2009 8:47 am
Location: EUROPE-FRANCE-MANDELIEU

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by christophe_y2k »

Hi, my camera come with this latest firmware(buy in june 2013)

Foscam and other constructor (clone) may upgrade system login because recently
user found a serious bug that permit to read login and password from the web interface of cam...
all Chinese camera are impacted with one or two serious security issue.

This is in this thread: http://www.computerworld.com/s/article/ ... geNumber=1

And on the foscam forum but i do not found the topic ...

I think you need to upgrade your camera firmware...
Last edited by christophe_y2k on Sun Mar 22, 2015 12:00 pm, edited 1 time in total.
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by knight-of-ni »

It's interesting that you've listed the following as the Source Path:

rtsp://{user}:{pwd}@{camera_ip}:554/11

I guess I misread the documentation for this camera. When I read the portion that states how to get a video stream via the rtsp method, I thought it stated that embedding the username and password like this would not work. Well, I'm glad it does indeed work!

Lastly, I can't seem to view the images in your post from my work. They appear just fine when viewed from home, however.
Our office Sonicwall firewall is tripping up on the site the images live: http://www.gh-pc.com/
It seems to think that site is tied to some kind of botnet.
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
christophe_y2k
Posts: 102
Joined: Mon Oct 12, 2009 8:47 am
Location: EUROPE-FRANCE-MANDELIEU

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by christophe_y2k »

My domain do not have any bot ...virus ..., but is ip is partaged by another website.
User avatar
knight-of-ni
Posts: 2404
Joined: Thu Oct 18, 2007 1:55 pm
Location: Shiloh, IL

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by knight-of-ni »

I just created a pull request to add this camera, and your other foscam cameras, to the zoneminder source tree. These cameras would also appear as a zoneminder preset; thus making it easier to program.

https://github.com/ZoneMinder/ZoneMinder/pull/85

I notced your instruction indicate a camera resolution of 704 x 576 for the fi8620. However the Foscam website indiates this camera's resolution should be 720 x 576. Can you verify which is correct?
Visit my blog for ZoneMinder related projects using the Raspberry Pi, Orange Pi, Odroid, and the ESP8266
All of these can be found at https://zoneminder.blogspot.com/
christophe_y2k
Posts: 102
Joined: Mon Oct 12, 2009 8:47 am
Location: EUROPE-FRANCE-MANDELIEU

Re: FOSCAM FI-8620 dome ptz h264 control script on gentoo

Post by christophe_y2k »

704x576 is the value detected by VLC
in ZoneMinder 704x576 or 720x576 works because ffmpeg can open it , if you want 1024*768 that works too... ffmpeg zoom the image

this camera resolution have a native bug (Foscam = Bug if you're product haven't got a bug it's not a Foscam) resolution
and there is a black square all over the image...

For me vlc is relevant, if this soft detect 704 ... this is the original resolution.
Post Reply