zoneminder/onvif/scripts/zmonvif-probe.pl

286 lines
7.3 KiB
Perl
Raw Normal View History

2014-07-15 02:36:18 +08:00
# ==========================================================================
#
# ZoneMinder ONVIF Control Protocol Module
# Copyright (C) Jan M. Hochstein
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
#
# This module contains the implementation of the ONVIF capability prober
#
require SOAP::WSDL::Transport::HTTP;
require WSDiscovery::Interfaces::WSDiscovery::WSDiscoveryPort;
require WSDiscovery::Elements::Types;
require WSDiscovery::Elements::Scopes;
require WSDiscovery::TransportUDP;
require WSSecurity::SecuritySerializer;
require ONVIF::Device::Interfaces::Device::DevicePort;
require ONVIF::Media::Interfaces::Media::MediaPort;
require ONVIF::PTZ::Interfaces::PTZ::PTZPort;
use Data::Dump qw(dump);
# ========================================================================
# Globals
my %namespace_map = (
'http://www.onvif.org/ver10/device/wsdl' => 'device',
'http://www.onvif.org/ver10/media/wsdl' => 'media',
'http://www.onvif.org/ver20/imaging/wsdl' => 'imaging',
'http://www.onvif.org/ver20/analytics/wsdl' => 'analytics',
'http://www.onvif.org/ver10/deviceIO/wsdl' => 'deviceio',
'http://www.onvif.org/ver10/ptz/wsdl' => 'ptz',
'http://www.onvif.org/ver10/events/wsdl' => 'events',
);
my %services = { };
my $serializer;
# =========================================================================
sub discover
{
my $svc_discover = WSDiscovery::Interfaces::WSDiscovery::WSDiscoveryPort->new();
my $result = $svc_discover->ProbeOp(
{ # WSDiscovery::Types::ProbeType
Types => { 'dn:NetworkVideoTransmitter', 'tds:Device' }, # QNameListType
Scopes => { value => '' },
},,
);
die $result if not $result;
# print $result;
foreach my $xaddr (split ' ', $result->get_ProbeMatch()->get_XAddrs()) {
# find IPv4 address
if($xaddr =~ m|//[0-9]+.[0-9]+.[0-9]+.[0-9]+./|) {
print $xaddr . ", ";
last;
}
}
print "(";
my $scopes = $result->get_ProbeMatch()->get_Scopes();
my $count = 0;
foreach my $scope(split ' ', $scopes) {
if($scope =~ m|onvif://www\.onvif\.org/(.+)/(.*)|) {
my ($attr, $value) = ($1,$2);
if( 0 < $count ++) {
print ", ";
}
print $attr . "=\'" . $value . "\'";
}
}
print ")\n";
}
sub get_services
{
my $result = $services{device}{ep}->GetServices( {
IncludeCapability => 'true', # boolean
},,
);
die $result if not $result;
# print $result . "\n";
foreach my $svc ( @{ $result->get_Service() } ) {
my $short_name = $namespace_map{$svc->get_Namespace()};
my $url_svc = $svc->get_XAddr()->get_value();
if(defined $short_name && defined $url_svc) {
# print "Got $short_name service\n";
$services{$short_name}{url} = $url_svc;
}
}
}
sub create_services
{
if(defined $services{media}{url}) {
$services{media}{ep} = ONVIF::Media::Interfaces::Media::MediaPort->new({
proxy => $services{media}{url},
serializer => $serializer,
# transport => $transport
});
}
if(defined $services{ptz}{url}) {
$services{ptz}{ep} = ONVIF::PTZ::Interfaces::PTZ::PTZPort->new({
proxy => $services{ptz}{url},
serializer => $serializer,
# transport => $transport
});
}
}
sub get_users
{
my $result = $services{device}{ep}->GetUsers( { },, );
die $result if not $result;
print $result . "\n";
}
sub create_user
{
my ($username, $password) = @_;
my $result = $services{device}{ep}->CreateUsers( {
},,
);
die $result if not $result;
print $result . "\n";
}
sub http_digest {
my ($service, $username, $password) = @_;
# my $transport = SecurityTransport->new();
# $transport->set_username($username);
# $transport->set_password($password);
# warn "transport: " . $service->get_transport();
*SOAP::Transport::HTTP::Client::get_basic_credentials = sub {
#*SOAP::WSDL::Transport::HTTP::get_basic_credentials = sub {
my ($self, $realm, $uri, $isproxy) = @_;
warn "### Requested credentials for $uri ###";
return ($username, $password)
};
}
sub profiles
{
# my $result = $services{media}{ep}->GetVideoSources( { } ,, );
# die $result if not $result;
# print $result . "\n";
$result = $services{media}{ep}->GetProfiles( { } ,, );
die $result if not $result;
# print $result . "\n";
my $profiles = $result->get_Profiles();
foreach my $profile ( @{ $profiles } ) {
my $token = $profile->attr()->get_token() ;
print $token . ", " .
$profile->get_Name() . ", " .
$profile->get_VideoEncoderConfiguration()->get_Encoding() . ", " .
$profile->get_VideoEncoderConfiguration()->get_Resolution()->get_Width() . ", " .
$profile->get_VideoEncoderConfiguration()->get_Resolution()->get_Height() . ", " .
$profile->get_VideoEncoderConfiguration()->get_RateControl()->get_FrameRateLimit() .
", ";
$result = $services{media}{ep}->GetStreamUri( {
StreamSetup => { # ONVIF::Media::Types::StreamSetup
Stream => 'RTP_unicast', # StreamType
Transport => { # ONVIF::Media::Types::Transport
Protocol => 'RTSP', # TransportProtocol
},
},
ProfileToken => $token, # ReferenceToken
} ,, );
die $result if not $result;
# print $result . "\n";
print $result->get_MediaUri()->get_Uri() .
"\n";
}
#
# use message parser without schema validation ???
#
}
sub move
{
my ($dir) = @_;
my $result = $services{ptz}{ep}->GetNodes( { } ,, );
die $result if not $result;
print $result . "\n";
}
# ========================================================================
# MAIN
my $action = shift;
if($action eq "probe") {
discover();
}
else {
# all other actions need URI and credentials
my $url_svc_device = shift;
my $username = shift;
my $password = shift;
my $svc_device = ONVIF::Device::Interfaces::Device::DevicePort->new({
proxy => $url_svc_device,
deserializer_args => { strict => 0 }
});
$services{'device'} = { url => $url_svc_device, ep => $svc_device };
get_services();
# TODO: snyc device and client time
# If GetUsers() is ok but empty then CreateUser()
# if(not get_users()) {
# create_user($username, $password);
# }
## from here on use authorization
$serializer = WSSecurity::SecuritySerializer->new();
$serializer->set_username($username);
$serializer->set_password($password);
$services{device}{ep}->set_serializer($serializer);
create_services($username, $password);
if($action eq "profiles") {
profiles();
}
elsif($action eq "move") {
my $dir = shift;
move($dir);
}
else {
print("Error: Unknown command\"$action\"");
exit(1);
}
}