2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-02-07 16:59:18 +00:00

49_SSCam: function "snap" for taking snapshots added,

fixed a bug that functions may impact each other

git-svn-id: https://svn.fhem.de/fhem/trunk@10210 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
nasseeder1 2015-12-20 07:44:08 +00:00
parent 2c49fceb67
commit 236fef3880
2 changed files with 449 additions and 223 deletions

View File

@ -1,5 +1,7 @@
# 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 "snap" for taking snapshots added,
- bugfix: 49_SSCam: fixed a bug that functions may impact each other
- feature: 31_MilightDevice: Add restoreAtStart attribute so group devices (slot 'A') do not restore state by default at startup
- bugfix: 30_MilightBridge/31_MilightDevice: Fix startup restore. Fix crash on invalid hostname.
- feature: 30_pilight_xyz: possibility to change IO-Device (IODEV)

View File

@ -4,7 +4,7 @@
# 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
# This Modul is 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.
@ -25,6 +25,8 @@
######################################################################################################
# Versionshistorie:
#
# 1.3 19.12.2015 function "snap" for taking snapshots added,
# fixed a bug that functions may impact each other
# 1.2 14.12.2015 improve usage of verbose-modes
# 1.1 13.12.2015 use of InternalTimer instead of fhem(sleep)
# 1.0 12.12.2015 changed completly to HttpUtils_NonblockingGet for calling websites nonblocking,
@ -54,9 +56,7 @@ use warnings;
use HttpUtils;
sub
SSCam_Initialize($)
{
sub SSCam_Initialize($) {
# die Namen der Funktionen, die das Modul implementiert und die fhem.pl aufrufen soll
my ($hash) = @_;
$hash->{DefFn} = "SSCam_Define";
@ -68,7 +68,7 @@ SSCam_Initialize($)
$hash->{AttrList} =
"webCmd ".
$readingFnAttributes;
}
sub SSCam_Define {
@ -105,11 +105,16 @@ sub SSCam_Define {
$hash->{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 !
$hash->{HELPER}{APIAUTH} = "SYNO.API.Auth";
$hash->{HELPER}{APIEXTREC} = "SYNO.SurveillanceStation.ExternalRecording";
$hash->{HELPER}{APICAM} = "SYNO.SurveillanceStation.Camera";
$hash->{HELPER}{APIINFO} = "SYNO.API.Info"; # Info-Seite für alle API's, einzige statische Seite !
$hash->{HELPER}{APIAUTH} = "SYNO.API.Auth";
$hash->{HELPER}{APIEXTREC} = "SYNO.SurveillanceStation.ExternalRecording";
$hash->{HELPER}{APICAM} = "SYNO.SurveillanceStation.Camera";
$hash->{HELPER}{APISNAPSHOT} = "SYNO.SurveillanceStation.SnapShot";
# Anfangswerte setzen
$hash->{HELPER}{ACTIVE} = "off";
readingsSingleUpdate($hash,"Record","Stop",0);
return undef;
}
@ -126,64 +131,149 @@ sub SSCam_Attr {
sub SSCam_Set {
my ( $hash, @a ) = @_;
return "\"set X\" needs at least an argument" if ( @a < 2 );
my $device = shift @a;
my $name = shift @a;
my $opt = shift @a;
my %SSCam_sets = (
on => "on",
off => "off");
my $camname = $hash->{CAMNAME};
on => "on",
off => "off",
snap => "snap"
);
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 {
# Aufnahme starten
if ($opt eq "on")
{
$logstr = "Recording of Camera $camname should be started now";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Start";
&getapisites_nonbl($hash);
}
# Aufnahme stoppen
if ($opt eq "off")
{
$logstr = "Recording of Camera $camname should be stopped now";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Stop";
&getapisites_nonbl($hash);
}
if(!defined($SSCam_sets{$opt}))
{
@cList = keys %SSCam_sets;
return "Unknown argument $opt, choose one of " . join(" ", @cList);
}
else
{
if ($opt eq "on")
{
&camstartrec($hash);
}
elsif ($opt eq "off")
{
&camstoprec($hash);
}
elsif ($opt eq "snap")
{
&camsnap($hash);
}
}
}
#############################################################################################################################
######### OpMode-Startroutinen #############
######### #############
######### $hash->{HELPER}{ACTIVE} = "on" -> eine Routine läuft, Start anderer Routine erst wenn "off". #############
######### $hash->{HELPER}{ACTIVE} = "off" -> keine andere Routine läuft, sofortiger Start möglich #############
#############################################################################################################################
###############################################################################
### Kamera Aufnahme starten
sub camstartrec ($) {
my ($hash) = @_;
my $camname = $hash->{CAMNAME};
my $name = $hash->{NAME};
my $logstr;
if ($hash->{HELPER}{ACTIVE} ne "on" and ReadingsVal("$name", "Record", "Start") ne "Start") {
# Aufnahme starten
$logstr = "Recording of Camera $camname should be started now";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Start";
$hash->{HELPER}{ACTIVE} = "on";
&getapisites_nonbl($hash);
}
else
{
InternalTimer(gettimeofday()+0.1, "camstartrec", $hash, 0);
}
}
###############################################################################
### Kamera Aufnahme stoppen
sub camstoprec ($) {
my ($hash) = @_;
my $camname = $hash->{CAMNAME};
my $name = $hash->{NAME};
my $logstr;
if ($hash->{HELPER}{ACTIVE} ne "on" and ReadingsVal("$name", "Record", "Stop") ne "Stop") {
# Aufnahme stoppen
$logstr = "Recording of Camera $camname should be stopped now";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Stop";
$hash->{HELPER}{ACTIVE} = "on";
&getapisites_nonbl($hash);
}
else
{
InternalTimer(gettimeofday()+0.1, "camstoprec", $hash, 0);
}
}
###############################################################################
### Kamera Schappschuß aufnehmen
sub camsnap ($) {
my ($hash) = @_;
my $camname = $hash->{CAMNAME};
my $name = $hash->{NAME};
my $logstr;
if ($hash->{HELPER}{ACTIVE} ne "on") {
# einen Schnappschuß aufnehmen
$logstr = "Take Snapshot of Camera $camname";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Snap";
$hash->{HELPER}{ACTIVE} = "on";
&getapisites_nonbl($hash);
}
else
{
InternalTimer(gettimeofday()+0.1, "camsnap", $hash, 0);
}
}
#############################################################################################################################
####### Begin Kameraoperationen mit NonblockingGet (nicht blockierender HTTP-Call) #######
####### #######
####### Ablauflogik: #######
####### #######
####### #######
####### OpMode-Startroutine #######
####### | #######
####### getapisites_nonbl -> login_nonbl -> getcamid_nonbl -> camop_nonbl -> camret_nonbl -> logout_nonbl #######
####### | | #######
####### Start Stop #######
####### | #######
####### OpMode #######
####### #######
#############################################################################################################################
sub getapisites_nonbl {
my ($hash) = @_;
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $apiinfo = $hash->{HELPER}{APIINFO}; # Info-Seite für alle API's, einzige statische Seite !
my $apiauth = $hash->{HELPER}{APIAUTH}; # benötigte API-Pfade für Funktionen,
my $apiextrec = $hash->{HELPER}{APIEXTREC}; # in der Abfrage-Url an Parameter "&query="
my $apicam = $hash->{HELPER}{APICAM}; # mit Komma getrennt angeben
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $apiinfo = $hash->{HELPER}{APIINFO}; # Info-Seite für alle API's, einzige statische Seite !
my $apiauth = $hash->{HELPER}{APIAUTH}; # benötigte API-Pfade für Funktionen,
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 $logstr;
my $url;
my $param;
@ -194,7 +284,7 @@ sub getapisites_nonbl {
&printlog($hash,$logstr,"4");
# URL zur Abfrage der Eigenschaften von API SYNO.SurveillanceStation.ExternalRecording,$apicam
$url = "http://$servername:$serverport/webapi/query.cgi?api=$apiinfo&method=Query&version=1&query=$apiauth,$apiextrec,$apicam";
$url = "http://$servername:$serverport/webapi/query.cgi?api=$apiinfo&method=Query&version=1&query=$apiauth,$apiextrec,$apicam,$apitakesnap";
$param = {
url => $url,
@ -216,15 +306,16 @@ sub getapisites_nonbl {
sub login_nonbl ($) {
my ($param, $err, $myjson) = @_;
my $hash = $param->{hash};
my $device = $hash->{NAME};
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $username = $hash->{USERNAME};
my $password = $hash->{HELPER}{PASSWORD};
my $apiauth = $hash->{HELPER}{APIAUTH};
my $apiextrec = $hash->{HELPER}{APIEXTREC};
my $apicam = $hash->{HELPER}{APICAM};
my $hash = $param->{hash};
my $device = $hash->{NAME};
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $username = $hash->{USERNAME};
my $password = $hash->{HELPER}{PASSWORD};
my $apiauth = $hash->{HELPER}{APIAUTH};
my $apiextrec = $hash->{HELPER}{APIEXTREC};
my $apicam = $hash->{HELPER}{APICAM};
my $apitakesnap = $hash->{HELPER}{APISNAPSHOT};
my $data;
my $logstr;
my $url;
@ -235,6 +326,8 @@ sub login_nonbl ($) {
my $apiextrecmaxver;
my $apicampath;
my $apicammaxver;
my $apitakesnappath;
my $apitakesnapmaxver;
my $error;
# Verarbeitung der asynchronen Rückkehrdaten aus sub "getapisites_nonbl"
@ -269,92 +362,100 @@ sub login_nonbl ($) {
$logstr = "JSON returned: ". Dumper $data;
&printlog($hash,$logstr,"4");
# Pfad und Maxversion von "SYNO.API.Auth" ermitteln
# Pfad und Maxversion von "SYNO.API.Auth" ermitteln
$apiauthpath = $data->{'data'}->{$apiauth}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apiauthpath =~ tr/_//d;
$apiauthpath = $data->{'data'}->{$apiauth}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apiauthpath =~ tr/_//d;
$apiauthmaxver = $data->{'data'}->{$apiauth}->{'maxVersion'};
# 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");
$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
# Pfad und Maxversion von "SYNO.SurveillanceStation.ExternalRecording" ermitteln
$apiextrecpath = $data->{'data'}->{$apiextrec}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apiextrecpath =~ tr/_//d;
$apiextrecmaxver = $data->{'data'}->{$apiextrec}->{'maxVersion'};
$apiextrecpath = $data->{'data'}->{$apiextrec}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apiextrecpath =~ tr/_//d;
$logstr = "Path of $apiextrec selected: $apiextrecpath";
&printlog($hash, $logstr,"4");
$logstr = "MaxVersion of $apiextrec selected: $apiextrecmaxver";
&printlog($hash, $logstr,"4");
# maximale Version ermitteln
$apiextrecmaxver = $data->{'data'}->{$apiextrec}->{'maxVersion'};
# Pfad und Maxversion von "SYNO.SurveillanceStation.Camera" ermitteln
$apicampath = $data->{'data'}->{$apicam}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apicampath =~ tr/_//d;
$apicammaxver = $data->{'data'}->{$apicam}->{'maxVersion'};
# um 1 verringern - Fehlerprävention
if (defined $apicammaxver) {$apicammaxver -= 1};
$logstr = "Path of $apiextrec selected: $apiextrecpath";
&printlog($hash, $logstr,"4");
$logstr = "MaxVersion of $apiextrec selected: $apiextrecmaxver";
&printlog($hash, $logstr,"4");
$logstr = "Path of $apicam selected: $apicampath";
&printlog($hash, $logstr,"4");
$logstr = "MaxVersion of $apicam (optimized): $apicammaxver";
&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 (optimized): $apicammaxver";
&printlog($hash, $logstr,"4");
# ermittelte Werte in $hash einfügen
$hash->{HELPER}{APIAUTHPATH} = $apiauthpath;
$hash->{HELPER}{APIAUTHMAXVER} = $apiauthmaxver;
$hash->{HELPER}{APIEXTRECPATH} = $apiextrecpath;
$hash->{HELPER}{APIEXTRECMAXVER} = $apiextrecmaxver;
$hash->{HELPER}{APICAMPATH} = $apicampath;
$hash->{HELPER}{APICAMMAXVER} = $apicammaxver;
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash,1);
# Logausgabe
$logstr = "--- End Function getapisites nonblocking ---";
&printlog($hash,$logstr,"4");
}
else
{
# Fehlertext setzen
$error = "couldn't call API-Infosite";
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error",$error);
readingsEndUpdate($hash, 1);
# Pfad und Maxversion von "SYNO.SurveillanceStation.SnapShot" ermitteln
$apitakesnappath = $data->{'data'}->{$apitakesnap}->{'path'};
# Unterstriche im Ergebnis z.B. "_______entry.cgi" eleminieren
$apitakesnappath =~ tr/_//d;
$apitakesnapmaxver = $data->{'data'}->{$apitakesnap}->{'maxVersion'};
$logstr = "Path of $apitakesnap selected: $apitakesnappath";
&printlog($hash, $logstr,"4");
$logstr = "MaxVersion of $apitakesnap: $apitakesnapmaxver";
&printlog($hash, $logstr,"4");
# Logausgabe
$logstr = "ERROR - the API-Query couldn't be executed successfully";
&printlog($hash,$logstr,"1");
$logstr = "--- End Function getapisites nonblocking with error ---";
&printlog($hash,$logstr,"4");
return;
}
# ermittelte Werte in $hash einfügen
$hash->{HELPER}{APIAUTHPATH} = $apiauthpath;
$hash->{HELPER}{APIAUTHMAXVER} = $apiauthmaxver;
$hash->{HELPER}{APIEXTRECPATH} = $apiextrecpath;
$hash->{HELPER}{APIEXTRECMAXVER} = $apiextrecmaxver;
$hash->{HELPER}{APICAMPATH} = $apicampath;
$hash->{HELPER}{APICAMMAXVER} = $apicammaxver;
$hash->{HELPER}{APITAKESNAPPATH} = $apitakesnappath;
$hash->{HELPER}{APITAKESNAPMAXVER} = $apitakesnapmaxver;
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash,1);
# Logausgabe
$logstr = "--- End Function getapisites nonblocking ---";
&printlog($hash,$logstr,"4");
}
else
{
# ausgeführte Funktion ist erledigt
$hash->{HELPER}{ACTIVE} = "off";
# 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");
$logstr = "--- End Function getapisites nonblocking with error ---";
&printlog($hash,$logstr,"4");
return;
}
}
# Login und SID ermitteln
@ -455,6 +556,9 @@ sub getcamid_nonbl ($) {
}
else
{
# ausgeführte Funktion ist erledigt
$hash->{HELPER}{ACTIVE} = "off";
# Errorcode aus JSON ermitteln
$errorcode = $data->{'error'}->{'code'};
@ -507,15 +611,18 @@ sub getcamid_nonbl ($) {
sub camop_nonbl ($) {
my ($param, $err, $myjson) = @_;
my $hash = $param->{hash};
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $camname = $hash->{CAMNAME};
my $apiextrec = $hash->{HELPER}{APIEXTREC};
my $apiextrecpath = $hash->{HELPER}{APIEXTRECPATH};
my $apiextrecmaxver = $hash->{HELPER}{APIEXTRECMAXVER};
my $sid = $hash->{HELPER}{SID};
my $OpMode = $hash->{OPMODE};
my $hash = $param->{hash};
my $servername = $hash->{SERVERNAME};
my $serverport = $hash->{SERVERPORT};
my $camname = $hash->{CAMNAME};
my $apiextrec = $hash->{HELPER}{APIEXTREC};
my $apiextrecpath = $hash->{HELPER}{APIEXTRECPATH};
my $apiextrecmaxver = $hash->{HELPER}{APIEXTRECMAXVER};
my $apitakesnap = $hash->{HELPER}{APISNAPSHOT};
my $apitakesnappath = $hash->{HELPER}{APITAKESNAPPATH};
my $apitakesnapmaxver = $hash->{HELPER}{APITAKESNAPMAXVER};
my $sid = $hash->{HELPER}{SID};
my $OpMode = $hash->{OPMODE};
my $url;
my $camid;
my $data;
@ -607,6 +714,9 @@ sub camop_nonbl ($) {
else
{
# die Abfrage konnte nicht ausgeführt werden
# ausgeführte Funktion ist erledigt
$hash->{HELPER}{ACTIVE} = "off";
# Errorcode aus JSON ermitteln
$errorcode = $data->{'error'}->{'code'};
@ -641,6 +751,11 @@ sub camop_nonbl ($) {
# 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\"";
}
elsif ($OpMode eq "Snap")
{
# ein Schnappschuß wird gemacht und in SS gespeichert, Rückkehr wird mit "camret_nonbl" verarbeitet
$url = "http://$servername:$serverport/webapi/$apitakesnappath?api=\"$apitakesnap\"&dsId=0&method=\"TakeSnapshot\"&version=\"$apitakesnapmaxver\"&camId=$camid&blSave=true&_sid=\"$sid\"";
}
$param = {
url => $url,
@ -681,6 +796,7 @@ sub camret_nonbl ($) {
my $success;
my $error;
my $errorcode;
my $snapid;
# Verarbeitung der asynchronen Rückkehrdaten aus sub "camop_nonbl"
if ($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
@ -717,6 +833,7 @@ sub camret_nonbl ($) {
if ($OpMode eq "Start")
{
# bedingt Browseraktualisierung und Status der "Lampen"
$hash->{STATE} = "on";
# Setreading
@ -725,30 +842,25 @@ sub camret_nonbl ($) {
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash, 1);
# Logausgabe
$logstr = "Camera $camname with Recordtime $rectime"."s started";
&printlog($hash,$logstr,"3");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
# Generiert das Ereignis "on", bedingt Browseraktualisierung und Status der "Lampen" wenn kein longpoll=1
# { fhem "trigger $device on" }
# Logausgabe
$logstr = "Time for Recording is set to: $rectime";
&printlog($hash,$logstr,"4");
# Stop der Aufnahme wird eingeleitet
$logstr = "Recording of Camera $camname should be stopped in $rectime seconds";
&printlog($hash,$logstr,"4");
$hash->{OPMODE} = "Stop";
InternalTimer(gettimeofday()+$rectime, "getapisites_nonbl", $hash, 0);
# Stop der Aufnahme nach Ablauf $rectime
InternalTimer(gettimeofday()+$rectime, "camstoprec", $hash, 0);
}
elsif ($OpMode eq "Stop")
{
# bedingt Browseraktualisierung und Status der "Lampen"
$hash->{STATE} = "off";
# Setreading
@ -769,6 +881,25 @@ sub camret_nonbl ($) {
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
}
elsif ($OpMode eq "Snap")
{
# ein Schnapschuß wurde aufgenommen
$snapid = $data->{data}{'id'};
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsBulkUpdate($hash,"LastSnapId",$snapid);
readingsEndUpdate($hash, 1);
# Logausgabe
$logstr = "Snapshot of Camera $camname has been done successfully";
&printlog($hash,$logstr,"3");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
}
}
else
{
@ -790,6 +921,10 @@ sub camret_nonbl ($) {
&printlog($hash,$logstr,"1");
$logstr = "--- End Function cam: $OpMode nonblocking with error ---";
&printlog($hash,$logstr,"4");
# ausgeführte Funktion ist erledigt
$hash->{HELPER}{ACTIVE} = "off";
return;
}
@ -829,7 +964,9 @@ sub logout_nonbl ($) {
my $error;
my $errorcode;
# Verarbeitung der asynchronen Rückkehrdaten aus sub "camop_nonbl"
# ausgeführte Funktion ist erledigt
$hash->{HELPER}{ACTIVE} = "off";
if($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
{
$logstr = "error while requesting ".$param->{url}." - $err";
@ -843,7 +980,7 @@ sub logout_nonbl ($) {
{
$logstr = "URL-Call: ".$param->{url};
&printlog($hash,$logstr,"4");
# An dieser Stelle die Antwort parsen / verarbeiten mit $myjson
# Evaluiere ob Daten im JSON-Format empfangen wurden
@ -984,7 +1121,7 @@ sub experror {
414 => "Some events not exist",
415 => "message connect failed",
417 => "Test Connection Error",
418 => "Object is not exist / The VisualStation ID does not exist",
418 => "Object is not exist",
419 => "Visualstation name repetition",
439 => "Too many items selected",
);
@ -1017,36 +1154,44 @@ return;
<h3>SSCam</h3>
<ul>
<br>
Using this Modul you are able to start and stop recordings of cameras which are defined in Synology Surveillance Station. <br>
The recordings are stored in Synology Surveillance Station and are managed like the other (normal) recordings defined by Surveillance Station rules.<br>
Using this Module you are able to operate with cameras which are defined in Synology Surveillance Station. <br>
At present the following functions are available: <br><br>
<li>Start a Rocording</li>
<li>Stop a Recording</li>
<li>Trigger a Snapshot </li><br>
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.<br>
For example the recordings are stored for a defined time in Surveillance Station and will be deleted after that period.<br><br>
<b> Prerequisites </b> <br><br>
This module uses the CPAN-module JSON. Consider to install these package (Debian: libjson-perl).<br>
You don't need to install LWP anymore, because of SSCam is now completely using the nonblocking functions of HttpUtils respectively HttpUtils_NonblockingGet. <br>
This module uses the CPAN-module JSON. Please consider to install this package (Debian: libjson-perl).<br>
You don't need to install LWP anymore, because of SSCam is completely using the nonblocking functions of HttpUtils respectively HttpUtils_NonblockingGet now. <br>
You also need to add an user in Synology DSM as member of Administrators group for using in this module. <br><br>
<a name="SCamdefine"></a>
<b>Define</b>
<ul>
<br>
<code>define &lt;name&gt; SSCam &lt;Servername&gt; &lt;Port&gt; &lt;Username&gt; &lt;Password&gt; &lt;Cameraname&gt; &lt;RecordTime&gt;</code><br>
<br>
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. <br><br>
The parameter "RecordTime" describes the minimum Recordtime. Dependend on other factors like the performance of you Synology Diskstation and <br>
The parameter &lt;RecordTime&gt; describes the minimum Recordtime. Dependend on other factors like the performance of your Synology Diskstation and <br>
Surveillance Station the effective Recordtime could be longer.
The Modul SSCam ist based on functions of Synology Surveillance Station API. <br>
Please refer the <a href="http://global.download.synology.com/download/Document/DeveloperGuide/Surveillance_Station_Web_API_v2.0.pdf">Web API Guide</a>. <br><br>
At present only HTTP-Protokoll is supported to call Synology DS. <br><br>
At present only HTTP-protocol is supported to call Synology DS. <br><br>
The parameters are in detail:
<br>
<br>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>name :</td><td>the name of the new device to use in FHEM</td></tr>
<tr><td>Servername :</td><td>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 </td></tr>
<tr><td>Port :</td><td>the Port Synology surveillance Station Host, normally 5000 (HTTP only)</td></tr>
@ -1058,43 +1203,80 @@ return;
<br><br>
Examples:
<b>Examples:</b>
<pre>
define CamDoor SSCAM ds1.myds.ds 5000 apiuser apipass Door 10
</pre>
</ul>
<br>
<a name="SSCamset"></a>
<b>Set </b>
<a name="SSCamset"></a>
<b>Set </b>
<ul>
There are two options for set.<br><br>
"on" : starts a recording. The recording will be stopped after the period given by the value of &lt;RecordTime&gt; in device definition.
<pre>
Command: set &lt;name&gt on
</pre>
"off" : stops a running recording manually or other event (for example by using <a href="#at">at</a>, <a href="#notify">notify</a> or others).
<pre>
Command: set &lt;name&gt off
</pre>
There are the following options for "Set" at present: <br><br>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>"on": </td><td>starts a recording. The recording will be stopped automatically after a period of &lt;RecordTime&gt; as determined</td></tr>
<tr><td>"off" : </td><td>stopps a running recording manually or using other events (e.g. with at, notify)</td></tr>
<tr><td>"snap": </td><td>triggers a snapshot of the relevant camera and store it into Synology Surveillance Station</td></tr>
</table>
<br><br>
<b>Example</b> for simple Start/Stop of Recording: <br><br>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>set &lt;name&gt; on </td><td>starts a recording of camera &lt;name&gt;, stops automatically after the time &lt;RecordTime&gt; as determined in device-definition </td></tr>
<tr><td>set &lt;name&gt; off </td><td>stops the recording of camera &lt;name&gt;</td></tr>
</table>
<br>
A snapshot can be triggered with:
<pre>
set &lt;name&gt; snap
</pre>
Subsequent some <b>Examples</b> for taking snapshots: <br><br>
If a serial of snapshots should be released, it can be done using the following notify command.
For the example a serial of snapshots are to be triggerd if the recording of a camera starts. <br>
When the recording of camera "CamHE1" starts (Attribut event-on-change-reading -> "Record" has to be set), then 3 snapshots at intervals of 2 seconds are triggered.
<pre>
define he1_snap_3 notify CamHE1:Record.*Start define h3 at +*{3}00:00:02 set CamHE1 snap
</pre>
Release of 2 Snapshots of camera "CamHE1" at intervals of 6 seconds after the motion sensor "MelderHE1" has sent an event, <br>
can be done e.g. with following notify-command:
<pre>
define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
</pre>
The ID of the last snapshot will be displayed as value of variable "LastSnapId" in the device-Readings. <br><br>
</ul>
<br>
<a name="SSCamattr"></a>
<b>Attributes</b>
<a name="SSCamattr"></a>
<b>Attributes</b>
<ul>
Different Verbose-Level are supported.<br>
Those are in detail:<br>
Those are in detail:<br><br>
<pre>
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 - all outputs will be logged for error-analyses. Please use it carefully, a lot of data could be written into the logfile !
</pre>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> 0 </td><td> Start/Stop-Event will be logged </td></tr>
<tr><td> 1 </td><td> Error messages will be logged <td></tr>
<tr><td> 3 </td><td> sended commands will be logged <td></tr>
<tr><td> 4 </td><td> sended and received informations will be logged <td></tr>
<tr><td> 5 </td><td> all outputs will be logged for error-analyses. <b>Caution:</b> a lot of data could be written into the logfile ! <td></tr>
<table>
<br><br>
@ -1111,30 +1293,37 @@ return;
<h3>SSCam</h3>
<ul>
<br>
Mit diesem Modul kann die Aufnahme von in der Synology Surveillance Station definierten Kameras gestartet bzw. gestoppt werden. <br>
Mit diesem Modul können Operationen von in der Synology Surveillance Station definierten Kameras ausgeführt werden. <br>
Zur Zeit werden folgende Funktionen unterstützt: <br><br>
<li>Start einer Aufnahme</li>
<li>Stop einer Aufnahme</li>
<li>Aufnehmen eines Schnappschusses und Ablage in der Synology Surveillance Station </li><br>
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. <br>
So werden zum Beispiel die Aufnahmen entsprechend ihrer Archivierungsfrist gehalten und dann gelöscht.<br><br>
So werden zum Beispiel die Aufnahmen entsprechend ihrer Archivierungsfrist gehalten und dann gelöscht. <br><br>
<b>Vorbereitung </b> <br><br>
Dieses Modul nutzt das CPAN Module JSON. Bitte darauf achten dieses Paket zu installieren. (Debian: libjson-perl). <br>
Das CPAN-Modul LWP wird für SSCam nicht mehr benötigt. Das Modul verwendet für HTTP-Calls die nichtblockierenden Funktionen von HttpUtils bzw. HttpUtils_NonblockingGet. <br>
Im DSM muß ebenfalls ein Nutzer als Mitglied der Administratorgruppe angelegt sein. Die Daten werden beim define des Gerätes benötigt.<br><br>
Im DSM muß ebenfalls ein Nutzer als Mitglied der Administratorgruppe angelegt sein. Die Daten werden bei der Definition des Gerätes benötigt.<br><br>
<a name="SCamdefine"></a>
<b>Define</b>
<a name="SCamdefine"></a>
<b>Define</b>
<ul>
<br>
<code>define &lt;name&gt; SSCam &lt;Servername&gt; &lt;Port&gt; &lt;Username&gt; &lt;Password&gt; &lt;Cameraname&gt; &lt;RecordTime&gt;</code><br>
<br>
Definiert eine neue Kamera für SSCam. Zunächst muß diese Kamera in der Synology Surveillance Station 7.0 oder höher eingebunden sein und entsprechend funktionieren.<br><br>
Der Parameter "RecordTime" beschreibt die Mindestaufnahmezeit. Abhängig von Faktoren wie Performance der Synology Diskstation und der Surveillance Station <br>
Der Parameter "&lt;RecordTime&gt; beschreibt die Mindestaufnahmezeit. Abhängig von Faktoren wie Performance der Synology Diskstation und der Surveillance Station <br>
kann die effektive Aufnahmezeit geringfügig länger sein.<br><br>
Das Modul SSCam basiert auf Funktionen der Synology Surveillance Station API. <br>
Weitere Inforamtionen unter: <a href="http://global.download.synology.com/download/Document/DeveloperGuide/Surveillance_Station_Web_API_v2.0.pdf">Web API Guide</a>. <br><br>
Weitere Informationen unter: <a href="http://global.download.synology.com/download/Document/DeveloperGuide/Surveillance_Station_Web_API_v2.0.pdf">Web API Guide</a>. <br><br>
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. <br><br>
Die Parameter beschreiben im Einzelnen:
@ -1142,56 +1331,91 @@ return;
<br>
<table>
<tr><td>name :</td><td>der Name des neuen Gerätes in FHEM</td></tr>
<tr><td>Servername :</td><td>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.</td></tr>
<tr><td>Port :</td><td>der Port des Synology Surveillance Station Host. Normalerweise ist das 5000 (nur HTTP)</td></tr>
<tr><td>Username :</td><td>Name des in der Diskstation definierten Nutzers. Er muß ein Mitglied der Admin-Gruppe sein</td></tr>
<tr><td>Password :</td><td>das Passwort des Nutzers</td></tr>
<tr><td>Cameraname :</td><td>Kameraname wie er in der Synology Surveillance Station angegeben ist. Leerzeichen im Namen sind nicht erlaubt !</td></tr>
<tr><td>Recordtime :</td><td>die definierte Aufnahmezeit</td></tr>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>name: </td><td>der Name des neuen Gerätes in FHEM</td></tr>
<tr><td>Servername: </td><td>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.</td></tr>
<tr><td>Port: </td><td>der Port des Synology Surveillance Station Host. Normalerweise ist das 5000 (nur HTTP)</td></tr>
<tr><td>Username: </td><td>Name des in der Diskstation definierten Nutzers. Er muß ein Mitglied der Admin-Gruppe sein</td></tr>
<tr><td>Password: </td><td>das Passwort des Nutzers</td></tr>
<tr><td>Cameraname: </td><td>Kameraname wie er in der Synology Surveillance Station angegeben ist. Leerzeichen im Namen sind nicht erlaubt !</td></tr>
<tr><td>Recordtime: </td><td>die definierte Aufnahmezeit</td></tr>
</table>
<br><br>
Beispiel:
<b>Beispiel:</b>
<pre>
define CamTür SSCAM ds1.myds.ds 5000 apiuser apipass Tür 10
</pre>
</ul>
<a name="SSCamset"></a>
<b>Set </b>
<ul>
Es gibt zur Zeit zwei Optionen für "Set".<br><br>
<a name="SSCamset"></a>
<b>Set </b>
<ul>
Es gibt zur Zeit folgende Optionen für "Set": <br><br>
"on" : startet eine Aufnahme. Die Aufnahme wird automatisch nach Ablauf der Zeit &lt;RecordTime&gt; gestoppt.
<pre>
Befehl: set &lt;name&gt on
</pre>
"off" : stoppt eine laufende Aufnahme manuell oder durch die Nutzung anderer Events (z.B. durch <a href="#at">at</a>, <a href="#notify">notify</a> oder andere)
<pre>
Befehl: set &lt;name&gt off
</pre>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>"on": </td><td>startet eine Aufnahme. Die Aufnahme wird automatisch nach Ablauf der Zeit &lt;RecordTime&gt; gestoppt.</td></tr>
<tr><td>"off" : </td><td>stoppt eine laufende Aufnahme manuell oder durch die Nutzung anderer Events (z.B. über at, notify)</td></tr>
<tr><td>"snap": </td><td>löst einen Schnappschuß der entsprechenden Kamera aus und speichert ihn in der Synology Surveillance Station</td></tr>
</table>
<br><br>
<b>Beispiele</b> für einfachen Start/Stop einer Aufnahme: <br><br>
</ul>
<table>
<colgroup> <col width=15%> <col width=85%> </colgroup>
<tr><td>set &lt;name&gt; on </td><td>startet die Aufnahme der Kamera &lt;name&gt;, automatischer Stop der Aufnahme nach Ablauf der Zeit &lt;RecordTime&gt; wie im define angegeben</td></tr>
<tr><td>set &lt;name&gt; off </td><td>stoppt die Aufnahme der Kamera &lt;name&gt;</td></tr>
</table>
<br>
<a name="SSCamattr"></a>
<b>Attributes</b>
Ein <b>Schnappschuß</b> kann ausgelöst werden durch:
<pre>
set &lt;name&gt; snap
</pre>
Nachfolgend einige <b>Beispiele</b> für die Auslösung von Schnappschüssen. <br><br>
Soll eine Reihe von Schnappschüssen ausgelöst werden wenn eine Aufnahme startet, kann das z.B. durch folgendes notify geschehen. <br>
Sobald der Start der Kamera CamHE1 ausgelöst wird (Attribut event-on-change-reading -> "Record" setzen), werden abhängig davon 3 Snapshots im Abstand von 2 Sekunden getriggert.
<pre>
define he1_snap_3 notify CamHE1:Record.*Start define h3 at +*{3}00:00:02 set CamHE1 snap
</pre>
Triggern von 2 Schnappschüssen der Kamera "CamHE1" im Abstand von 6 Sekunden nachdem der Bewegungsmelder "MelderHE1" einen Event gesendet hat, <br>
kann z.B. mit folgendem notify geschehen:
<pre>
define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
</pre>
Es wird die ID des letzten Snapshots als Wert der Variable "LastSnapId" in den Readings der Kamera ausgegeben. <br><br>
</ul>
<br>
<a name="SSCamattr"></a>
<b>Attributes</b>
<ul>
Es werden verschiedene Verbose-Level unterstützt.<br>
Dies sind im Einzelnen:<br>
Dies sind im Einzelnen:<br><br>
<pre>
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: unter Umständen sehr viele Daten im Logfile !
</pre>
<table>
<colgroup> <col width=5%> <col width=95%> </colgroup>
<tr><td> 0 </td><td> Start/Stop-Ereignisse werden geloggt </td></tr>
<tr><td> 1 </td><td> Fehlermeldungen werden geloggt </td></tr>
<tr><td> 3 </td><td> gesendete Kommandos werden geloggt </td></tr>
<tr><td> 4 </td><td> gesendete und empfangene Daten werden geloggt </td></tr>
<tr><td> 5 </td><td> alle Ausgaben zur Fehleranalyse werden geloggt. <b>ACHTUNG:</b> möglicherweise werden sehr viele Daten in das Logfile geschrieben! </td></tr>
</table>
<br><br>