diff --git a/fhem/CHANGED b/fhem/CHANGED
index 7e056401b8..e2341c37da 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,8 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - feature: 49_SSCam: V8.0.0, new type "hls" of streaming devices, hls
+ playback now available for all common browsers,
+ tooltip hints in streaming devices, minor fixes
- feature: 30_HUEBridge, 31_HUEDevice: added get startup command
- change: 55_DWD_OpenData: maintenance release (forum #83097 msg #869647)
- change: mqtt2.template: change name convention + cleanup
diff --git a/fhem/FHEM/49_SSCam.pm b/fhem/FHEM/49_SSCam.pm
index 0e566e1f87..6982b97d2b 100644
--- a/fhem/FHEM/49_SSCam.pm
+++ b/fhem/FHEM/49_SSCam.pm
@@ -45,6 +45,7 @@ use HttpUtils;
# Versions History intern
our %SSCam_vNotesIntern = (
+ "8.0.0" => "13.12.2018 HLS with sscam_hls.js integrated for SSCamSTRM type hls, realize tooltipps in streaming devices, minor fixes",
"7.7.1" => "12.12.2018 change autocreateCams: define new device only if ne device with Internal CAMNAME is defined, ".
"fix getsnapinfo function get wrong snapid or none if cam is new defined ",
"7.7.0" => "10.12.2018 SVS-Device: autocreateCams command added, some other fixes and improvements, minor code rewrite, ".
@@ -101,6 +102,8 @@ our %SSCam_vNotesIntern = (
# Versions History extern
our %SSCam_vNotesExtern = (
+ "8.0.0" => "18.12.2018 HLS is integrated using sscam_hls.js in Streaming device types \"hls\". HLS streaming is now available ".
+ "for all common used browser types. Tooltipps are added to streaming devices and snapgallery.",
"7.7.0" => "10.12.2018 autocreateCams command added to SVS device. By this command all cameras installed in SVS can be ".
"defined automatically. ".
"In SSCamSTRM devices the \"set <name> popupStream\" command is implemented which may open a popup window with the ".
@@ -277,9 +280,40 @@ my %SSCam_errlist = (
600 => "Presetname and PresetID not found in Hash",
);
+# Tooltipps Textbausteine (http://www.walterzorn.de/tooltip/tooltip.htm#download), §NAME§ wird durch Kameranamen ersetzt
+our %SSCam_ttips_en = (
+ ttrefresh => "The playback of streaming content of camera of "§NAME§" will be restartet.",
+ ttrecstart => "Start an endless recording of camera "§NAME§". You have to stop the recording manually.",
+ ttrecstop => "Stopp the recording of camera "§NAME§".",
+ ttsnap => "Take a snapshot of camera "§NAME§".",
+ ttcmdstop => "Stopp playback of camera "§NAME§"",
+ tthlsreact => "Reactivate HTTP Livestreaming Interface of camera "§NAME§". The camera is enforced to restart HLS transmission.",
+ ttmjpegrun => "Playback the MJPEG Livestream of camera "§NAME§".",
+ tthlsrun => "Playback the native HTTP Livestream of camera "§NAME§".",
+ ttlrrun => "Playback of last recording of camera "§NAME§" in an iFrame. Both MJPEG and H.264 recordings are rendered.",
+ tth264run => "Playback of last H.264 recording of camera "§NAME§". It only starts if the recording is type H.264",
+ ttlmjpegrun => "Playback of last MJPEG recording of camera "§NAME§". It only starts if the recording is type MJPEG",
+ ttlsnaprun => "Playback of last snapshot of camera "§NAME§".",
+);
+
+our %SSCam_ttips_de = (
+ ttrefresh => "Die Wiedergabe des Streams von Kamera "§NAME§" wird neu gestartet.",
+ ttrecstart => "Startet eine Endlosaufnahme von Kamera "§NAME§". Die Aufnahme muß manuell gestoppt werden.",
+ ttrecstop => "Stoppt die laufende Aufnahme von Kamera "§NAME§".",
+ ttsnap => "Ein Schnappschuß von Kamera "§NAME§" wird aufgenommen.",
+ ttcmdstop => "Stopp Wiedergabe von Kamera "§NAME§"",
+ tthlsreact => "Reactiviert das HTTP Livestreaming Interface von camera "§NAME§". Die Kamera wird aufgefordert die HLS Übertragung zu restarten.",
+ ttmjpegrun => "Wiedergabe des MJPEG Livestreams von Kamera "§NAME§"",
+ tthlsrun => "Wiedergabe des HTTP Livestreams von Kamera "§NAME§". Es wird die HLS Funktion der Synology Surveillance Station verwendet.",
+ ttlrrun => "Wiedergabe der letzten Aufnahme von Kamera "§NAME§" in einem iFrame. Es werden sowohl MJPEG als auch H.264 Aufnahmen wiedergegeben.",
+ tth264run => "Wiedergabe der letzten H.264 Aufnahme von Kamera "§NAME§". Die Wiedergabe startet nur wenn die Aufnahme vom Typ H.264 ist.",
+ ttlmjpegrun => "Wiedergabe der letzten MJPEG Aufnahme von Kamera "§NAME§". Die Wiedergabe startet nur wenn die Aufnahme vom Typ MJPEG ist.",
+ ttlsnaprun => "Wiedergabe des letzten Schnappschusses von Kamera "§NAME§".",
+);
+
# Standardvariablen
my $SSCam_slim = 3; # default Anzahl der abzurufenden Schnappschüsse mit snapGallery
-my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery
+my $SSCAM_snum = "1,2,3,4,5,6,7,8,9,10"; # mögliche Anzahl der abzurufenden Schnappschüsse mit snapGallery
use vars qw($FW_ME); # webname (default is fhem), used by 97_GROUP/weblink
use vars qw($FW_subdir); # Sub-path in URL, used by FLOORPLAN/weblink
@@ -288,6 +322,7 @@ use vars qw($FW_detail); # currently selected device for detail view
use vars qw($FW_wname); # Web instance
sub FW_pH(@); # add href
+################################################################
sub SSCam_Initialize($) {
my ($hash) = @_;
$hash->{DefFn} = "SSCam_Define";
@@ -304,6 +339,8 @@ sub SSCam_Initialize($) {
$hash->{AttrList} =
"disable:1,0 ".
"genericStrmHtmlTag ".
+ "hlsNetScript:1,0 ".
+ "hlsStrmObject ".
"httptimeout ".
"htmlattr ".
"livestreamprefix ".
@@ -454,6 +491,10 @@ sub SSCam_Attr($$$$) {
# $name is device name
# aName and aVal are Attribute name and value
+ if ($aName =~ /hlsNetScript/ && SSCam_IsModelCam($hash)) {
+ return " The attribute \"$aName\" is only valid for devices of type \"SVS\"! Please set this attribute in a device of this type.";
+ }
+
# dynamisch PTZ-Attribute setzen (wichtig beim Start wenn Reading "DeviceType" nicht gesetzt ist)
if ($cmd eq "set" && ($aName =~ m/ptzPanel_.*/)) {
foreach my $n (0..9) {
@@ -639,7 +680,7 @@ sub SSCam_Set($@) {
"snap:noArg ".
(AttrVal($name, "snapGalleryBoost",0)?(AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$SSCAM_snum ":" ").
"createSnapGallery:noArg ".
- "createStreamDev:generic,mjpeg,switched ".
+ "createStreamDev:generic,hls,mjpeg,switched ".
((ReadingsVal("$name", "CapPTZPan", "false") ne "false") ? "createPTZcontrol:noArg ": "").
"enable:noArg ".
"disable:noArg ".
@@ -754,7 +795,7 @@ sub SSCam_Set($@) {
$sgdev = "SSCamSTRM.$name.snapgallery";
$ret = CommandDefine($hash->{CL},"$sgdev SSCamSTRM {SSCam_composegallery('$name','$sgdev','snapgallery')}");
return $ret if($ret);
- my $room = "SnapGallery";
+ my $room = "SSCam";
$attr{$sgdev}{room} = $room;
return "Snapgallery device \"$sgdev\" created and assigned to room \"$room\".";
@@ -763,7 +804,7 @@ sub SSCam_Set($@) {
my $ptzcdev = "SSCamSTRM.$name.PTZcontrol";
my $ret = CommandDefine($hash->{CL},"$ptzcdev SSCamSTRM {SSCam_ptzpanel('$name','$ptzcdev','ptzcontrol')}");
return $ret if($ret);
- my $room = AttrVal($name,"room","PTZcontrol");
+ my $room = AttrVal($name,"room","SSCam");
$attr{$ptzcdev}{room} = $room;
$attr{$ptzcdev}{group} = $name."_PTZcontrol";
return "PTZ control device \"$ptzcdev\" created and assigned to room \"$room\".";
@@ -781,6 +822,13 @@ sub SSCam_Set($@) {
$livedev = "SSCamSTRM.$name.generic";
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','generic')}");
return $ret if($ret);
+ }
+ if($prop =~ /hls/) {
+ $livedev = "SSCamSTRM.$name.hls";
+ $ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {SSCam_StreamDev('$name','$livedev','hls')}");
+ return $ret if($ret);
+ my $c = "The device needs to set attribute \"hlsStrmObject\" in camera device \"$name\" to a valid HLS videostream";
+ CommandAttr($hash->{CL},"$livedev comment $c");
}
if($prop =~ /switched/) {
$livedev = "SSCamSTRM.$name.switched";
@@ -788,7 +836,7 @@ sub SSCam_Set($@) {
return $ret if($ret);
}
- my $room = AttrVal($name,"room","Livestream");
+ my $room = AttrVal($name,"room","SSCam");
$attr{$livedev}{room} = $room;
return "Livestream device \"$livedev\" created and assigned to room \"$room\".";
@@ -802,7 +850,7 @@ sub SSCam_Set($@) {
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
'<%it_server>,On/Off>,< >,,< >, >,< >,< >,< >,< >, >,< >,< >,< >,< >,< >,< >,< >,< >,< >,< >'."\n".
- 'TYPE=SSCam:FILTER=MODEL=SVS:HomeModeState,< >,state,< >,< >,< >,< >,< >,< >, >,< >,< >,< >,?!disable,< >,< >,< >,< >,< >'."\n".
+ 'TYPE=SSCam:FILTER=MODEL=SVS:!HomeModeState,< >,state,< >,< >,< >,< >,< >,< >, >,< >,< >,< >,?!disable,< >,< >,< >,< >,< >'."\n".
'';
my $ret = CommandDefine($hash->{CL},"$rgdev readingsGroup $rgdef");
@@ -1423,7 +1471,7 @@ sub SSCam_FWsummaryFn ($$$$) {
if($hash->{HELPER}{RUNVIEW} =~ /live_fw/) {
if(ReadingsVal($d, "Record", "Stop") eq "Stop") {
# Aufnahmebutton endlos Start
- $ret .= "$imgrecendless ";
+ $ret .= "$imgrecendless ";
} else {
# Aufnahmebutton Stop
$ret .= "$imgrecstop ";
@@ -5775,7 +5823,7 @@ sub SSCam_Autocreate ($$) {
}
return ($err,$camname);
-}
+}
###############################################################################
# Test ob JSON-String empfangen wurde
@@ -6211,6 +6259,11 @@ return;
# Funktion für SSCamSTRM-Devices - Kamera Liveview weblink device
# API: SYNO.SurveillanceStation.VideoStreaming
# Methode: GetLiveViewPath
+#
+# $camname = Name der Kamaera (Parent-Device)
+# $strmdev = Name des Streaming-Devices
+# $fmt = Streaming Format
+#
######################################################################################
sub SSCam_StreamDev($$$) {
my ($camname,$strmdev,$fmt) = @_;
@@ -6273,7 +6326,40 @@ sub SSCam_StreamDev($$$) {
$pws =~ s/"//g if($pws);
my $StmKey = ReadingsVal($camname,"StmKey",undef);
+ # Javascript Bibliothek für Tooltips (http://www.walterzorn.de/tooltip/tooltip.htm#download) und Texte
+ my $calias = $hash->{CAMNAME}; # Alias der Kamera
+ my $ttjs = "/fhem/pgm2/sscam_tooltip.js";
+ my ($ttrefresh, $ttrecstart, $ttrecstop, $ttsnap, $ttcmdstop, $tthlsreact, $ttmjpegrun, $tthlsrun, $ttlrrun, $tth264run, $ttlmjpegrun, $ttlsnaprun);
+ if(AttrVal("global","language","EN") =~ /EN/) {
+ $ttrefresh = $SSCam_ttips_en{"ttrefresh"}; $ttrefresh =~ s/§NAME§/$calias/g;
+ $ttrecstart = $SSCam_ttips_en{"ttrecstart"}; $ttrecstart =~ s/§NAME§/$calias/g;
+ $ttrecstop = $SSCam_ttips_en{"ttrecstop"}; $ttrecstop =~ s/§NAME§/$calias/g;
+ $ttsnap = $SSCam_ttips_en{"ttsnap"}; $ttsnap =~ s/§NAME§/$calias/g;
+ $ttcmdstop = $SSCam_ttips_en{"ttcmdstop"}; $ttcmdstop =~ s/§NAME§/$calias/g;
+ $tthlsreact = $SSCam_ttips_en{"tthlsreact"}; $tthlsreact =~ s/§NAME§/$calias/g;
+ $ttmjpegrun = $SSCam_ttips_en{"ttmjpegrun"}; $ttmjpegrun =~ s/§NAME§/$calias/g;
+ $tthlsrun = $SSCam_ttips_en{"tthlsrun"}; $tthlsrun =~ s/§NAME§/$calias/g;
+ $ttlrrun = $SSCam_ttips_en{"ttlrrun"}; $ttlrrun =~ s/§NAME§/$calias/g;
+ $tth264run = $SSCam_ttips_en{"tth264run"}; $tth264run =~ s/§NAME§/$calias/g;
+ $ttlmjpegrun= $SSCam_ttips_en{"ttlmjpegrun"}; $ttlmjpegrun =~ s/§NAME§/$calias/g;
+ $ttlsnaprun = $SSCam_ttips_en{"ttlsnaprun"}; $ttlsnaprun =~ s/§NAME§/$calias/g;
+ } else {
+ $ttrefresh = $SSCam_ttips_de{"ttrefresh"}; $ttrefresh =~ s/§NAME§/$calias/g;
+ $ttrecstart = $SSCam_ttips_de{"ttrecstart"}; $ttrecstart =~ s/§NAME§/$calias/g;
+ $ttrecstop = $SSCam_ttips_de{"ttrecstop"}; $ttrecstop =~ s/§NAME§/$calias/g;
+ $ttsnap = $SSCam_ttips_de{"ttsnap"}; $ttsnap =~ s/§NAME§/$calias/g;
+ $ttcmdstop = $SSCam_ttips_de{"ttcmdstop"}; $ttcmdstop =~ s/§NAME§/$calias/g;
+ $tthlsreact = $SSCam_ttips_de{"tthlsreact"}; $tthlsreact =~ s/§NAME§/$calias/g;
+ $ttmjpegrun = $SSCam_ttips_de{"ttmjpegrun"}; $ttmjpegrun =~ s/§NAME§/$calias/g;
+ $tthlsrun = $SSCam_ttips_de{"tthlsrun"}; $tthlsrun =~ s/§NAME§/$calias/g;
+ $ttlrrun = $SSCam_ttips_de{"ttlrrun"}; $ttlrrun =~ s/§NAME§/$calias/g;
+ $tth264run = $SSCam_ttips_de{"tth264run"}; $tth264run =~ s/§NAME§/$calias/g;
+ $ttlmjpegrun= $SSCam_ttips_de{"ttlmjpegrun"}; $ttlmjpegrun =~ s/§NAME§/$calias/g;
+ $ttlsnaprun = $SSCam_ttips_de{"ttlsnaprun"}; $ttlsnaprun =~ s/§NAME§/$calias/g;
+ }
+
$ret = "";
+ $ret .= "";
$ret .= '
';
$ret .= '';
$ret .= '
';
@@ -6281,8 +6367,8 @@ sub SSCam_StreamDev($$$) {
if(!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname)) {
# Ausgabe bei Fehler
my $cam = AttrVal($camname, "alias", $camname);
- $cause = !$StmKey?"Cam $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled";
- $cause = "Cam \"$cam\" is disabled" if(IsDisabled($camname));
+ $cause = !$StmKey?"Camera $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled";
+ $cause = "Camera \"$cam\" is disabled" if(IsDisabled($camname));
$ret .= "