on-for-timer [rectime]" verwendet -> dann [rectime] nutzen,
# sonst Attribut "rectime" wenn es gesetzt ist, falls nicht -> "RECTIME_DEF"
if (defined($hash->{HELPER}{RECTIME_TEMP})) {
$rectime = delete $hash->{HELPER}{RECTIME_TEMP};
}
else
{
$rectime = AttrVal($name, "rectime",undef) ? AttrVal($name, "rectime",undef) : $hash->{HELPER}{RECTIME_DEF};
}
# Verarbeitung der asynchronen Rückkehrdaten aus sub "camop_nonbl"
if ($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
{
$logstr = "error while requesting ".$param->{url}." - $err";
&printlog($hash,$logstr,"1"); # Eintrag fürs Log
$logstr = "--- End Function cam: $OpMode nonblocking with error ---";
&printlog($hash,$logstr,"4");
readingsSingleUpdate($hash, "Error", $err, 1); # Readings erzeugen
# ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
$hash->{HELPER}{ACTIVE} = "off";
return;
}
elsif ($myjson ne "") # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
{
$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
($hash, $success) = &evaljson($hash,$myjson,$param->{url});
unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)};
$data = decode_json($myjson);
$success = $data->{'success'};
if ($success)
{
# Kameraoperation entsprechend "OpMode" war erfolgreich
# Logausgabe decodierte JSON Daten
$logstr = "JSON returned: ". Dumper $data;
&printlog($hash,$logstr,"4");
if ($OpMode eq "Start")
{
# bedingt Browseraktualisierung und Status der "Lampen"
$hash->{STATE} = "on";
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Record","Start");
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash, 1);
# Logausgabe
$logstr = $rectime != "0" ? "Camera $camname Recording with Recordtime $rectime"."s started" : "Camera $camname endless Recording started - stop it manually or by stop-command !";
&printlog($hash,$logstr,"2");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
# Logausgabe
$logstr = "Time for Recording is set to: $rectime";
&printlog($hash,$logstr,"4");
if ($rectime != "0") {
# Stop der Aufnahme nach Ablauf $rectime, wenn rectime = 0 -> endlose Aufnahme
InternalTimer(gettimeofday()+$rectime, "camstoprec", $hash, 0);
}
}
elsif ($OpMode eq "Stop")
{
# bedingt Browseraktualisierung und Status der "Lampen"
$hash->{STATE} = "off";
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Record","Stop");
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash, 1);
# RemoveInternalTimer($hash);
# Logausgabe
$logstr = "Camera $camname Recording stopped";
&printlog($hash,$logstr,"2");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
}
elsif ($OpMode eq "Snap")
{
# ein Schnapschuß wurde aufgenommen
# falls Aufnahme noch läuft -> STATE = on setzen
if (ReadingsVal("$name", "Record", "Stop") eq "Start") {
$hash->{STATE} = "on";
}
else
{
$hash->{STATE} = "off";
}
$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,"2");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
}
elsif ($OpMode eq "Enable")
{
# Kamera wurde aktiviert, sonst kann nichts laufen -> "off"
$hash->{STATE} = "off";
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Availability","enabled");
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash, 1);
# Logausgabe
$logstr = "Camera $camname has been enabled successfully";
&printlog($hash,$logstr,"2");
$logstr = "--- End Function cam: $OpMode nonblocking ---";
&printlog($hash,$logstr,"4");
}
elsif ($OpMode eq "Disable")
{
# Kamera wurde deaktiviert
$hash->{STATE} = "disabled";
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Availability","disabled");
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","none");
readingsEndUpdate($hash, 1);
# Logausgabe
$logstr = "Camera $camname has been disabled successfully";
&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
{
# 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 - Operation $OpMode of Camera $camname was not successful. Errorcode: $errorcode - $error";
&printlog($hash,$logstr,"1");
$logstr = "--- End Function cam: $OpMode nonblocking with error ---";
&printlog($hash,$logstr,"4");
# ausgeführte Funktion ist abgebrochen, Freigabe Funktionstoken
$hash->{HELPER}{ACTIVE} = "off";
return;
}
# logout wird ausgeführt, Rückkehr wird mit "logout_nonbl" verarbeitet
# Logausgabe
$logstr = "--- Begin Function logout nonblocking ---";
&printlog($hash,$logstr,"4");
$httptimeout = AttrVal($name, "httptimeout",undef) ? AttrVal($name, "httptimeout",undef) : "4";
# Logausgabe
$logstr = "HTTP-Call will be done with httptimeout-Value: $httptimeout s";
&printlog($hash,$logstr,"5");
$url = "http://$serveraddr:$serverport/webapi/$apiauthpath?api=$apiauth&version=$apiauthmaxver&method=Logout&_sid=$sid";
$param = {
url => $url,
timeout => $httptimeout,
hash => $hash,
method => "GET",
header => "Accept: application/json",
callback => \&logout_nonbl
};
HttpUtils_NonblockingGet ($param);
}
}
###################################################################################
#### Rückkehr aus Funktion camret_nonbl,
#### check Funktion logout
sub logout_nonbl ($) {
my ($param, $err, $myjson) = @_;
my $hash = $param->{hash};
my $username = $hash->{HELPER}{USERNAME};
my $sid = $hash->{HELPER}{SID};
my $data;
my $logstr;
my $success;
my $error;
my $errorcode;
if($err ne "") # wenn ein Fehler bei der HTTP Abfrage aufgetreten ist
{
$logstr = "error while requesting ".$param->{url}." - $err";
&printlog($hash,$logstr,"1"); # Eintrag fürs Log
$logstr = "--- End Function logout nonblocking with error ---";
&printlog($hash,$logstr,"4");
readingsSingleUpdate($hash, "Error", $err, 1); # Readings erzeugen
}
elsif($myjson ne "") # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes)
{
$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
($hash, $success) = &evaljson($hash,$myjson,$param->{url});
unless ($success) {$logstr = "Data returned: ".$myjson; &printlog($hash,$logstr,"4"); $hash->{HELPER}{ACTIVE} = "off"; return($hash,$success)};
$data = decode_json($myjson);
$success = $data->{'success'};
if ($success)
{
# die Logout-URL konnte erfolgreich aufgerufen werden
# Logausgabe decodierte JSON Daten
$logstr = "JSON returned: ". Dumper $data;
&printlog($hash,$logstr,"4");
# Session-ID aus Helper-hash löschen
delete $hash->{HELPER}{SID};
# Logausgabe
$logstr = "Session of User $username has ended - SID: $sid has been deleted";
&printlog($hash,$logstr,"4");
$logstr = "--- End Function logout nonblocking ---";
&printlog($hash,$logstr,"4");
}
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");
$logstr = "--- End Function logout nonblocking with error ---";
&printlog($hash,$logstr,"4");
}
}
# ausgeführte Funktion ist erledigt (auch wenn logout nicht erfolgreich), Freigabe Funktionstoken
$hash->{HELPER}{ACTIVE} = "off";
return;
}
#############################################################################################################################
######### Ende Kameraoperationen mit NonblockingGet (nicht blockierender HTTP-Call) #############
#############################################################################################################################
#############################################################################################################################
######### Hilfsroutinen #############
#############################################################################################################################
###############################################################################
### Test ob JSON-String empfangen wurde
sub evaljson {
my ($hash,$myjson,$url)= @_;
my $success = 1;
my $e;
my $logstr;
eval {decode_json($myjson);1;} or do
{
$success = 0;
$e = $@;
# Setreading
readingsBeginUpdate($hash);
readingsBulkUpdate($hash,"Errorcode","none");
readingsBulkUpdate($hash,"Error","malformed JSON string received");
readingsEndUpdate($hash, 1);
};
return($hash,$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 = "Message for Errorode $errorcode not found. Please turn to Synology Web API-Guide."; 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 supported",
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 activation 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",
419 => "Visualstation name repetition",
439 => "Too many items selected",
);
unless (exists ($errorlist {$errorcode})) {$error = "Message for Errorode $errorcode not found. Please turn to Synology Web API-Guide."; 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;
}
1;
=pod
=begin html
SSCam
Using this Module you are able to operate with cameras which are defined in Synology Surveillance Station (SVS).
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
- Retrieval of Camera Properties (Polling)
The recordings and snapshots will be stored in Synology Surveillance Station (SVS) 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.
Prerequisites
This module uses the CPAN-module JSON. Please consider to install this package (Debian: libjson-perl).
You don't need to install LWP anymore, because of SSCam is completely using the nonblocking functions of HttpUtils respectively HttpUtils_NonblockingGet now.
You also need to add an user in Synology DSM as member of Administrators group.
Define
define <name> SSCam <ServerAddr> <Port> <Username> <Password> <Cameraname>
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.
The Modul SSCam ist based on functions of Synology Surveillance Station API.
Please refer the Web API Guide.
At present only HTTP-protocol is supported to call Synology DS.
The parameters are in detail:
name: | the name of the new device to use in FHEM |
ServerAddr: | 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 |
Cameraname: | Cameraname as defined in Synology Surveillance Station, Spaces are not allowed in Cameraname ! |
Examples:
define CamCP SSCAM 192.168.2.20 5000 apiuser apipass Carport
When a new Camera is defined, as a start the recordingtime of 15 seconds will be assigned to the device.
Using the attribute "rectime" you can adapt the recordingtime for every camera individually.
The value of "0" for rectime will lead to an endless recording which has to be stopped by a "set <name> off" command.
Due to a Log-Entry with a hint to that circumstance will be written.
If the attribute "rectime" would be deleted again, the default-value for recording-time (15s) become active.
With command "set <name> on [rectime]" a temporary recordingtime is determinded which would overwrite the dafault-value of recordingtime
and the attribute "rectime" (if it is set) uniquely.
In that case the command "set <name> on 0" leads also to an endless recording.
If you have specified a pre-recording time in SVS it will be considered too.
HTTP-Timeout Settings
All functions of the SSCam-Module are using HTTP-Calls to the SVS Web API.
The Default-Value of the HTTP-Timeout amounts 4 seconds. You can set the Attribute "httptimeout" > 0 to adjust the value as needed in your technical environment.
Set
Currently there are the following options for "Set <name> ..." :
"on [rectime]": | starts a recording. The recording will be stopped automatically after a period of [rectime] |
| if [rectime] = 0 an endless recording will be started |
"off" : | stopps a running recording manually or using other events (e.g. with at, notify) |
"snap": | triggers a snapshot of the relevant camera and store it into Synology Surveillance Station |
"disable": | deactivates a camera in Synology Surveillance Station |
"enable": | activates a camera in Synology Surveillance Station |
Examples for simple Start/Stop a Recording:
set <name> on [rectime] | starts a recording of camera <name>, stops automatically after [rectime] (default 15s or defined by attribute) |
set <name> off | stops the recording of camera <name> |
A snapshot can be triggered with:
set <name> snap
Subsequent some Examples for taking snapshots:
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.
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.
define he1_snap_3 notify CamHE1:Record.*on define h3 at +*{3}00:00:02 set CamHE1 snap
Release of 2 Snapshots of camera "CamHE1" at intervals of 6 seconds after the motion sensor "MelderHE1" has sent an event,
can be done e.g. with following notify-command:
define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
The ID of the last snapshot will be displayed as value of variable "LastSnapId" in the device-Readings.
For
deactivating / activating a list of cameras or all cameras using a Regex-expression, subsequent two examples using "at":
define a13 at 21:46 set CamCP1,CamFL,CamHE1,CamTER disable (enable)
define a14 at 21:46 set Cam.* disable (enable)
A bit more convenient is it to use a dummy-device for enable/disable all available cameras in Surveillance Station.
At first the Dummy will be created.
define allcams dummy
attr allcams eventMap on:enable off:disable
attr allcams room Cams
attr allcams webCmd enable:disable
With combination of two created notifies, respectively one for "enable" and one for "diasble", you are able to switch all cameras into "enable" or "disable" state at the same time if you set the dummy to "enable" or "disable".
define all_cams_disable notify allcams:.*off set CamCP1,CamFL,CamHE1,CamTER disable
attr all_cams_disable room Cams
define all_cams_enable notify allcams:on set CamCP1,CamFL,CamHE1,CamTER enable
attr all_cams_enable room Cams
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-Properties:
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.
Because of that if HTTP-Timeout (pls. refer Attribut "httptimeout") is set to 4 seconds, the theoretical processing time couldn't be higher than 80 seconds.
Considering a safety margin, in that example you shouldn't set the polling interval lower than 160 seconds.
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.
- 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
- httptimeout - Timeout-Value of HTTP-Calls to Synology Surveillance Station, Default: 4 seconds (if httptimeout = "0" or not set)
- 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
- rectime - the determined recordtime when a recording starts. If rectime = 0 an endless recording will be started. If it isn't defined, the default recordtime of 15s is activated
- verbose
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 | all outputs will be logged for error-analyses. Caution: a lot of data could be written into logfile ! |
further Attributes:
- readingFnAttributes
=end html
=begin html_DE
SSCam
Mit diesem Modul können Operationen von in der Synology Surveillance Station (SVS) definierten Kameras ausgeführt werden.
Zur Zeit werden folgende Funktionen unterstützt:
- Start einer Aufnahme
- Stop einer Aufnahme (per Befehl bzw. automatisch nach Ablauf der Aufnahmedauer)
- Aufnehmen eines Schnappschusses und Ablage in der Synology Surveillance Station
- Deaktivieren einer Kamera in Synology Surveillance Station
- Aktivieren einer Kamera in Synology Surveillance Station
- Abfrage von Kameraeigenschaften (Polling)
Die Aufnahmen stehen in der Synology Surveillance Station (SVS) 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 gespeichert und dann gelöscht.
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
Dieses Modul nutzt das CPAN Module JSON. Bitte darauf achten dieses Paket zu installieren. (Debian: libjson-perl).
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.
Im DSM muß ebenfalls ein Nutzer als Mitglied der Administratorgruppe angelegt sein. Die Daten werden bei der Definition des Gerätes benötigt.
Definition
define <name> SSCam <ServerAddr> <Port> <Username> <Password> <Kameraname in SVS>
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.
Das Modul SSCam basiert auf Funktionen der Synology Surveillance Station API.
Weitere Informationen unter: Web API Guide.
Momentan wird nur das HTTP-Protokoll unterstützt um die Web-Services der Synology DS aufzurufen.
Die Parameter beschreiben im Einzelnen:
name: | der Name des neuen Gerätes in FHEM |
ServerAddr: | 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 |
Cameraname: | Kameraname wie er in der Synology Surveillance Station angegeben ist. Leerzeichen im Namen sind nicht erlaubt ! |
Beispiel:
define CamCP SSCAM 192.168.2.20 5000 apiuser apipass Carport
Wird eine neue Kamera definiert, wird diesem Device zunächst eine Standardaufnahmedauer von 15 zugewiesen.
Über das Attribut "rectime" kann die Aufnahmedauer für jede Kamera individuell angepasst werden. Der Wert "0" für "rectime" führt zu einer Endlosaufnahme, die durch "set <name> off" wieder gestoppt werden muß.
Ein Logeintrag mit einem entsprechenden Hinweis auf diesen Umstand wird geschrieben.
Wird das Attribut "rectime" gelöscht, greift wieder der Default-Wert (15s) für die Aufnahmedauer.
Mit dem Befehl "set <name> on [rectime]" wird die Aufnahmedauer temporär festgelegt und überschreibt einmalig sowohl den Defaultwert als auch den Wert des gesetzten Attributs "rectime".
Auch in diesem Fall führt "set <name> on 0" zu einer Daueraufnahme.
Eine eventuell in der SVS eingestellte Dauer der Voraufzeichnung wird weiterhin berücksichtigt.
HTTP-Timeout setzen
Alle Funktionen dieses Moduls verwenden HTTP-Aufrufe gegenüber der SVS Web API.
Der Standardwert für den HTTP-Timeout beträgt 4 Sekunden. Durch Setzen des Attributes "httptimeout" > 0 kann dieser Wert bei Bedarf entsprechend den technischen Gegebenheiten angepasst werden.
Set
Es gibt zur Zeit folgende Optionen für "Set <name> ...":
"on [rectime]": | startet eine Aufnahme. Die Aufnahme wird automatisch nach Ablauf der Zeit [rectime] gestoppt. |
| Mit rectime = 0 wird eine Daueraufnahme gestartet die durch "set <name> off" wieder gestoppt werden muß. |
"off" : | stoppt eine laufende Aufnahme manuell oder durch die Nutzung anderer Events (z.B. über at, notify) |
"snap": | löst einen Schnappschuß der entsprechenden Kamera aus und speichert ihn in der Synology Surveillance Station |
"disable": | deaktiviert eine Kamera in der Synology Surveillance Station |
"enable": | aktiviert eine Kamera in der Synology Surveillance Station |
Beispiele für einfachen Start/Stop einer Aufnahme:
set <name> on [rectime] | startet die Aufnahme der Kamera <name>, automatischer Stop der Aufnahme nach Ablauf der Zeit [rectime] (default 15s oder wie im Attribut "rectime" angegeben) |
set <name> off | stoppt die Aufnahme der Kamera <name> |
Ein Schnappschuß kann ausgelöst werden mit:
set <name> snap
Nachfolgend einige Beispiele für die Auslösung von Schnappschüssen.
Soll eine Reihe von Schnappschüssen ausgelöst werden wenn eine Aufnahme startet, kann das z.B. durch folgendes notify geschehen.
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.
define he1_snap_3 notify CamHE1:Record.*Start define h3 at +*{3}00:00:02 set CamHE1 snap
Triggern von 2 Schnappschüssen der Kamera "CamHE1" im Abstand von 6 Sekunden nachdem der Bewegungsmelder "MelderHE1" einen Event gesendet hat,
kann z.B. mit folgendem notify geschehen:
define he1_snap_2 notify MelderHE1:on.* define h2 at +*{2}00:00:06 set CamHE1 snap
Es wird die ID des letzten Snapshots als Wert der Variable "LastSnapId" in den Readings der Kamera ausgegeben.
Um eine Liste von Kameras oder alle Kameras (mit Regex) zum Beispiel um 21:46 zu deaktivieren / zu aktivieren zwei Beispiele mit at:
define a13 at 21:46 set CamCP1,CamFL,CamHE1,CamTER disable (enable)
define a14 at 21:46 set Cam.* disable (enable)
Etwas komfortabler gelingt das Schalten aller Kameras über einen Dummy. Zunächst wird der Dummy angelegt:
define allcams dummy
attr allcams eventMap on:enable off:disable
attr allcams room Cams
attr allcams webCmd enable:disable
Durch Verknüpfung mit zwei angelegten notify, jeweils ein notify für "enable" und "disable", kann man durch Schalten des Dummys auf "enable" bzw. "disable" alle Kameras auf einmal aktivieren bzw. deaktivieren.
define all_cams_disable notify allcams:.*off set CamCP1,CamFL,CamHE1,CamTER disable
attr all_cams_disable room Cams
define all_cams_enable notify allcams:on set CamCP1,CamFL,CamHE1,CamTER enable
attr all_cams_enable room Cams
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.
Das eingestellte Intervall sollte nicht kleiner sein als die Summe aller HTTP-Verarbeitungszeiten.
Pro Pollingaufruf und Kamera werden ca. 10 - 20 Http-Calls gegen die Surveillance Station abgesetzt.
Bei einem eingestellten HTTP-Timeout (siehe Attribut) "httptimeout") von 4 Sekunden kann die theoretische Verarbeitungszeit Zeit nicht höher als 80 Sekunden betragen.
In dem Beispiel sollte man das Pollingintervall mit einem Sicherheitszuschlag auf nicht weniger 160 Sekunden setzen.
Ein praktikabler Richtwert könnte zwischen 600 - 1800 (s) liegen.
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.
- 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
- httptimeout - Timeout-Wert für HTTP-Aufrufe zur Synology Surveillance Station, Default: 4 Sekunden (wenn httptimeout = "0" oder nicht gesetzt)
- 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
- rectime - festgelegte Aufnahmezeit wenn eine Aufnahme gestartet wird. Mit rectime = 0 wird eine Endlosaufnahme gestartet. Ist "rectime" nicht gesetzt, wird der Defaultwert von 15s verwendet.
- 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! |
weitere Attribute:
- readingFnAttributes
=end html_DE
=cut