From 789a03ec01b8f9c895ad5a72c8f89e64a7ebeb74 Mon Sep 17 00:00:00 2001 From: Sailor <> Date: Fri, 26 Feb 2021 14:15:09 +0000 Subject: [PATCH] 73_DoorBird: Feature - Maximum Size of files stored for Image, Video & Audio git-svn-id: https://svn.fhem.de/fhem/trunk@23832 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/73_DoorBird.pm | 265 +++++++++++++++++++++++++++++++++++---- 1 file changed, 241 insertions(+), 24 deletions(-) diff --git a/fhem/FHEM/73_DoorBird.pm b/fhem/FHEM/73_DoorBird.pm index 8da729523..200a04b62 100644 --- a/fhem/FHEM/73_DoorBird.pm +++ b/fhem/FHEM/73_DoorBird.pm @@ -62,8 +62,7 @@ use Data::Dumper; use File::Spec::Functions ':ALL'; ###START###### Initialize module ##############################################################################START#### -sub DoorBird_Initialize($) -{ +sub DoorBird_Initialize($) { my ($hash) = @_; $hash->{STATE} = "Init"; @@ -84,8 +83,11 @@ sub DoorBird_Initialize($) "KeepAliveTimeout " . "UdpPort:6524,35344 " . "ImageFileDir " . + "ImageFileDirMaxSize " . "AudioFileDir " . + "AudioFileDirMaxSize " . "VideoFileDir " . + "VideoFileDirMaxSize " . "VideoFileFormat:mpeg,mpg,mp4,avi,mov,dvd,vob,ogg,ogv,mkv,flv,webm " . "VideoDurationDoorbell " . "VideoDurationMotion " . @@ -104,8 +106,7 @@ sub DoorBird_Initialize($) ###START###### Activate module after module has been used via fhem command "define" ##########################START#### -sub DoorBird_Define($$) -{ +sub DoorBird_Define($$) { my ($hash, $def) = @_; my @a = split("[ \t][ \t]*", $def); my $name = $a[0]; @@ -181,8 +182,11 @@ sub DoorBird_Define($$) $hash->{helper}{UdpPort} = AttrVal($name, "UdpPort", 6524); $hash->{helper}{SessionIdSec} = AttrVal($name, "SessionIdSec", 540); $hash->{helper}{ImageFileDir} = AttrVal($name, "ImageFileDir", ""); + $hash->{helper}{ImageFileDirMaxSize} = AttrVal($name, "ImageFileDirMaxSize", 50); $hash->{helper}{AudioFileDir} = AttrVal($name, "AudioFileDir", ""); + $hash->{helper}{AudioFileDirMaxSize} = AttrVal($name, "AudioFileDirMaxSize", 50); $hash->{helper}{VideoFileDir} = AttrVal($name, "VideoFileDir", ""); + $hash->{helper}{VideoFileDirMaxSize} = AttrVal($name, "VideoFileDirMaxSize", 50); $hash->{helper}{VideoFileFormat} = AttrVal($name, "VideoFileFormat","mpeg"); $hash->{helper}{VideoDurationDoorbell} = AttrVal($name, "VideoDurationDoorbell", 0); $hash->{helper}{VideoDurationMotion} = AttrVal($name, "VideoDurationMotion", 0); @@ -229,8 +233,7 @@ sub DoorBird_Define($$) ###START###### Handle Notifications received by this module ##################################################START#### -sub DoorBird_Notify($$) -{ +sub DoorBird_Notify($$) { my ($hash, $dev) = @_; my $name = $hash->{NAME}; my $devName = $dev->{NAME}; # Device that created the events @@ -259,8 +262,7 @@ sub DoorBird_Notify($$) ##START###### Initialize the device when all attributes are available ########################################START#### -sub DoorBird_InitializeDevice($) -{ +sub DoorBird_InitializeDevice($) { my($hash) = @_; my $name = $hash->{NAME}; @@ -292,8 +294,7 @@ sub DoorBird_InitializeDevice($) ###START###### Deactivate module module after "undefine" command by fhem ######################################START#### -sub DoorBird_Undefine($$) -{ +sub DoorBird_Undefine($$) { my ($hash, $def) = @_; my $name = $hash->{NAME}; my $url = $hash->{URL}; @@ -317,8 +318,7 @@ sub DoorBird_Undefine($$) ###START###### Handle attributes after changes via fhem GUI ###################################################START#### -sub DoorBird_Attr(@) -{ +sub DoorBird_Attr(@) { my @a = @_; my $name = $a[1]; my $hash = $defs{$name}; @@ -469,7 +469,7 @@ sub DoorBird_Attr(@) InternalTimer(gettimeofday()+$hash->{helper}{SessionIdSec}, "DoorBird_RenewSessionID", $hash, 0); } } - ### Check whether ImageFileSave attribute has been provided + ### Check whether ImageFileDir attribute has been provided elsif ($a[2] eq "ImageFileDir") { ### Check whether ImageFileSave is defined if (defined($a[3])) { @@ -481,6 +481,34 @@ sub DoorBird_Attr(@) $hash->{helper}{ImageFileDir} = ""; } } + ### Check whether ImageFileDirMaxSize attribute has been provided + elsif ($a[2] eq "ImageFileDirMaxSize") { + + ### If the attribute has not been deleted entirely + if (defined $a[3]) { + ### Check whether ImageFileDirMaxSize is 0 = disabled + if ($a[3] == int($a[3]) && ($a[3] <= 50)) { + ### Save standard value + $hash->{helper}{ImageFileDirMaxSize} = 50; + } + ### If ImageFileDirMaxSize is numeric and greater than 50 + elsif ($a[3] == int($a[3]) && ($a[3] > 50)) { + + ### Save attribute as internal + $hash->{helper}{ImageFileDirMaxSize} = $a[3]; + } + ### If KeepAliveTimeout is NOT numeric or smaller than 50 + else{ + ### Save standard interval as internal + $hash->{helper}{ImageFileDirMaxSize} = 50; + } + } + ### If the attribute has been deleted entirely + else { + ### Save standard interval as internal + $hash->{helper}{ImageFileDirMaxSize} = 50; + } + } ### Check whether AudioFileDir attribute has been provided elsif ($a[2] eq "AudioFileDir") { ### Check whether AudioFileSave is defined @@ -493,6 +521,34 @@ sub DoorBird_Attr(@) $hash->{helper}{AudioFileDir} = ""; } } + ### Check whether AudioFileDirMaxSize attribute has been provided + elsif ($a[2] eq "AudioFileDirMaxSize") { + + ### If the attribute has not been deleted entirely + if (defined $a[3]) { + ### Check whether AudioFileDirMaxSize is 0 = disabled + if ($a[3] == int($a[3]) && ($a[3] <= 50)) { + ### Save standard value + $hash->{helper}{AudioFileDirMaxSize} = 50; + } + ### If AudioFileDirMaxSize is numeric and greater than 50 + elsif ($a[3] == int($a[3]) && ($a[3] > 50)) { + + ### Save attribute as internal + $hash->{helper}{AudioFileDirMaxSize} = $a[3]; + } + ### If KeepAliveTimeout is NOT numeric or smaller than 50 + else{ + ### Save standard interval as internal + $hash->{helper}{AudioFileDirMaxSize} = 50; + } + } + ### If the attribute has been deleted entirely + else { + ### Save standard interval as internal + $hash->{helper}{AudioFileDirMaxSize} = 50; + } + } ### Check whether VideoFileDir attribute has been provided elsif ($a[2] eq "VideoFileDir") { ### Check whether VideoFileSave is defined @@ -505,6 +561,34 @@ sub DoorBird_Attr(@) $hash->{helper}{VideoFileDir} = ""; } } + ### Check whether VideoFileDirMaxSize attribute has been provided + elsif ($a[2] eq "VideoFileDirMaxSize") { + + ### If the attribute has not been deleted entirely + if (defined $a[3]) { + ### Check whether VideoFileDirMaxSize is 0 = disabled + if ($a[3] == int($a[3]) && ($a[3] <= 50)) { + ### Save standard value + $hash->{helper}{VideoFileDirMaxSize} = 50; + } + ### If VideoFileDirMaxSize is numeric and greater than 50 + elsif ($a[3] == int($a[3]) && ($a[3] > 50)) { + + ### Save attribute as internal + $hash->{helper}{VideoFileDirMaxSize} = $a[3]; + } + ### If KeepAliveTimeout is NOT numeric or smaller than 50 + else{ + ### Save standard interval as internal + $hash->{helper}{VideoFileDirMaxSize} = 50; + } + } + ### If the attribute has been deleted entirely + else { + ### Save standard interval as internal + $hash->{helper}{VideoFileDirMaxSize} = 50; + } + } ### Check whether VideoDurationDoorbell attribute has been provided elsif ($a[2] eq "VideoDurationDoorbell") { ### Check whether VideoDurationDoorbell is defined @@ -644,8 +728,7 @@ sub DoorBird_Attr(@) ####END####### Handle attributes after changes via fhem GUI ####################################################END##### ###START###### Obtain value after "get" command by fhem #######################################################START#### -sub DoorBird_Get($@) -{ +sub DoorBird_Get($@) { my ( $hash, @a ) = @_; ### If not enough arguments have been provided @@ -742,8 +825,7 @@ sub DoorBird_Get($@) ###START###### Manipulate service after "set" command by fhem #################################################START#### -sub DoorBird_Set($@) -{ +sub DoorBird_Set($@) { my ( $hash, @a ) = @_; ### If not enough arguments have been provided @@ -2514,6 +2596,7 @@ sub DoorBird_Image_Request($$) { ### Get current working directory my $cwd = getcwd(); + my $ImageFileDir; ### Log Entry for debugging purposes Log3 $name, 5, $name. " : DoorBird_Image_Request - working directory : " . $cwd; @@ -2534,9 +2617,17 @@ sub DoorBird_Image_Request($$) { ### Check whether the last "/" at the end of the path has been given otherwise add it an create complete path if ($hash->{helper}{ImageFileDir} =~ /\/\z/) { + ### Save directory + $ImageFileDir = $ImageFileName; + + ### Create full datapath $ImageFileName .= $ImageFileTimeStamp . "_snapshot.jpg"; } else { + ### Save directory + $ImageFileDir = $ImageFileName . "/"; + + ### Create full datapath $ImageFileName .= "/" . $ImageFileTimeStamp . "_snapshot.jpg"; } } @@ -2553,12 +2644,23 @@ sub DoorBird_Image_Request($$) { else { $ImageFileName = $hash->{helper}{ImageFileDir}; } + + ### Save directory + $ImageFileDir = $ImageFileName; ### Check whether the last "/" at the end of the path has been given otherwise add it an create complete path if ($hash->{helper}{ImageFileDir} =~ /\\\z/) { + ### Save directory + $ImageFileDir = $ImageFileName; + + ### Create full datapath $ImageFileName .= $ImageFileTimeStamp . "_snapshot.jpg"; } else { + ### Save directory + $ImageFileDir = $ImageFileName . "\\"; + + ### Create full datapath $ImageFileName .= "\\" . $ImageFileTimeStamp . "_snapshot.jpg"; } } @@ -2588,9 +2690,13 @@ sub DoorBird_Image_Request($$) { close $fh or do { ### Log Entry Log3 $name, 2, $name. " : DoorBird_Image_Request - close file error : " . $! . " - ". $ImageFileName; - } + }; + + ### Free FileDirSpace if exxeeds maximum + DoorBird_FileSpace($hash, $ImageFileDir, "jpg", $hash->{helper}{ImageFileDirMaxSize}); } + ### Log Entry for debugging purposes Log3 $name, 5, $name. " : DoorBird_Image_Request - ImageData size : " . length($ImageData); Log3 $name, 5, $name. " : DoorBird_Image_Request - ImageTimeStamp : " . $ImageTimeStamp; @@ -3955,6 +4061,7 @@ sub DoorBird_Video_Request($$$$) { ### Get current working directory my $cwd = getcwd(); + my $VideoFileDir; ### Log Entry for debugging purposes Log3 $name, 5, $name. " : DoorBird_Video_Request - working directory : " . $cwd; @@ -3975,9 +4082,17 @@ sub DoorBird_Video_Request($$$$) { ### Check whether the last "/" at the end of the path has been given otherwise add it an create complete path if ($hash->{helper}{VideoFileDir} =~ /\/\z/) { + ### Save directory + $VideoFileDir = $VideoFileName; + + ### Create complete datapath $VideoFileName .= $VideoFileTimeStamp . "_" . $event . "." . $hash->{helper}{VideoFileFormat}; } else { + ### Save directory + $VideoFileDir = $VideoFileName . "/"; + + ### Create complete datapath $VideoFileName .= "/" . $VideoFileTimeStamp . "_" . $event . "." . $hash->{helper}{VideoFileFormat}; } @@ -4018,9 +4133,17 @@ sub DoorBird_Video_Request($$$$) { ### Check whether the last "/" at the end of the path has been given otherwise add it an create complete path if ($hash->{helper}{VideoFileDir} =~ /\\\z/) { + ### Save directory + $VideoFileDir = $VideoFileName; + + ### Create full datapath $VideoFileName .= $VideoFileTimeStamp . "_" . $event . "." . $hash->{helper}{VideoFileFormat}; } else { + ### Save directory + $VideoFileDir = $VideoFileName . "\\"; + + ### Create full datapath $VideoFileName .= "\\" . $VideoFileTimeStamp . "_" . $event . "." . $hash->{helper}{VideoFileFormat}; } @@ -4028,6 +4151,9 @@ sub DoorBird_Video_Request($$$$) { Log3 $name, 2, $name. " : DoorBird_Video_Request - Video-Request ha not been implemented for Windows file system. Contact fhem forum and WIKI."; } + ### Free FileDirSpace if exxeeds maximum + DoorBird_FileSpace($hash, $VideoFileDir, $hash->{helper}{VideoFileFormat}, $hash->{helper}{VideoFileDirMaxSize}); + ### Update the history list for images and videos after the video has been taken InternalTimer(gettimeofday()+$duration+3,"DoorBird_History_List", $hash, 0); } @@ -4509,8 +4635,7 @@ sub DoorBird_Rel_Path($$) { # this means that still multiple versions matching a single product could be in the hash, # e. g. for different prefixes all matching the final product name. -sub DoorBird_parseChangelog($$) -{ +sub DoorBird_parseChangelog($$) { my ($hash, $data) = @_; my $name = $hash->{NAME}; @@ -4553,8 +4678,7 @@ sub DoorBird_parseChangelog($$) undef $version; } ### If version cannot be found - else - { + else { ### Log Entry for debugging purposes Log3 $name, 3, $name. " : DoorBird_parseChangelog - Products without version found in changelog, ignored."; } @@ -4565,8 +4689,7 @@ sub DoorBird_parseChangelog($$) # Find newest firmware version for this device by name or prefix. # The versions hash ref expected as second argument should match the format returned from DoorBird_parseChangelog(). -sub DoorBird_findNewestFWVersion($$$) -{ +sub DoorBird_findNewestFWVersion($$$) { my ($hash, $versions, $product_name) = @_; my $name = $hash->{NAME}; my $newest = 0; @@ -4588,6 +4711,94 @@ sub DoorBird_findNewestFWVersion($$$) } ####END####### Processing Change Log ###########################################################################END##### +###START###### Limit File Space ###############################################################################START#### +sub DoorBird_FileSpace($$$$) { + my ($hash, $FileDir, $FileExt, $FileDirMaxSize) = @_; + my $name = $hash->{NAME}; + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - __________________________________________________________"; + Log3 $name, 5, $name. " : DoorBird_FileSpace - FileDir : " . $FileDir; + Log3 $name, 5, $name. " : DoorBird_FileSpace - FileExt : " . $FileExt; + Log3 $name, 5, $name. " : DoorBird_FileSpace - FileDirMaxSize : " . $FileDirMaxSize . " MByte"; + + + + + my $SizeOfFiles = 0; + my @FileList; + opendir( my $dh, $FileDir ) or die "Cannot opendir '$FileDir': $!\n"; + + ### Search for files of specified extension (FileExt) in specified directory (FileDir) + for my $i ( readdir( $dh ) ) { + if ($i =~ m/$FileExt/) { + + push(@FileList, $FileDir . $i); + my $s = -s $FileDir . $i; + + $SizeOfFiles += $s; + $SizeOfFiles += getdirsize( $FileDir . $i ) if -d $FileDir . $i && $i !~ /^\.\.?$/; + } + } + + ### Sort list of files by name => timestamp + @FileList = sort(@FileList); + + ### Log Entry for debugging purposes + #Log3 $name, 5, $name. " : DoorBird_FileSpace - FileList sorted : \n" . Dumper(@FileList); + + ### Transform Byte in MByte + $SizeOfFiles = int($SizeOfFiles / 1024 / 1024); + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - Dirsize : " . $SizeOfFiles . " MByte"; + + if ($SizeOfFiles > $FileDirMaxSize) { + + ### Calculate Delta Volume to be deleted + my $DeltaVol = $SizeOfFiles - $FileDirMaxSize; + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - MaxDirSize exceeded dV : " . $DeltaVol . " MByte"; + + my $CountVol = 0; + my @FileListToBeDeleted; + + ### If there are files available at all which could be deleted + if (@FileList > 0) { + my $i = 0; + + ### As long their need more files to be deleted + while (($CountVol / 1024 / 1024) < $DeltaVol) { + + ### Add to the list of deleted files + push (@FileListToBeDeleted, $FileList[$i]); + + ### Sum up the volume freed if file is deleted + $CountVol += -s $FileList[$i]; + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - CountVol collected so far : " . int($CountVol/1024/1024) . " MByte"; + + $i++ + } + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - FileListToBeDeleted : \n" . Dumper(@FileListToBeDeleted); + } + + ### Delete oldestFile + my $NoOfDeletedFiles = unlink @FileListToBeDeleted; + + ### Log Entry for debugging purposes + Log3 $name, 5, $name. " : DoorBird_FileSpace - NumberOfDeletedFiles : " . $NoOfDeletedFiles; + } + + ### Close directory + closedir( $dh ); +} +####END####### Limit File Space ################################################################################END##### + 1; ###START###### Description for fhem commandref ################################################################START#### @@ -4662,8 +4873,11 @@ sub DoorBird_findNewestFWVersion($$$) + + + @@ -4742,8 +4956,11 @@ sub DoorBird_findNewestFWVersion($$$) + + +