mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
49_SSCam(STRM): new Streaming Device model "master"
git-svn-id: https://svn.fhem.de/fhem/trunk@22446 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
642515b665
commit
3377f861f1
@ -1,5 +1,6 @@
|
||||
# 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(STRM): new Streaming Device model "master"
|
||||
- bugfix: 00_SIGNALduino.pm
|
||||
Fix some perlcritic 5 warnings
|
||||
some operator fixes #835
|
||||
|
@ -159,6 +159,7 @@ BEGIN {
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"9.5.0" => "15.07.2020 streamDev master type added, comref revised ",
|
||||
"9.4.5" => "15.07.2020 fix crash while autocreate CommandDelete, CommandSave is missing ",
|
||||
"9.4.4" => "14.07.2020 fix crash while autocreate makeDeviceName is missing ",
|
||||
"9.4.3" => "13.07.2020 streamDev refactored, comref revised ",
|
||||
@ -762,8 +763,8 @@ sub Define {
|
||||
$hash->{HELPER}{APIREC} = "SYNO.SurveillanceStation.Recording"; # This API provides method to query recording information.
|
||||
|
||||
# Startwerte setzen
|
||||
if(IsModelCam($hash)) {
|
||||
$attr{$name}{webCmd} = "on:off:snap:enable:disable:runView:stopView"; # initiale Webkommandos setzen
|
||||
if(IsModelCam($hash)) { # initiale Webkommandos setzen
|
||||
$attr{$name}{webCmd} = "on:off:snap:enable:disable:runView:stopView";
|
||||
} else {
|
||||
$attr{$name}{webCmd} = "homeMode";
|
||||
$attr{$name}{webCmdLabel} = "HomeMode";
|
||||
@ -1148,7 +1149,7 @@ sub Set {
|
||||
"off:noArg ".
|
||||
"motdetsc:disable,camera,SVS ".
|
||||
"snap ".
|
||||
(AttrVal($name, "snapGalleryBoost",0) ? (AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0))?"snapGallery:noArg ":"snapGallery:$defSnum ":" ").
|
||||
(AttrVal($name, "snapGalleryBoost",0) ? (AttrVal($name,"snapGalleryNumber",undef) || AttrVal($name,"snapGalleryBoost",0)) ? "snapGallery:noArg " : "snapGallery:$defSnum " : " ").
|
||||
"createReadingsGroup ".
|
||||
"createSnapGallery:noArg ".
|
||||
"createStreamDev:generic,hls,lastsnap,mjpeg,switched ".
|
||||
@ -1175,10 +1176,11 @@ sub Set {
|
||||
$setlist = "Unknown argument $opt, choose one of ".
|
||||
"autocreateCams:noArg ".
|
||||
"credentials ".
|
||||
"createStreamDev:master ".
|
||||
"smtpcredentials ".
|
||||
"createReadingsGroup ".
|
||||
"extevent:1,2,3,4,5,6,7,8,9,10 ".
|
||||
($hash->{HELPER}{APIHMMAXVER}?"homeMode:on,off ": "").
|
||||
($hash->{HELPER}{APIHMMAXVER} ? "homeMode:on,off " : "").
|
||||
"snapCams ";
|
||||
}
|
||||
|
||||
@ -1437,7 +1439,11 @@ sub Set {
|
||||
} else {
|
||||
# Snaphash ist vorhanden und wird zur Ausgabe aufbereitet (Polling ist aktiv)
|
||||
$hash->{HELPER}{SNAPLIMIT} = AttrVal($name,"snapGalleryNumber",$defSlim);
|
||||
my $htmlCode = composeGallery($name);
|
||||
my %pars = ( linkparent => $name,
|
||||
linkname => '',
|
||||
ftui => 0
|
||||
);
|
||||
my $htmlCode = composeGallery(\%pars);
|
||||
for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
|
||||
if ($hash->{HELPER}{CL}{$k}->{COMP}) {
|
||||
# CL zusammengestellt (Auslösung durch Notify)
|
||||
@ -1472,7 +1478,7 @@ sub Set {
|
||||
$attr{$ptzcdev}{group} = $name."_PTZcontrol";
|
||||
return qq{PTZ control device "$ptzcdev" created and assigned to room "$room".};
|
||||
|
||||
} elsif ($opt eq "createStreamDev" && IsModelCam($hash)) {
|
||||
} elsif ($opt eq "createStreamDev") {
|
||||
if (!$hash->{CREDENTIALS}) {return qq{Credentials of $name are not set - make sure you've set it with "set $name credentials username password"};}
|
||||
my ($livedev,$ret);
|
||||
|
||||
@ -1507,6 +1513,11 @@ sub Set {
|
||||
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {FHEM::SSCam::streamDev('$name','$livedev','switched')}");
|
||||
return $ret if($ret);
|
||||
}
|
||||
if($prop =~ /master/x) {
|
||||
$livedev = "SSCamSTRM.$name.master";
|
||||
$ret = CommandDefine($hash->{CL},"$livedev SSCamSTRM {FHEM::SSCam::streamDev('$name','$livedev','master')}");
|
||||
return $ret if($ret);
|
||||
}
|
||||
|
||||
my $room = AttrVal($name,"room","SSCam");
|
||||
$attr{$livedev}{room} = $room;
|
||||
@ -1999,7 +2010,11 @@ sub Get {
|
||||
} else {
|
||||
# Snaphash ist vorhanden und wird zur Ausgabe aufbereitet
|
||||
$hash->{HELPER}{SNAPLIMIT} = AttrVal($name,"snapGalleryNumber",$defSlim);
|
||||
my $htmlCode = composeGallery($name);
|
||||
my %pars = ( linkparent => $name,
|
||||
linkname => '',
|
||||
ftui => 0
|
||||
);
|
||||
my $htmlCode = composeGallery(\%pars);
|
||||
for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
|
||||
if ($hash->{HELPER}{CL}{$k}->{COMP}) {
|
||||
# CL zusammengestellt (Auslösung durch Notify)
|
||||
@ -2308,7 +2323,12 @@ sub FWdetailFn {
|
||||
$ret .= $hash->{".setup"};
|
||||
}
|
||||
|
||||
$hash->{".ptzhtml"} = ptzPanel($name,$name) if($hash->{".ptzhtml"} eq "");
|
||||
my %pars = ( linkparent => $name,
|
||||
linkname => $name,
|
||||
ftui => 0
|
||||
);
|
||||
|
||||
$hash->{".ptzhtml"} = ptzPanel(\%pars) if($hash->{".ptzhtml"} eq "");
|
||||
|
||||
if($hash->{".ptzhtml"} ne "" && AttrVal($name,"ptzPanel_use",1)) {
|
||||
$ret .= $hash->{".ptzhtml"};
|
||||
@ -6299,7 +6319,11 @@ sub camOp_Parse {
|
||||
|
||||
# Direktausgabe Snaphash wenn nicht gepollt wird
|
||||
if(!AttrVal($name, "snapGalleryBoost",0)) {
|
||||
my $htmlCode = composeGallery($name);
|
||||
my %pars = ( linkparent => $name,
|
||||
linkname => '',
|
||||
ftui => 0
|
||||
);
|
||||
my $htmlCode = composeGallery(\%pars);
|
||||
|
||||
for (my $k=1; (defined($hash->{HELPER}{CL}{$k})); $k++ ) {
|
||||
asyncOutput($hash->{HELPER}{CL}{$k},"$htmlCode");
|
||||
@ -7439,37 +7463,38 @@ return ($hash,$success,$myjson);
|
||||
sub roomRefresh {
|
||||
my ($hash,$pload,$lpoll_scm,$lpoll_strm) = @_;
|
||||
my ($name,$st);
|
||||
if (ref $hash ne "HASH")
|
||||
{
|
||||
|
||||
if (ref $hash ne "HASH") {
|
||||
($name,$pload,$lpoll_scm,$lpoll_strm) = split ",",$hash;
|
||||
$hash = $defs{$name};
|
||||
} else {
|
||||
$name = $hash->{NAME};
|
||||
}
|
||||
|
||||
my $fpr = 0;
|
||||
|
||||
# SSCamSTRM-Device mit hinterlegter FUUID ($hash->{HELPER}{INFORM}) selektieren
|
||||
my @spgs = devspec2array("TYPE=SSCamSTRM");
|
||||
my @spgs = devspec2array("TYPE=SSCamSTRM"); # alle Streaming Devices !
|
||||
my @mstd = devspec2array("TYPE=SSCamSTRM:FILTER=MODEL=master"); # alle Streaming MODEL=master Devices
|
||||
my $room = "";
|
||||
for(@spgs) {
|
||||
if($defs{$_}{PARENT} eq $name) {
|
||||
next if(IsDisabled($defs{$_}{NAME}) || !$hash->{HELPER}{INFORM} || $hash->{HELPER}{INFORM} ne $defs{$_}{FUUID});
|
||||
$fpr = AttrVal($defs{$_}{NAME},"forcePageRefresh",0);
|
||||
$room = AttrVal($defs{$_}{NAME},"room","");
|
||||
Log3($name, 4, "$name - roomRefresh - pagerefresh: $defs{$_}{NAME}") if($fpr);
|
||||
|
||||
for my $sd (@spgs) {
|
||||
if($defs{$sd}{LINKPARENT} eq $name) {
|
||||
next if(IsDisabled($defs{$sd}{NAME}) || !$hash->{HELPER}{INFORM} || $hash->{HELPER}{INFORM} ne $defs{$sd}{FUUID});
|
||||
$fpr = AttrVal($defs{$sd}{NAME},"forcePageRefresh",0);
|
||||
$room = AttrVal($defs{$sd}{NAME},"room","");
|
||||
Log3($name, 4, qq{$name - roomRefresh - pagerefresh forced by $defs{$sd}{NAME}}) if($fpr);
|
||||
}
|
||||
}
|
||||
|
||||
# Page-Reload
|
||||
if($pload && $room) {
|
||||
if(!$fpr) {
|
||||
if($pload && $room && !$fpr) {
|
||||
# nur Räume mit dem SSCamSTRM-Device reloaden
|
||||
my @rooms = split(",",$room);
|
||||
for (@rooms) {
|
||||
my $r = $_;
|
||||
for my $r (@rooms) {
|
||||
{ map { FW_directNotify("FILTER=room=$r", "#FHEMWEB:$_", "location.reload('true')", "") } devspec2array("TYPE=FHEMWEB") }
|
||||
}
|
||||
}
|
||||
|
||||
} elsif ($pload || $fpr) {
|
||||
# trifft zu bei Detailansicht oder im FLOORPLAN bzw. Dashboard oder wenn Seitenrefresh mit dem
|
||||
# SSCamSTRM-Attribut "forcePageRefresh" erzwungen wird
|
||||
@ -7484,21 +7509,34 @@ sub roomRefresh {
|
||||
readingsSingleUpdate($hash,"state", $st, 0);
|
||||
}
|
||||
|
||||
# parentState des SSCamSTRM-Device updaten
|
||||
# parentState des SSCamSTRM-Device updaten ($hash->{HELPER}{INFORM} des LINKPARENT Devices muss FUUID des Streaming Devices haben)
|
||||
if($lpoll_strm) {
|
||||
$st = ReadingsVal($name, "state", "initialized");
|
||||
for(@spgs) {
|
||||
if($defs{$_}{PARENT} eq $name) {
|
||||
next if(IsDisabled($defs{$_}{NAME}) || !$hash->{HELPER}{INFORM} || $hash->{HELPER}{INFORM} ne $defs{$_}{FUUID});
|
||||
for my $sp (@spgs) { # $sp = ein Streaming Device aus allen Streaming Devices
|
||||
if($defs{$sp}{LINKPARENT} eq $name) {
|
||||
next if(IsDisabled($defs{$sp}{NAME}) || !$hash->{HELPER}{INFORM} || $hash->{HELPER}{INFORM} ne $defs{$sp}{FUUID});
|
||||
|
||||
readingsBeginUpdate($defs{$_});
|
||||
readingsBulkUpdate ($defs{$_},"parentState", $st);
|
||||
readingsBulkUpdate ($defs{$_},"state", "updated");
|
||||
readingsEndUpdate ($defs{$_}, 1);
|
||||
readingsBeginUpdate($defs{$sp});
|
||||
readingsBulkUpdate ($defs{$sp},"parentState", $st);
|
||||
readingsBulkUpdate ($defs{$sp},"state", "updated");
|
||||
readingsEndUpdate ($defs{$sp}, 1);
|
||||
|
||||
Log3($name, 4, "$name - roomRefresh - caller: $_, FUUID: $hash->{HELPER}{INFORM}");
|
||||
for my $sm (@mstd) { # Wenn Streaming Device von Streaming Master adoptiert wurde auch den Master updaten
|
||||
next if($defs{$sm}{LINKNAME} ne $sp);
|
||||
|
||||
readingsBeginUpdate($defs{$sm});
|
||||
readingsBulkUpdate ($defs{$sm},"parentState", $st);
|
||||
readingsBulkUpdate ($defs{$sm},"state", "updated");
|
||||
readingsEndUpdate ($defs{$sm}, 1);
|
||||
|
||||
Log3($name, 4, "$name - roomRefresh - caller: $sp, Master: $sm updated");
|
||||
}
|
||||
|
||||
Log3($name, 4, "$name - roomRefresh - caller: $sp, FUUID: $hash->{HELPER}{INFORM}");
|
||||
delete $hash->{HELPER}{INFORM};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -7589,6 +7627,14 @@ sub IsCapPIR { # hat K
|
||||
return $cap;
|
||||
}
|
||||
|
||||
sub IsModelMaster { # ist des Streamdevices MODEL=master
|
||||
my $model = shift;
|
||||
|
||||
my $mm = $model eq "master" ? 1 : 0;
|
||||
|
||||
return $mm;
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# JSON Boolean Test und Mapping
|
||||
###############################################################################
|
||||
@ -7735,7 +7781,11 @@ return ($ret);
|
||||
# das generierte Widget und das weblink-Device ptzPanel_$name
|
||||
###############################################################################
|
||||
sub ptzPanel {
|
||||
my ($name,$ptzcdev,$ptzcontrol,$ftui) = @_;
|
||||
my $paref = shift;
|
||||
my $name = $paref->{linkparent};
|
||||
my $ptzcdev = $paref->{linkname};
|
||||
my $ftui = $paref->{ftui};
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $iconpath = AttrVal ("$name", "ptzPanel_iconPath", "www/images/sscam");
|
||||
my $iconprefix = AttrVal ("$name", "ptzPanel_iconPrefix", "black_btn_" );
|
||||
@ -7867,10 +7917,9 @@ sub ptzPanel {
|
||||
### add Preset / Patrols
|
||||
###############################
|
||||
if(!$ftui) {
|
||||
my ($Presets,$Patrols,$zoom);
|
||||
my ($Presets,$Patrols);
|
||||
my $cmdPreset = "goPreset";
|
||||
my $cmdPatrol = "runPatrol";
|
||||
my $cmdZoom = "setZoom";
|
||||
|
||||
## Presets
|
||||
for my $fn (sort keys %{$data{webCmdFn}}) {
|
||||
@ -7999,21 +8048,27 @@ return;
|
||||
}
|
||||
|
||||
######################################################################################
|
||||
# Funktion für SSCamSTRM-Devices - Kamera Liveview weblink device
|
||||
# API: SYNO.SurveillanceStation.VideoStreaming
|
||||
# Methode: GetLiveViewPath
|
||||
# Funktion für SSCamSTRM-Devices
|
||||
#
|
||||
# $camname = Name der Kamaera (Parent-Device)
|
||||
# $strmdev = Name des Streaming-Devices
|
||||
# $fmt = Streaming Format (Vergleich auf "eq" !)
|
||||
# $omodel = originäres MODEL des Streaming Devices (wg. master)
|
||||
# $oname = originäres NAME des Streaming Devices (wg. master)
|
||||
#
|
||||
######################################################################################
|
||||
sub streamDev { ## no critic 'complexity'
|
||||
my ($camname,$strmdev,$fmt,$ftui) = @_;
|
||||
my $paref = shift;
|
||||
my $camname = $paref->{linkparent};
|
||||
my $strmdev = $paref->{linkname};
|
||||
my $fmt = $paref->{linkmodel};
|
||||
my $omodel = $paref->{omodel};
|
||||
my $oname = $paref->{oname};
|
||||
my $ftui = $paref->{ftui};
|
||||
|
||||
my $hash = $defs{$camname};
|
||||
my $streamHash = $defs{$strmdev}; # Hash des SSCamSTRM-Devices
|
||||
my $uuid = $streamHash->{FUUID}; # eindeutige UUID des Streamingdevices
|
||||
$ftui = ($ftui && $ftui eq "ftui") ? 1 : 0;
|
||||
my $hdrAlign = "center";
|
||||
|
||||
delete $streamHash->{HELPER}{STREAM};
|
||||
@ -8067,7 +8122,8 @@ sub streamDev { ## no critic 'comp
|
||||
# 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);
|
||||
my ($ttrefresh, $ttrecstart, $ttrecstop, $ttsnap, $ttcmdstop, $tthlsreact);
|
||||
my ($ttmjpegrun, $tthlsrun, $ttlrrun, $tth264run, $ttlmjpegrun, $ttlsnaprun);
|
||||
|
||||
# Hinweis Popups
|
||||
if(AttrVal("global","language","EN") =~ /EN/x) {
|
||||
@ -8188,10 +8244,12 @@ sub streamDev { ## no critic 'comp
|
||||
$ret .= '<tbody>';
|
||||
$ret .= '<tr class="odd">';
|
||||
|
||||
if(!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname)) {
|
||||
my $ismm = IsModelMaster($omodel); # prüfen ob Streaming Dev ist MODEL = master
|
||||
|
||||
if(!$ismm && (!$StmKey || ReadingsVal($camname, "Availability", "") ne "enabled" || IsDisabled($camname))) {
|
||||
# Ausgabe bei Fehler
|
||||
my $cam = AttrVal($camname, "alias", $camname); # Linktext als Aliasname oder Devicename setzen
|
||||
$cause = !$StmKey?"Camera $cam has no Reading \"StmKey\" set !":"Cam \"$cam\" is disabled";
|
||||
$cause = !$StmKey ? "Camera $cam has no Reading \"StmKey\" set !" : "Cam \"$cam\" is disabled";
|
||||
$cause = "Camera \"$cam\" is disabled" if(IsDisabled($camname));
|
||||
$ret .= "<td> <br> <b> $cause </b> <br><br></td>";
|
||||
$ret .= '</tr>';
|
||||
@ -8207,6 +8265,7 @@ sub streamDev { ## no critic 'comp
|
||||
$ret .= &{$sdfn{$fmt}{fn}} (\%params);
|
||||
} else {
|
||||
$cause = qq{Streaming of format "$fmt" is not supported};
|
||||
$cause = qq{Select a Streaming client with the "adopt" command.} if($ismm);
|
||||
$ret .= "<td> <br> <b> $cause </b> <br><br></td>";
|
||||
}
|
||||
use strict "refs";
|
||||
@ -8270,6 +8329,8 @@ sub _streamDevMJPEG {
|
||||
$link = $hash->{HELPER}{STMKEYMJPEGHTTP};
|
||||
}
|
||||
|
||||
return $ret if(!$link);
|
||||
|
||||
if($apiaudiostmmaxver) {
|
||||
$audiolink = "$proto://$serveraddr:$serverport/webapi/$apiaudiostmpath?api=$apiaudiostm&version=$apiaudiostmmaxver&method=Stream&cameraId=$camid&_sid=$sid";
|
||||
}
|
||||
@ -8298,7 +8359,11 @@ sub _streamDevMJPEG {
|
||||
$ret .= "</td>";
|
||||
|
||||
if(AttrVal($camname,"ptzPanel_use",1)) {
|
||||
my $ptz_ret = ptzPanel($camname,$strmdev,'',$ftui);
|
||||
my %pars = ( linkparent => $camname,
|
||||
linkname => $strmdev,
|
||||
ftui => $ftui
|
||||
);
|
||||
my $ptz_ret = ptzPanel(\%pars);
|
||||
if($ptz_ret) {
|
||||
$ret .= "<td>$ptz_ret</td>";
|
||||
}
|
||||
@ -8463,7 +8528,11 @@ sub _streamDevGENERIC {
|
||||
$ret .= "</td>";
|
||||
|
||||
if(AttrVal($camname,"ptzPanel_use",1)) {
|
||||
my $ptz_ret = ptzPanel($camname,$strmdev,'',$ftui);
|
||||
my %pars = ( linkparent => $camname,
|
||||
linkname => $strmdev,
|
||||
ftui => $ftui
|
||||
);
|
||||
my $ptz_ret = ptzPanel(\%pars);
|
||||
if($ptz_ret) {
|
||||
$ret .= "<td>$ptz_ret</td>";
|
||||
}
|
||||
@ -8549,7 +8618,11 @@ sub _streamDevHLS {
|
||||
$ret .= "</td>";
|
||||
|
||||
if(AttrVal($camname,"ptzPanel_use",1)) {
|
||||
my $ptz_ret = ptzPanel($camname,$strmdev,'',$ftui);
|
||||
my %pars = ( linkparent => $camname,
|
||||
linkname => $strmdev,
|
||||
ftui => $ftui
|
||||
);
|
||||
my $ptz_ret = ptzPanel(\%pars);
|
||||
if($ptz_ret) {
|
||||
$ret .= "<td>$ptz_ret</td>";
|
||||
}
|
||||
@ -8685,7 +8758,11 @@ sub __switchedIMAGE {
|
||||
$ret .= "</td>";
|
||||
|
||||
if(AttrVal($camname,"ptzPanel_use",1) && $hash->{HELPER}{RUNVIEW} =~ /live_fw/x) {
|
||||
my $ptz_ret = ptzPanel($camname,$strmdev,'',$ftui);
|
||||
my %pars = ( linkparent => $camname,
|
||||
linkname => $strmdev,
|
||||
ftui => $ftui
|
||||
);
|
||||
my $ptz_ret = ptzPanel(\%pars);
|
||||
if($ptz_ret) {
|
||||
$ret .= "<td>$ptz_ret</td>";
|
||||
}
|
||||
@ -8954,7 +9031,11 @@ sub __switchedHLS {
|
||||
$ret .= "</td>";
|
||||
|
||||
if(AttrVal($camname,"ptzPanel_use",1)) {
|
||||
my $ptz_ret = ptzPanel($camname,$strmdev,'',$ftui);
|
||||
my %pars = ( linkparent => $camname,
|
||||
linkname => $strmdev,
|
||||
ftui => $ftui
|
||||
);
|
||||
my $ptz_ret = ptzPanel(\%pars);
|
||||
if($ptz_ret) {
|
||||
$ret .= "<td>$ptz_ret</td>";
|
||||
}
|
||||
@ -9014,7 +9095,11 @@ return $ret;
|
||||
# Verwendung durch SSCamSTRM-Devices
|
||||
###############################################################################
|
||||
sub composeGallery {
|
||||
my ($name,$strmdev,$model,$ftui) = @_;
|
||||
my $paref = shift;
|
||||
my $name = $paref->{linkparent};
|
||||
my $strmdev = $paref->{linkname};
|
||||
my $ftui = $paref->{ftui};
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $camname = $hash->{CAMNAME};
|
||||
my $sgc = AttrVal($name,"snapGalleryColumns",3); # Anzahl der Images in einer Tabellenzeile
|
||||
@ -9023,7 +9108,6 @@ sub composeGallery {
|
||||
my $limit = AttrVal($name,"snapGalleryNumber",3); # abgerufene Anzahl Snaps
|
||||
my $totalcnt = $hash->{HELPER}{TOTALCNT}; # totale Anzahl Snaps
|
||||
$limit = $totalcnt if ($limit > $totalcnt); # wenn weniger Snaps vorhanden sind als $limit -> Text in Anzeige korrigieren
|
||||
$ftui = ($ftui && $ftui eq "ftui")?1:0;
|
||||
my $uuid = "";
|
||||
my $hdrAlign = "center";
|
||||
my $lupt = ((ReadingsTimestamp($name,"LastSnapTime"," ") gt ReadingsTimestamp($name,"LastUpdateTime"," "))
|
||||
@ -9033,11 +9117,6 @@ sub composeGallery {
|
||||
my ($alias,$dlink,$hb) = ("","","");
|
||||
my ($cache,$imgdat,$imgTm);
|
||||
|
||||
# Kontext des SSCamSTRM-Devices speichern für roomRefresh
|
||||
#$hash->{HELPER}{STRMDEV} = $strmdev; # Name des aufrufenden SSCamSTRM-Devices
|
||||
#$hash->{HELPER}{STRMROOM} = $FW_room?$FW_room:""; # Raum aus dem das SSCamSTRM-Device die Funktion aufrief
|
||||
#$hash->{HELPER}{STRMDETAIL} = $FW_detail?$FW_detail:""; # Name des SSCamSTRM-Devices (wenn Detailansicht)
|
||||
|
||||
if($strmdev) {
|
||||
my $streamHash = $defs{$strmdev}; # Hash des SSCamSTRM-Devices
|
||||
$uuid = $streamHash->{FUUID}; # eindeutige UUID des Streamingdevices
|
||||
@ -9111,7 +9190,7 @@ sub composeGallery {
|
||||
my $gattr = (AttrVal($name,"snapGallerySize","Icon") eq "Full")?$ha:"";
|
||||
|
||||
# Ausgabetabelle erstellen
|
||||
my ($htmlCode);
|
||||
my $htmlCode;
|
||||
$htmlCode = "<html>";
|
||||
$htmlCode .= "<script type=\"text/javascript\" src=\"$ttjs\"></script>";
|
||||
$htmlCode .= "<div class=\"makeTable wide\"; style=\"text-align:$hdrAlign\"> $header <br>";
|
||||
@ -9142,6 +9221,7 @@ sub composeGallery {
|
||||
|
||||
$idata = "";
|
||||
}
|
||||
|
||||
} else {
|
||||
my @as;
|
||||
for(cache($name, "c_getkeys")) { # relevant keys aus allen vorkommenden selektieren
|
||||
@ -9151,6 +9231,7 @@ sub composeGallery {
|
||||
}
|
||||
my %seen;
|
||||
my @unique = sort{$a<=>$b} grep { !$seen{$_}++ } @as; # distinct / unique the keys
|
||||
|
||||
for my $key (@unique) {
|
||||
$imgdat = cache($name, "c_read", "{SNAPHASH}{$key}{imageData}");
|
||||
$imgTm = cache($name, "c_read", "{SNAPHASH}{$key}{createdTm}");
|
||||
@ -9177,12 +9258,18 @@ sub composeGallery {
|
||||
}
|
||||
|
||||
$htmlCode .= "</tr>";
|
||||
|
||||
if(!$hb) {
|
||||
$htmlCode .= "<tr>";
|
||||
$htmlCode .= "<td style='text-align:left' colspan=10>";
|
||||
$htmlCode .= "<a onClick=\"$cmddosnap\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>" if($strmdev);
|
||||
$htmlCode .= "</td>";
|
||||
$htmlCode .= "</tr>";
|
||||
}
|
||||
|
||||
$htmlCode .= "</tbody>";
|
||||
$htmlCode .= "</table>";
|
||||
$htmlCode .= "</div>";
|
||||
if(!$hb) {
|
||||
$htmlCode .= "<a onClick=\"$cmddosnap\" onmouseover=\"Tip('$ttsnap')\" onmouseout=\"UnTip()\">$imgdosnap </a>" if($strmdev);
|
||||
}
|
||||
$htmlCode .= "</html>";
|
||||
|
||||
undef $imgdat;
|
||||
@ -11435,7 +11522,7 @@ return;
|
||||
<b>Integration into FHEM TabletUI: </b> <br><br>
|
||||
There is a widget provided for integration of SSCam-Streaming devices (Type SSCamSTRM) into FTUI. For further information please be informed by the
|
||||
(german) FHEM Wiki article: <br>
|
||||
<a href="https://wiki.fhem.de/wiki/FTUI_Widget_f%C3%BCr_Streaming_Devices_(SSCamSTRM)">FTUI Widget für SSCam Streaming Devices (SSCamSTRM)</a>.
|
||||
<a href="https://wiki.fhem.de/wiki/FTUI_Widget_f%C3%BCr_SSCam_Streaming_Devices_(SSCamSTRM)">FTUI Widget für SSCam Streaming Devices (SSCamSTRM)</a>.
|
||||
<br><br><br>
|
||||
|
||||
<b>Prerequisites </b> <br><br>
|
||||
@ -11670,7 +11757,10 @@ return;
|
||||
|
||||
<ul>
|
||||
<a name="SSCamcreateStreamDev"></a>
|
||||
<li><b> createStreamDev [generic | hls | lastsnap | mjpeg | switched] </b> (valid for CAM)</li> <br>
|
||||
<li><b> createStreamDev [generic | hls | lastsnap | mjpeg | switched] </b> (valid for CAM) <br>
|
||||
respectively <br>
|
||||
<b> createStreamDev [master] </b> (valid for SVS) <br>
|
||||
<br>
|
||||
|
||||
A separate Streaming-Device (type SSCamSTRM) will be created. This device can be used as a discrete device in a dashboard
|
||||
for example.
|
||||
@ -11680,17 +11770,19 @@ return;
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=10%> <col width=90%> </colgroup>
|
||||
<tr><td>generic </td><td>- the streaming device playback a content determined by attribute "genericStrmHtmlTag" </td></tr>
|
||||
<tr><td>generic </td><td>- the streaming device playback a content determined by attribute <a href="#genericStrmHtmlTag">genericStrmHtmlTag</a> </td></tr>
|
||||
<tr><td>hls </td><td>- the streaming device playback a permanent HLS video stream </td></tr>
|
||||
<tr><td>lastsnap </td><td>- the streaming device playback the newest snapshot </td></tr>
|
||||
<tr><td>mjpeg </td><td>- the streaming device playback a permanent MJPEG video stream (Streamkey method) </td></tr>
|
||||
<tr><td>switched </td><td>- playback of different streaming types. Buttons for mode control are provided. </td></tr>
|
||||
<tr><td>master </td><td>- with the master device another defined streaming device can be adopted and its content displayed </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
You can control the design with HTML tags in <a href="#SSCamattr">attribute</a> "htmlattr" of the camera device or by
|
||||
You can control the design with HTML tags in attribute <a href="#htmlattr">htmlattr</a> of the camera device or by
|
||||
specific attributes of the SSCamSTRM-device itself. <br><br>
|
||||
</li>
|
||||
|
||||
<b>Streaming device "hls"</b> <br><br>
|
||||
|
||||
@ -11740,10 +11832,16 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
As default the snapshot is retrieved in a reduced resolution. In order to use the original resolution, the attribute
|
||||
<b>"snapGallerySize = Full"</b> has to be set in the associated camera device (compare Internal PARENT).
|
||||
There also the attribute "pollcaminfoall" should be set to retrieve the newest snapshot regularly.
|
||||
<br>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
<b>Streaming Device "master"</b> <br><br>
|
||||
|
||||
This type cannot play back streams itself. Switching the playback of the content of another defined
|
||||
Streaming Devices is done by the Set command <b>adopt</b> in the Master Streaming Device.
|
||||
<br>
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
<li><b> createPTZcontrol </b> (valid for PTZ-CAM)</li> <br>
|
||||
|
||||
@ -11752,6 +11850,7 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
With the "ptzPanel_.*"-<a href="#SSCamattr">attributes</a> or respectively the specific attributes of the SSCamSTRM-device
|
||||
the properties of the control panel can be affected. <br>
|
||||
<br><br>
|
||||
<br>
|
||||
</ul>
|
||||
|
||||
<ul>
|
||||
@ -13356,7 +13455,7 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<b>Integration in FHEM TabletUI: </b> <br><br>
|
||||
Zur Integration von SSCam Streaming Devices (Typ SSCamSTRM) wird ein Widget bereitgestellt.
|
||||
Für weitere Information dazu bitte den Artikel im Wiki durchlesen: <br>
|
||||
<a href="https://wiki.fhem.de/wiki/FTUI_Widget_f%C3%BCr_Streaming_Devices_(SSCamSTRM)">FTUI Widget für SSCam Streaming Devices (SSCamSTRM)</a>.
|
||||
<a href="https://wiki.fhem.de/wiki/FTUI_Widget_f%C3%BCr_SSCam_Streaming_Devices_(SSCamSTRM)">FTUI Widget für SSCam Streaming Devices (SSCamSTRM)</a>.
|
||||
<br><br><br>
|
||||
|
||||
|
||||
@ -13591,7 +13690,10 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
|
||||
<ul>
|
||||
<a name="SSCamcreateStreamDev"></a>
|
||||
<li><b> createStreamDev [generic | hls | lastsnap | mjpeg | switched] </b> (gilt für CAM)</li> <br>
|
||||
<li><b> createStreamDev [generic | hls | lastsnap | mjpeg | switched] </b> (gilt für CAM) <br>
|
||||
bzw. <br>
|
||||
<b> createStreamDev [master] </b> (gilt für SVS) <br>
|
||||
<br>
|
||||
|
||||
Es wird ein separates Streaming-Device (Typ SSCamSTRM) erstellt. Dieses Device kann z.B. als separates Device
|
||||
in einem Dashboard genutzt werden.
|
||||
@ -13601,17 +13703,19 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=10%> <col width=90%> </colgroup>
|
||||
<tr><td>generic </td><td>- das Streaming-Device gibt einen durch das Attribut "genericStrmHtmlTag" bestimmten Content wieder </td></tr>
|
||||
<tr><td>generic </td><td>- das Streaming-Device gibt einen durch das Attribut <a href="#genericStrmHtmlTag">genericStrmHtmlTag</a> bestimmten Content wieder </td></tr>
|
||||
<tr><td>hls </td><td>- das Streaming-Device gibt einen permanenten HLS Datenstrom wieder </td></tr>
|
||||
<tr><td>lastsnap </td><td>- das Streaming-Device zeigt den neuesten Schnappschuß an </td></tr>
|
||||
<tr><td>mjpeg </td><td>- das Streaming-Device gibt einen permanenten MJPEG Kamerastream wieder (Streamkey Methode) </td></tr>
|
||||
<tr><td>switched </td><td>- Wiedergabe unterschiedlicher Streamtypen. Drucktasten zur Steuerung werden angeboten. </td></tr>
|
||||
<tr><td>master </td><td>- mit dem Master Device kann ein anderes definiertes Streaming Device adoptiert und dessen Content angezeigt werden </td></tr>
|
||||
</table>
|
||||
</ul>
|
||||
<br><br>
|
||||
<br>
|
||||
|
||||
Die Gestaltung kann durch HTML-Tags im <a href="#SSCamattr">Attribut</a> "htmlattr" im Kameradevice oder mit den
|
||||
Die Gestaltung kann durch HTML-Tags im Attribut <a href="#htmlattr">htmlattr</a> im Kameradevice oder mit den
|
||||
spezifischen Attributen im Streaming-Device beeinflusst werden. <br><br>
|
||||
</li>
|
||||
|
||||
<b>Streaming Device "hls"</b> <br><br>
|
||||
|
||||
@ -13660,6 +13764,12 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
Auflösung abgerufen. Um die Originalauflösung zu verwenden, ist im zugehörigen Kameradevice (Internal PARENT) das Attribut
|
||||
<b>"snapGallerySize = Full"</b> zu setzen.
|
||||
Dort sollte ebenfalls das Attribut "pollcaminfoall" gesetzt sein, um regelmäßig die neuesten Schnappschußdaten abzurufen.
|
||||
<br><br>
|
||||
|
||||
<b>Streaming Device "master"</b> <br><br>
|
||||
|
||||
Dieser Typ kann selbst keine Streams wiedergeben. Die Umschaltung der Wiedergabe des Contents eines anderen definierten
|
||||
Streaming Devices erfolgt durch den Set-Befehl <b>adopt</b> im Master Streaming Device.
|
||||
<br>
|
||||
<br><br>
|
||||
</ul>
|
||||
|
@ -42,6 +42,8 @@ BEGIN {
|
||||
qw(
|
||||
AnalyzePerlCommand
|
||||
AttrVal
|
||||
CommandSet
|
||||
data
|
||||
defs
|
||||
devspec2array
|
||||
FmtDateTime
|
||||
@ -62,6 +64,8 @@ BEGIN {
|
||||
FW_cmd
|
||||
FW_directNotify
|
||||
FW_wname
|
||||
FW_pH
|
||||
FW_widgetFallbackFn
|
||||
FHEM::SSCam::ptzPanel
|
||||
FHEM::SSCam::streamDev
|
||||
FHEM::SSCam::composeGallery
|
||||
@ -84,9 +88,9 @@ BEGIN {
|
||||
|
||||
}
|
||||
|
||||
|
||||
# Versions History intern
|
||||
my %vNotesIntern = (
|
||||
"2.13.0" => "14.07.2020 integrate streamDev master ",
|
||||
"2.12.0" => "28.06.2020 upgrade SSCam functions due to SSCam switch to packages ",
|
||||
"2.11.0" => "24.06.2020 switch to packages, changes according to PBP ",
|
||||
"2.10.2" => "08.11.2019 undef \$link in FwFn / streamAsHtml to save memory ",
|
||||
@ -127,11 +131,29 @@ my %fupgrade = ( # Fun
|
||||
3 => { of => "SSCam_StreamDev", nf => "FHEM::SSCam::streamDev" },
|
||||
);
|
||||
|
||||
my %SSCAM_imc = ( # disbled String modellabhängig (SVS / CAM)
|
||||
0 => { 0 => "initialized", 1 => "inactive" },
|
||||
1 => { 0 => "off", 1 => "inactive" },
|
||||
my %hvattr = ( # Hash zur Validierung von Attributen
|
||||
adoptSubset => { master => 1, nomaster => 0 },
|
||||
autoRefresh => { master => 1, nomaster => 1 },
|
||||
autoRefreshFW => { master => 1, nomaster => 1 },
|
||||
disable => { master => 1, nomaster => 1 },
|
||||
forcePageRefresh => { master => 1, nomaster => 1 },
|
||||
genericStrmHtmlTag => { master => 0, nomaster => 1 },
|
||||
htmlattr => { master => 0, nomaster => 1 },
|
||||
htmlattrFTUI => { master => 0, nomaster => 1 },
|
||||
hideAudio => { master => 0, nomaster => 1 },
|
||||
hideButtons => { master => 0, nomaster => 1 },
|
||||
hideDisplayName => { master => 1, nomaster => 1 },
|
||||
hideDisplayNameFTUI => { master => 1, nomaster => 1 },
|
||||
noLink => { master => 1, nomaster => 1 },
|
||||
popupWindowSize => { master => 0, nomaster => 1 },
|
||||
popupStreamFW => { master => 0, nomaster => 1 },
|
||||
popupStreamTo => { master => 0, nomaster => 1 },
|
||||
ptzButtonSize => { master => 0, nomaster => 1 },
|
||||
ptzButtonSizeFTUI => { master => 0, nomaster => 1 },
|
||||
);
|
||||
|
||||
my %sdevs = (); # Hash der vorhandenen Streaming Devices
|
||||
|
||||
my $todef = 5; # Default Popup Zeit für set <> popupStream
|
||||
|
||||
################################################################
|
||||
@ -139,11 +161,13 @@ sub Initialize {
|
||||
my $hash = shift;
|
||||
|
||||
my $fwd = join(",",devspec2array("TYPE=FHEMWEB:FILTER=STATE=Initialized"));
|
||||
my $sd = "--reset--,".allStreamDevs();
|
||||
|
||||
$hash->{DefFn} = \&Define;
|
||||
$hash->{SetFn} = \&Set;
|
||||
$hash->{GetFn} = \&Get;
|
||||
$hash->{AttrList} = "autoRefresh:selectnumbers,120,0.2,1800,0,log10 ".
|
||||
$hash->{AttrList} = "adoptSubset:sortable-strict,$sd ".
|
||||
"autoRefresh:selectnumbers,120,0.2,1800,0,log10 ".
|
||||
"autoRefreshFW:$fwd ".
|
||||
"disable:1,0 ".
|
||||
"forcePageRefresh:1,0 ".
|
||||
@ -188,16 +212,19 @@ sub Define {
|
||||
|
||||
$link = migrateFunc($hash,$link);
|
||||
|
||||
explodeDEF ($hash,$link);
|
||||
explodeLinkData ($hash, $link, 1);
|
||||
|
||||
$hash->{HELPER}{MODMETAABSENT} = 1 if($modMetaAbsent); # Modul Meta.pm nicht vorhanden
|
||||
$hash->{LINK} = $link;
|
||||
|
||||
# Versionsinformationen setzen
|
||||
setVersionInfo($hash);
|
||||
|
||||
readingsSingleUpdate($hash,"state", "initialized", 1); # Init für "state"
|
||||
readingsSingleUpdate($hash,"parentState", "initialized", 1); # Init für "parentState" Forum: https://forum.fhem.de/index.php/topic,45671.msg985136.html#msg985136
|
||||
my @r;
|
||||
push @r, "adoptSubset:--reset--" if(IsModelMaster($hash)); # Init für FTUI Subset wenn benutzt (Attr adoptSubset)
|
||||
push @r, "parentState:initialized"; # Init für "parentState" Forum: https://forum.fhem.de/index.php/topic,45671.msg985136.html#msg985136
|
||||
push @r, "state:initialized"; # Init für "state"
|
||||
|
||||
setReadings($hash, \@r, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -227,7 +254,7 @@ sub Rename {
|
||||
my $hash = $defs{$new_name} // return;
|
||||
|
||||
$hash->{DEF} =~ s/\'$old_name\'/\'$new_name\'/xg;
|
||||
$hash->{LINK} =~ s/\'$old_name\'/\'$new_name\'/xg;
|
||||
explodeLinkData ($hash, $hash->{DEF}, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -238,7 +265,7 @@ sub Copy {
|
||||
my $hash = $defs{$new_name} // return;
|
||||
|
||||
$hash->{DEF} =~ s/\'$old_name\'/\'$new_name\'/xg;
|
||||
$hash->{LINK} =~ s/\'$old_name\'/\'$new_name\'/xg;
|
||||
explodeLinkData ($hash, $hash->{DEF}, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -253,16 +280,31 @@ sub Set {
|
||||
|
||||
return if(IsDisabled($name) || $hash->{MODEL} =~ /ptzcontrol|snapgallery/x);
|
||||
|
||||
my $setlist = "Unknown argument $opt, choose one of ".
|
||||
my $setlist;
|
||||
|
||||
if(!IsModelMaster($hash)) {
|
||||
$setlist = "Unknown argument $opt, choose one of ".
|
||||
"popupStream "
|
||||
;
|
||||
} else {
|
||||
my $as = "--reset--,".allStreamDevs();
|
||||
my $sd = AttrVal($name, "adoptSubset", $as);
|
||||
$sd =~ s/\s+/#/gx;
|
||||
|
||||
my $rsd = $as;
|
||||
$rsd =~ s/#/ /g; ## no critic 'regular expression' # Regular expression without "/x" flag nicht anwenden !!!
|
||||
push my @ado, "adoptList:$rsd";
|
||||
setReadings($hash, \@ado, 0);
|
||||
|
||||
$setlist = "Unknown argument $opt, choose one of ".
|
||||
"adopt:$sd "
|
||||
;
|
||||
}
|
||||
|
||||
if ($opt eq "popupStream") {
|
||||
my $txt = FHEM::SSCam::getClHash($hash);
|
||||
return $txt if($txt);
|
||||
|
||||
my $link = AnalyzePerlCommand(undef, $hash->{LINK});
|
||||
|
||||
# OK-Dialogbox oder Autoclose
|
||||
my $temp = AttrVal($name, "popupStreamTo", $todef);
|
||||
my $to = $prop // $temp;
|
||||
@ -270,8 +312,6 @@ sub Set {
|
||||
$to = ($to =~ /\d+/x) ? (1000 * $to) : $to;
|
||||
|
||||
my $pd = AttrVal($name, "popupStreamFW", "TYPE=FHEMWEB");
|
||||
my $parent = $hash->{PARENT};
|
||||
my $parentHash = $defs{$parent};
|
||||
my $htmlCode = $hash->{HELPER}{STREAM};
|
||||
|
||||
if ($hash->{HELPER}{STREAMACTIVE}) {
|
||||
@ -289,6 +329,62 @@ sub Set {
|
||||
}
|
||||
}
|
||||
|
||||
} elsif ($opt eq "adopt") {
|
||||
shift @a; shift @a;
|
||||
$prop = join "#", @a;
|
||||
|
||||
if($prop eq "--reset--") {
|
||||
CommandSet(undef, "$name reset");
|
||||
return;
|
||||
}
|
||||
|
||||
my $strmd = $sdevs{"$prop"} // "";
|
||||
my $valid = ($strmd && $defs{$strmd} && $defs{$strmd}{TYPE} eq "SSCamSTRM");
|
||||
|
||||
return qq{The command "$opt" needs a valid SSCamSTRM device as argument instead of "$strmd"} if(!$valid);
|
||||
|
||||
# Übernahme der Readings
|
||||
my @r;
|
||||
delReadings($hash);
|
||||
for my $key (keys %{$defs{$strmd}{READINGS}}) {
|
||||
my $val = ReadingsVal($strmd, $key, "");
|
||||
next if(!$val);
|
||||
push @r, "$key:$val";
|
||||
}
|
||||
|
||||
# Übernahme Link-Parameter
|
||||
my $link = "{$defs{$strmd}{LINKFN}('$defs{$strmd}{LINKPARENT}','$defs{$strmd}{LINKNAME}','$defs{$strmd}{LINKMODEL}')}";
|
||||
|
||||
explodeLinkData ($hash, $link, 0);
|
||||
|
||||
push @r, "clientLink:$link";
|
||||
push @r, "parentCam:$hash->{LINKPARENT}";
|
||||
|
||||
if(@r) {
|
||||
setReadings($hash, \@r, 1);
|
||||
}
|
||||
|
||||
my $camname = $hash->{LINKPARENT};
|
||||
$defs{$camname}{HELPER}{INFORM} = $hash->{FUUID};
|
||||
|
||||
InternalTimer(gettimeofday()+1.5, "FHEM::SSCam::roomRefresh", "$camname,0,0,0", 0);
|
||||
|
||||
} elsif ($opt eq "reset") {
|
||||
delReadings($hash);
|
||||
explodeLinkData ($hash, $hash->{DEF}, 1);
|
||||
|
||||
my @r;
|
||||
push @r, "parentState:initialized";
|
||||
push @r, "state:initialized";
|
||||
push @r, "parentCam:initialized";
|
||||
|
||||
setReadings($hash, \@r, 1);
|
||||
|
||||
my $camname = $hash->{LINKPARENT};
|
||||
$defs{$camname}{HELPER}{INFORM} = $hash->{FUUID};
|
||||
|
||||
InternalTimer(gettimeofday()+1.5, "FHEM::SSCam::roomRefresh", "$camname,0,0,0", 0);
|
||||
|
||||
} else {
|
||||
return "$setlist";
|
||||
}
|
||||
@ -316,15 +412,32 @@ sub Get {
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Attr
|
||||
# $cmd can be "del" or "set"
|
||||
# $name is device name
|
||||
# aName and aVal are Attribute name and value
|
||||
################################################################
|
||||
sub Attr {
|
||||
my ($cmd,$name,$aName,$aVal) = @_;
|
||||
my $hash = $defs{$name};
|
||||
my $model = $hash->{MODEL};
|
||||
|
||||
my ($do,$val);
|
||||
|
||||
# $cmd can be "del" or "set"
|
||||
# $name is device name
|
||||
# aName and aVal are Attribute name and value
|
||||
if(defined $hvattr{$aName}) {
|
||||
if ($model eq "master" && !$hvattr{$aName}{master}) {
|
||||
return qq{The attribute "$aName" is only valid if MODEL is not "$model" !};
|
||||
}
|
||||
|
||||
if ($model ne "master" && !$hvattr{$aName}{nomaster}) {
|
||||
return qq{The attribute "$aName" is only valid if MODEL is "master" !};
|
||||
}
|
||||
}
|
||||
|
||||
if($aName eq "genericStrmHtmlTag" && $hash->{MODEL} ne "generic") {
|
||||
return qq{This attribute is only valid if MODEL is "generic" !};
|
||||
}
|
||||
|
||||
if($aName eq "disable") {
|
||||
if($cmd eq "set") {
|
||||
@ -336,8 +449,12 @@ sub Attr {
|
||||
readingsSingleUpdate($hash, "state", $val, 1);
|
||||
}
|
||||
|
||||
if($aName eq "genericStrmHtmlTag" && $hash->{MODEL} ne "generic") {
|
||||
return "This attribute is only usable for devices of MODEL \"generic\" ";
|
||||
if($aName eq "adoptSubset") {
|
||||
if($cmd eq "set") {
|
||||
readingsSingleUpdate($hash, "adoptSubset", $aVal, 1);
|
||||
} else {
|
||||
readingsSingleUpdate($hash, "adoptSubset", "--reset--", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if ($cmd eq "set") {
|
||||
@ -355,22 +472,52 @@ return;
|
||||
sub FwFn {
|
||||
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||
my $hash = $defs{$name};
|
||||
my $link = $hash->{LINK};
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
$hash->{HELPER}{FW} = $FW_wname;
|
||||
|
||||
$link = AnalyzePerlCommand(undef, $link) if($link =~ m/^{(.*)}$/xs);
|
||||
$hash->{HELPER}{FW} = $FW_wname;
|
||||
my $clink = ReadingsVal($name, "clientLink", "");
|
||||
|
||||
explodeLinkData ($hash, $clink, 0);
|
||||
|
||||
# Beispielsyntax: "{$hash->{LINKFN}('$hash->{LINKPARENT}','$hash->{LINKNAME}','$hash->{LINKMODEL}')}";
|
||||
|
||||
my $ftui = 0;
|
||||
my $linkfn = $hash->{LINKFN};
|
||||
my %pars = ( linkparent => $hash->{LINKPARENT},
|
||||
linkname => $hash->{LINKNAME},
|
||||
linkmodel => $hash->{LINKMODEL},
|
||||
omodel => $hash->{MODEL},
|
||||
oname => $hash->{NAME},
|
||||
ftui => $ftui
|
||||
);
|
||||
|
||||
no strict "refs"; ## no critic 'NoStrict'
|
||||
my $html = eval{ &{$linkfn}(\%pars) } or do { return qq{Error in Streaming function definition of <html><a href=\"/fhem?detail=$name\">$name</a></html>} };
|
||||
use strict "refs";
|
||||
|
||||
my $ret = "";
|
||||
|
||||
if(IsModelMaster($hash) && $clink) {
|
||||
my $alias = AttrVal($name, "alias", $name); # Linktext als Aliasname oder Devicename setzen
|
||||
my $lang = AttrVal("global", "language", "EN");
|
||||
my $txt = "is Streaming master of";
|
||||
$txt = "ist Streaming Master von " if($lang eq "DE");
|
||||
my $dlink = "<a href=\"/fhem?detail=$name\">$alias</a> $txt ";
|
||||
$dlink = "$alias $txt " if(AttrVal($name, "noLink", 0)); # keine Links im Stream-Dev generieren
|
||||
$ret .= "<span align=\"center\">$dlink </span>" if(!AttrVal($name,"hideDisplayName",0));
|
||||
}
|
||||
|
||||
if(IsDisabled($name)) {
|
||||
if(AttrVal($name,"hideDisplayName",0)) {
|
||||
$ret .= "Stream-device <a href=\"/fhem?detail=$name\">$name</a> is disabled";
|
||||
} else {
|
||||
$ret .= "<html>Stream-device is disabled</html>";
|
||||
}
|
||||
|
||||
} else {
|
||||
$ret .= $link;
|
||||
$ret .= $html;
|
||||
$ret .= sDevsWidget($name) if(IsModelMaster($hash));
|
||||
}
|
||||
|
||||
my $al = AttrVal($name, "autoRefresh", 0); # Autorefresh nur des aufrufenden FHEMWEB-Devices
|
||||
@ -379,25 +526,52 @@ sub FwFn {
|
||||
Log3($name, 5, "$name - next start of autoRefresh: ".FmtDateTime(gettimeofday()+$al));
|
||||
}
|
||||
|
||||
undef $link;
|
||||
undef $html;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
#############################################################################################
|
||||
# Bestandteile des DEF auflösen
|
||||
# Bestandteile des DEF (oder Link) auflösen
|
||||
# $link = aufzulösender String
|
||||
# $def = 1 -> es ist ein Shash->{DEF} Inhalt, 0 -> eine andere Quelle
|
||||
#############################################################################################
|
||||
sub explodeDEF {
|
||||
sub explodeLinkData {
|
||||
my $hash = shift;
|
||||
my $link = shift;
|
||||
my $def = shift;
|
||||
|
||||
return if(!$link);
|
||||
|
||||
my ($fn,$arg) = split("[()]",$link);
|
||||
|
||||
my $arg = (split("[()]",$link))[1];
|
||||
$arg =~ s/'//xg;
|
||||
($hash->{PARENT},undef,$hash->{MODEL}) = split(",",$arg);
|
||||
$fn =~ s/{//xg;
|
||||
|
||||
if($def) {
|
||||
($hash->{PARENT},$hash->{LINKNAME},$hash->{MODEL}) = split(",",$arg);
|
||||
$hash->{LINKMODEL} = $hash->{MODEL};
|
||||
$hash->{LINKPARENT} = $hash->{PARENT};
|
||||
} else {
|
||||
($hash->{LINKPARENT},$hash->{LINKNAME},$hash->{LINKMODEL}) = split(",",$arg);
|
||||
}
|
||||
|
||||
$hash->{LINKFN} = $fn;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#############################################################################################
|
||||
# Ist das MODEL "master" ?
|
||||
#############################################################################################
|
||||
sub IsModelMaster {
|
||||
my $hash = shift;
|
||||
|
||||
my $mm = $hash->{MODEL} eq "master" ? 1 : 0;
|
||||
|
||||
return $mm;
|
||||
}
|
||||
|
||||
#############################################################################################
|
||||
# Seitenrefresh
|
||||
# festgelegt durch SSCamSTRM-Attribut "autoRefresh" und "autoRefreshFW"
|
||||
@ -459,16 +633,32 @@ return;
|
||||
# Grafik als HTML zurück liefern (z.B. für Widget)
|
||||
################################################################
|
||||
sub streamAsHtml {
|
||||
my ($hash,$ftui) = @_;
|
||||
my $hash = shift;
|
||||
my $ftui = shift;
|
||||
my $name = $hash->{NAME};
|
||||
my $link = $hash->{LINK};
|
||||
|
||||
if ($ftui && $ftui eq "ftui") { # Aufruf aus TabletUI -> FW_cmd ersetzen gemäß FTUI Syntax
|
||||
my $s = substr($link,0,length($link)-2);
|
||||
$link = $s.",'$ftui')}";
|
||||
if($ftui && $ftui eq "ftui") {
|
||||
$ftui = 1;
|
||||
} else {
|
||||
$ftui = 0;
|
||||
}
|
||||
|
||||
$link = AnalyzePerlCommand(undef, $link) if($link =~ m/^{(.*)}$/xs);
|
||||
my $clink = ReadingsVal($name, "clientLink", "");
|
||||
|
||||
explodeLinkData ($hash, $clink, 0);
|
||||
|
||||
my $linkfn = $hash->{LINKFN};
|
||||
my %pars = ( linkparent => $hash->{LINKPARENT},
|
||||
linkname => $hash->{LINKNAME},
|
||||
linkmodel => $hash->{LINKMODEL},
|
||||
omodel => $hash->{MODEL},
|
||||
oname => $hash->{NAME},
|
||||
ftui => $ftui
|
||||
);
|
||||
|
||||
no strict "refs"; ## no critic 'NoStrict'
|
||||
my $html = eval{ &{$linkfn}(\%pars) } or do { return qq{Error in Streaming function definition of <html><a href=\"/fhem?detail=$name\">$name</a></html>} };
|
||||
use strict "refs";
|
||||
|
||||
my $ret = "<html>";
|
||||
if(IsDisabled($name)) {
|
||||
@ -479,11 +669,134 @@ sub streamAsHtml {
|
||||
}
|
||||
|
||||
} else {
|
||||
$ret .= $link;
|
||||
$ret .= $html;
|
||||
}
|
||||
|
||||
$ret .= "</html>";
|
||||
undef $link;
|
||||
|
||||
undef $html;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# delete Readings
|
||||
# $rd = angegebenes Reading löschen
|
||||
################################################################
|
||||
sub delReadings {
|
||||
my $hash = shift;
|
||||
my $rd = shift;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $bl = "state|parentState|adoptSubset"; # Blacklist
|
||||
|
||||
if($rd) { # angegebenes Reading löschen wenn nicht im providerLevel enthalten
|
||||
readingsDelete($hash, $rd) if($rd !~ /$bl/x);
|
||||
return;
|
||||
}
|
||||
|
||||
for my $key (keys %{$hash->{READINGS}}) {
|
||||
readingsDelete($hash, $key) if($key !~ /$bl/x);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# set Readings
|
||||
# $rref = Referenz zum Array der zu setzenen Reading
|
||||
# (Aufbau: <Reading>:<Wert>)
|
||||
# $event = 1 wenn Event generiert werden soll
|
||||
################################################################
|
||||
sub setReadings {
|
||||
my $hash = shift;
|
||||
my $rref = shift;
|
||||
my $event = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
for my $elem (@$rref) {
|
||||
my ($rn,$rval) = split ":", $elem, 2;
|
||||
readingsBulkUpdate($hash, $rn, $rval);
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, $event);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# liefert String aller Streamingdevices außer MODEL = master
|
||||
# und füllt Hash %sdevs{Alias} = Devicename zu Auflösung
|
||||
#
|
||||
# (es wird Alias (wenn gesetzt) oder Devicename verwendet,
|
||||
# Leerzeichen werden durch "#" ersetzt)
|
||||
################################################################
|
||||
sub allStreamDevs {
|
||||
|
||||
my $sd = "";
|
||||
undef %sdevs;
|
||||
|
||||
my @strmdevs = devspec2array("TYPE=SSCamSTRM:FILTER=MODEL!=master"); # Liste Streaming devices außer MODEL = master
|
||||
for my $da (@strmdevs) {
|
||||
next if(!$defs{$da});
|
||||
my $alias = AttrVal($da, "alias", $da);
|
||||
$alias =~ s/\s+/#/gx;
|
||||
$sdevs{$alias} = "$da";
|
||||
}
|
||||
|
||||
for my $a (sort keys %sdevs) {
|
||||
$sd .= "," if($sd);
|
||||
$sd .= $a;
|
||||
}
|
||||
|
||||
for my $d (@strmdevs) { # Devicenamen zusätzlich als Schlüssel speichern damit set <> adopt ohne Widget funktioniert
|
||||
next if(!$defs{$d});
|
||||
$sdevs{$d} = "$d";
|
||||
}
|
||||
|
||||
return $sd;
|
||||
}
|
||||
|
||||
################################################################
|
||||
# Streaming Devices Drop-Down Widget zur Auswahl
|
||||
# in einem Master Streaming Device
|
||||
################################################################
|
||||
sub sDevsWidget {
|
||||
my $name = shift;
|
||||
|
||||
my $Adopts;
|
||||
my $ret = "";
|
||||
my $cmdAdopt = "adopt";
|
||||
my $as = "--reset--,".allStreamDevs();
|
||||
my $valAdopts = AttrVal($name, "adoptSubset", $as);
|
||||
$valAdopts =~ s/\s+/#/gx;
|
||||
|
||||
for my $fn (sort keys %{$data{webCmdFn}}) {
|
||||
next if($data{webCmdFn}{$fn} ne "FW_widgetFallbackFn");
|
||||
no strict "refs"; ## no critic 'NoStrict'
|
||||
$Adopts = &{$data{webCmdFn}{$fn}}($FW_wname,$name,"",$cmdAdopt,$valAdopts);
|
||||
use strict "refs";
|
||||
last if(defined($Adopts));
|
||||
}
|
||||
|
||||
if($Adopts) {
|
||||
$Adopts =~ s,^<td[^>]*>(.*)</td>$,$1,x;
|
||||
} else {
|
||||
$Adopts = FW_pH "cmd.$name=set $name $cmdAdopt", $cmdAdopt, 0, "", 1, 1;
|
||||
}
|
||||
|
||||
## Tabellenerstellung
|
||||
$ret .= "<style>.defsize { font-size:16px; } </style>";
|
||||
$ret .= '<table class="rc_body defsize">';
|
||||
|
||||
$ret .= "<tr>";
|
||||
$ret .= "<td>Streaming Device: </td><td>$Adopts</td>";
|
||||
$ret .= "</tr>";
|
||||
|
||||
$ret .= "</table>";
|
||||
|
||||
return $ret;
|
||||
}
|
||||
@ -501,7 +814,8 @@ return $ret;
|
||||
<ul>
|
||||
The module SSCamSTRM is a special device module synchronized to the SSCam module. It is used for definition of
|
||||
Streaming-Devices. <br>
|
||||
Dependend of the Streaming-Device state, different buttons are provided to start actions:
|
||||
Dependend of the Streaming-Device state, different buttons are provided to start actions: <br><br>
|
||||
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=25%> <col width=75%> </colgroup>
|
||||
@ -534,7 +848,12 @@ return $ret;
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
A SSCam Streaming-device is defined by the SSCam "set <name> createStreamDev" command.
|
||||
A SSCam Streaming-device is defined by the SSCam command: <br><br>
|
||||
|
||||
<ul>
|
||||
set <name> createStreamDev <Device Typ> <br><br>
|
||||
</ul>
|
||||
|
||||
Please refer to SSCam <a href="#SSCamcreateStreamDev">"createStreamDev"</a> command.
|
||||
<br><br>
|
||||
</ul>
|
||||
@ -544,7 +863,7 @@ return $ret;
|
||||
<ul>
|
||||
|
||||
<ul>
|
||||
<li><b>popupStream</b> <br>
|
||||
<li><b>popupStream</b> (only valid if MODEL != master)<br>
|
||||
|
||||
The current streaming content is depicted in a popup window. By setting attribute "popupWindowSize" the
|
||||
size of display can be adjusted. The attribute "popupStreamTo" determines the type of the popup window.
|
||||
@ -555,6 +874,14 @@ return $ret;
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<li><b>adopt <Streaming device> </b> (only valid if MODEL = master)<br>
|
||||
|
||||
A Streaming Device of type <b>master</b> adopts the content of another defined Streaming Device.
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
@ -578,6 +905,14 @@ return $ret;
|
||||
<ul>
|
||||
<ul>
|
||||
|
||||
<a name="adoptSubset"></a>
|
||||
<li><b>adoptSubset</b> (only valid for MODEL "master") <br>
|
||||
In a Streaming <b>master</b> Device a subset of all defined Streaming Devices is selected and used for
|
||||
the <b>adopt</b> command is provided. <br>
|
||||
For control in the FTUI, the selection is also stored in the Reading of the same name.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a name="autoRefresh"></a>
|
||||
<li><b>autoRefresh</b><br>
|
||||
If set, active browser pages of the FHEMWEB-Device which has called the SSCamSTRM-Device, are new reloaded after
|
||||
@ -742,7 +1077,7 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<ul>
|
||||
<br>
|
||||
Das Modul SSCamSTRM ist ein mit SSCam abgestimmtes Gerätemodul zur Definition von Streaming-Devices. <br>
|
||||
Abhängig vom Zustand des Streaming-Devices werden zum Start von Aktionen unterschiedliche Drucktasten angeboten:
|
||||
Abhängig vom Zustand des Streaming-Devices werden zum Start von Aktionen unterschiedliche Drucktasten angeboten: <br><br>
|
||||
<ul>
|
||||
<table>
|
||||
<colgroup> <col width=25%> <col width=75%> </colgroup>
|
||||
@ -775,8 +1110,13 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
Ein SSCam Streaming-Device wird durch den SSCam Befehl "set <name> createStreamDev" erstellt.
|
||||
Siehe auch die Beschreibung zum SSCam <a href="#SSCamcreateStreamDev">"createStreamDev"</a> Befehl.
|
||||
Ein SSCam Streaming-Device wird durch den SSCam Befehl <br><br>
|
||||
|
||||
<ul>
|
||||
set <name> createStreamDev <Device Typ> <br><br>
|
||||
</ul>
|
||||
|
||||
erstellt. Siehe auch die Beschreibung zum SSCam <a href="#SSCamcreateStreamDev">"createStreamDev"</a> Befehl.
|
||||
<br><br>
|
||||
</ul>
|
||||
|
||||
@ -785,7 +1125,7 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<ul>
|
||||
|
||||
<ul>
|
||||
<li><b>popupStream [OK | <Sekunden>]</b> <br>
|
||||
<li><b>popupStream [OK | <Sekunden>]</b> (nur wenn MODEL != master)<br>
|
||||
|
||||
Der aktuelle Streaminhalt wird in einem Popup-Fenster dargestellt. Mit dem Attribut "popupWindowSize" kann die
|
||||
Darstellungsgröße eingestellt werden. Das Attribut "popupStreamTo" legt die Art des Popup-Fensters fest.
|
||||
@ -797,6 +1137,14 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<ul>
|
||||
<li><b>adopt <Streaming Device> </b> (nur wenn MODEL = master)<br>
|
||||
|
||||
Ein Streaming Device vom Type <b>master</b> übernimmt (adoptiert) den Content eines anderen definierten Streaming Devices.
|
||||
</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
@ -821,6 +1169,14 @@ attr <name> genericStrmHtmlTag <img $HTMLATTR
|
||||
<ul>
|
||||
<ul>
|
||||
|
||||
<a name="adoptSubset"></a>
|
||||
<li><b>adoptSubset</b> (nur für MODEL "master") <br>
|
||||
In einem Streaming <b>master</b> Device wird eine Teilmenge aller definierten Streaming Devices ausgewählt und für
|
||||
das <b>adopt</b> Kommando bereitgestellt. <br>
|
||||
Für die Steuerung im FTUI wird die Auswahl ebenfalls im gleichnamigen Reading gespeichert.
|
||||
</li>
|
||||
<br>
|
||||
|
||||
<a name="autoRefresh"></a>
|
||||
<li><b>autoRefresh</b><br>
|
||||
Wenn gesetzt, werden aktive Browserseiten des FHEMWEB-Devices welches das SSCamSTRM-Device aufgerufen hat, nach der
|
||||
|
@ -215,7 +215,6 @@ sub Define {
|
||||
explodeLinkData ($hash, $link, 1);
|
||||
|
||||
$hash->{HELPER}{MODMETAABSENT} = 1 if($modMetaAbsent); # Modul Meta.pm nicht vorhanden
|
||||
# $hash->{LINK} = $link;
|
||||
|
||||
# Versionsinformationen setzen
|
||||
setVersionInfo($hash);
|
||||
@ -224,7 +223,6 @@ sub Define {
|
||||
push @r, "adoptSubset:--reset--" if(IsModelMaster($hash)); # Init für FTUI Subset wenn benutzt (Attr adoptSubset)
|
||||
push @r, "parentState:initialized"; # Init für "parentState" Forum: https://forum.fhem.de/index.php/topic,45671.msg985136.html#msg985136
|
||||
push @r, "state:initialized"; # Init für "state"
|
||||
push @r, "parentCam:initialized"; # Init für Elternkamera
|
||||
|
||||
setReadings($hash, \@r, 1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user