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:
parent
b8fcd7c85f
commit
36f11158df
|
@ -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);
|
||||
|
|
|
@ -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__
|
||||
|
|
Loading…
Reference in New Issue