Replaced the onvif control module with a modified version of Netcat.

The original onvif module was NOT at all ONVIF protocol implementation.
This one pretty much copies the Netcat module but with a bit of clarity
to the XML that is sent to the camera but most importantly allows
specification of full onvif URL including authentication and control URI
through the Control Address field. Parsing of the url is done through a
combination of sane defaults and the URI module.
This commit is contained in:
Arek Kossendowski 2021-02-25 22:37:34 +00:00
parent b8fcd7c85f
commit 36f11158df
2 changed files with 463 additions and 168 deletions

View File

@ -893,7 +893,7 @@ INSERT INTO Controls VALUES (NULL,'Loftek Sentinel','Remote','LoftekSentinel',0,
INSERT INTO Controls VALUES (NULL,'Toshiba IK-WB11A','Remote','Toshiba_IK_WB11A',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,0,1,10,0,1,1,0,1,0,1,0,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,'WanscamPT','Remote','Wanscam',1,1,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,1,0,1,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,16,0,0,0,0,0,1,16,1,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,'3S Domo N5071', 'Remote', '3S', 0, 0, 1, 0,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,0,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,'ONVIF Camera','Ffmpeg','onvif',0,0,1,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,1,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,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,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);
INSERT INTO `Controls` VALUES (NULL,'SunEyes SP-P1802SWPTZ','Libvlc','SPP1802SWPTZ',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,0,0,0,0,1,8,0,1,1,0,0,0,0,1,1,0,0,0,0,1,0,64,0,0,1,0,0,0,0,1,0,64,0,0,0,0);

View File

@ -1,7 +1,7 @@
# ==========================================================================
#
# ZoneMinder ONVIF Control Protocol Module
# Copyright (C) Jan M. Hochstein
# ZoneMinder ONVIF Control Protocol Module, $Date: 2021-02-25 22:07:00 +0000 (Thu, 25 Feb 2021) $, $Revision: 0001 $
# Based on the Netcat onvif script by Andrew Bauer (knnniggett@users.sourceforge.net)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@ -19,28 +19,55 @@
#
# ==========================================================================
#
# This module contains the implementation of the ONVIF device control protocol
# This module contains the implementation of onvif protocol
#
package ZoneMinder::Control::onvif;
use 5.006;
use strict;
use warnings;
use MIME::Base64;
use Digest::SHA;
use DateTime;
use URI;
use Data::Dumper;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our %CamParams = ();
our ($profileToken, $address, $port, %identity);
my ( $controlUri, $scheme );
# ==========================================================================
#
# ONVIF Control Protocol
# This script sends ONVIF compliant commands and may work with other cameras
#
# On ControlAddress use the format :
# USERNAME:PASSWORD@ADDRESS:PORT
# eg : admin:@10.1.2.1:80
# zoneminder:zonepass@10.0.100.1:40000
# Configuration options (Source->Control tab)
# - Control Type: ONVIF
# - Control Device: prof0 - this is dependant on camera. It maybe required to sniff the traffic using Wireshark to find this out. If left empty value of "000" will be used.
# - Control Address: <scheme>://[<user>:<password>@]<ip_or_host_of_onvif_enabled_camera>[:port][control_uri]
# - Auto Stop Timeout: 1.00 - how long shold the camera move for when move command is issued. Value of 1.00 means 1s.
# - Track Motion: NOT IMPLEMENTED - this suppose to be a feature for automatic camera scrolling (moving).
# - Track Delay: NOT IMPLEMENTED
# - Return Location: Home|Preset 1 - NOT IMPLEMENTED
#
# Absolute minimum required supported "Control Address" would be:
# - 192.168.1.199
# This will use the following defaults:
# - port: 80
# - Control Device: 000
# - Control URI: /onvif/device_control
# - No authentication
# - No Auto Stop Timeout (on movement command the camera will keep moving until it reaches it's edge)
#
# Example Control Address values:
# - http://user:password@192.168.1.199:888/onvif/device_control :Connect to camera at IP: 192.168.1.199 on port 888 with "username" and "password" credentials using /onvif/device_control URI
# - user:password@192.168.1.199 :Connect to camera at IP: 192.168.1.199 on default port 80 with "username" and "password" credentials using default /onvif/device_control URI
# - 192.168.1.199 :Connect to camera at IP: 192.168.1.199 without any authentication and use the default /onvif/device_control URI over HTTP.
#
# ==========================================================================
@ -54,6 +81,11 @@ sub open {
$self->loadMonitor();
$profileToken = $self->{Monitor}->{ControlDevice};
if ($profileToken eq '') { $profileToken = '000'; }
parseControlAddress($self->{Monitor}->{ControlAddress});
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
@ -61,39 +93,140 @@ sub open {
$self->{state} = 'open';
}
sub parseControlAddress {
my $controlAddress = shift;
#make sure url start with a scheme
if ( $controlAddress !~ m'^https?://') {
$scheme = "http";
$controlAddress = $scheme."://".$controlAddress;
}
my $url = URI->new($controlAddress);
#set the scheme
$scheme = $url->scheme;
#If we have authinfo
if ($url->userinfo){
my ($username , $password) = split /:/, $url->userinfo;
%identity = (username => $username, password => $password);
}
#If we have no explicitly defined port
if (!$url->port){
$port = $url->default_port;
} else {
$port = $url->port;
}
if (!$url->path){
$controlUri = "/onvif/device_control";
} else {
$controlUri = $url->path;
}
$address = $url->host;
}
sub digestBase64 {
my ($nonce, $date, $password) = @_;
my $shaGenerator = Digest::SHA->new(1);
$shaGenerator->add($nonce . $date . $password);
return encode_base64($shaGenerator->digest, '');
}
sub authentificationHeader {
my ($username, $password) = @_;
my @set = ('0' ..'9', 'A' .. 'Z', 'a' .. 'z');
my $nonce = join '' => map $set[rand @set], 1 .. 20;
my $nonceBase64 = encode_base64($nonce, '');
my $currentDate = DateTime->now()->iso8601().'Z';
return '
<s:Header>
<Security s:mustUnderstand="1" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<Username>' . $username . '</Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">' . digestBase64($nonce, $currentDate, $password) . '</Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">' . $nonceBase64 . '</Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">' . $currentDate . '</Created>
</UsernameToken>
</Security>
</s:Header>';
}
sub sendCmd {
my $self = shift;
my $cmd = shift;
my $msg_body = shift;
my $content_type = shift;
my $result = undef;
my $msg = '
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">'.
((%identity) ? authentificationHeader($identity{username}, $identity{password}) : '') .
$msg_body . '
</s:Envelope>';
$self->printMsg($cmd, 'Tx');
my $req = HTTP::Request->new(GET=>'http://'.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
my $server_endpoint = $scheme.'://'.$address.':'.$port.$controlUri;
my $req = HTTP::Request->new(POST => $server_endpoint);
$req->header('content-type' => $content_type);
$req->header('Host' => $address . ':' . $port);
$req->header('content-length' => length($msg));
$req->header('accept-encoding' => 'gzip, deflate');
$req->header('connection' => 'Close');
$req->content($msg);
my $res = $self->{ua}->request($req);
if ( $res->is_success ) {
$result = !undef;
} else {
Error("Error check failed:'".$res->status_line()."'" );
Error("After sending PTZ command, camera returned the following error:'".$res->status_line()."'\nMSG:$msg\nResponse:".$res->content);
}
return $result;
}
sub getCamParams {
my $self = shift;
my $msg = '
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl">
<VideoSourceToken>000</VideoSourceToken>
</GetImagingSettings>
</s:Body>
</s:Envelope>';
my $server_endpoint = $scheme.'://'.$address.':'.$port.'/onvif/imaging';
my $req = HTTP::Request->new(POST => $server_endpoint);
$req->header('content-type' => 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/GetImagingSettings"');
$req->header('Host' => $address . ':' . $port);
$req->header('content-length' => length($msg));
$req->header('accept-encoding' => 'gzip, deflate');
$req->header('connection' => 'Close');
$req->content($msg);
my $req = HTTP::Request->new(GET=>'http://'.$self->{Monitor}->{ControlAddress}.'/get_camera_params.cgi');
my $res = $self->{ua}->request($req);
if ( $res->is_success ) {
# Parse results setting values in %FCParams
# We should really use an xml or soap library to parse the xml tags
my $content = $res->decoded_content;
while ($content =~ s/var\s+([^=]+)=([^;]+);//ms) {
if ( $content =~ /.*<tt:(Brightness)>(.+)<\/tt:Brightness>.*/ ) {
$CamParams{$1} = $2;
}
if ( $content =~ /.*<tt:(Contrast)>(.+)<\/tt:Contrast>.*/ ) {
$CamParams{$1} = $2;
}
} else {
Error("Error check failed:'".$res->status_line()."'");
Error("Unable to retrieve camera image settings:'".$res->status_line()."'");
}
}
@ -101,256 +234,418 @@ sub getCamParams {
#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab
sub autoStop {
my $self = shift;
my $stop_command = shift;
my $autostop = shift;
if ( $stop_command && $autostop ) {
if ( $autostop ) {
Debug('Auto Stop');
my $cmd = $controlUri;
my $msg_body = '
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Stop xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>'.$profileToken.'</ProfileToken>
<PanTilt>
true
</PanTilt>
<Zoom>
false
</Zoom>
</Stop>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
usleep($autostop);
my $cmd = 'decoder_control.cgi?command='.$stop_command;
$self->sendCmd($cmd);
$self->sendCmd($cmd, $msg_body, $content_type);
}
}
# Reset the Camera
sub reset {
# Reboot
sub reboot {
Debug('Camera reboot');
my $self = shift;
my $cmd = '';
my $msg_body = << "END_MESSAGE";
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SystemReboot xmlns="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
END_MESSAGE
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/device/wsdl/SystemReboot"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
# Reset(Reboot) the Camera
sub reset {
Debug('Camera Reset');
my $cmd = 'reboot.cgi?';
$self->sendCmd($cmd);
my $self = shift;
my $cmd = '';
my $msg_body = << "END_MESSAGE";
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SystemReboot xmlns="http://www.onvif.org/ver10/device/wsdl"/>
</s:Body>
END_MESSAGE
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/device/wsdl/SystemReboot"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
sub moveCamera {
my $type = shift;
my $x = shift;
my $y = shift;
my $msg_move_body = "";
if ( $type == "move" ){
$msg_move_body = '
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContinuousMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>'.$profileToken.'</ProfileToken>
<Velocity>
<PanTilt
x="'.$x.'"
y="'.$y.'"
xmlns="http://www.onvif.org/ver10/schema"/>
</Velocity>
</ContinuousMove>
</s:Body>';
} elsif ( $type == "zoom" ) {
$msg_move_body = '
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContinuousMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>'.$profileToken.'</ProfileToken>
<Velocity>
<Zoom
x="'.$x.'"
xmlns="http://www.onvif.org/ver10/schema"/>
</Velocity>
</ContinuousMove>
</s:Body>';
}
return $msg_move_body;
}
#Up Arrow
sub moveConUp
{
sub moveConUp {
Debug('Move Up');
my $self = shift;
my $stop_command = "1";
Debug( "Move Up" );
my $cmd = "decoder_control.cgi?command=0";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("move", "0","0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Down Arrow
sub moveConDown
{
sub moveConDown {
Debug('Move Down');
my $self = shift;
my $stop_command = "3";
Debug( "Move Down" );
my $cmd = "decoder_control.cgi?command=2";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","0","-0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Left Arrow
sub moveConLeft
{
sub moveConLeft {
Debug('Move Left');
my $self = shift;
my $stop_command = "5";
Debug( "Move Left" );
my $cmd = "decoder_control.cgi?command=4";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","-0.49","0");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Right Arrow
sub moveConRight
{
sub moveConRight {
Debug('Move Right');
my $self = shift;
my $stop_command = "7";
Debug( "Move Right" );
my $cmd = "decoder_control.cgi?command=6";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","0.49","0");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Zoom In
sub zoomConTele
{
sub zoomConTele {
Debug('Zoom Tele');
my $self = shift;
my $stop_command = "17";
Debug( "Zoom Tele" );
my $cmd = "decoder_control.cgi?command=18";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("zoom","0.49","0");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Zoom Out
sub zoomConWide
{
sub zoomConWide {
Debug('Zoom Wide');
my $self = shift;
my $stop_command = "19";
Debug( "Zoom Wide" );
my $cmd = "decoder_control.cgi?command=16";
$self->sendCmd( $cmd );
$self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
my $cmd = $controlUri;
my $msg_body = moveCamera("zoom","-0.49","0");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Diagonally Up Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpRight
{
sub moveConUpRight {
Debug('Move Diagonally Up Right');
my $self = shift;
Debug( "Move Diagonally Up Right" );
$self->moveConUp( );
$self->moveConRight( );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","0.5","0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Diagonally Down Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownRight
{
sub moveConDownRight {
Debug('Move Diagonally Down Right');
my $self = shift;
Debug( "Move Diagonally Down Right" );
$self->moveConDown( );
$self->moveConRight( );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","0.5","-0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Diagonally Up Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpLeft
{
sub moveConUpLeft {
Debug('Move Diagonally Up Left');
my $self = shift;
Debug( "Move Diagonally Up Left" );
$self->moveConUp( );
$self->moveConLeft( );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","-0.5","0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Diagonally Down Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownLeft
{
sub moveConDownLeft {
Debug('Move Diagonally Down Left');
my $self = shift;
Debug( "Move Diagonally Down Left" );
$self->moveConDown( );
$self->moveConLeft( );
my $cmd = $controlUri;
my $msg_body = moveCamera("move","-0.5","-0.5");
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
$self->autoStop($self->{Monitor}->{AutoStopTimeout});
}
#Stop
sub moveStop
{
sub moveStop {
Debug('Move Stop');
my $self = shift;
Debug( "Move Stop" );
my $cmd = "decoder_control.cgi?command=1";
$self->sendCmd( $cmd );
my $cmd = $controlUri;
my $msg_body = '
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Stop xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>'.$profileToken.'</ProfileToken>
<PanTilt>true</PanTilt>
<Zoom>false</Zoom>
</Stop>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/ContinuousMove"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
#Set Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 30,32,34,36,38,40,42,44 for presets 1-8 respectively
sub presetSet
{
sub presetSet {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
if (( $preset >= 1 ) && ( $preset <= 8 )) {
my $cmd = "decoder_control.cgi?command=".(($preset*2) + 28);
$self->sendCmd( $cmd );
}
my $preset = $self->getParam($params, 'preset');
Debug("Set Preset $preset");
my $cmd = $controlUri;
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetPreset xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
<PresetToken>'.$preset.'</PresetToken>
</SetPreset>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/SetPreset"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
#Recall Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 31,33,35,37,39,41,43,45 for presets 1-8 respectively
sub presetGoto
{
sub presetGoto {
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $preset = $self->getParam($params, 'preset');
if (( $preset >= 1 ) && ( $preset <= 8 )) {
my $cmd = "decoder_control.cgi?command=".(($preset*2) + 29);
$self->sendCmd( $cmd );
}
if ( $preset == 9 ) {
$self->horizontalPatrol();
}
if ( $preset == 10 ) {
$self->horizontalPatrolStop();
}
Debug("Goto Preset $preset");
my $cmd = $controlUri;
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GotoPreset xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
<PresetToken>'.$preset.'</PresetToken>
</GotoPreset>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/GotoPreset"';
$self->sendCmd( $cmd, $msg_body, $content_type );
}
#Horizontal Patrol - Vertical Patrols are not supported
sub horizontalPatrol
{
#Recall Camera Preset
sub presetHome {
my $self = shift;
Debug( "Horizontal Patrol" );
my $cmd = "decoder_control.cgi?command=20";
$self->sendCmd( $cmd );
my $params = shift;
Debug("Goto Home preset");
my $cmd = $controlUri;
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GotoHomePosition xmlns="http://www.onvif.org/ver20/ptz/wsdl">
<ProfileToken>' . $profileToken . '</ProfileToken>
</GotoHomePosition>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/ptz/wsdl/GotoPreset"';
$self->sendCmd( $cmd, $msg_body, $content_type );
}
#Horizontal Patrol
#To be determined if this camera supports this feature
sub horizontalPatrol {
Debug('Horizontal Patrol');
my $self = shift;
my $cmd = '';
my $msg ='';
my $content_type = '';
# $self->sendCmd( $cmd, $msg, $content_type );
Error('PTZ Command not implemented in control script.');
}
#Horizontal Patrol Stop
sub horizontalPatrolStop
{
#To be determined if this camera supports this feature
sub horizontalPatrolStop {
Debug('Horizontal Patrol Stop');
my $self = shift;
Debug( "Horizontal Patrol Stop" );
my $cmd = "decoder_control.cgi?command=21";
$self->sendCmd( $cmd );
my $cmd = '';
my $msg ='';
my $content_type = '';
# $self->sendCmd( $cmd, $msg, $content_type );
Error('PTZ Command not implemented in control script.');
}
# Increase Brightness
sub irisAbsOpen
{
sub irisAbsOpen {
Debug("Iris $CamParams{Brightness}");
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'brightness'});
my $step = $self->getParam( $params, 'step' );
$self->getCamParams() unless($CamParams{Brightness});
my $step = $self->getParam($params, 'step');
my $max = 100;
$CamParams{'brightness'} += $step;
$CamParams{'brightness'} = 255 if ($CamParams{'brightness'} > 255);
Debug( "Iris $CamParams{'brightness'}" );
my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
$self->sendCmd( $cmd );
$CamParams{Brightness} += $step;
$CamParams{Brightness} = $max if ($CamParams{Brightness} > $max);
my $cmd = 'onvif/imaging';
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl">
<VideoSourceToken>000</VideoSourceToken>
<ImagingSettings>
<Brightness xmlns="http://www.onvif.org/ver10/schema">'.$CamParams{Brightness}.'</Brightness>
</ImagingSettings>
<ForcePersistence>true</ForcePersistence>
</SetImagingSettings>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
# Decrease Brightness
sub irisAbsClose
{
sub irisAbsClose {
Debug("Iris $CamParams{Brightness}");
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'brightness'});
my $step = $self->getParam( $params, 'step' );
$self->getCamParams() unless($CamParams{brightness});
my $step = $self->getParam($params, 'step');
my $min = 0;
$CamParams{'brightness'} -= $step;
$CamParams{'brightness'} = 0 if ($CamParams{'brightness'} < 0);
Debug( "Iris $CamParams{'brightness'}" );
my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
$self->sendCmd( $cmd );
$CamParams{Brightness} -= $step;
$CamParams{Brightness} = $min if ($CamParams{Brightness} < $min);
my $cmd = 'onvif/imaging';
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl">
<VideoSourceToken>000</VideoSourceToken>
<ImagingSettings>
<Brightness xmlns="http://www.onvif.org/ver10/schema">'.$CamParams{Brightness}.'</Brightness>
</ImagingSettings>
<ForcePersistence>true</ForcePersistence>
</SetImagingSettings>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
# Increase Contrast
sub whiteAbsIn
{
sub whiteAbsIn {
Debug("Iris $CamParams{Contrast}");
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'contrast'});
my $step = $self->getParam( $params, 'step' );
$self->getCamParams() unless($CamParams{Contrast});
my $step = $self->getParam($params, 'step');
my $max = 100;
$CamParams{'contrast'} += $step;
$CamParams{'contrast'} = 6 if ($CamParams{'contrast'} > 6);
Debug( "Iris $CamParams{'contrast'}" );
my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
$self->sendCmd( $cmd );
$CamParams{Contrast} += $step;
$CamParams{Contrast} = $max if ($CamParams{Contrast} > $max);
my $cmd = 'onvif/imaging';
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl">
<VideoSourceToken>000</VideoSourceToken>
<ImagingSettings>
<Contrast xmlns="http://www.onvif.org/ver10/schema">'.$CamParams{Contrast}.'</Contrast>
</ImagingSettings>
<ForcePersistence>true</ForcePersistence>
</SetImagingSettings>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
# Decrease Contrast
sub whiteAbsOut
{
sub whiteAbsOut {
Debug("Iris $CamParams{Contrast}");
my $self = shift;
my $params = shift;
$self->getCamParams() unless($CamParams{'contrast'});
my $step = $self->getParam( $params, 'step' );
$self->getCamParams() unless($CamParams{Contrast});
my $step = $self->getParam($params, 'step');
my $min = 0;
$CamParams{'contrast'} -= $step;
$CamParams{'contrast'} = 0 if ($CamParams{'contrast'} < 0);
Debug( "Iris $CamParams{'contrast'}" );
my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
$self->sendCmd( $cmd );
$CamParams{Contrast} -= $step;
$CamParams{Contrast} = $min if ($CamParams{Contrast} < $min);
my $cmd = 'onvif/imaging';
my $msg_body ='
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl">
<VideoSourceToken>000</VideoSourceToken>
<ImagingSettings>
<Contrast xmlns="http://www.onvif.org/ver10/schema">'.$CamParams{Contrast}.'</Contrast>
</ImagingSettings>
<ForcePersistence>true</ForcePersistence>
</SetImagingSettings>
</s:Body>';
my $content_type = 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver20/imaging/wsdl/SetImagingSettings"';
$self->sendCmd($cmd, $msg_body, $content_type);
}
1;
__END__