From bd8b9ed197a4ec935cd8fe0be6d76299dfb0aa2b Mon Sep 17 00:00:00 2001 From: nasseeder1 Date: Sun, 27 Jan 2019 15:36:11 +0000 Subject: [PATCH] 49_SSCam: contrib 8.7.0 git-svn-id: https://svn.fhem.de/fhem/trunk@18433 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/contrib/DS_Starter/49_SSCam.pm | 492 +++++++++++++++++++++------- 1 file changed, 382 insertions(+), 110 deletions(-) diff --git a/fhem/contrib/DS_Starter/49_SSCam.pm b/fhem/contrib/DS_Starter/49_SSCam.pm index 9b6d4b91c..304430591 100644 --- a/fhem/contrib/DS_Starter/49_SSCam.pm +++ b/fhem/contrib/DS_Starter/49_SSCam.pm @@ -1,5 +1,5 @@ ######################################################################################################################## -# $Id: 49_SSCam.pm 18216 2019-01-11 14:20:30Z DS_Starter $ +# $Id: 49_SSCam.pm 18411 2019-01-25 13:17:13Z DS_Starter $ ######################################################################################################################### # 49_SSCam.pm # @@ -47,7 +47,9 @@ use Encode; # Versions History intern our %SSCam_vNotesIntern = ( - "8.6.1" => "20.01.2019 time format in readings and galleries depends from global language attribute, minor bug fixes ", + "8.7.0" => "27.01.2019 send recording by email ", + "8.6.2" => "25.01.2019 fix version numbering ", + "8.6.1" => "21.01.2019 time format in readings and galleries depends from global language attribute, minor bug fixes ", "8.6.0" => "20.01.2019 new attribute snapReadingRotate ", "8.5.0" => "17.01.2019 SVS device has \"snapCams\" command ", "8.4.5" => "15.01.2019 fix event generation after request snapshots ", @@ -120,7 +122,10 @@ our %SSCam_vNotesIntern = ( # Versions History extern our %SSCam_vNotesExtern = ( - "8.6.1" => "20.01.2019 new attribute \"snapReadingRotate\" to activate versioning of snap data, ". + "8.7.0" => "27.01.2019 SMTP Email delivery of recordings implemented. You can send a recording after it was created subsequentely ". + "with the integrated Email client. You have to store SMTP credentials with \"smtpcredentials\" before. ", + "8.6.2" => "25.01.2019 fix version numbering ", + "8.6.1" => "21.01.2019 new attribute \"snapReadingRotate\" to activate versioning of snap data, ". "time format in readings and galleries depends from global language attribute ", "8.5.0" => "17.01.2019 SVS device has \"snapCams\" command. Now are able to take snapshots of all defined cameras and may ". "optionally send them alltogether by Email.", @@ -128,7 +133,7 @@ our %SSCam_vNotesExtern = ( "<Mitteilung-Text>\"]\". Now you are able to trigger several number of ". "snapshots by only one snap-command. The triggered snapshots can be shipped alltogether with the internal email client. ", "8.3.0" => "02.01.2019 new get command \"saveRecording\"", - "8.2.0" => "02.01.2019 SMTP Email delivery of snapshots implemented. You can send snapshots after it is created subsequentely ". + "8.2.0" => "02.01.2019 SMTP Email delivery of snapshots implemented. You can send snapshots after it was created subsequentely ". "with the integrated Email client. You have to store SMTP credentials with \"smtpcredentials\" before. ", "8.1.0" => "19.12.2018 Tooltipps added to camera device control buttons.", "8.0.0" => "18.12.2018 HLS is integrated using sscam_hls.js in Streaming device types \"hls\". HLS streaming is now available ". @@ -360,6 +365,7 @@ sub SSCam_Initialize($) { "snapReadingRotate:0,1,2,3,4,5,6,7,8,9,10 ". "pollnologging:1,0 ". "debugactivetoken:1,0 ". + "recEmailTxt ". "rectime ". "recextend:1,0 ". "noQuotesForSID:1,0 ". @@ -399,7 +405,7 @@ sub SSCam_Define($@) { $hash->{SERVERADDR} = $serveraddr; $hash->{SERVERPORT} = $serverport; $hash->{CAMNAME} = $camname; - $hash->{VERSION} = (reverse sort(keys %SSCam_vNotesIntern))[0]; + $hash->{VERSION} = (SSCam_sortVersion("desc",keys %SSCam_vNotesIntern))[0]; $hash->{MODEL} = ($camname =~ m/^SVS$/i)?"SVS":"CAM"; # initial, CAM wird später ersetzt durch CamModel $hash->{PROTOCOL} = $proto; $hash->{COMPATIBILITY} = $compstat; # getestete SVS-version Kompatibilität @@ -777,15 +783,30 @@ sub SSCam_Set($@) { if ($opt eq "on" && SSCam_IsModelCam($hash)) { if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";} - if (defined($prop)) { - unless ($prop =~ /^\d+$/) { return " The Value for \"$opt\" is not valid. Use only figures 0-9 without decimal places !";} + if (defined($prop) && $prop =~ /^\d+$/) { $hash->{HELPER}{RECTIME_TEMP} = $prop; } + + my $emtxt = AttrVal($name, "recEmailTxt", ""); + my $at = join(" ",@a); + if($at =~ /recEmailTxt:/) { + $at =~ m/.*recEmailTxt:"(.*)".*/i; + $emtxt = $1; + } + + if($emtxt) { + # Recording soll nach Erstellung per Email versendet werden + # recEmailTxt muss sein: subject => , body => + if (!$hash->{SMTPCREDENTIALS}) {return "Due to \"recEmailTxt\" is set, you want to send recordings by email but SMTP credentials are not set - make sure you've set credentials with \"set $name smtpcredentials username password\"";} + $hash->{HELPER}{SMTPRECMSG} = $emtxt; + } + SSCam_camstartrec($hash); } elsif ($opt eq "off" && SSCam_IsModelCam($hash)) { if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";} - SSCam_camstoprec($hash); + my $emtxt = $hash->{HELPER}{SMTPRECMSG}?delete $hash->{HELPER}{SMTPRECMSG}:""; + SSCam_camstoprec("$name:$emtxt"); } elsif ($opt eq "snap" && SSCam_IsModelCam($hash)) { if (!$hash->{CREDENTIALS}) {return "Credentials of $name are not set - make sure you've set it with \"set $name credentials username password\"";} @@ -1513,7 +1534,7 @@ sub SSCam_Get($@) { } } $i = 0; - foreach my $key (reverse sort(keys %hs)) { + foreach my $key (SSCam_sortVersion("desc",keys %hs)) { $val0 = $hs{$key}; $ret .= sprintf("$key $val0" ); $ret .= ""; @@ -1538,7 +1559,7 @@ sub SSCam_Get($@) { $ret .= ""; $ret .= ""; $i = 0; - foreach my $key (reverse sort(keys %SSCam_vNotesExtern)) { + foreach my $key (SSCam_sortVersion("desc",keys %SSCam_vNotesExtern)) { ($val0,$val1) = split(/\s/,$SSCam_vNotesExtern{$key},2); $ret .= sprintf("$key $val0 $val1" ); $ret .= ""; @@ -1755,7 +1776,8 @@ sub SSCam_initonboot ($) { # check ob alle Recordings = "Stop" nach Reboot -> sonst stoppen if (ReadingsVal($hash->{NAME}, "Record", "Stop") eq "Start") { Log3($name, 2, "$name - Recording of $hash->{CAMNAME} seems to be still active after FHEM restart - try to stop it now"); - SSCam_camstoprec($hash); + my $emtxt = ""; + SSCam_camstoprec("$name:$emtxt"); } # Konfiguration der Synology Surveillance Station abrufen @@ -2056,9 +2078,10 @@ sub SSCam_camstartrec ($) { # Kamera Aufnahme stoppen ############################################################################### sub SSCam_camstoprec ($) { - my ($hash) = @_; - my $camname = $hash->{CAMNAME}; - my $name = $hash->{NAME}; + my ($str) = @_; + my ($name,$emtxt) = split(":",$str); + my $hash = $defs{$name}; + my $camname = $hash->{CAMNAME}; my $errorcode; my $error; @@ -2093,12 +2116,16 @@ sub SSCam_camstoprec ($) { if ($hash->{HELPER}{ACTIVE} eq "off") { $hash->{OPMODE} = "Stop"; $hash->{HELPER}{LOGINRETRIES} = 0; - + if($emtxt) { + $hash->{HELPER}{CANSENDREC} = 1; # Versand Aufnahme soll erfolgen + $hash->{HELPER}{SMTPRECMSG} = $emtxt; # Text für Email-Versand + } + SSCam_setActiveToken($hash); SSCam_getapisites($hash); } else { - InternalTimer(gettimeofday()+0.3, "SSCam_camstoprec", $hash, 0); + InternalTimer(gettimeofday()+0.3, "SSCam_camstoprec", "$name:$emtxt", 0); } } @@ -2241,7 +2268,7 @@ sub SSCam_camsnap($) { $hash->{HELPER}{SNAPNUM} = $num if($num); # Gesamtzahl der auszulösenden Schnappschüsse $hash->{HELPER}{SNAPLAG} = $lag if($lag); # Zeitverzögerung zwischen zwei Schnappschüssen $hash->{HELPER}{SNAPNUMCOUNT} = $ncount if($ncount); # Restzahl der auszulösenden Schnappschüsse (wird runtergezählt) - $hash->{HELPER}{SMTPMSG} = $emtxt if($emtxt); # alternativer Text für Email-Versand + $hash->{HELPER}{SMTPMSG} = $emtxt if($emtxt); # Text für Email-Versand SSCam_setActiveToken($hash); SSCam_getapisites($hash); @@ -2252,6 +2279,52 @@ sub SSCam_camsnap($) { } } +############################################################################### +# Kamera gemachte Aufnahme abrufen +############################################################################### +sub SSCam_getrec($) { + my ($hash) = @_; + my $camname = $hash->{CAMNAME}; + my $name = $hash->{NAME}; + my $errorcode; + my $error; + + RemoveInternalTimer($hash, "SSCam_getrec"); + return if(IsDisabled($name)); + + if (ReadingsVal("$name", "state", "") =~ /^dis.*/) { + if (ReadingsVal("$name", "state", "") eq "disabled") { + $errorcode = "402"; + } elsif (ReadingsVal("$name", "state", "") eq "disconnected") { + $errorcode = "502"; + } + + # Fehlertext zum Errorcode ermitteln + $error = SSCam_experror($hash,$errorcode); + + # Setreading + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode",$errorcode); + readingsBulkUpdate($hash,"Error",$error); + readingsEndUpdate($hash, 1); + + Log3($name, 2, "$name - ERROR - Save Recording of Camera $camname in local file can't be executed - $error"); + + return; + } + + if ($hash->{HELPER}{ACTIVE} eq "off") { + $hash->{OPMODE} = "GetRec"; + $hash->{HELPER}{LOGINRETRIES} = 0; + + SSCam_setActiveToken($hash); + SSCam_getapisites($hash); + + } else { + InternalTimer(gettimeofday()+0.3, "SSCam_getrec", $hash, 0); + } +} + ############################################################################### # Kamera gemachte Aufnahme lokal speichern ############################################################################### @@ -2286,8 +2359,7 @@ sub SSCam_getsaverec($) { return; } - if ($hash->{HELPER}{ACTIVE} eq "off") { - # einen Schnappschuß aufnehmen + if ($hash->{HELPER}{ACTIVE} eq "off") { $hash->{OPMODE} = "SaveRec"; $hash->{HELPER}{LOGINRETRIES} = 0; @@ -4269,13 +4341,13 @@ sub SSCam_camop ($) { readingsSingleUpdate($hash,"state", "snap", 1); #readingsSingleUpdate($hash, "LastSnapId", "", 0); - } elsif ($OpMode eq "SaveRec") { + } elsif ($OpMode eq "SaveRec" || $OpMode eq "GetRec") { # eine Aufnahme soll in lokalem File (.mp4) gespeichert werden my $recid = ReadingsVal("$name", "CamLastRecId", 0); if($recid) { $url = "$proto://$serveraddr:$serverport/webapi/$apirecpath?api=\"$apirec\"&id=$recid&mountId=0&version=\"$apirecmaxver\"&method=\"Download\"&_sid=\"$sid\""; } else { - Log3($name, 2, "$name - WARNING - Can't save recording in local file due to no recording available."); + Log3($name, 2, "$name - WARNING - Can't fetch recording due to no recording available."); SSCam_delActiveToken($hash); return; } @@ -4668,7 +4740,7 @@ sub SSCam_camop_parse ($) { } elsif ($myjson ne "") { # wenn die Abfrage erfolgreich war ($data enthält die Ergebnisdaten des HTTP Aufrufes) # Evaluiere ob Daten im JSON-Format empfangen wurden - if($OpMode !~ /SaveRec/) { # "SaveRec" liefert MP4-Daten und kein JSON + if($OpMode !~ /SaveRec|GetRec/) { # "SaveRec/GetRec" liefern MP4-Daten und kein JSON ($hash,$success,$myjson) = SSCam_evaljson($hash,$myjson); unless ($success) { Log3($name, 4, "$name - Data returned: ".$myjson); @@ -4707,7 +4779,7 @@ sub SSCam_camop_parse ($) { # Aufnahme läuft schon und wird verlängert Log3($name, 3, "$name - running recording renewed to $rectime s"); } else { - Log3($name, 3, "$name - Camera $camname Recording with Recordtime $rectime s started"); + Log3($name, 3, "$name - Camera $camname recording with recording time $rectime s started"); } } @@ -4720,8 +4792,9 @@ sub SSCam_camop_parse ($) { if ($rectime != 0) { # Stop der Aufnahme nach Ablauf $rectime, wenn rectime = 0 -> endlose Aufnahme + my $emtxt = $hash->{HELPER}{SMTPRECMSG}?$hash->{HELPER}{SMTPRECMSG}:""; RemoveInternalTimer($hash, "SSCam_camstoprec"); - InternalTimer(gettimeofday()+$rectime, "SSCam_camstoprec", $hash); + InternalTimer(gettimeofday()+$rectime, "SSCam_camstoprec", "$name:$emtxt"); } SSCam_refresh($hash,0,0,1); # kein Room-Refresh, kein SSCam-state-Event, SSCamSTRM-Event @@ -4753,17 +4826,39 @@ sub SSCam_camop_parse ($) { # Logausgabe Log3($name, 3, "$name - Camera $camname exposure mode was set to \"$hash->{HELPER}{EXPMODE}\""); + } elsif ($OpMode eq "GetRec") { + + my $recid = ReadingsVal("$name", "CamLastRecId", ""); + my $createdTm = ReadingsVal("$name", "CamLastRecTime", ""); + my $lrec = ReadingsVal("$name", "CamLastRec", ""); + my $fileName = (split("/",$lrec))[1]; + + my %sendrecs = (); # Recording Hash zum Versand wird leer erstellt + my $sn = 0; + $sendrecs{$sn}{recid} = $recid; + $sendrecs{$sn}{createdTm} = $createdTm; + $sendrecs{$sn}{fileName} = $fileName; + $sendrecs{$sn}{".imageData"} = $myjson; + Log3($name,4, "$name - Snap '$sn' added to send recording hash: ID => $sendrecs{$sn}{recid}, File => $sendrecs{$sn}{fileName}, Created => $sendrecs{$sn}{createdTm}"); + + # prüfen ob Recording als Email versendet werden soll + SSCam_prepareSendEmail ($hash, $OpMode, \%sendrecs); + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"Errorcode","none"); + readingsBulkUpdate($hash,"Error",$err); + readingsEndUpdate($hash, 1); + + } elsif ($OpMode eq "SaveRec") { - my $recid = ReadingsVal("$name", "CamLastRecId", 0); - my $lrec = ReadingsVal("$name", "CamLastRec", ""); - $lrec = (split("/",$lrec))[1]; - + my $lrec = ReadingsVal("$name", "CamLastRec", ""); + $lrec = (split("/",$lrec))[1]; my $sp = $hash->{HELPER}{RECSAVEPATH}?$hash->{HELPER}{RECSAVEPATH}:$attr{global}{modpath}; my $file = $sp."/$lrec"; delete $hash->{HELPER}{RECSAVEPATH}; - if(open (FH, '>', $file)) { # in-memory IO Handle + if(open (FH, '>', $file)) { binmode FH; print FH $myjson; close(FH); @@ -4979,11 +5074,11 @@ sub SSCam_camop_parse ($) { } elsif ($OpMode eq "Snap") { # ein Schnapschuß wurde aufgenommen # falls Aufnahme noch läuft -> state = on setzen - SSCam_refresh($hash,0,1,0); # kein Room-Refresh, SSCam-state-Event, kein SSCamSTRM-Event + SSCam_refresh($hash,0,1,0); # kein Room-Refresh, SSCam-state-Event, kein SSCamSTRM-Event my $tac = ""; if($hash->{HELPER}{CANSENDSNAP}) { - $tac = SSCam_openOrgetTrans($hash); # Transaktion starten oder vorhandenen Code holen + $tac = SSCam_openOrgetTrans($hash); # Transaktion starten oder vorhandenen Code holen } $snapid = $data->{data}{'id'}; @@ -5703,6 +5798,11 @@ sub SSCam_camop_parse ($) { # Logausgabe Log3($name, $verbose, "$name - Query eventlist of camera $camname retrieved"); + + # Versand Aufnahme initiieren + if($hash->{HELPER}{CANSENDREC}) { + SSCam_getrec($hash); + } } elsif ($OpMode eq "getmotionenum") { @@ -7300,6 +7400,29 @@ sub SSCam_experror ($$) { return ($error); } +################################################################ +# sortiert eine Liste von Versionsnummern x.x.x +# Schwartzian Transform and the GRT transform +# Übergabe: "asc | desc", +################################################################ +sub SSCam_sortVersion (@){ + my ($sseq,@versions) = @_; + + my @sorted = map {$_->[0]} + sort {$a->[1] cmp $b->[1]} + map {[$_, pack "C*", split /\./]} @versions; + + @sorted = map {join ".", unpack "C*", $_} + sort + map {pack "C*", split /\./} @versions; + + if($sseq eq "desc") { + @sorted = reverse @sorted; + } + +return @sorted; +} + ############################################################################## # Zusätzliche Redings in Rotation erstellen # Sub ($hash,,,,) @@ -7344,7 +7467,7 @@ sub SSCam_prepareSendEmail ($$;$) { my ($hash, $OpMode, $data) = @_; my $name = $hash->{NAME}; my $calias = AttrVal($name,"alias",$hash->{CAMNAME}); # Alias der Kamera wenn gesetzt oder Originalname aus SVS - my ($ret,$sdat,$fname,$snapid,$lsnaptime,$tac) = ('','','','','',''); + my ($ret,$sdat,$vdat,$fname,$snapid,$lsnaptime,$tac) = ('','','','','',''); ### prüfen ob Schnappschnüsse aller Kameras durch ein SVS-Device angefordert wurde, ### Bilddaten werden erst zum Versand weitergeleitet wenn Schnappshußhash komplett gefüllt ist @@ -7385,19 +7508,71 @@ sub SSCam_prepareSendEmail ($$;$) { } } + my $sp = AttrVal($name, "smtpPort", 25); + my $nousessl = AttrVal($name, "smtpNoUseSSL", 0); + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; + my $date = sprintf "%02d.%02d.%04d" , $mday , $mon+=1 ,$year+=1900; + my $time = sprintf "%02d:%02d:%02d" , $hour , $min , $sec; + + my $sslfrominit = 0; + my $smtpsslport = 465; + if(AttrVal($name,"smtpSSLPort",0)) { + $sslfrominit = 1; + $smtpsslport = AttrVal($name,"smtpSSLPort",0); + } + ### Bilddaten als Email versenden wenn Attribut "snapEmailTxt" definiert ist - if(AttrVal($name, "snapEmailTxt", "")) { - my $sp = AttrVal($name, "smtpPort", 25); - my $nousessl = AttrVal($name, "smtpNoUseSSL", 0); - my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime; - my $date = sprintf "%02d.%02d.%04d" , $mday , $mon+=1 ,$year+=1900; - my $time = sprintf "%02d:%02d:%02d" , $hour , $min , $sec; - - # Extraktion EMail-Texte + if($OpMode =~ /^getsnap/ && AttrVal($name, "snapEmailTxt", "")) { # Attribut snapEmailTxt kann übersteuert werden mit: $hash->{HELPER}{SMTPMSG} + # Extraktion EMail-Texte # Format in $hash->{HELPER}{SMTPMSG} muss sein: subject => , body => my $mth = delete $hash->{HELPER}{SMTPMSG}; - my $mt = $mth?$mth:AttrVal($name, "snapEmailTxt", ""); + my $mt = $mth?$mth:AttrVal($name, "snapEmailTxt", ""); + $mt =~ s/['"]//g; + + my($subj,$body) = split(",", $mt, 2); + my($subjk,$subjt) = split("=>", $subj); + my($bodyk,$bodyt) = split("=>", $body); + $subjk = SSCam_trim($subjk); + $subjt = SSCam_trim($subjt); + $subjt =~ s/\$CAM/$calias/g; + $subjt =~ s/\$DATE/$date/g; + $subjt =~ s/\$TIME/$time/g; + $bodyk = SSCam_trim($bodyk); + $bodyt = SSCam_trim($bodyt); + $bodyt =~ s/\$CAM/$calias/g; + $bodyt =~ s/\$DATE/$date/g; + $bodyt =~ s/\$TIME/$time/g; + my %smtpmsg = (); + $smtpmsg{$subjk} = "$subjt"; + $smtpmsg{$bodyk} = "$bodyt"; + + $tac = $hash->{HELPER}{TRANSACTION}; # Code der laufenden Transaktion + + $sdat = $data; + delete $hash->{HELPER}{CANSENDSNAP}; + + $ret = SSCam_sendEmail($hash, {'subject' => $smtpmsg{subject}, + 'part1txt' => $smtpmsg{body}, + 'part2type' => 'image/jpeg', + 'smtpport' => $sp, + 'sdat' => $sdat, + 'opmode' => $OpMode, + 'smtpnousessl' => $nousessl, + 'sslfrominit' => $sslfrominit, + 'smtpsslport' => $smtpsslport, + 'tac' => $tac, + } + ); + + return $ret; + } + + ### Recordings als Email versenden wenn Attribut "recEmailTxt" definiert ist + if($OpMode =~ /^GetRec/ && $hash->{HELPER}{CANSENDREC}) { + # recEmailTxt aus $hash->{HELPER}{SMTPRECMSG} + delete $hash->{HELPER}{CANSENDREC}; + my $mt = delete $hash->{HELPER}{SMTPRECMSG}; $mt =~ s/['"]//g; my($subj,$body) = split(",", $mt, 2); @@ -7417,34 +7592,18 @@ sub SSCam_prepareSendEmail ($$;$) { $smtpmsg{$subjk} = "$subjt"; $smtpmsg{$bodyk} = "$bodyt"; - my $sslfrominit = 0; - my $smtpsslport = 465; - if(AttrVal($name,"smtpSSLPort",0)) { - $sslfrominit = 1; - $smtpsslport = AttrVal($name,"smtpSSLPort",0); - } - - $tac = $hash->{HELPER}{TRANSACTION}; # Code der laufenden Transaktion - - if($OpMode =~ /^getsnap/) { - $sdat = $data; - delete $hash->{HELPER}{CANSENDSNAP}; - delete $hash->{HELPER}{SMTPMSG}; - + $vdat = $data; $ret = SSCam_sendEmail($hash, {'subject' => $smtpmsg{subject}, 'part1txt' => $smtpmsg{body}, - 'part2type' => 'image/jpeg', + 'part2type' => 'video/mpeg', 'smtpport' => $sp, - 'sdat' => $sdat, + 'vdat' => $vdat, 'opmode' => $OpMode, 'smtpnousessl' => $nousessl, 'sslfrominit' => $sslfrominit, - 'smtpsslport' => $smtpsslport, - 'tac' => $tac, + 'smtpsslport' => $smtpsslport, } - ); - } - + ); return $ret; } @@ -7461,7 +7620,7 @@ sub SSCam_sendEmail ($$) { my $ret; Log3($name, 4, "$name - ####################################################"); - Log3($name, 4, "$name - ### start send snapshot by email "); + Log3($name, 4, "$name - ### start send snapshot or recording by email "); Log3($name, 4, "$name - ####################################################"); my $m1 = "Net::SMTP"; @@ -7521,14 +7680,15 @@ sub SSCam_sendEmail ($$) { 'smtpsslport' => {'attr'=>'smtpSSLPort', 'default'=>'', 'required'=>0, 'set'=>1}, # SSL-Port, verwendet bei direktem SSL-Aufbau 'smtpnousessl' => {'attr'=>'smtpNoUseSSL','default'=>'0', 'required'=>0, 'set'=>1}, 'smtpdebug' => {'attr'=>'smtpDebug', 'default'=>'0', 'required'=>0, 'set'=>0}, - 'sdat' => { 'default'=>'', 'required'=>0, 'set'=>1}, # (Hash)Daten base64 codiert, wenn gesetzt muss 'part2' auf 'image/jpeg' gesetzt werden - 'image' => { 'default'=>'', 'required'=>0, 'set'=>1}, # Daten als File, wenn gesetzt muss 'part2' auf 'image/jpeg' gesetzt werden - 'fname' => { 'default'=>'image.jpg', 'required'=>0, 'set'=>1}, # Filename für "image" oder "sdat" + 'sdat' => { 'default'=>'', 'required'=>0, 'set'=>1}, # (Hash)Daten base64 codiert, wenn gesetzt muss 'part2type' auf 'image/jpeg' gesetzt sein + 'image' => { 'default'=>'', 'required'=>0, 'set'=>1}, # Daten als File, wenn gesetzt muss 'part2type' auf 'image/jpeg' gesetzt sein + 'fname' => { 'default'=>'image.jpg', 'required'=>0, 'set'=>1}, # Filename für "image" 'lsnaptime' => { 'default'=>'', 'required'=>0, 'set'=>1}, # Zeitstempel der Bilddaten 'opmode' => { 'default'=>'', 'required'=>1, 'set'=>1}, # OpMode muss gesetzt sein 'sslfb' => { 'default'=>$sslfb, 'required'=>0, 'set'=>1}, # Flag für Verwendung altes Net::SMTP::SSL 'sslfrominit' => { 'default'=>'', 'required'=>0, 'set'=>1}, # SSL soll sofort ! aufgebaut werden 'tac' => { 'default'=>'', 'required'=>0, 'set'=>1}, # übermittelter Transaktionscode der ausgewerteten Transaktion + 'vdat' => { 'default'=>'', 'required'=>0, 'set'=>1}, # Videodaten, wenn gesetzt muss 'part2type' auf 'video/mpeg' gesetzt sein ); my %params = (); @@ -7584,13 +7744,14 @@ sub SSCam_sendEmailblocking($) { my $msgtext = $paref->{msgtext}; my $smtpdebug = $paref->{smtpdebug}; my $sdat = $paref->{sdat}; # Hash von Imagedaten base64 codiert - my $image = $paref->{image}; # Image, wenn gesetzt muss 'part2' auf 'image/jpeg' gesetzt sein + my $image = $paref->{image}; # Image, wenn gesetzt muss 'part2type' auf 'image/jpeg' gesetzt sein my $fname = $paref->{fname}; # Filename -> verwendet wenn $image ist gesetzt my $lsnaptime = $paref->{lsnaptime}; # Zeit des letzten Schnappschusses wenn gesetzt my $opmode = $paref->{opmode}; # aktueller Operation Mode my $sslfb = $paref->{sslfb}; # Flag für Verwendung altes Net::SMTP::SSL my $sslfrominit = $paref->{sslfrominit}; # SSL soll sofort ! aufgebaut werden my $tac = $paref->{tac}; # übermittelter Transaktionscode der ausgewerteten Transaktion + my $vdat = $paref->{vdat}; # Videodaten, wenn gesetzt muss 'part2type' auf 'video/mpeg' gesetzt sein my $hash = $defs{$name}; my $sslver = ""; @@ -7649,7 +7810,38 @@ sub SSCam_sendEmailblocking($) { print $fh $decoded; close $fh; open ($fh, '<', \$mh); - Log3($name, 4, "$name - image data were saved to memory handle for smtp prepare"); + Log3($name, 4, "$name - image data were saved into memory handle for smtp prepare"); + } else { + $err = "Can't open memory handle: $!"; + Log3($name, 2, "$name - $err"); + $err = encode_base64($err,""); + return "$name|$err|''"; + } + $mailmsg->attach( + Type => $part2type, + FH => $fh, + Filename => $fname, + Disposition => 'attachment', + ); + } + } + + if($vdat) { + ### Videodaten (mp4) wurden geliefert und werden in ein "in-memory IO" gespeichert + my ($ct,$video); + @as = sort{$a<=>$b}keys%{$vdat}; + foreach my $key (@as) { + $ct = $vdat->{$key}{createdTm}; + $video = $vdat->{$key}{".imageData"}; + $fname = $vdat->{$key}{fileName}; + $fh = '$fh'.$key; + my $mh = ''; + if(open ($fh, '>', \$mh)) { # in-memory IO Handle + binmode $fh; + print $fh $video; + close $fh; + open ($fh, '<', \$mh); + Log3($name, 4, "$name - video data were saved into memory handle for smtp prepare"); } else { $err = "Can't open memory handle: $!"; Log3($name, 2, "$name - $err"); @@ -7777,7 +7969,7 @@ sub SSCam_sendEmailblocking($) { my $ret = "Email transaction \"$tac\" successfully sent ".( $sslver?"encoded by $sslver":"" ); Log3($name, 3, "$name - $ret To: $to".(($cc)?", CC: $cc":"") ); - if($sdat) { + if($sdat || $vdat) { # handles schließen foreach my $key (@as) { close '$fh'.$key; @@ -8048,8 +8240,8 @@ return ($str); At present the following functions are available:

      -
    • Start a Recording
    • -
    • Stop a Recording (using command or automatically after the <RecordTime> period
    • +
    • Start a recording and send it optionally by Email
    • +
    • Stop a recording by command or automatically after an adjustable period
    • Trigger of snapshots and optionally send them alltogether by Email using the integrated Email client
    • Trigger snapshots of all defined cams and optionally send them alltogether by Email using the integrated Email client
    • Deaktivate a Camera in Synology Surveillance Station
    • @@ -8622,30 +8814,37 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> set <name> move dir_20 0.7 : moves PTZ 1,5 Sek. (plus processing time) to left-bottom ("CapPTZDirections = 32)"
    +
    + +
      +
    • set <name> off     (valid for CAM)

    • + + Stops the current recording. +


      -
    • set <name> [on [<rectime>] | off]     (valid for CAM)

    • +
    • set <name> on [<rectime>] [recEmailTxt:"subject => <subject text>, body => <message text>"]     (valid for CAM)

    • - The command "set <name> on" starts a recording. The default recording time takes 15 seconds. It can be changed by - the attribute "rectime" individualy. - With the attribute (respectively the default value) provided recording time can be overwritten - once by "set <name> on <rectime>". + A recording will be started. The default recording time is 15 seconds. It can be individually changed by + the attribute "rectime". + The recording time can be overwritten on-time by "set <name> on <rectime>" for the current recording. The recording will be stopped after processing time "rectime"automatically.
      - A special case is start recording by "set <name> on 0" respectively the attribute value "rectime = 0". In that case - a endless-recording will be started. One have to stop this recording by command "set <name> off" explicitely.
      + A special case is start recording by "set <name> on 0" respectively the attribute value "rectime = 0". In this case + an endless-recording will be started. One have to explicitely stop this recording with command "set <name> off".
      - The recording behavior can be impacted with attribute "recextend" furthermore as explained as follows.

      + Furthermore the recording behavior can be impacted with attribute "recextend" as explained as + follows.

      - Attribute "recextend = 0" or not set (default):

      + Attribute "recextend = 0" or not set (default):
      • if, for example, a recording with rectimeme=22 is started, no other startcommand (for a recording) will be accepted until this started recording is finished. A hint will be logged in case of verboselevel = 3.

      - Attribute "recextend = 1" is set:

      + Attribute "recextend = 1" is set:
      • a before started recording will be extend by the recording time "rectime" if a new start command is received. That means, the timer for the automatic stop-command will be renewed to "rectime" given bei the command, attribute or default value. This procedure will be repeated every time a new start command for recording is received. @@ -8656,13 +8855,20 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay>

      - 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>
      + The Email shipping of recordings can be activated by setting attribute "recEmailTxt". + Before you have to prepare the Email shipping as described in section Setup Email shipping. + (for further information execute "get <name> versionNotes 7")
      + Alternatively you can activate the Email-shipping one-time when you specify the "recEmailTxt:"-tag in the "on"-command. + In this case the tag-text is used for creating the Email instead the text specified in "recEmailTxt"-attribute. +

      + + Examples:

      + set <name> on [rectime]
      + # starts a recording, stops automatically after [rectime]
      + set <name> on 0
      + # starts a permanent record which must be stopped with the "off"-command.
      + set <name> on recEmailTxt:"subject => New recording for $CAM created, body => The last recording of $CAM is atteched."
      + # starts a recording and send it after completion by Email.


    @@ -9096,9 +9302,9 @@ http(s)://<hostname><port>/webapi/entry.cgi?api=SYNO.SurveillanceSta Setup Email shipping

      - Snapshots can be sent by Email alltogether after creation. For this purpose the module contains its own Email client. - Before you can use this function you have to install the Perl-module MIME::Lite. On debian systems it can be - installed with command:

      + Snapshots and recordings can be sent by Email after creation. For this purpose the module contains its + own Email client. Before you can use this function you have to install the Perl-module MIME::Lite. On debian + systems it can be installed with command:

        sudo apt-get install libmime-lite-perl @@ -9115,11 +9321,19 @@ http(s)://<hostname><port>/webapi/entry.cgi?api=SYNO.SurveillanceSta
          - + @@ -9362,6 +9576,21 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> (e.g. "attr WEB iconPath default:fhemSVG:openautomation:sscam").
          + +
        • recEmailTxt subject => <subject text>, body => <message text>
          + Activates the Email shipping of recordings after whose creation.
          + The attribute has to be definied in the form as described. You can use the placeholder variables $CAM, $DATE and $TIME. + The variable $CAM is replaced by the device alias or the name of the camera in SVS if the device alias isn't available. + $DATE and $TIME are replaced with the current date and time. +

          + +
            + Example:
            + recEmailTxt subject => New recording $CAM, body => A new recording of $CAM is created and atteched. +
          +
          +
        • +
        • rectime
          determines the recordtime when a recording starts. If rectime = 0 an endless recording will be started. If @@ -9434,7 +9663,7 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay>
        • snapEmailTxt subject => <subject text>, body => <message text>
          - Activates the Email shipping of snapshots after its creation.
          + Activates the Email shipping of snapshots after whose creation.
          The attribute has to be definied in the form as described. You can use the placeholder variables $CAM, $DATE and $TIME. The variable $CAM is replaced by the device alias or the name of the camera in SVS if the device alias isn't available. $DATE and $TIME are replaced with the current date and time. @@ -9623,8 +9852,8 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> Zur Zeit werden folgende Funktionen unterstützt:

              -
            • Start einer Aufnahme
            • -
            • Stop einer Aufnahme (per Befehl bzw. automatisch nach Ablauf der Aufnahmedauer)
            • +
            • Start einer Aufnahme und optionaler Versand per Email
            • +
            • Stop einer Aufnahme per Befehl bzw. automatisch nach Ablauf einer einstellbaren Dauer
            • Auslösen von Schnappschnüssen und optionaler Email-Versand mittels integrierten Email-Client
            • Auslösen von Schnappschnüssen aller definierten Kameras und optionaler gemeinsamer Email-Versand mittels integrierten Email-Client
            • Deaktivieren einer Kamera in Synology Surveillance Station
            • @@ -10203,12 +10432,19 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> set <name> move dir_20 0.7 : bewegt PTZ 1,5 Sek. (zzgl. Prozesszeit) nach links-unten ("CapPTZDirections = 32)"
            +
            + +
              +
            • set <name> off     (gilt für CAM)

            • + + Stoppt eine laufende Aufnahme. +


              -
            • set <name> [ on [<rectime>] | off ]     (gilt für CAM)

            • +
            • set <name> on [<rectime>] [recEmailTxt:"subject => <Betreff-Text>, body => <Mitteilung-Text>"]     (gilt für CAM)

            • - Der Befehl "set <name> on" startet eine Aufnahme. Die Standardaufnahmedauer beträgt 15 Sekunden. Sie kann mit dem + Startet eine Aufnahme. Die Standardaufnahmedauer beträgt 15 Sekunden. Sie kann mit dem Attribut "rectime" individuell festgelegt werden. Die im Attribut (bzw. im Standard) hinterlegte Aufnahmedauer kann einmalig mit "set <name> on <rectime>" überschrieben werden. @@ -10220,16 +10456,16 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> Das Aufnahmeverhalten kann weiterhin mit dem Attribut "recextend" beeinflusst werden.

              - Attribut "recextend = 0" bzw. nicht gesetzt (Standard):

              + Attribut "recextend = 0" bzw. nicht gesetzt (Standard):
                -
              • wird eine Aufnahme mit z.B. rectime=22 gestartet, wird kein weiterer Startbefehl für eine Aufnahme akzeptiert bis diese gestartete Aufnahme nach 22 Sekunden +
              • Wird eine Aufnahme mit z.B. rectime=22 gestartet, wird kein weiterer Startbefehl für eine Aufnahme akzeptiert bis diese gestartete Aufnahme nach 22 Sekunden beendet ist. Ein Hinweis wird bei verbose=3 im Logfile protokolliert.

              Attribut "recextend = 1" gesetzt:
                -
              • eine zuvor gestartete Aufnahme wird bei einem erneuten "set on" -Befehl um die Aufnahmezeit "rectime" verlängert. Das bedeutet, dass der Timer für +
              • Eine zuvor gestartete Aufnahme wird bei einem erneuten "set on" -Befehl um die Aufnahmezeit "rectime" verlängert. Das bedeutet, dass der Timer für den automatischen Stop auf den Wert "rectime" neu gesetzt wird. Dieser Vorgang wiederholt sich mit jedem Start-Befehl. Dadurch verlängert sich eine laufende Aufnahme bis kein Start-Inpuls mehr registriert wird.
              • @@ -10238,13 +10474,22 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay>

              - Beispiele für einfachen Start/Stop einer Aufnahme:

              + Ein Email-Versand der letzten Aufnahme kann durch Setzen des Attributs "recEmailTxt" + aktiviert werden. Zuvor ist der Email-Versand, wie im Abschnitt Einstellung Email-Versand beschrieben, + einzustellen. (Für weitere Informationen "get <name> versionNotes 7" ausführen)
              + Alternativ kann durch Verwendung des optionalen "snapEmailTxt:"-Tags der Email-Versand der gestarteten Aufnahme nach deren + Beendigung aktiviert werden. Sollte das Attribut "recEmailTxt" bereits gesetzt sein, wird der Text des "snapEmailTxt:"-Tags + anstatt des Attribut-Textes verwendet.

              + + Beispiele :

              + 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> on 0
              + # startet eine Daueraufnahme die mit "off" gestoppt werden muss.
              + set <name> on recEmailTxt:"subject => Neue Aufnahme $CAM, body => Die aktuelle Aufnahme von $CAM ist angehängt."
              + # startet eine Aufnahme und vesendet sie nach Beendigung per Email.
              -
        • snapEmailTxt - Activates the Email shipping. This attribute has the format:
          +
          snapEmailTxt - Activates the Email shipping of snapshots. This attribute has the format:
          subject => <subject text>, body => <message text>
          The placeholder $CAM, $DATE and $TIME can be used. $CAM is replaced by the device name, device alias or the name of camera in SVS if alias is not defined. $DATE and $TIME are replaced with the current date and time.
          recEmailTxt - Activates the Email shipping of recordings. This attribute has the format:
          + subject => <subject text>, body => <message text>
          + The placeholder $CAM, $DATE and $TIME can be used. $CAM is + replaced by the device name, device alias or the name of camera in SVS if alias is not + defined. $DATE and $TIME are replaced with the current date and time. + Alternatively you can specify the "recEmailTxt:"-tag when start recording with the "On"-command. + In this case the Email shipping is temporaray activated for the started recording and the tag-text + is used instead of the text defined in the "recEmailTxt"-attribute.
          smtpHost - Hostname of outgoing Email server (e.g. securesmtp.t-online.de)
          smtpFrom - Return address (<name>@<domain>)
          smtpTo - Receiving address(es) (<name>@<domain>)
          - - - -
          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>


        @@ -10705,8 +10950,8 @@ http(s)://<hostname><port>/webapi/entry.cgi?api=SYNO.SurveillanceSta Einstellung Email-Versand

          - Schnappschüsse können nach der Erstellung per Email gemeinsam versendet werden. Dazu enthält das Modul einen - eigenen Email-Client. + Schnappschüsse und Aufnahmen können nach der Erstellung per Email versendet werden. Dazu enthält das + Modul einen eigenen Email-Client. Zur Verwendung dieser Funktion muss das Perl-Modul MIME::Lite installiert sein. Auf Debian-Systemen kann es mit

          @@ -10729,7 +10974,8 @@ http(s)://<hostname><port>/webapi/entry.cgi?api=SYNO.SurveillanceSta
            - + + @@ -10984,7 +11242,21 @@ attr <name> genericStrmHtmlTag <video $HTMLATTR controls autoplay> Das PTZ-Panel benutzt einen eigenen Satz Icons. Damit das System sie finden kann, ist im FHEMWEB Device das Attribut "iconPath" um "sscam" zu ergänzen (z.B. "attr WEB iconPath default:fhemSVG:openautomation:sscam"). -
            +
            + + +
          • recEmailTxt subject => <Betreff-Text>, body => <Mitteilung-Text>
            + Aktiviert den Emailversand von Aufnahmen nach deren Erstellung.
            + Das Attribut muß in der angegebenen Form definiert werden. Es können die Platzhalter $CAM, $DATE und $TIME verwendet werden. + $CAM wird durch den Device-Alias bzw. den Namen der Kamera in der SVS ersetzt falls der Device-Alias nicht vorhanden + ist. $DATE und $TIME werden durch das aktuelle Datum und Zeit ersetzt.

            + +
              + Beispiel:
              + recEmailTxt subject => Neue Aufnahme $CAM, body => Die aktuelle Aufnahme von $CAM ist angehängt. +
            +
            +
          • rectime
          • snapEmailTxt - Aktiviert den Email-Versand. Das Attribut hat das Format:
            +
            snapEmailTxt - Aktiviert den Email-Versand von Schnappschüssen. + Das Attribut hat das Format:
              subject => <Betreff-Text>, body => <Mitteilung-Text>
            @@ -10737,6 +10983,18 @@ http(s)://<hostname><port>/webapi/entry.cgi?api=SYNO.SurveillanceSta durch den Device-Namen, Device-Alias bzw. den Namen der Kamera in der SVS ersetzt falls der Device-Alias nicht gesetzt ist. $DATE und $TIME werden durch das aktuelle Datum und Zeit ersetzt.
            recEmailTxt - Aktiviert den Email-Versand von Aufnahmen. + Das Attribut hat das Format:
            +
              + subject => <Betreff-Text>, body => <Mitteilung-Text>
              +
            + Es können die Platzhalter $CAM, $DATE und $TIME verwendet werden. $CAM wird + durch den Device-Namen, Device-Alias bzw. den Namen der Kamera in der SVS + ersetzt falls der Device-Alias nicht gesetzt ist. + $DATE und $TIME werden durch das aktuelle Datum und Zeit ersetzt.
            + Der Email-Versand der letzten Aufnahme wird temporär aktiviert falls der "recEmailTxt:"-Tag beim + On-Kommando verwendet wird.
            smtpHost - Hostname oder IP-Adresse des Postausgangsservers (z.B. securesmtp.t-online.de)
            smtpFrom - Absenderadresse (<name>@<domain>)
            smtpTo - Empfängeradresse(n) (<name>@<domain>)