diff --git a/fhem/FHEM/49_SSCam.pm b/fhem/FHEM/49_SSCam.pm new file mode 100644 index 000000000..3ee392902 --- /dev/null +++ b/fhem/FHEM/49_SSCam.pm @@ -0,0 +1,1156 @@ +##################################################################################################### +# 49_SSCam.pm +# +# Copyright by Heiko Maaz +# e-mail: Heiko dot Maaz at t-online dot de +# +# This Modul is used to manage 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. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see .# +# +###################################################################################################### +# Definition: define SSCam +# +# Beispiel: define CamCP1 SSCAM dd.myds.net 5000 apiuser apipw Carport 5 +# +# Parameters: +# +# $servername = ""; # DS-Sername oder IP +# $serverport = ""; # DS Port +# $username = ""; # User für login auf DS +# $password = ""; # Passwort für User login +# $camname = ""; # Name der Kamera +# $rectime = ""; # Dauer der Aufnahme in Sekunden + + +package main; + +use LWP::Simple; # From CPAN , Debian libwww-perl +use JSON qw( decode_json ); # From CPAN,, Debian libjson-perl +use strict; # Good practice +use warnings; # Good practice + + +sub +SSCam_Initialize($) +{ + # die Namen der Funktionen, die das Modul implementiert und die fhem.pl aufrufen soll + my ($hash) = @_; + $hash->{DefFn} = "SSCam_Define"; + $hash->{UndefFn} = "SSCam_Undef"; + $hash->{SetFn} = "SSCam_Set"; + # $hash->{AttrFn} = "SSCam_Attr"; + + + $hash->{AttrList} = + "webCmd ". + $readingFnAttributes; + +} + +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 sds1.myds.me 5000 apiuser Support4me Carport 5 + # ($hash) [1] [2] [3] [4] [5] [6] [7] + # + my ($hash, $def) = @_; + + my @a = split("[ \t][ \t]*", $def); + + if(int(@a) < 8) { + return "You need to specify more parameters.\n". "Format: define SSCAM "; + } + + my $servername = $a[2]; + my $serverport = $a[3]; + my $username = $a[4]; + my $password = $a[5]; + my $camname = $a[6]; + my $rectime = $a[7]; + + + unless ($rectime =~ /^\d+$/) { return " The given Recordtime is not valid. Use only figures 0-9 without decimal places !";} + # führende Nullen entfernen + $rectime =~ s/^0+//; + + $hash->{SERVERNAME} = $servername; + $hash->{SERVERPORT} = $serverport; + $hash->{USERNAME} = $username; + $hash->{PASSWORD} = $password; + $hash->{CAMNAME} = $camname; + $hash->{RECTIME} = $rectime; + + return undef; +} + + +sub SSCam_Undef { + my ($hash, $arg) = @_; + return undef; +} + +sub SSCam_Attr { +} + +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 $value = join("", @a); + my %SSCam_sets = ( + on => "on", + off => "off"); + my $errorcode; + my $s; + 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 { + + # Aufnahme starten + if ($opt eq "on") { + # wegen Syno-105-Fehler mehrfaches durchlaufen bis kein 105-Fehler mehr oder Aufgabe nach x Durchläufen ($s = Schleifendurchlauf) + $errorcode = "105"; + $s = 30; + while ($errorcode eq "105" && $s > 0) { + &camstart($hash); + $errorcode = ReadingsVal("$name","Errorcode","none"); + # Logausgabe + $logstr = "Readingsval $name".":Errorcode is: $errorcode"; + $logstr = "Readingsval $name".":Errorcode is still $errorcode but end of loop reached, giving up!" if ($s == 1); + &printlog($hash,$logstr,"5"); + $s -=1; + } + } + + + # Aufnahme stoppen + if ($opt eq "off") { + # wegen Syno-105-Fehler mehrfaches durchlaufen bis kein 105-Fehler mehr oder Aufgabe nach x Durchläufen ($s = Schleifendurchlauf) + $errorcode = "105"; + $s = 30; + while ($errorcode eq "105" && $s > 0) { + &camstop($hash); + $errorcode = ReadingsVal("$name","Errorcode","none"); + # Logausgabe + $logstr = "Readingsval $name".":Errorcode is: $errorcode"; + $logstr = "Readingsval $name".":Errorcode is still $errorcode but end of loop reached, giving up!" if ($s == 1); + &printlog($hash,$logstr,"5"); + $s -=1; + } + } + } +} + + +############################################################################### +#### Starten einer Kameraaufnahme + +sub camstart { + # Übernahmewerte sind $username, $password,$camname, $servername, $serverport + my ($hash) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $username = $hash->{USERNAME}; + my $password = $hash->{PASSWORD}; + my $camname = $hash->{CAMNAME}; + my $device = $hash->{NAME}; + my $rectime = $hash->{RECTIME}; + my $logstr; + my $validurl; + my $success; + my $sid; + my $camid; + my $apiextrecpath; + my $apiextrecmaxver; + my $errorcode; + my $url; + my $myjson; + my $data; + my $error; + + # Logausgabe + $logstr = "--- Begin Function camstart ---"; + &printlog($hash,$logstr,"5"); + + $logstr = "Recording of Camera $camname should be started now"; + &printlog($hash,$logstr,"5"); + + # Erreichbarkeit Disk Station Url testen + $validurl = &validurl($hash); + unless ($validurl eq "true") {return}; + + # API-Pfade und MaxVersions ermitteln + ($hash, $success) = &getapisites($hash); + unless ($success eq "true") {return}; + + # Login und SID ermitteln + ($sid, $success) = &serverlogin($hash); + unless ($success eq "true") {return}; + + # Kamera-ID anhand des Kamaeranamens ermitteln + ($camid, $success) = &getcamid($hash,$sid); + unless ($success eq "true") {&serverlogout($hash,$sid); return}; + + # Start der Aufnahme + $apiextrecpath = $hash->{APIEXTRECPATH}; + $apiextrecmaxver = $hash->{APIEXTRECMAXVER}; + $errorcode = ""; + $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=SYNO.SurveillanceStation.ExternalRecording&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=start&session=SurveillanceStation&_sid=$sid"; + $myjson = get $url; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$url); + unless ($success eq "true") {&serverlogout($hash,$sid); return}; + + # Logausgabe + $logstr = "URL call: $url"; + &printlog($hash,$logstr,"4"); + $logstr = "JSON response: $myjson"; + &printlog($hash,$logstr,"4"); + + # dekodiere Response aus JSON Format + $data = decode_json($myjson); + $success = $data->{'success'}; + + + if ($success eq "true") { + + # die URL konnte erfolgreich aufgerufen werden + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Record","Start"); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + $hash->{STATE} = "on"; + + # bedingt Browseraktualisierung und Status der "Lampen" + { fhem "trigger $device on" } + + # Logausgabe + $logstr = "Camera $camname with Recordtime $rectime"."s started"; + &printlog($hash,$logstr,"3"); + + # FHEM Sleep Kommando, kein blockieren von FHEM + {fhem("sleep $rectime;set $device off")}; + $logstr = "Autostop command: {fhem(\"sleep $rectime quiet;set $device off\")}"; + &printlog($hash,$logstr,"5"); + + } + else { + # die URL konnte nicht erfolgreich aufgerufen werden + # Errorcode aus JSON ermitteln + $errorcode = $data->{'error'}->{'code'}; + + # Fehlertext zum Errorcode ermitteln + $error = &experror($hash,$errorcode); + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode",$errorcode); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "ERROR - Start Recording of Camera $camname not possible. Errorcode: $errorcode - $error"; + &printlog($hash,$logstr,"1"); + } + &serverlogout($hash,$sid); + + # Logausgabe + $logstr = "--- End Function camstart ---"; + &printlog($hash,$logstr,"5"); + +return; +} + +############################################################################## +### Stoppen Kameraaufnahme + +sub camstop { + # Übernahmewerte sind $username, $password,$camname, $servername, $serverport + my ($hash) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $username = $hash->{USERNAME}; + my $password = $hash->{PASSWORD}; + my $camname = $hash->{CAMNAME}; + my $device = $hash->{NAME}; + my $logstr; + my $validurl; + my $success; + my $sid; + my $camid; + my $apiextrecpath; + my $apiextrecmaxver; + my $errorcode; + my $url; + my $myjson; + + # Logausgabe + $logstr = "--- Begin Function camstop ---"; + &printlog($hash,$logstr,"5"); + + $logstr = "Recording of Camera $camname should be stopped now"; + &printlog($hash,$logstr,"5"); + + # Erreichbarkeit Disk Station Url testen + $validurl = &validurl($hash); + unless ($validurl eq "true") {return}; + + # API-Pfade und MaxVersions ermitteln + ($hash, $success) = &getapisites($hash); + unless ($success eq "true") {return}; + + # SID ermitteln nach Login + ($sid, $success) = &serverlogin($hash); + unless ($success eq "true") {return}; + + ($camid, $success) = &getcamid($hash,$sid); + unless ($success eq "true") {&serverlogout($hash,$sid); return}; + + $apiextrecpath = $hash->{APIEXTRECPATH}; + $apiextrecmaxver = $hash->{APIEXTRECMAXVER}; + + $errorcode = ""; + $url = "http://$servername:$serverport/webapi/$apiextrecpath?api=SYNO.SurveillanceStation.ExternalRecording&method=Record&version=$apiextrecmaxver&cameraId=$camid&action=stop&session=SurveillanceStation&_sid=$sid"; + $myjson = get $url; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$url); + unless ($success eq "true") {&serverlogout($hash,$sid); return}; + + # Logausgabe + $logstr = "URL call: $url"; + &printlog($hash,$logstr,"4"); + $logstr = "JSON response: $myjson"; + &printlog($hash,$logstr,"4"); + + # dekodiere Response aus JSON Format + my $data = decode_json($myjson); + $success = $data->{'success'}; + + if ($success eq "true") { + # die URL konnte erfolgreich aufgerufen werden + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Record","Stop"); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + $hash->{STATE} = "off"; + + # bedingt Browseraktualisierung und Status der "Lampen" + { fhem "trigger $device on" } + + # Logausgabe + $logstr = "Camera $camname Recording stopped"; + &printlog($hash,$logstr,"3"); + } + else { + # die URL konnte nicht erfolgreich aufgerufen werden + # Errorcode aus JSON ermitteln + $errorcode = $data->{'error'}->{'code'}; + + # Fehlertext zum Errorcode ermitteln + my $error = &experror($hash,$errorcode); + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode",$errorcode); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + # Logausgabe + my $logstr = "ERROR - Stop Recording Camera $camname not possible. Errorcode: $errorcode - $error"; + &printlog($hash,$logstr,"1"); + } + + &serverlogout($hash,$sid); + + # Logausgabe + $logstr = "--- End Function camstop ---"; + &printlog($hash,$logstr,"5"); + +return; +} + +############################################################################ +#### Login auf SS Server und ermitteln _sid + +sub serverlogin { + my ($hash) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $username = $hash->{USERNAME}; + my $password = $hash->{PASSWORD}; + my $apiauthpath = $hash->{APIAUTHPATH}; + my $apiauthmaxver = $hash->{APIAUTHMAXVER}; + my $sid = ""; + my $logstr; + my $loginurl; + my $myjson; + my $success; + my $data; + my $errorcode; + my $error; + + + # Logausgabe + $logstr = "--- Begin Function serverlogin ---"; + &printlog($hash,$logstr,"5"); + + $loginurl = "http://$servername:$serverport/webapi/$apiauthpath?api=SYNO.API.Auth&version=$apiauthmaxver&method=Login&account=$username&passwd=$password&session=SurveillanceStation&format=sid"; + $myjson = get $loginurl; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$loginurl); + unless ($success eq "true") {return($sid, $success)}; + + # Logausgabe + $logstr = "URL call: $loginurl"; + &printlog($hash,$logstr,"4"); + $logstr = "JSON response: $myjson"; + &printlog($hash,$logstr,"4"); + + # die Response wird im JSON Format geliefert, Beispiel: {"data":{"sid":"zvJraLU.5Yg6E14A0MIN235902"},"success":true} + $data = decode_json($myjson); + $success = $data->{'success'}; + + # der login war erfolgreich + if ($success eq "true") { + $sid = $data->{'data'}->{'sid'}; + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "Login of User $username successful - SID: $sid"; + &printlog($hash,$logstr,"5"); + } else { + # Errorcode aus JSON ermitteln + $errorcode = $data->{'error'}->{'code'}; + + # Fehlertext zum Errorcode ermitteln + $error = &experrorauth($hash,$errorcode); + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode",$errorcode); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "ERROR - Login of User $username unsuccessful. Errorcode: $errorcode - $error"; + &printlog($hash,$logstr,"1"); + } + + # Logausgabe + $logstr = "--- End Function serverlogin ---"; + &printlog($hash,$logstr,"5"); + +return ($sid, $success); +} + + +############################################################################ +### Logout Session + +sub serverlogout { + # Übernahmewerte sind Session-id: $sid, $servername, $serverport + my ($hash,@sid) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $apiauthpath = $hash->{APIAUTHPATH}; + my $apiauthmaxver = $hash->{APIAUTHMAXVER}; + my $username = $hash->{USERNAME}; + my $sid = shift @sid; + my $logstr; + my $logouturl; + my $myjson; + my $success; + my $data; + my $errorcode; + my $error; + + + # Logausgabe + $logstr = "--- Begin Function serverlogout ---"; + &printlog($hash,$logstr,"5"); + + $logouturl = "http://$servername:$serverport/webapi/$apiauthpath?api=SYNO.API.Auth&version=$apiauthmaxver&method=Logout&session=SurveillanceStation&_sid=$sid"; + $myjson = get $logouturl; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$logouturl); + unless ($success eq "true") {return}; + + # Logausgabe + $logstr = "URL call: $logouturl"; + &printlog($hash,$logstr,"4"); + $logstr = "JSON response: $myjson"; + &printlog($hash,$logstr,"4"); + + # Response erfolgt im JSON Format der Art: {"success":true} + $data = decode_json($myjson); + $success = $data->{'success'}; + + if ($success eq "true") { + # die URL konnte erfolgreich aufgerufen werden + + # Logausgabe + $logstr = "Session of User $username quit - SID: $sid."; + &printlog($hash,$logstr,"5"); + } else { + # Errorcode aus JSON ermitteln + $errorcode = $data->{'error'}->{'code'}; + + # Fehlertext zum Errorcode ermitteln + $error = &experrorauth($hash,$errorcode); + + # Logausgabe + $logstr = "ERROR - Logout of User $username was not successful. Errorcode: $errorcode - $error"; + &printlog($hash,$logstr,"1"); + } + # Logausgabe + $logstr = "--- End Function serverlogout ---"; + &printlog($hash,$logstr,"5"); + +return; +} + +############################################################################### +### Test ob JSON-String empfangen wurde + +sub evaljson { + my ($hash,$myjson,$url)= @_; + my $success = "true"; + my $e; + my $logstr; + + eval {decode_json($myjson);1;} or do + { + $success = "false"; + $e = $@; + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","malformed JSON string received"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "URL call: $url"; + &printlog($hash,$logstr,"4"); + $logstr = "Output eval: ERROR - $e"; + &printlog($hash,$logstr,"3"); + }; +return($hash,$success); +} + + +############################################################################### +### Id für einen Kameranamen ermitteln + +sub getcamid { + # Übernahmewerte sind Session-id $sid, Kameraname: $camname, $servername, $serverport + my ($hash,@sid) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $camname = $hash->{CAMNAME}; + my $apicampath = $hash->{APICAMPATH}; + my $apicammaxver = $hash->{APICAMMAXVER}; + my $sid = shift @sid; + my $camid = ""; + my $logstr; + my $url; + my $myjson; + my $success; + my $data; + my $camcount; + my $i; + my %allcams; + my $name; + my $id; + my $errorcode; + my $error; + + # Logausgabe + $logstr = "--- Begin Function getcamid ---"; + &printlog($hash,$logstr,"5"); + + # einlesen aller Kameras + $url = "http://$servername:$serverport/webapi/$apicampath?api=SYNO.SurveillanceStation.Camera&version=$apicammaxver&method=List&session=SurveillanceStation&_sid=$sid"; + $myjson = get $url; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$url); + unless ($success eq "true") {return($camid,$success)}; + + # Logausgabe + $logstr = "URL call: $url"; + &printlog($hash,$logstr,"4"); + # $logstr = "JSON response: $myjson"; + # &printlog($hash,$logstr,"5"); + + # Response erfolgt im JSON Format der Art: {"success":true} + $data = decode_json($myjson); + $success = $data->{'success'}; + + + if ($success eq "true") { + # die Liste aller Kameras konnte ausgelesen werden + # Anzahl der definierten Kameras ist in Var "total" + $camcount = $data->{'data'}->{'total'}; + + $i = 0; + # Namen aller installierten Kameras mit Id's in Hash (Assoziatives Array) einlesen + %allcams = (); + while ($i < $camcount) { + $name = $data->{'data'}->{'cameras'}->[$i]->{'name'}; + $id = $data->{'data'}->{'cameras'}->[$i]->{'id'}; + $allcams{"$name"} = "$id"; + $i += 1; + } + # Ist der gesuchte Kameraname im Hash enhalten (in SS eingerichtet ?) + if (exists($allcams{$camname})) { + $camid = $allcams{$camname}; + } else { + # Kameraname nicht gefunden, id = "" + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","Kamera(ID) nicht gefunden"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "ERROR - Cameraname $camname wasn't found in Surveillance Station. Check Cameraname and Spelling."; + &printlog($hash,$logstr,"1"); + $success = "false"; + } + } + else { + # die Abfrage konnte nicht ausgeführt werden + # Errorcode aus JSON ermitteln + $errorcode = $data->{'error'}->{'code'}; + + # Fehlertext zum Errorcode ermitteln + $error = &experror($hash,$errorcode); + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode",$errorcode); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "ERROR - ID of Camera $camname couldn't be selected. Errorcode: $errorcode - $error"; + &printlog($hash,$logstr,"1"); + } + # Logausgabe + $logstr = "--- End Function getcamid ---"; + &printlog($hash,$logstr,"5"); + +return ($camid,$success); +} + +############################################################################## +### Auflösung Errorcodes bei Login / Logout + +sub experrorauth { + # Übernahmewerte sind $hash, $errorcode + my ($hash,@errorcode) = @_; + my $device = $hash->{NAME}; + my $errorcode = shift @errorcode; + my %errorlist; + my $error; + + # Aufbau der Errorcode-Liste (siehe Surveillance_Station_Web_API_v2.0.pdf) + %errorlist = ( + 100 => "Unknown error", + 101 => "The account parameter is not specified", + 102 => "API does not exist", + 400 => "Invalid user or password", + 401 => "Guest or disabled account", + 402 => "Permission denied", + 403 => "One time password not specified", + 404 => "One time password authenticate failed", + ); + unless (exists ($errorlist {$errorcode})) {$error = "Meldung nicht gefunden. (bitte API-Guide konsultieren)"; return ($error);} + + # Fehlertext aus Hash-Tabelle oben ermitteln + $error = $errorlist {$errorcode}; +return ($error); +} + +############################################################################## +### Auflösung Errorcodes SS API + +sub experror { + # Übernahmewerte sind $hash, $errorcode + my ($hash,@errorcode) = @_; + my $device = $hash->{NAME}; + my $errorcode = shift @errorcode; + my %errorlist; + my $error; + + + # Aufbau der Errorcode-Liste (siehe Surveillance_Station_Web_API_v2.0.pdf) + %errorlist = ( + 100 => "Unknown error", + 101 => "Invalid parameters", + 102 => "API does not exist", + 103 => "Method does not exist", + 104 => "This API version is not supporte", + 105 => "Insufficient user privilege", + 106 => "Connection time out", + 107 => "Multiple login detected", + 400 => "Execution failed", + 401 => "Parameter invalid", + 402 => "Camera disabled", + 403 => "Insufficient license", + 404 => "Codec acitvation failed", + 405 => "CMS server connection failed", + 407 => "CMS closed", + 410 => "Service is not enabled", + 412 => "Need to add license", + 413 => "Reach the maximum of platform", + 414 => "Some events not exist", + 415 => "message connect failed", + 417 => "Test Connection Error", + 418 => "Object is not exist / The VisualStation ID does not exist", + 419 => "Visualstation name repetition", + 439 => "Too many items selected", + ); + unless (exists ($errorlist {$errorcode})) {$error = "Meldung nicht gefunden. (bitte API-Guide konsultieren)"; return ($error);} + + # Fehlertext aus Hash-Tabelle oben ermitteln + $error = $errorlist {$errorcode}; + return ($error); +} + +############################################################################ +### Logausgabe + +sub printlog { + # Übernahmewerte ist $hash, $logstr, $verb (Verbose-Level) + my ($hash,$logstr,$verb)= @_; + my $name = $hash->{NAME}; + + Log3 ($name, $verb, "$name - $logstr"); +return; +} + +############################################################################ +### ist die angegebene URL erreichbar ? + +sub validurl { + # Übernahmewerte ist $hash + my ($hash)= @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $validurl = " "; + my $url; + my $logstr; + + # Seite zum testen + $url = "http://$servername:$serverport"; + + # Logausgabe + $logstr = "--- Begin Function validurl ---"; + &printlog($hash,$logstr,"5"); + + if (head($url)) { + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "Site http://$servername:$serverport reachable"; + &printlog($hash,$logstr,"5"); + $validurl = "true"; + + } else { + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","Site http://$servername:$serverport not reachable"); + readingsEndUpdate($hash, 1); + + #Logausgabe + $logstr = "ERROR - Site http://$servername:$serverport not reachable. Check Servername / IP-Adresse and Port"; + &printlog($hash,$logstr,"1"); + $validurl = "false"; + } + + # Logausgabe + $logstr = "--- End Function validurl ---"; + &printlog($hash,$logstr,"5"); + +return($validurl); +} + +############################################################################ +#### Ermittlung der Web API -Pfade und MaxVersionen + +sub getapisites { + # Übernahmewerte sind $servername, $serverport + my ($hash) = @_; + my $servername = $hash->{SERVERNAME}; + my $serverport = $hash->{SERVERPORT}; + my $success = " "; + my $apiauth; + my $apiextrec; + my $apicam; + my $logstr; + my $url; + my $myjson; + my $data; + my $apiauthpath; + my $apiauthmaxver; + my $apiextrecpath; + my $apiextrecmaxver; + my $apicampath; + my $apicammaxver; + my $error; + + + # benötigte API-Pfade, in der Abfrage-Url an Parameter "&query=" mit Komma getrennt angeben + $apiauth = "SYNO.API.Auth"; + $apiextrec = "SYNO.SurveillanceStation.ExternalRecording"; + $apicam = "SYNO.SurveillanceStation.Camera"; + + # Logausgabe + $logstr = "--- Begin Function getapisites ---"; + &printlog($hash,$logstr,"5"); + + # Abfrage der Eigenschaften von API SYNO.SurveillanceStation.ExternalRecording,$apicam + $url = "http://$servername:$serverport/webapi/query.cgi?api=SYNO.API.Info&method=Query&version=1&query=$apiauth,$apiextrec,$apicam"; + $myjson = get $url; + + # Evaluiere ob Daten im JSON-Format empfangen + ($hash, $success) = &evaljson($hash,$myjson,$url); + unless ($success eq "true") {return($hash,$success)}; + + # Logausgabe + $logstr = "URL call: $url"; + &printlog($hash,$logstr,"4"); + $logstr = "JSON response: $myjson"; + &printlog($hash,$logstr,"4"); + + # Response erfolgt im JSON Format + $data = decode_json($myjson); + $success = $data->{'success'}; + + + if ($success eq "true") { + + # Pfad und Maxversion von "SYNO.API.Auth" ermitteln + + $apiauthpath = $data->{'data'}->{$apiauth}->{'path'}; + # Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren + $apiauthpath =~ tr/_//d; + + # maximale Version ermitteln + $apiauthmaxver = $data->{'data'}->{$apiauth}->{'maxVersion'}; + + $logstr = "Path of $apiauth selected: $apiauthpath"; + &printlog($hash, $logstr,"4"); + $logstr = "MaxVersion of $apiauth selected: $apiauthmaxver"; + &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; + + # maximale Version ermitteln + $apiextrecmaxver = $data->{'data'}->{$apiextrec}->{'maxVersion'}; + + $logstr = "Path of $apiextrec selected: $apiextrecpath"; + &printlog($hash, $logstr,"4"); + $logstr = "MaxVersion of $apiextrec selected: $apiextrecmaxver"; + &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; + + # maximale Version ermitteln + $apicammaxver = $data->{'data'}->{$apicam}->{'maxVersion'}; + # um 1 verringern - Fehlerprävention + if (defined $apicammaxver) {$apicammaxver -= 1}; + + $logstr = "Path of $apicam selected: $apicampath"; + &printlog($hash, $logstr,"4"); + $logstr = "MaxVersion of $apicam: $apicammaxver"; + &printlog($hash, $logstr,"4"); + + # ermittelte Werte in $hash einfügen + $hash->{APIAUTHPATH} = $apiauthpath; + $hash->{APIAUTHMAXVER} = $apiauthmaxver; + $hash->{APIEXTRECPATH} = $apiextrecpath; + $hash->{APIEXTRECMAXVER} = $apiextrecmaxver; + $hash->{APICAMPATH} = $apicampath; + $hash->{APICAMMAXVER} = $apicammaxver; + + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error","none"); + readingsEndUpdate($hash, 1); + + } else { + + # Fehlertext setzen + $error = "couldn't call API-Infosite"; + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + # Logausgabe + $logstr = "ERROR - the API-Query couldn't be executed successfully"; + &printlog($hash,$logstr,"1"); + } + # Logausgabe + $logstr = "--- End Function getapisites ---"; + &printlog($hash,$logstr,"5"); + +return($hash,$success); +} + + + +1; + +=pod +=begin html + + +

SSCam

+
    +
    + Prerequisites

    + This module uses other CPAN-modules LWP and JSON. Consider to install these packages (Debian: libwww-perl, libjson-perl).
    + You also need to add an user in Synology DSM as member of Administrators group for using in this module.

    + + + + Define +
      + define <name> SSCam <Servername> <Port> <Username> <Password> <Cameraname> <RecordTime>
      +
      + Defines a new camera device for SSCam. At first the devices have to be set up and operable in Synology Surveillance Station 7.0 and above.

      + Using this Modul you are able to start and stop recordings of cameras defined in Synology Surveillance Station.
      + The recordings are stored in Synology Surveillance Station Database
      + and managed like the other (normal) recordings defined by Surveillance Station rules.

      + + The parameter describes the minimum Recordtime. Dependend on other factors like the performance of you Synology Diskstation and
      + Surveillance Station the effective Recordtime could be longer. + + The Modul SSCam ist based on functions of Synology Surveillance Station API.
      + Please refer the Web API Guide.

      + + At the time only HTTP-Protokoll is supported to call Synology DS.

      + +Known Issues

      + + Sometimes the Error 105 "Insuffucient privileges" occurs because of problems with Synology User check implementation.
      + Until Synology is solving that problem I have implemented a workaround.
      + Please consider it if you will get some entries like "Insuffucient privileges" in FHEM-Logfile.
      +

      + + The parameters are in detail: +
      +
      + + + + + + + + + +
      name :the name of the new device to use in FHEM
      Servername :the name or IP-address of Synology Surveillance Station Host. If Servername is used, make sure the name can be discovered in network by DNS
      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
      Cameraname :Cameraname as defined in Synology Surveillance Station, Spaces are not allowed in Cameraname !
      Recordtime :it's the time for recordings
      + +

      + + Examples: +
      +      define CamDoor SSCAM ds1.myds.ds 5000 apiuser apipass Door 10      
      +    
      +  
    +
    + + Set +
      + + There are two options for set.

      + +
      +    "on"    :   triggers start of record.
      +    "off"   :   triggers stop of record.
      +
      + +
    +
    + + + Attributes +
      + + Different Verbose-Level are supported.
      + Those are in detail:
      + +
      +    0   -   Start/Stop-Event will be logged
      +    1   -   Error messages will be logged
      +    3   -   sended commands will be logged
      +    4   -   sended and received informations will be logged
      +    5   -   further outputs will be logged due to error-analyses
      +
      + +

      + +
    • readingFnAttributes
    • +
    +
    +
+ + +=end html +=begin html_DE + + +

SSCam

+
    +
    +Vorbereitung

    + Dieses Modul nutzt weitere CPAN Module LWP und JSON. Bitte darauf achten diese Pakete zu installieren. (Debian: libwww-perl, libjson-perl).
    + Im DSM muß ebenfalls ein Nutzer als Mitglied der Administratorgruppe angelegt sein. Die Daten werden beim define des Gerätes benötigt.

    + + + Define +
      + define <name> SSCam <Servername> <Port> <Username> <Password> <Cameraname> <RecordTime>
      +
      + + Definiert eine neues Kamera für SSCam. Zunächst muß diese Kamera in der Synology Surveillance Station 7.0 oder höher eingebunden sein und entsprechend funktionieren.

      + Mit diesem Modul kann die Aufnahme einer in der Synology Surveillance Station definierten Kamera gestartet oder gestoppt werden.
      + Die Aufnahmen stehen in der Synology Surveillance Station Datenbank zur Verfügung und unterliegen wie jede andere Aufnahme den in der Synology Surveillance Station eingestellten Regeln.

      + + Der Parameter beschreibt die Mindestaufnahmezeit. Abhängig von Faktoren wie Performance der Synology Diskstation und der Surveillance Station
      + kann die effektive Aufnahmezeit geringfügig länger sein.

      + + Das Modul SSCam basiert auf Funktionen der Synology Surveillance Station API.
      + Weitere Inforamtionen unter: Web API Guide.

      + + Es müssen die Perl-Module LWP (Debian: libwww-perl) und JSON (Debian: libjson-perl) installiert sein. + Momentan wird nur das HTTP-Protokoll unterstützt um die Web-Services der Synology DS aufzurufen.

      + +Bekannte Probleme

      + + Manchmal taucht der Fehler 105 "Insuffucient privileges" auf wegen eines Problems in dem Standard Synology User check auf.
      + Bis Synology diesen Fehler gefixt hat, habe ich einen Workaround eingebaut.
      + Bitte diesen Umstand berücksichtigen wenn im FHEM-Logfile etliche Einträge der Form "Insuffucient privileges" auftauchen.
      +

      + + Die Parameter sind im Einzelnen: +
      +
      + + + + + + + + + +
      name :der Name des neuen Gerätes in FHEM
      Servername :der Name oder die IP-Addresse des Synology Surveillance Station Host. Wenn der Servername benutzt wird ist sicherzustellen dass der Name im Netzwerk aufgelöst werden kann.
      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
      Cameraname :Kameraname wie er in der Synology Surveillance Station angegeben ist. Leerzeichen im Namen sind nicht erlaubt !
      Recordtime :die definierte Aufnahmezeit
      + +

      + + Examples: +
      +      define CamTür SSCAM ds1.myds.ds 5000 apiuser apipass Tür 10      
      +    
      +  
    + + + Set +
      + + Es gibt zwei Optionen für "Set".

      + +
      +    "on"    :   startet die Aufnahme.
      +    "off"   :   stoppt die Aufnahme.
      +
      + +
    +
    + + + Attributes +
      + + 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   -   weitere Ausgaben zur Fehleranalyse werden geloggt
      +
      + +

      + +
    • readingFnAttributes
    • +
    +
    +
+ +=end html_DE +=cut +