73_DoorBird: New Feature for ftui image history

git-svn-id: https://svn.fhem.de/fhem/trunk@21857 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Sailor
2020-05-04 06:31:32 +00:00
parent 078c128f64
commit 05a2766d9e

View File

@@ -59,6 +59,7 @@ use LWP::UserAgent;
use constant false => 0;
use constant true => 1;
use Data::Dumper;
use File::Spec::Functions ':ALL';
###START###### Initialize module ##############################################################################START####
sub DoorBird_Initialize($)
@@ -89,6 +90,7 @@ sub DoorBird_Initialize($)
"VideoDurationDoorbell " .
"VideoDurationMotion " .
"VideoDurationKeypad " .
"HistoryFilePath:1,0 " .
"EventReset " .
"SessionIdSec:slider,0,10,600 " .
"WaitForHistory " .
@@ -188,6 +190,7 @@ sub DoorBird_Define($$)
$hash->{helper}{EventReset} = AttrVal($name, "EventReset", 5);
$hash->{helper}{WaitForHistory} = AttrVal($name, "WaitForHistory", 7);
$hash->{helper}{CameraInstalled} = false;
$hash->{helper}{HistoryFilePath} = 0;
$hash->{helper}{SessionId} = 0;
$hash->{helper}{UdpMessageId} = 0;
$hash->{helper}{UdpMotionId} = 0;
@@ -265,7 +268,7 @@ sub DoorBird_InitializeDevice($)
DoorBird_OpenSocketConn($hash);
### Initialize Readings
DoorBird_Info_Request($hash, "");
DoorBird_Info_Request($hash, "");
DoorBird_Image_Request($hash, "");
DoorBird_Live_Video($hash, "off");
@@ -538,6 +541,30 @@ sub DoorBird_Attr(@)
$hash->{helper}{VideoDurationKeypad} = "0";
}
}
### Check whether HistoryFilePath attribute has been provided
elsif ($a[2] eq "HistoryFilePath") {
### Check whether HistoryFilePath is defined
if (defined($a[3])) {
### Set helper in hash
$hash->{helper}{HistoryFilePath} = $a[3];
if ($a[3] == true) {
### Update the history list for images and videos
DoorBird_History_List($hash);
}
else {
### Delete all reading entries to files
fhem("deleteReading " . $name . " HistoryFilePath.*");
}
}
else {
### Set helper in hash
$hash->{helper}{HistoryFilePath} = "0";
### Delete all reading entries to files
fhem("deleteReading " . $name . " HistoryFilePath.*");
}
}
### Check whether VideoFileFormat attribute has been provided
elsif ($a[2] eq "VideoFileFormat") {
### Check whether VideoFileFormat is defined
@@ -907,6 +934,10 @@ sub DoorBird_Set($@)
### Call Subroutine and hand back return value
return DoorBird_Transmit_Audio($hash, $option)
}
### TEST
elsif ($command eq "Test") {
DoorBird_History_List($hash);
}
### ADD OR CHANGE FAVORITE
### DELETE FAVORITE
### ADD OR UPDATE SCHEDULE ENTRY
@@ -2550,6 +2581,9 @@ sub DoorBird_Image_Request($$) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Image_Request - write file : Successfully written " . $ImageFileName;
### Update the history list for images and videos
DoorBird_History_List($hash);
### Close file or write error message in log
close $fh or do {
### Log Entry
@@ -2771,6 +2805,9 @@ sub DoorBird_LastEvent_Image($$$) {
### Write Last Image into reading
readingsSingleUpdate($hash, $ReadingImage, $ImageFileName, 1);
### Update the history list for images and videos
DoorBird_History_List($hash);
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_LastEvent_Image - ImageData - event : " . length($ImageData);
@@ -3519,6 +3556,9 @@ sub DoorBird_History_Request_Parse($) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_Request - write file : Successfully written " . $ImageFileName;
### Update the history list for images and videos
DoorBird_History_List($hash);
### Close file or write error message in log
close $fh or do {
### Log Entry
@@ -3555,6 +3595,284 @@ sub DoorBird_History_Request_Parse($) {
}
####END####### Define Subfunction for HISTORY IMAGE REQUEST ####################################################END#####
###START###### Define Subfunction for history list update as readings #########################################START####
sub DoorBird_History_List($) {
my ($hash) = @_;
### Obtain values from hash
my $name = $hash->{NAME};
### If the HistoryFile List shall be created
if ($hash->{helper}{HistoryFilePath} == true) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List ___________________________________________________________";
Log3 $name, 5, $name. " : DoorBird_History_List - The HistoryList has been activated. Processing...";
### Delete all older reading entries to files
#fhem("deleteReading " . $name . " HistoryFilePath.*", 1);
foreach my $DeleteReading (keys %{$hash->{READINGS}}) {
if ($DeleteReading =~ m/HistoryFilePath/ ){
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - Delete Reading : " . $DeleteReading;
### Delete Reading
readingsDelete($hash, $DeleteReading);
}
}
### Get current working directory
my $cwd = getcwd();
### If the ImageFileDir has been defined and images are taken
if ((defined($hash->{helper}{ImageFileDir})) && (($hash->{helper}{ImageFileDir} =~ m/\/fhem\/www/)) || (($hash->{helper}{ImageFileDir} =~ m/\\fhem\\www/))){
my $ImageFileName;
my @ImageFileList;
### If the path is given as UNIX file system format
if ($cwd =~ /\//) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - file system format : UNIX";
### Find out whether it is an absolute path or an relative one (leading "/")
if ($hash->{helper}{ImageFileDir} =~ /^\//) {
$ImageFileName = $hash->{helper}{ImageFileDir};
}
else {
$ImageFileName = $cwd . "/" . $hash->{helper}{ImageFileDir};
}
}
### If the path is given as Windows file system format
if ($hash->{helper}{ImageFileDir} =~ /\\/) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - file system format : WINDOWS";
### Find out whether it is an absolute path or an relative one (containing ":\")
if ($hash->{helper}{ImageFileDir} != /^.:\//) {
$ImageFileName = $cwd . $hash->{helper}{ImageFileDir};
}
else {
$ImageFileName = $hash->{helper}{ImageFileDir};
}
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ImageFileName : " . $ImageFileName;
### Get list of directory items
if (opendir(FileSearch,$ImageFileName)) {
@ImageFileList = readdir(FileSearch);
close FileSearch;
### Define Types to be searched for
my @FileTypes = ("motionsensor", "doorbell", "keypad", "snapshot", "manual");
readingsBeginUpdate($hash);
foreach my $SearchType (@FileTypes) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - SearchType : " . $SearchType;
### Extract all Filenames which matches the SearchType
my @ImageFileListSearch = grep {/$SearchType/} @ImageFileList;
### Extract all Filenames which matches the file extension
my @ImageFileListExt = grep {/jpg/} @ImageFileListSearch;
# Sort list
@ImageFileListExt=sort(@ImageFileListExt);
### Get the last n elements (hash->{helper}{MaxHistory})
@ImageFileListExt = ($hash->{helper}{MaxHistory} >= @ImageFileListExt) ? @ImageFileListExt : @ImageFileListExt[-$hash->{helper}{MaxHistory}..-1];
# Sort list
@ImageFileListExt=sort({$b cmp $a} @ImageFileListExt);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ImageFileListSearch : \n" . Dumper(@ImageFileListExt);
### Update Readings
my $index = 0;
foreach my $FileName (@ImageFileListExt){
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - FileName : " . $FileName;
### Extract timestamp from Filename
my $TimeStamp = substr($FileName,0,4) . "-" . substr($FileName, 4,2) . "-" . substr($FileName, 6,2) . " ";
$TimeStamp .= substr($FileName,9,2) . ":" . substr($FileName,11,2) . ":" . substr($FileName,13,2);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - TimeStamp : " . $TimeStamp;
### Complete relative path from /opt/fhem/www/tablet to $hash->{helper}{ImageFileDir}
my $FilePath = abs2rel(rel2abs($ImageFileName), rel2abs("/opt/fhem/www/tablet"));
my $ReadingsValue = $FilePath . "/" . $FileName;
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - FilePath : " . $FilePath;
### Create ReadingsName for Imagepath and write reading
my $ReadingsName = "HistoryFilePath_" . $SearchType . "_Image_" . sprintf("%02d", $index);
readingsBulkUpdate($hash, $ReadingsName, $ReadingsValue);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsName-Image : " . $ReadingsName;
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsValue-Image : " . $ReadingsValue;
### Create ReadingsName for Timestamp and write reading
$ReadingsName = "HistoryFilePath_" . $SearchType . "_Image_" . sprintf("%02d", $index) . "_Timestamp";
readingsBulkUpdate($hash, $ReadingsName, $TimeStamp);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsName-Timestamp : " . $ReadingsName;
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsValue-Timestamp : " . $TimeStamp;
### Increase Index
$index++;
}
}
}
else {
### Log Entry for warning
Log3 $name, 2, $name. " : DoorBird_History_List - The Attribute \"ImageFileDir\" leads to an directory which produced an error! - Does it actually exist?";
}
}
else {
### Log Entry for warning
Log3 $name, 4, $name. " : DoorBird_History_List - The ImageFileDir has not been provided or has not been created below the web-folder e.g. \"/opt/fhem/www/doorbird-images/\"";
}
### If the VideoFileDir has been defined and Videos are taken
if ((defined($hash->{helper}{VideoFileDir})) && (($hash->{helper}{VideoFileDir} =~ m/\/fhem\/www/) || (($hash->{helper}{ImageFileDir} =~ m/\\fhem\\www/)))){
my $VideoFileName;
my @VideoFileList;
### If the path is given as UNIX file system format
if ($cwd =~ /\//) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - file system format : UNIX";
### Find out whether it is an absolute path or an relative one (leading "/")
if ($hash->{helper}{VideoFileDir} =~ /^\//) {
$VideoFileName = $hash->{helper}{VideoFileDir};
}
else {
$VideoFileName = $cwd . "/" . $hash->{helper}{VideoFileDir};
}
}
### If the path is given as Windows file system format
if ($hash->{helper}{VideoFileDir} =~ /\\/) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - file system format : WINDOWS";
### Find out whether it is an absolute path or an relative one (containing ":\")
if ($hash->{helper}{VideoFileDir} != /^.:\//) {
$VideoFileName = $cwd . $hash->{helper}{VideoFileDir};
}
else {
$VideoFileName = $hash->{helper}{VideoFileDir};
}
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - VideoFileName : " . $VideoFileName;
### Get list of directory items
if (opendir(FileSearch,$VideoFileName)) {
@VideoFileList = readdir(FileSearch);
close FileSearch;
### Define Types to be searched for
my @FileTypes = ("motionsensor", "doorbell", "keypad", "snapshot", "manual");
readingsBeginUpdate($hash);
foreach my $SearchType (@FileTypes) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - SearchType : " . $SearchType;
### Extract all Filenames which matches the SearchType
my @VideoFileListSearch = grep {/$SearchType/} @VideoFileList;
### Extract all Filenames which matches the file extension
my @VideoFileListExt = grep {/$hash->{helper}{VideoFileFormat}/} @VideoFileListSearch;
# Sort list
@VideoFileListExt=sort(@VideoFileListExt);
### Get the last n elements (hash->{helper}{MaxHistory})
@VideoFileListExt = ($hash->{helper}{MaxHistory} >= @VideoFileListExt) ? @VideoFileListExt : @VideoFileListExt[-$hash->{helper}{MaxHistory}..-1];
# Sort list
@VideoFileListExt=sort({$b cmp $a} @VideoFileListExt);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - VideoFileListSearch : \n" . Dumper(@VideoFileListExt);
### Update Readings
my $index = 0;
foreach my $FileName (@VideoFileListExt){
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - FileName : " . $FileName;
### Extract timestamp from Filename
my $TimeStamp = substr($FileName,0,4) . "-" . substr($FileName, 4,2) . "-" . substr($FileName, 6,2) . " ";
$TimeStamp .= substr($FileName,9,2) . ":" . substr($FileName,11,2) . ":" . substr($FileName,13,2);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - TimeStamp : " . $TimeStamp;
### Complete relative path from /opt/fhem/www/tablet to $hash->{helper}{VideoFileDir}
my $FilePath = abs2rel(rel2abs($VideoFileName), rel2abs("/opt/fhem/www/tablet"));
my $ReadingsValue = $FilePath . "/" . $FileName;
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - FilePath : " . $FilePath;
### Create ReadingsName for Videopath and write reading
my $ReadingsName = "HistoryFilePath_" . $SearchType . "_Video_" . sprintf("%02d", $index);
readingsBulkUpdate($hash, $ReadingsName, $ReadingsValue);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsName-Video : " . $ReadingsName;
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsValue-Video : " . $ReadingsValue;
### Create ReadingsName for Timestamp and write reading
$ReadingsName = "HistoryFilePath_" . $SearchType . "_Video_" . sprintf("%02d", $index) . "_Timestamp";
readingsBulkUpdate($hash, $ReadingsName, $TimeStamp);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsName-Timestamp : " . $ReadingsName;
Log3 $name, 5, $name. " : DoorBird_History_List - ReadingsValue-Timestamp : " . $TimeStamp;
### Increase Index
$index++;
}
}
}
else {
### Log Entry for warning
Log3 $name, 2, $name. " : DoorBird_History_List - The Attribute \"VideoFileDir\" leads to an directory which produced an error! - Does it actually exist?";
}
}
else {
### Log Entry for warning
Log3 $name, 4, $name. " : DoorBird_History_List - The VideoFileDir has not been provided or has not been created below the web-folder e.g. \"/opt/fhem/www/doorbird-videos/\"";
}
### Initiate Readings Update
readingsEndUpdate($hash, 1);
}
else {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_List - The HistoryList has been disabled. Not Links to pictures are provided.";
}
}
####END####### Define Subfunction for history list update as readings ##########################################END#####
###START###### Define Subfunction for VIDEO REQUEST ###########################################################START####
sub DoorBird_Video_Request($$$$) {
my ($hash, $duration, $event, $timestamp) = @_;
@@ -3709,6 +4027,9 @@ sub DoorBird_Video_Request($$$$) {
### Log Entry for debugging purposes
Log3 $name, 2, $name. " : DoorBird_Video_Request - Video-Request ha not been implemented for Windows file system. Contact fhem forum and WIKI.";
}
### Update the history list for images and videos after the video has been taken
InternalTimer(gettimeofday()+$duration+3,"DoorBird_History_List", $hash, 0);
}
### If attribute to video directory has NOT been set
else {
@@ -4163,6 +4484,22 @@ sub DoorBird_BlockGet($$$$) {
}
####END####### Blocking Get ####################################################################################END#####
###START###### Calculate relative path ########################################################################START####
sub DoorBird_Rel_Path($$) {
my ($start,$target) = @_;
$start =~ s:/[^/]+:/:; # remove trailing filename
my @spath = grep {$_ ne ''} split(/\//,$start);
my @tpath = grep {$_ ne ''} split(/\//,$target);
# strip common start of the path
while ( @spath && @tpath && $spath[0] eq $tpath[0]) {
shift @spath;
shift @tpath;
}
return ("../"x(@spath)).join('/', @tpath);
}
####END####### Calculate relative path #########################################################################END#####
###START###### Processing Change Log ##########################################################################START####
# Changelog parser for DoorBird changelog as of 2020-02-22 (or earlier) containing multiple product lines.
@@ -4436,7 +4773,13 @@ sub DoorBird_findNewestFWVersion($$$)
<code>OpsModeList</code> : </td><td>A space separated list of names for operational modes (e.g. "Normal Party Fire") on which the DoorBird reacts automatically on events.<BR>
The default value is <code>""</code> = disabled<BR>
</td>
</tr>
</tr>
<tr>
<td>
<code>HistoryFilePath</code> : </td><td>Creates relative datapaths to the last pictures, and videos in order to indicate them directly (e.g. fhem ftui widget "image")<BR>
The default value is <code>"0"</code> = disabled<BR>
</td>
</tr>
</table>
</ul>
</ul>
@@ -4614,7 +4957,13 @@ sub DoorBird_findNewestFWVersion($$$)
<code>OpsModeList</code> : </td><td>Eine durch Leerzeichen getrennte Liste von Namen für Operationszust&auml;nde (e.g. "Normal Party Feuer" auf diese der DoorBird automatisch bei Events reagiert.<BR>
Der Default Wert ist "" = deaktiviert<BR>
</td>
</tr>
</tr>
<tr>
<td>
<code>HistoryFilePath</code> : </td><td>Erstellt Dateipfade zu den letzten Bildern und Videos um sie in den User Interfaces direkt anzuzeigen (e.g. fhem ftui Widget "Image")<BR>
Der Default Wert ist <code>"0"</code> = disabled<BR>
</td>
</tr>
</table>
</ul>
</ul>