From 06310bc1f7aa70620cd580b0aabd56ca7b01d811 Mon Sep 17 00:00:00 2001 From: nasseeder1 <> Date: Mon, 4 Jan 2016 22:50:22 +0000 Subject: [PATCH] 49_SSCam: Function "Get" for retrieval Camera-Readings added, Attributs pollcaminfoall, pollnologging added, Function for Polling Cam-Infos added. git-svn-id: https://svn.fhem.de/fhem/trunk@10364 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 3 + fhem/FHEM/49_SSCam.pm | 1070 +++++++++++++++++++++++++++++++++++------ 2 files changed, 933 insertions(+), 140 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index de408d5c6..b080cfd17 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -1,5 +1,8 @@ # Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # Do not insert empty lines here, update check depends on it. + - feature: 49_SSCam: Function "Get" for retrieval Camera-Readings added, + Attributs pollcaminfoall, pollnologging added, + Function for Polling Cam-Infos added. - bugfix: 89_HEATRONIC: fixed variable names - feature: 89_HEATRONIC: new reading ch_error: error code of boiler - change: SYSMON: end of support for barcharts diff --git a/fhem/FHEM/49_SSCam.pm b/fhem/FHEM/49_SSCam.pm index 5c37b00eb..c03bf1a5d 100644 --- a/fhem/FHEM/49_SSCam.pm +++ b/fhem/FHEM/49_SSCam.pm @@ -1,31 +1,35 @@ -##################################################################################################### +########################################################################################################## # $Id$ -##################################################################################################### +########################################################################################################## # 49_SSCam.pm # # written by Heiko Maaz # e-mail: Heiko dot Maaz at t-online dot de # -# This Modul can be used to operate Cameras defined in Synology Surveillance Station 7.0 or higher. +# This Module can be used to operate Cameras defined in Synology Surveillance Station 7.0 or higher. # It's based on Synology Surveillance Station API Guide 2.0 # -# This file is part of fhem. +# This file is part of fhem. # -# Fhem 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. +# Fhem 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. # -# Fhem 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. +# Fhem 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 fhem. If not, see .# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see .# # -###################################################################################################### -# Versionshistorie: +########################################################################################################## +# Versions History: +# +# 1.5 04.01.2016 Function "Get" for creating Camera-Readings integrated, +# Attributs pollcaminfoall, pollnologging added, +# Function for Polling Cam-Infos added. # 1.4 23.12.2015 function "enable" and "disable" for SS-Cams added, # changed timout of Http-calls to a higher value # 1.3 19.12.2015 function "snap" for taking snapshots added, @@ -38,7 +42,7 @@ # # Definition: define SSCam # -# Beispiel: define CamCP1 SSCAM 192.168.2.20 5000 apiuser apipw Carport 5 +# Example: define CamCP1 SSCAM 192.168.2.20 5000 apiuser apipw Carport 5 # # Parameters: # @@ -65,22 +69,27 @@ sub SSCam_Initialize($) { $hash->{DefFn} = "SSCam_Define"; $hash->{UndefFn} = "SSCam_Undef"; $hash->{SetFn} = "SSCam_Set"; - # $hash->{AttrFn} = "SSCam_Attr"; + $hash->{GetFn} = "SSCam_Get"; + $hash->{AttrFn} = "SSCam_Attr"; $hash->{AttrList} = + "pollcaminfoall ". + "pollnologging:1,0 ". "webCmd ". $readingFnAttributes; - + + return undef; } sub SSCam_Define { # Die Define-Funktion eines Moduls wird von Fhem aufgerufen wenn der Define-Befehl für ein Gerät ausgeführt wird # Welche und wie viele Parameter akzeptiert werden ist Sache dieser Funktion. Die Werte werden nach dem übergebenen Hash in ein Array aufgeteilt # define CamCP1 SSCAM 192.168.2.20 5000 apiuser Support4me Carport 5 - # ($hash) [1] [2] [3] [4] [5] [6] [7] + # ($hash) [1] [2] [3] [4] [5] [6] [7] # my ($hash, $def) = @_; + my $name = $hash->{NAME}; my @a = split("[ \t][ \t]*", $def); @@ -105,7 +114,11 @@ sub SSCam_Define { $hash->{USERNAME} = $username; $hash->{HELPER}{PASSWORD} = $password; $hash->{CAMNAME} = $camname; - $hash->{RECTIME} = $rectime; + $hash->{RECTIME} = $rectime; + # für später + # Standard für rectime setzen, überschreibbar durch Attribut "rectime" + # $hash->{RECTIME} = 15; + # $attr{$name}{rectime} = $rectime; # benötigte API's in $hash einfügen $hash->{HELPER}{APIINFO} = "SYNO.API.Info"; # Info-Seite für alle API's, einzige statische Seite ! @@ -113,47 +126,71 @@ sub SSCam_Define { $hash->{HELPER}{APIEXTREC} = "SYNO.SurveillanceStation.ExternalRecording"; $hash->{HELPER}{APICAM} = "SYNO.SurveillanceStation.Camera"; $hash->{HELPER}{APISNAPSHOT} = "SYNO.SurveillanceStation.SnapShot"; + $hash->{HELPER}{APIPTZ} = "SYNO.SurveillanceStation.PTZ"; # Anfangswerte setzen - $hash->{HELPER}{ACTIVE} = "off"; - readingsSingleUpdate($hash,"Record","Stop",0); - readingsSingleUpdate($hash, "Availability", "", 0); + $hash->{HELPER}{ACTIVE} = "off"; # Funktionstoken "off", Funktionen können sofort starten + $hash->{HELPER}{OLDVALPOLLNOLOGGING} ="0"; # Loggingfunktion für Polling ist an + $hash->{STATE} = "initialized"; # Anfangsstatus der Geräte + readingsSingleUpdate($hash,"Record","Stop",0); # Recordings laufen nicht + readingsSingleUpdate($hash,"Availability", "", 0); # Verfügbarkeit ist unbekannt + readingsSingleUpdate($hash,"PollState","Inactive",0); # es ist keine Gerätepolling aktiv - return undef; + RemoveInternalTimer($hash); # alle evtl. noch laufenden Timer löschen + + + # Subroutine Watchdog-Timer für Polling Kamera-Infos starten, verzögerter zufälliger Start 0-60s (Vermeidung v. Überschneidungen) + InternalTimer(gettimeofday()+int(rand(60)), "watchdogpollcaminfo", $hash, 0); + + +return undef; } sub SSCam_Undef { my ($hash, $arg) = @_; RemoveInternalTimer($hash); - return undef; +return undef; } -sub SSCam_Attr { +sub SSCam_Attr { + my ($cmd,$name,$aName,$aVal) = @_; + # $cmd can be "del" or "set" + # $name is device name + # aName and aVal are Attribute name and value + if ($cmd eq "set") { + if ($aName eq "pollcaminfoall") { + unless ($aVal =~ /^\d+$/) { return " The Value for $aName is not valid. Use only figures 0-9 without decimal places !";} + } + } +return undef; } sub SSCam_Set { my ( $hash, @a ) = @_; return "\"set X\" needs at least an argument" if ( @a < 2 ); - my $name = shift @a; - my $opt = shift @a; - my %SSCam_sets = ( - on => "on", - off => "off", - snap => "snap", - enable => "enable", - disable => "disable" - ); - - my $camname = $hash->{CAMNAME}; - my $logstr; - my @cList; - - # ist die angegebene Option verfügbar ? - if(!defined($SSCam_sets{$opt})) - { - @cList = keys %SSCam_sets; - return "Unknown argument $opt, choose one of " . join(" ", @cList); + my $name = shift @a; + my $opt = shift @a; + + my %SSCam_sets = ( + on => "on", + off => "off", + snap => "snap", + enable => "enable", + disable => "disable", + # presets => "presets", + ); + + my $camname = $hash->{CAMNAME}; + my $logstr; + my @cList; + + # ist die angegebene Option verfügbar ? + if(!defined($SSCam_sets{$opt})) + { + @cList = keys %SSCam_sets; + return "Unknown argument $opt, choose one of " . join(" ", @cList); + } else { @@ -178,10 +215,104 @@ sub SSCam_Set { &camdisable($hash); } - } + } +return undef; } +sub SSCam_Get { + my ($hash, @a) = @_; + return "\"get X\" needs at least an argument" if ( @a < 2 ); + my $name = shift @a; + my $opt = shift @a; + my %SSCam_gets = ( + caminfoall => "caminfoall", + ); + my @cList; + + # ist die angegebene Option verfügbar ? + if(!defined($SSCam_gets{$opt})) + { + @cList = keys %SSCam_gets; + return "Unknown argument $opt, choose one of " . join(" ", @cList); + } + else + { + # hier die Verarbeitung starten + if ($opt eq "caminfoall") + { + &getcaminfoall($hash); + } + + } +return undef; +} + + +sub watchdogpollcaminfo ($) { + # Überwacht die Wert von Attribut "pollcaminfoall" und Reading "PollState" + # wenn Attribut "pollcaminfoall" > 10 und "PollState"=Inactive -> start Polling + my ($hash) = @_; + my $name = $hash->{NAME}; + my $camname = $hash->{CAMNAME}; + my $logstr; + my $watchdogtimer = 90; + + if (defined(AttrVal($name, "pollcaminfoall", undef)) and AttrVal($name, "pollcaminfoall", undef) > 10 and ReadingsVal("$name", "PollState", "Active") eq "Inactive") { + + # Polling ist jetzt aktiv + readingsSingleUpdate($hash,"PollState","Active",0); + + $logstr = "Polling Camera $camname is activated now - Pollinginterval: ".AttrVal($name, "pollcaminfoall", undef)."s"; + &printlog($hash,$logstr,"2"); + + # in $hash eintragen für späteren Vergleich (Changes von pollcaminfoall) + $hash->{HELPER}{OLDVALPOLL} = AttrVal($name, "pollcaminfoall", undef); + + # Pollingroutine aufrufen + &getcaminfoall($hash); + } + + if (defined($hash->{HELPER}{OLDVALPOLL}) and defined(AttrVal($name, "pollcaminfoall", undef)) and AttrVal($name, "pollcaminfoall", undef) > 10) { + if ($hash->{HELPER}{OLDVALPOLL} != AttrVal($name, "pollcaminfoall", undef)) { + + $logstr = "Polling Camera $camname was changed to new Pollinginterval: ".AttrVal($name, "pollcaminfoall", undef)."s"; + &printlog($hash,$logstr,"2"); + + $hash->{HELPER}{OLDVALPOLL} = AttrVal($name, "pollcaminfoall", undef); + &getcaminfoall($hash); + } + } + + if (defined(AttrVal($name, "pollnologging", undef))) { + if ($hash->{HELPER}{OLDVALPOLLNOLOGGING} ne AttrVal($name, "pollnologging", undef)) { + if (AttrVal($name, "pollnologging", undef) == "1") { + $logstr = "Log of Polling Camera $camname is deactivated now"; + &printlog($hash,$logstr,"2"); + # in $hash eintragen für späteren Vergleich (Changes von pollnologging) + $hash->{HELPER}{OLDVALPOLLNOLOGGING} = AttrVal($name, "pollnologging", undef); + } else { + $logstr = "Log of Polling Camera $camname is activated now"; + &printlog($hash,$logstr,"2"); + # in $hash eintragen für späteren Vergleich (Changes von pollnologging) + $hash->{HELPER}{OLDVALPOLLNOLOGGING} = AttrVal($name, "pollnologging", undef); + } + } + } else { + # alter Wert von "pollnologging" war 1 -> Logging war deaktiviert + if ($hash->{HELPER}{OLDVALPOLLNOLOGGING} == "1") { + $logstr = "Log of Polling Camera $camname is activated now"; + &printlog($hash,$logstr,"2"); + # in $hash eintragen für späteren Vergleich (Changes von pollnologging) + $hash->{HELPER}{OLDVALPOLLNOLOGGING} = "0"; + } + } +InternalTimer(gettimeofday()+$watchdogtimer, "watchdogpollcaminfo", $hash, 0); +return undef; +} + + + ############################################################################################################################# ######### OpMode-Startroutinen ############# ######### $hash->{HELPER}{ACTIVE} = Funktionstoken ############# @@ -220,7 +351,7 @@ sub camstartrec ($) { if ($hash->{HELPER}{ACTIVE} ne "on" and ReadingsVal("$name", "Record", "Start") ne "Start") { # Aufnahme starten - $logstr = "Recording of Camera $camname should be started now"; + $logstr = "Recording of Camera $camname will be started now"; &printlog($hash,$logstr,"4"); $hash->{OPMODE} = "Start"; @@ -265,7 +396,7 @@ sub camstoprec ($) { if ($hash->{HELPER}{ACTIVE} ne "on" and ReadingsVal("$name", "Record", "Stop") ne "Stop") { # Aufnahme stoppen - $logstr = "Recording of Camera $camname should be stopped now"; + $logstr = "Recording of Camera $camname will be stopped now"; &printlog($hash,$logstr,"4"); $hash->{OPMODE} = "Stop"; @@ -347,7 +478,7 @@ sub camenable ($) { } else { - InternalTimer(gettimeofday()+0.1, "camenable", $hash, 0); + InternalTimer(gettimeofday()+0.2, "camenable", $hash, 0); } } @@ -378,6 +509,160 @@ sub camdisable ($) { } } +############################################################################### +### Kamera alle Informationen abrufen (Get) bzw. Einstieg Polling + +sub getcaminfoall ($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $logstr; + + if ($hash->{HELPER}{ACTIVE} ne "on") { + + &getcaminfo($hash); + &getcapabilities($hash); + &getptzlistpreset($hash); + &getptzlistpatrol($hash); + + } + else + { + InternalTimer(gettimeofday()+0.3, "getcaminfoall", $hash, 0); + } + + if (defined(AttrVal($name, "pollcaminfoall", undef)) and AttrVal($name, "pollcaminfoall", undef) > 10) { + # Pollen wenn pollcaminfo > 10, sonst kein Polling + InternalTimer(gettimeofday()+AttrVal($name, "pollcaminfoall", undef), "getcaminfoall", $hash, 0); + } + else + { + # Beenden Polling aller Caminfos + readingsSingleUpdate($hash,"PollState","Inactive",0); + + $logstr = "Polling of Camera $camname is deactivated now"; + &printlog($hash,$logstr,"2"); + + } +} + +########################################################################### +### Kamera allgemeine Informationen abrufen (Get), sub von getcaminfoall + +sub getcaminfo ($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $logstr; + + if ($hash->{HELPER}{ACTIVE} ne "on") { + # Kamerainfos abrufen + $logstr = "Retrieval Camera-Informations of $camname starts now"; + &printlog($hash,$logstr,"4"); + + $hash->{OPMODE} = "Getcaminfo"; + $hash->{HELPER}{ACTIVE} = "on"; + + &getapisites_nonbl($hash); + } + else + { + InternalTimer(gettimeofday()+0.5, "getcaminfo", $hash, 0); + } + +} + +########################################################################## +### Capabilities von Kamera abrufen (Get), sub von getcaminfoall + +sub getcapabilities ($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $logstr; + + if ($hash->{HELPER}{ACTIVE} ne "on") { + # PTZ-ListPresets abrufen + $logstr = "Retrieval Capabilities of Camera $camname starts now"; + &printlog($hash,$logstr,"4"); + + $hash->{OPMODE} = "Getcapabilities"; + $hash->{HELPER}{ACTIVE} = "on"; + + &getapisites_nonbl($hash); + } + else + { + InternalTimer(gettimeofday()+0.5, "getcapabilities", $hash, 0); + } + +} + +########################################################################## +### PTZ Presets abrufen (Get), sub von getcaminfoall + +sub getptzlistpreset ($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $logstr; + + if (defined(ReadingsVal("$name", "DeviceType", undef)) and ReadingsVal("$name", "DeviceType", undef) ne "PTZ") { + $logstr = "Retrieval of Presets for $camname can't be executed - $camname is not a PTZ-Camera"; + &printlog($hash,$logstr,"4"); + return; + } + + if ($hash->{HELPER}{ACTIVE} ne "on") { + # PTZ-ListPresets abrufen + $logstr = "Retrieval PTZ-ListPresets of $camname starts now"; + &printlog($hash,$logstr,"4"); + + $hash->{OPMODE} = "Getptzlistpreset"; + $hash->{HELPER}{ACTIVE} = "on"; + + &getapisites_nonbl($hash); + } + else + { + InternalTimer(gettimeofday()+0.5, "getptzlistpreset", $hash, 0); + } + +} + + +########################################################################## +### PTZ Patrols abrufen (Get), sub von getcaminfoall + +sub getptzlistpatrol ($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $logstr; + + if (defined(ReadingsVal("$name", "DeviceType", undef)) and ReadingsVal("$name", "DeviceType", undef) ne "PTZ") { + $logstr = "Retrieval of Patrols for $camname can't be executed - $camname is not a PTZ-Camera"; + &printlog($hash,$logstr,"4"); + return; + } + + if ($hash->{HELPER}{ACTIVE} ne "on") { + # PTZ-ListPatrols abrufen + $logstr = "Retrieval PTZ-ListPatrols of $camname starts now"; + &printlog($hash,$logstr,"4"); + + $hash->{OPMODE} = "Getptzlistpatrol"; + $hash->{HELPER}{ACTIVE} = "on"; + + &getapisites_nonbl($hash); + } + else + { + InternalTimer(gettimeofday()+0.5, "getptzlistpatrol", $hash, 0); + } + +} + ############################################################################################################################# ####### Begin Kameraoperationen mit NonblockingGet (nicht blockierender HTTP-Call) ####### @@ -402,6 +687,7 @@ sub getapisites_nonbl { my $apiextrec = $hash->{HELPER}{APIEXTREC}; # in der Abfrage-Url an Parameter "&query=" my $apicam = $hash->{HELPER}{APICAM}; # mit Komma getrennt angeben my $apitakesnap = $hash->{HELPER}{APISNAPSHOT}; + my $apiptz = $hash->{HELPER}{APIPTZ}; my $logstr; my $url; my $param; @@ -412,7 +698,7 @@ sub getapisites_nonbl { &printlog($hash,$logstr,"4"); # URL zur Abfrage der Eigenschaften der API's - $url = "http://$servername:$serverport/webapi/query.cgi?api=$apiinfo&method=Query&version=1&query=$apiauth,$apiextrec,$apicam,$apitakesnap"; + $url = "http://$servername:$serverport/webapi/query.cgi?api=$apiinfo&method=Query&version=1&query=$apiauth,$apiextrec,$apicam,$apitakesnap,$apiptz"; $param = { url => $url, @@ -444,6 +730,7 @@ sub login_nonbl ($) { my $apiextrec = $hash->{HELPER}{APIEXTREC}; my $apicam = $hash->{HELPER}{APICAM}; my $apitakesnap = $hash->{HELPER}{APISNAPSHOT}; + my $apiptz = $hash->{HELPER}{APIPTZ}; my $data; my $logstr; my $url; @@ -456,6 +743,8 @@ sub login_nonbl ($) { my $apicammaxver; my $apitakesnappath; my $apitakesnapmaxver; + my $apiptzpath; + my $apiptzmaxver; my $error; # Verarbeitung der asynchronen Rückkehrdaten aus sub "getapisites_nonbl" @@ -483,7 +772,7 @@ sub login_nonbl ($) { # Evaluiere ob Daten im JSON-Format empfangen wurden ($hash, $success) = &evaljson($hash,$myjson,$param->{url}); - unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); return($hash,$success)}; + unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)}; $data = decode_json($myjson); @@ -499,51 +788,63 @@ sub login_nonbl ($) { $apiauthpath = $data->{'data'}->{$apiauth}->{'path'}; # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren - $apiauthpath =~ tr/_//d; + $apiauthpath =~ tr/_//d if (defined($apiauthpath)); $apiauthmaxver = $data->{'data'}->{$apiauth}->{'maxVersion'}; - $logstr = "Path of $apiauth selected: $apiauthpath"; + $logstr = defined($apiauthpath) ? "Path of $apiauth selected: $apiauthpath" : "Path of $apiauth undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); - $logstr = "MaxVersion of $apiauth selected: $apiauthmaxver"; + $logstr = defined($apiauthmaxver) ? "MaxVersion of $apiauth selected: $apiauthmaxver" : "MaxVersion of $apiauth undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); # Pfad und Maxversion von "SYNO.SurveillanceStation.ExternalRecording" ermitteln $apiextrecpath = $data->{'data'}->{$apiextrec}->{'path'}; # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren - $apiextrecpath =~ tr/_//d; + $apiextrecpath =~ tr/_//d if (defined($apiextrecpath)); $apiextrecmaxver = $data->{'data'}->{$apiextrec}->{'maxVersion'}; - $logstr = "Path of $apiextrec selected: $apiextrecpath"; + $logstr = defined($apiextrecpath) ? "Path of $apiextrec selected: $apiextrecpath" : "Path of $apiextrec undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); - $logstr = "MaxVersion of $apiextrec selected: $apiextrecmaxver"; + $logstr = defined($apiextrecmaxver) ? "MaxVersion of $apiextrec selected: $apiextrecmaxver" : "MaxVersion of $apiextrec undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); # Pfad und Maxversion von "SYNO.SurveillanceStation.Camera" ermitteln $apicampath = $data->{'data'}->{$apicam}->{'path'}; # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren - $apicampath =~ tr/_//d; + $apicampath =~ tr/_//d if (defined($apicampath)); $apicammaxver = $data->{'data'}->{$apicam}->{'maxVersion'}; # um 1 verringern - Fehlerprävention if (defined $apicammaxver) {$apicammaxver -= 1}; - $logstr = "Path of $apicam selected: $apicampath"; + $logstr = defined($apicampath) ? "Path of $apicam selected: $apicampath" : "Path of $apicam undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); - $logstr = "MaxVersion of $apicam (optimized): $apicammaxver"; + $logstr = defined($apiextrecmaxver) ? "MaxVersion of $apicam (optimized): $apicammaxver" : "MaxVersion of $apicam undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); # Pfad und Maxversion von "SYNO.SurveillanceStation.SnapShot" ermitteln $apitakesnappath = $data->{'data'}->{$apitakesnap}->{'path'}; # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren - $apitakesnappath =~ tr/_//d; + $apitakesnappath =~ tr/_//d if (defined($apitakesnappath)); $apitakesnapmaxver = $data->{'data'}->{$apitakesnap}->{'maxVersion'}; - $logstr = "Path of $apitakesnap selected: $apitakesnappath"; + $logstr = defined($apitakesnappath) ? "Path of $apitakesnap selected: $apitakesnappath" : "Path of $apitakesnap undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); - $logstr = "MaxVersion of $apitakesnap: $apitakesnapmaxver"; + $logstr = defined($apitakesnapmaxver) ? "MaxVersion of $apitakesnap: $apitakesnapmaxver" : "MaxVersion of $apitakesnap undefined - Surveillance Station may be stopped"; &printlog($hash, $logstr,"4"); + + # Pfad und Maxversion von "SYNO.SurveillanceStation.PTZ" ermitteln + + $apiptzpath = $data->{'data'}->{$apiptz}->{'path'}; + # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren + $apiptzpath =~ tr/_//d if (defined($apiptzpath)); + $apiptzmaxver = $data->{'data'}->{$apiptz}->{'maxVersion'}; + + $logstr = defined($apiptzpath) ? "Path of $apiptz selected: $apiptzpath" : "Path of $apiptz undefined - Surveillance Station may be stopped"; + &printlog($hash, $logstr,"4"); + $logstr = defined($apiptzmaxver) ? "MaxVersion of $apiptz: $apiptzmaxver" : "MaxVersion of $apiptz undefined - Surveillance Station may be stopped"; + &printlog($hash, $logstr,"4"); # ermittelte Werte in $hash einfügen @@ -555,7 +856,8 @@ sub login_nonbl ($) { $hash->{HELPER}{APICAMMAXVER} = $apicammaxver; $hash->{HELPER}{APITAKESNAPPATH} = $apitakesnappath; $hash->{HELPER}{APITAKESNAPMAXVER} = $apitakesnapmaxver; - + $hash->{HELPER}{APIPTZPATH} = $apiptzpath; + $hash->{HELPER}{APIPTZMAXVER} = $apiptzmaxver; # Setreading readingsBeginUpdate($hash); @@ -566,6 +868,7 @@ sub login_nonbl ($) { # Logausgabe $logstr = "--- End Function getapisites nonblocking ---"; &printlog($hash,$logstr,"4"); + } else { @@ -597,8 +900,7 @@ sub login_nonbl ($) { $logstr = "--- Begin Function serverlogin nonblocking ---"; &printlog($hash,$logstr,"4"); - $url = "http://$servername:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=$password&session=SurveillanceStation&format=sid"; - + $url = "http://$servername:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Login&account=$username&passwd=$password&format=\"sid\""; $param = { url => $url, @@ -663,7 +965,7 @@ sub getcamid_nonbl ($) { # Evaluiere ob Daten im JSON-Format empfangen wurden ($hash, $success) = &evaljson($hash,$myjson,$param->{url}); - unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); return($hash,$success)}; + unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)}; $data = decode_json($myjson); @@ -728,7 +1030,7 @@ sub getcamid_nonbl ($) { &printlog($hash,$logstr,"4"); # einlesen aller Kameras - Auswertung in Rückkehrfunktion "camop_nonbl" - $url = "http://$servername:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=List&session=SurveillanceStation&_sid=\"$sid\""; + $url = "http://$servername:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=List&_sid=\"$sid\""; $param = { url => $url, @@ -755,6 +1057,7 @@ sub camop_nonbl ($) { my $servername = $hash->{SERVERNAME}; my $serverport = $hash->{SERVERPORT}; my $camname = $hash->{CAMNAME}; + my $username = $hash->{USERNAME}; my $apicam = $hash->{HELPER}{APICAM}; my $apicampath = $hash->{HELPER}{APICAMPATH}; my $apicammaxver = $hash->{HELPER}{APICAMMAXVER}; @@ -764,6 +1067,9 @@ sub camop_nonbl ($) { my $apitakesnap = $hash->{HELPER}{APISNAPSHOT}; my $apitakesnappath = $hash->{HELPER}{APITAKESNAPPATH}; my $apitakesnapmaxver = $hash->{HELPER}{APITAKESNAPMAXVER}; + my $apiptz = $hash->{HELPER}{APIPTZ}; + my $apiptzpath = $hash->{HELPER}{APIPTZPATH}; + my $apiptzmaxver = $hash->{HELPER}{APIPTZMAXVER}; my $sid = $hash->{HELPER}{SID}; my $OpMode = $hash->{OPMODE}; my $url; @@ -786,6 +1092,7 @@ sub camop_nonbl ($) { &printlog($hash,$logstr,"1"); # Eintrag fürs Log $logstr = "--- End Function getcamid nonblocking with error ---"; &printlog($hash,$logstr,"4"); + readingsSingleUpdate($hash, "Error", $err, 1); # Readings erzeugen # ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken @@ -802,7 +1109,7 @@ sub camop_nonbl ($) { # Evaluiere ob Daten im JSON-Format empfangen wurden, Achtung: sehr viele Daten mit verbose=5 ($hash, $success) = &evaljson($hash,$myjson,$param->{url}); - unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"5"); return($hash,$success)}; + unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)}; $data = decode_json($myjson); @@ -817,7 +1124,7 @@ sub camop_nonbl ($) { $camcount = $data->{'data'}->{'total'}; $i = 0; - # Namen aller installierten Kameras mit Id's in Hash (Assoziatives Array) einlesen + # Namen aller installierten Kameras mit Id's in Assoziatives Array einlesen %allcams = (); while ($i < $camcount) { @@ -851,7 +1158,7 @@ sub camop_nonbl ($) { readingsEndUpdate($hash, 1); # Logausgabe - $logstr = "ERROR - Cameraname $camname wasn't found in Surveillance Station. Check Cameraname and Spelling."; + $logstr = "ERROR - Cameraname $camname wasn't found in Surveillance Station. Check Userrights ($username), Cameraname and Spelling."; &printlog($hash,$logstr,"1"); $logstr = "--- End Function getcamid nonblocking with error ---"; &printlog($hash,$logstr,"4"); @@ -895,12 +1202,12 @@ sub camop_nonbl ($) { if ($OpMode eq "Start") { # die Aufnahme wird gestartet, Rückkehr wird mit "camret_nonbl" verarbeitet - $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=start&session=SurveillanceStation&_sid=\"$sid\""; + $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=start&_sid=\"$sid\""; } elsif ($OpMode eq "Stop") { # die Aufnahme wird gestoppt, Rückkehr wird mit "camret_nonbl" verarbeitet - $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=stop&session=SurveillanceStation&_sid=\"$sid\""; + $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=$apiextrec&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=stop&_sid=\"$sid\""; } elsif ($OpMode eq "Snap") { @@ -919,7 +1226,28 @@ sub camop_nonbl ($) { # eine Kamera wird aktiviert, Rückkehr wird mit "camret_nonbl" verarbeitet $url = "http://$servername:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=Disable&cameraIds=$camid&_sid=\"$sid\""; } - + elsif ($OpMode eq "Getcaminfo") + { + # Infos einer Kamera werden abgerufen, Rückkehr wird mit "camret_nonbl" verarbeitet + $url = "http://$servername:$serverport/webapi/$apicampath?api=\"$apicam\"&version=\"$apicammaxver\"&method=\"GetInfo\"&cameraIds=\"$camid\"&deviceOutCap=true&streamInfo=true&ptz=true&basic=true&camAppInfo=true&optimize=true&fisheye=true&eventDetection=true&_sid=\"$sid\""; + } + elsif ($OpMode eq "Getptzlistpreset") + { + # PTZ-ListPresets werden abgerufen, Rückkehr wird mit "camret_nonbl" verarbeitet + $url = "http://$servername:$serverport/webapi/$apiptzpath?api=$apiptz&version=$apiptzmaxver&method=ListPreset&cameraId=$camid&_sid=\"$sid\""; + } + elsif ($OpMode eq "Getcapabilities") + { + # Capabilities einer Cam werden abgerufen, Rückkehr wird mit "camret_nonbl" verarbeitet + $url = "http://$servername:$serverport/webapi/$apicampath?api=$apicam&version=$apicammaxver&method=GetCapabilityByCamId&cameraId=$camid&_sid=\"$sid\""; + } + elsif ($OpMode eq "Getptzlistpatrol") + { + # PTZ-ListPatrol werden abgerufen, Rückkehr wird mit "camret_nonbl" verarbeitet + $url = "http://$servername:$serverport/webapi/$apiptzpath?api=$apiptz&version=$apiptzmaxver&method=ListPatrol&cameraId=$camid&_sid=\"$sid\""; + } + + $param = { url => $url, timeout => 10, @@ -938,7 +1266,7 @@ sub camop_nonbl ($) { ################################################################################### #### Rückkehr aus Funktion camop_nonbl, #### Check ob Kameraoperation erfolgreich wie in "OpMOde" definiert -#### danach logout +#### danach Verarbeitung Nutzdaten und weiter zum Logout sub camret_nonbl ($) { my ($param, $err, $myjson) = @_; @@ -947,7 +1275,7 @@ sub camret_nonbl ($) { my $servername = $hash->{SERVERNAME}; my $serverport = $hash->{SERVERPORT}; my $camname = $hash->{CAMNAME}; - my $rectime = $hash->{RECTIME}; + my $rectime = AttrVal($name, "rectime",undef) ? AttrVal($name, "rectime",undef) : $hash->{RECTIME}; my $apiauth = $hash->{HELPER}{APIAUTH}; my $apiauthpath = $hash->{HELPER}{APIAUTHPATH}; my $apiauthmaxver = $hash->{HELPER}{APIAUTHMAXVER}; @@ -957,9 +1285,16 @@ sub camret_nonbl ($) { my $data; my $logstr; my $success; - my $error; - my $errorcode; + my ($error,$errorcode); my $snapid; + my $camLiveMode; + my $update_time; + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst); + my $deviceType; + my $camStatus; + my ($presetcnt,$cnt,%allpresets,$presid,$presname,@preskeys,$presetlist); + my $verbose; + # Verarbeitung der asynchronen Rückkehrdaten aus sub "camop_nonbl" if ($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist @@ -985,7 +1320,7 @@ sub camret_nonbl ($) { # Evaluiere ob Daten im JSON-Format empfangen wurden ($hash, $success) = &evaljson($hash,$myjson,$param->{url}); - unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); return($hash,$success)}; + unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)}; $data = decode_json($myjson); @@ -1012,8 +1347,8 @@ sub camret_nonbl ($) { readingsEndUpdate($hash, 1); # Logausgabe - $logstr = "Camera $camname with Recordtime $rectime"."s started"; - &printlog($hash,$logstr,"3"); + $logstr = "Camera $camname Recording with Recordtime $rectime"."s started"; + &printlog($hash,$logstr,"2"); $logstr = "--- End Function cam: $OpMode nonblocking ---"; &printlog($hash,$logstr,"4"); @@ -1042,7 +1377,7 @@ sub camret_nonbl ($) { # Logausgabe $logstr = "Camera $camname Recording stopped"; - &printlog($hash,$logstr,"3"); + &printlog($hash,$logstr,"2"); $logstr = "--- End Function cam: $OpMode nonblocking ---"; &printlog($hash,$logstr,"4"); } @@ -1069,14 +1404,14 @@ sub camret_nonbl ($) { # Logausgabe $logstr = "Snapshot of Camera $camname has been done successfully"; - &printlog($hash,$logstr,"3"); + &printlog($hash,$logstr,"2"); $logstr = "--- End Function cam: $OpMode nonblocking ---"; &printlog($hash,$logstr,"4"); } elsif ($OpMode eq "Enable") { - # Kamera wurde aktiviert - $hash->{STATE} = "enable"; + # Kamera wurde aktiviert, sonst kann nichts laufen -> "off" + $hash->{STATE} = "off"; # Setreading readingsBeginUpdate($hash); @@ -1087,14 +1422,14 @@ sub camret_nonbl ($) { # Logausgabe $logstr = "Camera $camname has been enabled successfully"; - &printlog($hash,$logstr,"3"); + &printlog($hash,$logstr,"2"); $logstr = "--- End Function cam: $OpMode nonblocking ---"; &printlog($hash,$logstr,"4"); } elsif ($OpMode eq "Disable") { # Kamera wurde deaktiviert - $hash->{STATE} = "disable"; + $hash->{STATE} = "disabled"; # Setreading readingsBeginUpdate($hash); @@ -1105,10 +1440,271 @@ sub camret_nonbl ($) { # Logausgabe $logstr = "Camera $camname has been disabled successfully"; - &printlog($hash,$logstr,"3"); + &printlog($hash,$logstr,"2"); $logstr = "--- End Function cam: $OpMode nonblocking ---"; &printlog($hash,$logstr,"4"); } + elsif ($OpMode eq "Getcaminfo") + { + # Parse Caminfos + $camLiveMode = $data->{'data'}->{'cameras'}->[0]->{'camLiveMode'}; + if ($camLiveMode eq "0") {$camLiveMode = "Liveview from DS";}elsif ($camLiveMode eq "1") {$camLiveMode = "Liveview from Camera";} + + $update_time = $data->{'data'}->{'cameras'}->[0]->{'update_time'}; + ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($update_time); + $update_time = sprintf "%02d.%02d.%04d / %02d:%02d:%02d" , $mday , $mon+=1 ,$year+=1900 , $hour , $min , $sec ; + + $deviceType = $data->{'data'}->{'cameras'}->[0]->{'deviceType'}; + if ($deviceType eq "1") { + $deviceType = "Camera"; + } + elsif ($deviceType eq "2") { + $deviceType = "Video_Server"; + } + elsif ($deviceType eq "4") { + $deviceType = "PTZ"; + } + elsif ($deviceType eq "8") { + $deviceType = "Fisheye"; + } + + $camStatus = $data->{'data'}->{'cameras'}->[0]->{'camStatus'}; + if ($camStatus eq "1") { + $camStatus = "enabled"; + + # falls Aufnahme noch läuft -> STATE = on setzen + if (ReadingsVal("$name", "Record", "Stop") eq "Start") { + $hash->{STATE} = "on"; + } + else + { + $hash->{STATE} = "off"; + } + } + elsif ($camStatus eq "3") { + $camStatus = "disconnected"; + } + elsif ($camStatus eq "7") { + $camStatus = "disabled"; + $hash->{STATE} = "disable"; + } + else { + $camStatus = "other"; + } + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"CamLiveMode",$camLiveMode); + readingsBulkUpdate($hash,"CamRecShare",$data->{'data'}->{'cameras'}->[0]->{'camRecShare'}); + readingsBulkUpdate($hash,"CamRecVolume",$data->{'data'}->{'cameras'}->[0]->{'camRecVolume'}); + readingsBulkUpdate($hash,"CamIP",$data->{'data'}->{'cameras'}->[0]->{'host'}); + readingsBulkUpdate($hash,"CamPort",$data->{'data'}->{'cameras'}->[0]->{'port'}); + readingsBulkUpdate($hash,"Availability",$camStatus); + readingsBulkUpdate($hash,"DeviceType",$deviceType); + readingsBulkUpdate($hash,"LastUpdateTime",$update_time); + readingsBulkUpdate($hash,"UsedSpaceMB",$data->{'data'}->{'cameras'}->[0]->{'volume_space'}); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "Camera-Informations of $camname retrieved"; + # wenn "pollnologging" = 1 -> logging nur bei Verbose=4, sonst 2 + if (defined(AttrVal($name, "pollnologging", undef)) and AttrVal($name, "pollnologging", undef) eq "1") { + $verbose = 4; + } + else + { + $verbose = 2; + } + &printlog($hash,$logstr,$verbose); + $logstr = "--- End Function cam: $OpMode nonblocking ---"; + &printlog($hash,$logstr,"4"); + } + elsif ($OpMode eq "Getcapabilities") + { + # Parse Infos + my $ptzfocus = $data->{'data'}{'ptzFocus'}; + if ($ptzfocus eq "0") { + $ptzfocus = "false"; + } + elsif ($ptzfocus eq "1") { + $ptzfocus = "support step operation"; + } + elsif ($ptzfocus eq "2") { + $ptzfocus = "support continuous operation"; + } + + my $ptztilt = $data->{'data'}{'ptzTilt'}; + if ($ptztilt eq "0") { + $ptztilt = "false"; + } + elsif ($ptztilt eq "1") { + $ptztilt = "support step operation"; + } + elsif ($ptztilt eq "2") { + $ptztilt = "support continuous operation"; + } + + my $ptzzoom = $data->{'data'}{'ptzZoom'}; + if ($ptzzoom eq "0") { + $ptzzoom = "false"; + } + elsif ($ptzzoom eq "1") { + $ptzzoom = "support step operation"; + } + elsif ($ptzzoom eq "2") { + $ptzzoom = "support continuous operation"; + } + + my $ptzpan = $data->{'data'}{'ptzPan'}; + if ($ptzpan eq "0") { + $ptzpan = "false"; + } + elsif ($ptzpan eq "1") { + $ptzpan = "support step operation"; + } + elsif ($ptzpan eq "2") { + $ptzpan = "support continuous operation"; + } + + my $ptziris = $data->{'data'}{'ptzIris'}; + if ($ptziris eq "0") { + $ptziris = "false"; + } + elsif ($ptziris eq "1") { + $ptziris = "support step operation"; + } + elsif ($ptziris eq "2") { + $ptziris = "support continuous operation"; + } + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"CapPTZAutoFocus",$data->{'data'}{'ptzAutoFocus'}); + readingsBulkUpdate($hash,"CapAudioOut",$data->{'data'}{'audioOut'}); + readingsBulkUpdate($hash,"CapChangeSpeed",$data->{'data'}{'ptzSpeed'}); + readingsBulkUpdate($hash,"CapPTZHome",$data->{'data'}{'ptzHome'}); + readingsBulkUpdate($hash,"CapPTZAbs",$data->{'data'}{'ptzAbs'}); + readingsBulkUpdate($hash,"CapPTZDirections",$data->{'data'}{'ptzDirection'}); + readingsBulkUpdate($hash,"CapPTZFocus",$ptzfocus); + readingsBulkUpdate($hash,"CapPTZIris",$ptziris); + readingsBulkUpdate($hash,"CapPTZPan",$ptzpan); + readingsBulkUpdate($hash,"CapPTZTilt",$ptztilt); + readingsBulkUpdate($hash,"CapPTZZoom",$ptzzoom); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "Capabilities of Camera $camname retrieved"; + # wenn "pollnologging" = 1 -> logging nur bei Verbose=4, sonst 2 + if (defined(AttrVal($name, "pollnologging", undef)) and AttrVal($name, "pollnologging", undef) eq "1") { + $verbose = 4; + } + else + { + $verbose = 2; + } + &printlog($hash,$logstr,$verbose); + $logstr = "--- End Function cam: $OpMode nonblocking ---"; + &printlog($hash,$logstr,"4"); + } + elsif ($OpMode eq "Getptzlistpreset") + { + # Parse PTZ-ListPresets + $presetcnt = $data->{'data'}->{'total'}; + $cnt = 0; + + # alle Presets der Kamera mit Id's in Assoziatives Array einlesen + %allpresets = (); + while ($cnt < $presetcnt) + { + $presid = $data->{'data'}->{'presets'}->[$cnt]->{'id'}; + $presname = $data->{'data'}->{'presets'}->[$cnt]->{'name'}; + $allpresets{$presname} = "$presid"; + $cnt += 1; + } + + # Presethash in $hash einfügen + $hash->{HELPER}{ALLPRESETS} = \%allpresets; + + @preskeys = sort(keys(%allpresets)); + $presetlist = join(",",@preskeys); + + # print "ID von Home ist : ". %allpresets->{"home"}; + # print "aus Hash: ".$hash->{HELPER}{ALLPRESETS}{home}; + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Presets",$presetlist); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + + # Logausgabe + $logstr = "PTZ Presets of $camname retrieved"; + # wenn "pollnologging" = 1 -> logging nur bei Verbose=4, sonst 2 + if (defined(AttrVal($name, "pollnologging", undef)) and AttrVal($name, "pollnologging", undef) eq "1") { + $verbose = 4; + } + else + { + $verbose = 2; + } + &printlog($hash,$logstr,$verbose); + $logstr = "--- End Function cam: $OpMode nonblocking ---"; + &printlog($hash,$logstr,"4"); + } + elsif ($OpMode eq "Getptzlistpatrol") + { + # Parse PTZ-ListPatrols + my $patrolcnt = $data->{'data'}->{'total'}; + $cnt = 0; + + # alle Patrols der Kamera mit Id's in Assoziatives Array einlesen + my %allpatrols = (); + while ($cnt < $patrolcnt) + { + my $patrolid = $data->{'data'}->{'patrols'}->[$cnt]->{'id'}; + my $patrolname = $data->{'data'}->{'patrols'}->[$cnt]->{'name'}; + $allpatrols{$patrolname} = $patrolid; + $cnt += 1; + } + + # Presethash in $hash einfügen + $hash->{HELPER}{ALLPATROLS} = \%allpatrols; + + my @patrolkeys = sort(keys(%allpatrols)); + my $patrollist = join(",",@patrolkeys); + + # print "ID von Tour1 ist : ". %allpatrols->{Tour1}; + # print "aus Hash: ".$hash->{HELPER}{ALLPRESETS}{Tour1}; + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Patrols",$patrollist); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + + # Logausgabe + $logstr = "PTZ Patrols of $camname retrieved"; + # wenn "pollnologging" = 1 -> logging nur bei Verbose=4, sonst 2 + if (defined(AttrVal($name, "pollnologging", undef)) and AttrVal($name, "pollnologging", undef) eq "1") { + $verbose = 4; + } + else + { + $verbose = 2; + } + &printlog($hash,$logstr,$verbose); + $logstr = "--- End Function cam: $OpMode nonblocking ---"; + &printlog($hash,$logstr,"4"); + } + } else { @@ -1142,7 +1738,7 @@ sub camret_nonbl ($) { $logstr = "--- Begin Function logout nonblocking ---"; &printlog($hash,$logstr,"4"); - $url = "http://$servername:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Logout&session=SurveillanceStation&_sid=$sid"; + $url = "http://$servername:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Logout&_sid=$sid"; $param = { url => $url, @@ -1173,9 +1769,6 @@ sub logout_nonbl ($) { my $error; my $errorcode; - # ausgeführte Funktion ist erledigt (auch wenn logout nicht erfolgreich), Freigabe Funktionstoken - $hash->{HELPER}{ACTIVE} = "off"; - if($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist { $logstr = "error while requesting ".$param->{url}." - $err"; @@ -1185,7 +1778,6 @@ sub logout_nonbl ($) { readingsSingleUpdate($hash, "Error", $err, 1); # Readings erzeugen - return; } elsif($myjson ne "") # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes) { @@ -1196,7 +1788,7 @@ sub logout_nonbl ($) { # Evaluiere ob Daten im JSON-Format empfangen wurden ($hash, $success) = &evaljson($hash,$myjson,$param->{url}); - unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); return($hash,$success)}; + unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)}; $data = decode_json($myjson); @@ -1234,6 +1826,10 @@ sub logout_nonbl ($) { &printlog($hash,$logstr,"4"); } } +# ausgeführte Funktion ist erledigt (auch wenn logout nicht erfolgreich), Freigabe Funktionstoken +$hash->{HELPER}{ACTIVE} = "off"; + +return; } ############################################################################################################################# @@ -1264,8 +1860,10 @@ sub evaljson { readingsBeginUpdate($hash); readingsBulkUpdate($hash,"Errorcode","none"); readingsBulkUpdate($hash,"Error","malformed JSON string received"); - readingsEndUpdate($hash, 1); + readingsEndUpdate($hash, 1); + }; + return($hash,$success); } @@ -1315,7 +1913,7 @@ sub experror { 101 => "Invalid parameters", 102 => "API does not exist", 103 => "Method does not exist", - 104 => "This API version is not supporte", + 104 => "This API version is not supported", 105 => "Insufficient user privilege", 106 => "Connection time out", 107 => "Multiple login detected", @@ -1323,7 +1921,7 @@ sub experror { 401 => "Parameter invalid", 402 => "Camera disabled", 403 => "Insufficient license", - 404 => "Codec acitvation failed", + 404 => "Codec activation failed", 405 => "CMS server connection failed", 407 => "CMS closed", 410 => "Service is not enabled", @@ -1364,23 +1962,22 @@ return;

SSCam

    -
    - Using this Module you are able to operate with cameras which are defined in Synology Surveillance Station.
    - At present the following functions are available:

    + Using this Module you are able to operate with cameras which are defined in Synology Surveillance Station.
    + At present the following functions are available:

    +
        -
          -
        • Start a Rocording
        • -
        • Stop a Recording (using command or automatically after the <RecordTime> period
        • -
        • Trigger a Snapshot
        • -
        • Deaktivate a Camera in Synology Surveillance Station
        • -
        • Activate a Camera in Synology Surveillance Station

        • -
        +
      • Start a Rocording
      • +
      • Stop a Recording (using command or automatically after the <RecordTime> period
      • +
      • Trigger a Snapshot
      • +
      • Deaktivate a Camera in Synology Surveillance Station
      • +
      • Activate a Camera in Synology Surveillance Station

      - The recordings and snapshots will be stored in Synology Surveillance Station and are managed like the other (normal) recordings / snapshots defined by Surveillance Station rules.
      - For example the recordings are stored for a defined time in Surveillance Station and will be deleted after that period.

      +
    + The recordings and snapshots will be stored in Synology Surveillance Station and are managed like the other (normal) recordings / snapshots defined by Surveillance Station rules.
    + For example the recordings are stored for a defined time in Surveillance Station and will be deleted after that period.

    - If you like to discuss or help to improve this module please use FHEM-Forum with link:
    - 49_SSCam: Fragen, Hinweise, Neuigkeiten und mehr rund um dieses Modul.

    + If you like to discuss or help to improve this module please use FHEM-Forum with link:
    + 49_SSCam: Fragen, Hinweise, Neuigkeiten und mehr rund um dieses Modul.

    Prerequisites

    This module uses the CPAN-module JSON. Please consider to install this package (Debian: libjson-perl).
    @@ -1411,7 +2008,7 @@ return; - + @@ -1505,14 +2102,108 @@ return;
    + + +Get +
      + With SSCam the properties of defined Cameras could be retrieved. It could be done by using the command: +
      +      get <name> caminfoall
      +  
      + Dependend from the type of Camera (e.g. Fix- or PTZ-Camera) the available properties will be retrieved and provided as Readings.
      + For example the Reading "Availability" will be set to "disconnected" if the Camera would be disconnected from Synology Surveillance Station and can be used for further
      + processing like crearing events.

      + + Polling of Camera-Preperties:

      + + Retrieval of Camera-Properties can be done automatically if the attribute "pollcaminfoall" will be set to a value > 10.
      + As default that attribute "pollcaminfoall" isn't be set and the automatic polling isn't be active.
      + The value of that attribute determines the interval of property-retrieval in seconds. If that attribute isn't be set or < 10 the automatic polling won't be started
      + respectively stopped when the value was set to > 10 before.

      + + The attribute "pollcaminfoall" is monitored by a watchdog-timer. Changes of th attributevalue will be checked every 90 seconds and transact correspondig.
      + Changes of the pollingstate and pollinginterval will be reported in FHEM-Logfile. The reporting can be switched off by setting the attribute "pollnologging=1".
      + Thereby the needless growing of the logfile can be avoided. But if verbose is set to 4 or above even though the attribute "pollnologging" is set as well, the polling
      + will be actived due to analysis purposes.

      + + If FHEM will be restarted, the first data retrieval will be done within 60 seconds after start.

      + + The state of automatic polling will be displayed by reading "PollState":
      +
      +    PollState = Active     -    automatic polling will be executed with interval correspondig value of attribute 
      +    PollState = Inactive   -    automatic polling won't be executed
      +  
      + + The meaning of reading values is described under Readings .

      + + Notes:

      + + If polling is used, the interval should be adjusted only as short as needed due to the detected camera values are predominantly static.
      + A feasible guide value for attribute "pollcaminfoall" could be between 600 - 1800 (s).
      + Per polling call and camera approximately 10 - 20 Http-calls will are stepped against Surveillance Station.

      + + If several Cameras are defined in SSCam, attribute "pollcaminfoall" of every Cameras shouldn't be set exactly to the same value to avoid processing bottlenecks
      + and thereby caused potential source of errors during request Synology Surveillance Station.
      + A marginal difference between the polling intervals of the defined cameras, e.g. 1 second, can already be faced as sufficient value.

      +
    + + +Readings +
      +
      + Using the polling mechanism or retrieval by "get"-call readings are provieded, The meaning of the readings are listed in subsequent table:
      + The transfered Readings can be deversified dependend on the type of camera.

      +
        +
    name: the name of the new device to use in FHEM
    ServerIP: IP-address of Synology Surveillance Station Host. Caution: avoid using hostnames because of DNS-Calls are not unblocking in FHEM
    ServerIP: IP-address of Synology Surveillance Station Host. Note: avoid using hostnames because of DNS-Calls are not unblocking in FHEM
    Port: the Port Synology surveillance Station Host, normally 5000 (HTTP only)
    Username: Username defined in the Diskstation. Has to be a member of Admin-group
    Password: the Password for the User
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  • Availability
  • - Availability of Camera (disabled, enabled, disconnected, other)
  • CamIP
  • - IP-Address of Camera
  • CamLiveMode
  • - Source of Live-View (DS, Camera)
  • CamPort
  • - IP-Port of Camera
  • CamRecShare
  • - shared folder on disk station for recordings
  • CamRecVolume
  • - Volume on disk station for recordings
  • CapAudioOut
  • - Capability to Audio Out over Surveillance Station (false/true)
  • CapChangeSpeed
  • - Capability to various motion speed
  • CapPTZAbs
  • - Capability to perform absolute PTZ action
  • CapPTZAutoFocus
  • - Capability to perform auto focus action
  • CapPTZDirections
  • - the PTZ directions that camera support
  • CapPTZFocus
  • - mode of support for focus action
  • CapPTZHome
  • - Capability to perform home action
  • CapPTZIris
  • - mode of support for iris action
  • CapPTZPan
  • - Capability to perform pan action
  • CapPTZTilt
  • - mode of support for tilt action
  • CapPTZZoom
  • - Capability to perform zoom action
  • DeviceType
  • - device type (Camera, Video_Server, PTZ, Fisheye)
  • Error
  • - message text of last error
  • Errorcode
  • - error code of last error
  • LastUpdateTime
  • - date / time of last update of Camera in Synology Surrveillance Station
  • Patrols
  • - in Synology Surveillance Station predefined patrols (at PTZ-Cameras)
  • PollState
  • - shows the state of automatic polling
  • Presets
  • - in Synology Surveillance Station predefined Presets (at PTZ-Cameras)
  • Record
  • - if recording is running = Start, if no recording is running = Stop
  • UsedSpaceMB
  • - used disk space of recordings by Camera
    +
+

+ + + Attributes -
    +

    +
      +
        +
      • pollcaminfoall - Interval of automatic polling the Camera properties (if < 10: no polling, if > 10: polling with interval)
      • + +
      • pollnologging - "0" resp. not set = Logging device polling active (default), "1" = Logging device polling inactive
      • + +
      • verbose

      • - Different Verbose-Level are supported.
        - Those are in detail:

        +
          + Different Verbose-Level are supported.
          + Those are in detail: @@ -1520,14 +2211,17 @@ return; - -
          1 Error messages will be logged
          3 sended commands will be logged
          4 sended and received informations will be logged
          5 all outputs will be logged for error-analyses. Caution: a lot of data could be written into the logfile !
          - + 5 all outputs will be logged for error-analyses. Caution: a lot of data could be written into logfile ! + +


        -
      • readingFnAttributes
      • + further Attributes:

        + +
      • readingFnAttributes
      • +
    -
    +

@@ -1537,7 +2231,6 @@ return;

SSCam

    -
    Mit diesem Modul können Operationen von in der Synology Surveillance Station definierten Kameras ausgeführt werden.
    Zur Zeit werden folgende Funktionen unterstützt:

      @@ -1552,7 +2245,7 @@ return; Die Aufnahmen stehen in der Synology Surveillance Station zur Verfügung und unterliegen, wie jede andere Aufnahme, den in der Synology Surveillance Station eingestellten Regeln.
      So werden zum Beispiel die Aufnahmen entsprechend ihrer Archivierungsfrist gehalten und dann gelöscht.

      - Wenn du über dieses Modul diskutieren oder zur Verbesserung des Moduls beitragen möchtest ist im FHEM-Forum ein Sammelplatz unter:
      + Wenn sie über dieses Modul diskutieren oder zur Verbesserung des Moduls beitragen möchten, ist im FHEM-Forum ein Sammelplatz unter:
      49_SSCam: Fragen, Hinweise, Neuigkeiten und mehr rund um dieses Modul.

      Vorbereitung

      @@ -1561,7 +2254,7 @@ return; Im DSM muß ebenfalls ein Nutzer als Mitglied der Administratorgruppe angelegt sein. Die Daten werden bei der Definition des Gerätes benötigt.

      -Define +Definition

        define <name> SSCam <ServerIP> <Port> <Username> <Password> <Kameraname in SS> <RecordTime>
        @@ -1584,7 +2277,7 @@ return; - + @@ -1676,30 +2369,127 @@ return;
        + +Get +
          + Mit SSCam können die Eigenschaften der Kameras aus der Surveillance Station abgefragt werden. Dazu steht der Befehl zur Verfügung: +
          +      get <name> caminfoall
          +  
          + Abhängig von der Art der Kamera (z.B. Fix- oder PTZ-Kamera) werden die verfügbaren Eigenschaften ermittelt und als Readings zur Verfügung gestellt.
          + So wird zum Beispiel das Reading "Availability" auf "disconnected" gesetzt falls die Kamera von der Surveillance Station getrennt wird und kann für weitere
          + Verarbeitungen genutzt werden.

          + + Polling der Kameraeigenschaften:

          + + Die Abfrage der Kameraeigenschaften erfolgt automatisch, wenn das Attribut "pollcaminfoall" (siehe Attribute) mit einem Wert > 10 gesetzt wird.
          + Per Default ist das Attribut "pollcaminfoall" nicht gesetzt und das automatische Polling nicht aktiv.
          + Der Wert dieses Attributes legt das Intervall der Abfrage in Sekunden fest. Ist das Attribut nicht gesetzt oder < 10 wird kein automatisches Polling
          + gestartet bzw. gestoppt wenn vorher der Wert > 10 gesetzt war.

          + + Das Attribut "pollcaminfoall" wird durch einen Watchdog-Timer überwacht. Änderungen des Attributwertes werden alle 90 Sekunden ausgewertet und entsprechend umgesetzt.
          + Eine Änderung des Pollingstatus / Pollingintervalls wird im FHEM-Logfile protokolliert. Diese Protokollierung kann durch Setzen des Attributes "pollnologging=1" abgeschaltet werden.
          + Dadurch kann ein unnötiges Anwachsen des Logs vermieden werden. Ab verbose=4 wird allerdings trotz gesetzten "pollnologging"-Attribut ein Log des Pollings
          + zu Analysezwecken aktiviert.

          + + Wird FHEM neu gestartet, wird bei aktivierten Polling der ersten Datenabruf innerhalb 60s nach dem Start ausgeführt.

          + + Der Status des automatischen Pollings wird durch das Reading "PollState" signalisiert:
          +
          +    PollState = Active     -    automatisches Polling wird mit Intervall entsprechend  ausgeführt
          +    PollState = Inactive   -    automatisches Polling wird nicht ausgeführt
          +  
          + + Die Bedeutung der Readingwerte ist unter Readings beschrieben.

          + + Hinweise:

          + + Wird Polling eingesetzt, sollte das Intervall nur so kurz wie benötigt eingestellt werden da die ermittelten Werte überwiegend statisch sind.
          + Ein praktikabler Richtwert könnte zwischen 600 - 1800 (s) liegen.
          + Pro Pollingaufruf und Kamera werden ca. 10 - 20 Http-Calls gegen die Surveillance Station abgesetzt.

          + + Sind mehrere Kameras in SSCam definiert, sollte "pollcaminfoall" nicht bei allen Kameras auf exakt den gleichen Wert gesetzt werden um Verarbeitungsengpässe
          + und dadurch versursachte potentielle Fehlerquellen bei der Abfrage der Synology Surveillance Station zu vermeiden.
          + Ein geringfügiger Unterschied zwischen den Pollingintervallen der definierten Kameras von z.B. 1s kann bereits als ausreichend angesehen werden.

          +
        + + +Readings +
          +
          + Über den Pollingmechanismus bzw. durch Abfrage mit "Get" werden Readings bereitgestellt, deren Bedeutung in der nachfolgenden Tabelle dargestellt sind.
          + Die übermittelten Readings können in Abhängigkeit des Kameratyps variieren.

          +
            +
        name: der Name des neuen Gerätes in FHEM
        ServerIP: die IP-Addresse des Synology Surveillance Station Host. Achtung: Es sollte kein Servername verwendet werden weil DNS-Aufrufe in FHEM blockierend sind.
        ServerIP: die IP-Addresse des Synology Surveillance Station Host. Hinweis: Es sollte kein Servername verwendet werden weil DNS-Aufrufe in FHEM blockierend sind.
        Port: der Port des Synology Surveillance Station Host. Normalerweise ist das 5000 (nur HTTP)
        Username: Name des in der Diskstation definierten Nutzers. Er muß ein Mitglied der Admin-Gruppe sein
        Password: das Passwort des Nutzers
        + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      • Availability
      • - Verfügbarkeit der Kamera (disabled, enabled, disconnected, other)
      • CamIP
      • - IP-Adresse der Kamera
      • CamLiveMode
      • - Quelle für Live-Ansicht (DS, Camera)
      • CamPort
      • - IP-Port der Kamera
      • CamRecShare
      • - gemeinsamer Ordner auf der DS für Aufnahmen
      • CamRecVolume
      • - Volume auf der DS für Aufnahmen
      • CapAudioOut
      • - Fähigkeit der Kamera zur Audioausgabe über Surveillance Station (false/true)
      • CapChangeSpeed
      • - Fähigkeit der Kamera verschiedene Bewegungsgeschwindigkeiten auszuführen
      • CapPTZAbs
      • - Fähigkeit der Kamera für absolute PTZ-Aktionen
      • CapPTZAutoFocus
      • - Fähigkeit der Kamera für Autofokus Aktionen
      • CapPTZDirections
      • - die verfügbaren PTZ-Richtungen der Kamera
      • CapPTZFocus
      • - Art der Kameraunterstützung für Fokussierung
      • CapPTZHome
      • - Unterstützung der Kamera für Home-Position
      • CapPTZIris
      • - Unterstützung der Kamera für Iris-Aktion
      • CapPTZPan
      • - Unterstützung der Kamera für Pan-Aktion
      • CapPTZTilt
      • - Unterstützung der Kamera für Tilt-Aktion
      • CapPTZZoom
      • - Unterstützung der Kamera für Zoom-Aktion
      • DeviceType
      • - Kameratyp (Camera, Video_Server, PTZ, Fisheye)
      • Error
      • - Meldungstext des letzten Fehlers
      • Errorcode
      • - Fehlercode des letzten Fehlers
      • LastUpdateTime
      • - Datum / Zeit der letzten Aktualisierung der Kamera in der Surrveillance Station
      • Patrols
      • - in Surveillance Station voreingestellte Überwachungstouren (bei PTZ-Kameras)
      • PollState
      • - zeigt den Status des automatischen Pollings an
      • Presets
      • - in Surveillance Station voreingestellte Positionen (bei PTZ-Kameras)
      • Record
      • - Aufnahme läuft = Start, keine Aufnahme = Stop
      • UsedSpaceMB
      • - durch Aufnahmen der Kamera belegter Plattenplatz auf dem Volume
        +
      +

      +
    + + Attribute +

      - - Es werden verschiedene Verbose-Level unterstützt.
      - Dies sind im Einzelnen:

      - - - - - - - - -
      0 Start/Stop-Ereignisse werden geloggt
      1 Fehlermeldungen werden geloggt
      3 gesendete Kommandos werden geloggt
      4 gesendete und empfangene Daten werden geloggt
      5 alle Ausgaben zur Fehleranalyse werden geloggt. ACHTUNG: möglicherweise werden sehr viele Daten in das Logfile geschrieben!
      +
        +
      • pollcaminfoall - Intervall der automatischen Eigenschaftsabfrage (Polling) einer Kamera (kleiner 10: kein Polling, größer 10: Polling mit Intervall)
      • +
      • pollnologging - "0" bzw. nicht gesetzt = Logging Gerätepolling aktiv (default), "1" = Logging Gerätepolling inaktiv
      • + +
      • verbose

      • + +
          + Es werden verschiedene Verbose-Level unterstützt. + Dies sind im Einzelnen: + + + + + + + + +
          0 - Start/Stop-Ereignisse werden geloggt
          1 - Fehlermeldungen werden geloggt
          3 - gesendete Kommandos werden geloggt
          4 - gesendete und empfangene Daten werden geloggt
          5 - alle Ausgaben zur Fehleranalyse werden geloggt. ACHTUNG: möglicherweise werden sehr viele Daten in das Logfile geschrieben!
          +


        - -
      • readingFnAttributes
      • + + weitere Attribute:

        + +
      • readingFnAttributes
      • +
    -
    +

=end html_DE =cut +