2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-19 00:26:03 +00:00

73_DoorBird: Feature - Videos on Events

git-svn-id: https://svn.fhem.de/fhem/trunk@20383 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Sailor 2019-10-19 19:35:22 +00:00
parent 372ac36f81
commit ce6c44cb54

View File

@ -34,7 +34,8 @@
########################################################################################################################
# List of open Problems:
#
# Check problems with error message after startup: "PERL WARNING: Prototype mismatch: sub main::memcmp: none vs ($$;$) at /usr/local/share/perl/5.24.1/Sub/Exporter.pm line 445."
# Problem with error message after startup: "PERL WARNING: Prototype mismatch: sub main::memcmp: none vs ($$;$) at /usr/local/share/perl/5.24.1/Sub/Exporter.pm line 445."
# This problem has been addressed to GitHub since its based on problems with sub-libary
#
#
########################################################################################################################
@ -83,6 +84,9 @@ sub DoorBird_Initialize($)
"ImageFileDir " .
"AudioFileDir " .
"VideoFileDir " .
"VideoDurationDoorbell " .
"VideoDurationMotion " .
"VideoDurationKeypad " .
"EventReset " .
"SessionIdSec:slider,0,10,600 " .
"WaitForHistory " .
@ -160,7 +164,7 @@ sub DoorBird_Define($$)
}
####END#### Check whether username and password are already encrypted ######################################END#####
###START###### Writing values to global hash ###############################################################START####
###START###### Writing values to global hash ##############################################################START####
$hash->{NAME} = $name;
$hash->{RevisonAPI} = "0.26";
$hash->{helper}{SOX} = "/usr/bin/sox"; #On Windows systems use "C:\Programme\sox\sox.exe"
@ -173,13 +177,14 @@ sub DoorBird_Define($$)
$hash->{helper}{HistoryTime} = "????-??-?? ??:??";
$hash->{helper}{UdpPort} = AttrVal($name, "UdpPort", 6524);
$hash->{helper}{SessionIdSec} = AttrVal($name, "SessionIdSec", 540);
$hash->{helper}{ImageFileDir} = AttrVal($name, "ImageFileDir", 0);
$hash->{helper}{AudioFileDir} = AttrVal($name, "AudioFileDir", 0);
$hash->{helper}{VideoFileDir} = AttrVal($name, "VideoFileDir", 0);
$hash->{helper}{ImageFileDir} = AttrVal($name, "ImageFileDir", "");
$hash->{helper}{AudioFileDir} = AttrVal($name, "AudioFileDir", "");
$hash->{helper}{VideoFileDir} = AttrVal($name, "VideoFileDir", "");
$hash->{helper}{VideoDurationDoorbell} = AttrVal($name, "VideoDurationDoorbell", 0);
$hash->{helper}{VideoDurationMotion} = AttrVal($name, "VideoDurationMotion", 0);
$hash->{helper}{VideoDurationKeypad} = AttrVal($name, "VideoDurationKeypad", 0);
$hash->{helper}{EventReset} = AttrVal($name, "EventReset", 5);
$hash->{helper}{WaitForHistory} = AttrVal($name, "WaitForHistory", 7);
@{$hash->{helper}{OpsModeList}} = split(/ /, AttrVal($name, "OpsModeList", ""));
${$hash->{helper}{OpsModeListBackup}}[0] = "Initial-gJ8990Gl";
$hash->{helper}{CameraInstalled} = false;
$hash->{helper}{SessionId} = 0;
$hash->{helper}{UdpMessageId} = 0;
@ -189,21 +194,25 @@ sub DoorBird_Define($$)
@{$hash->{helper}{RelayAdresses}} = (0);
@{$hash->{helper}{Images}{History}{doorbell}} = ();
@{$hash->{helper}{Images}{History}{motionsensor}} = ();
@{$hash->{helper}{OpsModeList}} = ();
${$hash->{helper}{OpsModeListBackup}}[0] = "Initial-gJ8990Gl";
$hash->{helper}{Images}{Individual}{Data} = "";
$hash->{helper}{Images}{Individual}{Timestamp} = "";
$hash->{helper}{HistoryDownloadActive} = false;
$hash->{helper}{HistoryDownloadCount} = 0;
$hash->{reusePort} = AttrVal($name, 'reusePort', defined(&SO_REUSEPORT)?1:0)?1:0;
####END####### Writing values to global hash ################################################################END#####
####END####### Writing values to global hash ##############################################################END#####
###START###### For Debugging purpose only ##################################################################START####
### For Debugging purpose only
Log3 $name, 5, $name. " : DoorBird - Define H : " . $hash;
Log3 $name, 5, $name. " : DoorBird - Define D : " . $def;
Log3 $name, 5, $name. " : DoorBird - Define A : " . @a;
Log3 $name, 5, $name. " : DoorBird - Define Name : " . $name;
Log3 $name, 5, $name. " : DoorBird - Define SipDevice : " . $hash->{helper}{SipDevice};
####END####### For Debugging purpose only ###################################################################END#####
Log3 $name, 5, $name. " : DoorBird - Define OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird - Define OpsModeListBackup[0] : " . ${$hash->{helper}{OpsModeListBackup}}[0];
### Initialize Socket connection
DoorBird_OpenSocketConn($hash);
@ -433,7 +442,7 @@ sub DoorBird_Attr(@)
$hash->{helper}{ImageFileDir} = "";
}
}
### Check whether AudioFileSave attribute has been provided
### Check whether AudioFileDir attribute has been provided
elsif ($a[2] eq "AudioFileDir") {
### Check whether AudioFileSave is defined
if (defined($a[3])) {
@ -445,7 +454,7 @@ sub DoorBird_Attr(@)
$hash->{helper}{AudioFileDir} = "";
}
}
### Check whether VideoFileSave attribute has been provided
### Check whether VideoFileDir attribute has been provided
elsif ($a[2] eq "VideoFileDir") {
### Check whether VideoFileSave is defined
if (defined($a[3])) {
@ -457,6 +466,42 @@ sub DoorBird_Attr(@)
$hash->{helper}{VideoFileDir} = "";
}
}
### Check whether VideoDurationDoorbell attribute has been provided
elsif ($a[2] eq "VideoDurationDoorbell") {
### Check whether VideoDurationDoorbell is defined
if (defined($a[3])) {
### Set helper in hash
$hash->{helper}{VideoDurationDoorbell} = $a[3];
}
else {
### Set helper in hash
$hash->{helper}{VideoDurationDoorbell} = "0";
}
}
### Check whether VideoDurationMotion attribute has been provided
elsif ($a[2] eq "VideoDurationMotion") {
### Check whether VideoDurationMotion is defined
if (defined($a[3])) {
### Set helper in hash
$hash->{helper}{VideoDurationMotion} = $a[3];
}
else {
### Set helper in hash
$hash->{helper}{VideoDurationMotion} = "0";
}
}
### Check whether VideoDurationKeypad attribute has been provided
elsif ($a[2] eq "VideoDurationKeypad") {
### Check whether VideoDurationKeypad is defined
if (defined($a[3])) {
### Set helper in hash
$hash->{helper}{VideoDurationKeypad} = $a[3];
}
else {
### Set helper in hash
$hash->{helper}{VideoDurationKeypad} = "0";
}
}
### Check whether EventReset attribute has been provided
elsif ($a[2] eq "EventReset") {
### Remove Timer for Event Reset
@ -490,18 +535,26 @@ sub DoorBird_Attr(@)
}
### Check whether OpsModeList attribute has been provided
elsif ($a[2] eq "OpsModeList") {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Attr - OpsModeList entered";
Log3 $name, 5, $name. " : DoorBird_Attr - {OpsModeListBackup}}[0] : " . ${$hash->{helper}{OpsModeListBackup}}[0];
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Attr - OpsModeListBackup is not initial ";
### If the attribute has not been deleted entirely or is empty
if (defined $a[3]) {
### Save backup and empty string as internal
@{$hash->{helper}{OpsModeList}} = split(/ /, $a[3]);
### Save OpsList and empty string as internal
@{$hash->{helper}{OpsModeList}} = split(/ /, $a[3]);
### Update depending Readings
DoorBird_OpsModeUpdate($hash);
}
### If the attribute has been deleted entirely or is empty
else {
### Save backup and empty string as internal
@{$hash->{helper}{OpsModeList}} = "";
### Save OpsList and empty string as internal
@{$hash->{helper}{OpsModeList}} = "";
### Update depending Readings
DoorBird_OpsModeUpdate($hash);
@ -645,7 +698,7 @@ sub DoorBird_Set($@)
$usage .= " Open_Door:" . join(",", @RelayAdresses) . " OpsMode:" . join(",", @OpsModeList) . " Restart:noArg Transmit_Audio";
### If the OpsModeList is not empty
if (${$hash->{helper}{OpsModeList}}[0] ne "") {
if ((defined(${$hash->{helper}{OpsModeList}}[0])) && (${$hash->{helper}{OpsModeList}}[0] ne "")) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Set - The OpsModeList is empty";
@ -750,15 +803,13 @@ sub DoorBird_Set($@)
}
### Log Entry for debugging purposes
Log3 $name, 5, $name . " - DoorBord_Set - " . $ErrorMessage;
Log3 $name, 2, $name . " - DoorBord_Set - Could not open directory for audiofiles. See commandref for attribute \"AudioFileDir\"." if $ErrorMessage ne "";
Log3 $name, 5, $name . " : DoorBord_Set - " . $ErrorMessage;
Log3 $name, 2, $name . " : DoorBord_Set - Could not open directory for audiofiles. See commandref for attribute \"AudioFileDir\"." if $ErrorMessage ne "";
Log3 $name, 5, $name . " : DoorBird_Set - usage : " . $usage;
### Return values
return $usage if $command eq '?';
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Set - usage : " . $usage;
Log3 $name, 3, $name . " - DoorBord_Set - " . $ErrorMessage;
Log3 $name, 2, $name . " - DoorBord_Set - Could not open directory for audiofiles. See commandref for attribute \"AudioFileDir\"." ;
######### Section for response on set-command ##########################################################
### LIVE VIDEO REQUEST
@ -793,11 +844,13 @@ sub DoorBird_Set($@)
### Call Subroutine and hand back return value
return DoorBird_Transmit_Audio($hash, $option)
}
# ### TEST
# elsif ($command eq "Test") {
# ### Call Subroutine and hand back return value
# return "Not doing anything yet";
# }
### TEST
elsif ($command eq "Test") {
### Call Subroutine and hand back return value
DoorBird_Video_Request($hash, 10, "doorbell_001", 1571506485);
return;
}
### ADD OR CHANGE FAVORITE
### DELETE FAVORITE
### ADD OR UPDATE SCHEDULE ENTRY
@ -824,6 +877,9 @@ sub DoorBird_OpsModeUpdate($) {
my $OpsModeActive = ReadingsVal($name, "OpsMode", "");
my $AudioFileDir = $hash->{helper}{AudioFileDir};
### Extract all names of Readings which start with "OpsMode"
my @OpsModeReadings = grep(/OpsMode/, keys(%{$hash->{READINGS}}));
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate ____________________________________________________________";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
@ -831,69 +887,115 @@ sub DoorBird_OpsModeUpdate($) {
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Size of OpsModeList : " . @OpsModeList;
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeActive : " . $OpsModeActive;
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - AudioFileDir : " . $AudioFileDir;
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings Current : " . Dumper(@OpsModeReadings);
### If the OpsModeList has been changed
if (join(",", @{$hash->{helper}{OpsModeListBackup}}) ne join(",", @{$hash->{helper}{OpsModeList}})) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is different from the Backup!";
### If the OpsModeList has not been deleted (is not empty) and the list has not been changed
if ((${$hash->{helper}{OpsModeList}}[0] ne "") && (${$hash->{helper}{OpsModeListBackup}}[0] ne "Initial-gJ8990Gl")) {
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
### Extract all names of Readings which start with "OpsMode"
my @OpsModeReadings = grep(/OpsMode/, keys(%{$hash->{READINGS}}));
### If the OpsModeList has not been deleted (is not empty) and is not in initial state
if ((${$hash->{helper}{OpsModeList}}[0] ne "") && (${$hash->{helper}{OpsModeListBackup}}[0] ne "Initial-gJ8990Gl")) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is filled ";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings : " . Dumper(@OpsModeReadings);
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
### Delete all Readings which start with "OpsMode"
foreach (@OpsModeReadings) {
### Delete all depending Readings
readingsDelete($hash, $_);
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is filled but not in initial state!";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings Old : " . Dumper(@OpsModeReadings);
### Update Reading for the active Operation Mode with the first item of the list
readingsSingleUpdate($hash, "OpsMode", ${$hash->{helper}{OpsModeList}}[0], 1);
### Delete all Readings which start with "OpsMode"
foreach (@OpsModeReadings) {
### Delete all depending Readings
readingsDelete($hash, $_);
}
### Update Reading for the active Operation Mode with the first item of the list
readingsSingleUpdate($hash, "OpsMode", ${$hash->{helper}{OpsModeList}}[0], 1);
### For each item in the list of possible Operation Modes
foreach (@OpsModeList) {
### For each item in the list of possible Operation Modes
foreach (@OpsModeList) {
### Set Prefix for ReadingsName
my $OpsModeReadingPrefix = "OpsMode" . $_;
### Set Prefix for ReadingsName
my $OpsModeReadingPrefix = "OpsMode" . $_;
### For each DoorBirdEvent, create Reading for the file path for the audio messages
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "DoorbellAudio", "", 1);
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "MotionAudio", "", 1);
#readingsSingleUpdate($hash, $OpsModeReadingPrefix . "KeypadAudio", "", 1);
### For each DoorBirdEvent, create Reading for the file path for the audio messages
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "DoorbellAudio", "", 1);
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "MotionAudio", "", 1);
#readingsSingleUpdate($hash, $OpsModeReadingPrefix . "KeypadAudio", "", 1);
### For each DoorBirdEvent, create Reading for relays to be activated in case of event
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "DoorbellRelay", "", 1);
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "MotionRelay", "", 1);
#readingsSingleUpdate($hash, $OpsModeReadingPrefix . "KeypadRelay", "", 1);
}
### Save new Readings in stat file
WriteStatefile();
### Log Entry for debugging purposes
my @OpsModeReadingsNew = grep(/OpsMode/, keys(%{$hash->{READINGS}}));
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings New : " . Dumper(@OpsModeReadingsNew);
### For each DoorBirdEvent, create Reading for relays to be activated in case of event
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "DoorbellRelay", "", 1);
readingsSingleUpdate($hash, $OpsModeReadingPrefix . "MotionRelay", "", 1);
#readingsSingleUpdate($hash, $OpsModeReadingPrefix . "KeypadRelay", "", 1);
}
### Save new Readings in stat file
WriteStatefile();
### If the OpsModeList is empty (is empty) and is not in initial state
elsif ((${$hash->{helper}{OpsModeList}}[0] eq "") && (${$hash->{helper}{OpsModeListBackup}}[0] ne "Initial-gJ8990Gl")) {
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
### Extract all names of Readings which start with "OpsMode"
my @OpsModeReadings = grep(/OpsMode/, keys(%{$hash->{READINGS}}));
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is empty but not in initial state!";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeListBackup : " . Dumper(@{$hash->{helper}{OpsModeListBackup}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings to be deleted : " . Dumper(@OpsModeReadings);
### Delete all Readings which start with "OpsMode"
foreach (@OpsModeReadings) {
### Delete all depending Readings
readingsDelete($hash, $_);
}
}
### If the OpsModeList has not been deleted (is not empty) and is in initial state
elsif ((${$hash->{helper}{OpsModeList}}[0] ne "") && (${$hash->{helper}{OpsModeListBackup}}[0] eq "Initial-gJ8990Gl")) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is NOT empty and in initial state!";
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
}
### If the OpsModeList has been deleted (is empty) and is in initial state
elsif ((${$hash->{helper}{OpsModeList}}[0] eq "") && (${$hash->{helper}{OpsModeListBackup}}[0] eq "Initial-gJ8990Gl")) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is empty and in initial state!";
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
}
### If the OpsModeList is in unknown state
else {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is in unknown state!";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeListBackup Old : " . Dumper(@{$hash->{helper}{OpsModeListBackup}});
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
Log3 $name, 3, $name. " : DoorBird_OpsModeUpdate - OpsModeListBackup New : " . Dumper(@{$hash->{helper}{OpsModeListBackup}});
}
}
### If the OpsModeList is empty
### If the OpsModeList has not been changed
else {
### Extract all names of Readings which start with "OpsMode"
my @OpsModeReadings = grep(/OpsMode/, keys(%{$hash->{READINGS}}));
### Save new list as backup
@{$hash->{helper}{OpsModeListBackup}} = @{$hash->{helper}{OpsModeList}};
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList is empty";
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeList : " . Dumper(@{$hash->{helper}{OpsModeList}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - OpsModeListBackup : " . Dumper(@{$hash->{helper}{OpsModeListBackup}});
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - Readings : " . Dumper(@OpsModeReadings);
### Delete all Readings which start with "OpsMode"
foreach (@OpsModeReadings) {
### Delete all depending Readings
readingsDelete($hash, $_);
}
Log3 $name, 5, $name. " : DoorBird_OpsModeUpdate - The OpsModeList has not been changed.";
}
}
####END####### Update Readings and variables after update of Operation Mode ####################################END#####
@ -923,12 +1025,12 @@ sub DoorBird_OpsModeExecute($$) {
my $cwd = getcwd();
### Log Entry for debugging purposes
Log3 $name, 3, $name. " : DoorBird_OpsModeExecute - working directory : " . $cwd;
Log3 $name, 5, $name. " : DoorBird_OpsModeExecute - working directory : " . $cwd;
### If the path is given as UNIX file system format
if ($cwd =~ /\//) {
### Log Entry for debugging purposes
Log3 $name, 3, $name. " : DoorBird_OpsModeExecute - file system format : LINUX";
Log3 $name, 5, $name. " : DoorBird_OpsModeExecute - file system format : LINUX";
### Find out whether it is an absolute path or an relative one (leading "/")
if ($AudioFileDir =~ /^\//) {
@ -947,7 +1049,7 @@ sub DoorBird_OpsModeExecute($$) {
### If the path is given as Windows file system format
elsif ($cwd =~ /\\/) {
### Log Entry for debugging purposes
Log3 $name, 3, $name. " : DoorBird_OpsModeExecute - file system format : WINDOWS";
Log3 $name, 5, $name. " : DoorBird_OpsModeExecute - file system format : WINDOWS";
### Find out whether it is an absolute path or an relative one (containing ":\")
if ($AudioFileDir != /^.:\//) {
@ -1400,7 +1502,7 @@ sub DoorBird_Read($) {
### Execute event trigger for Operation Mode
DoorBird_OpsModeExecute($hash, "motion");
### Log Entry
Log3 $name, 3, $name. " : An event has been triggered by the DoorBird unit : " . $EVENT;
Log3 $name, 5, $name. " : DoorBird_Read - Timer for reset reading in : " . $hash->{helper}{EventReset};
@ -1465,7 +1567,7 @@ sub DoorBird_Read($) {
### Execute event trigger for Operation Mode
DoorBird_OpsModeExecute($hash, "keypad");
### Log Entry
Log3 $name, 3, $name. " : An event has been triggered by the DoorBird unit : " . $EVENT;
Log3 $name, 5, $name. " : DoorBird_Read - Timer for reset reading in : " . $hash->{helper}{EventReset};
@ -2326,7 +2428,7 @@ sub DoorBird_Image_Request($$) {
Log3 $name, 5, $name. " : DoorBird_Image_Request - hash - ImageFileDir : " . $hash->{helper}{ImageFileDir};
### If pictures supposed to be saved as files
if ($hash->{helper}{ImageFileDir} ne "0") {
if ($hash->{helper}{ImageFileDir} ne "") {
### Get current working directory
my $cwd = getcwd();
@ -2421,16 +2523,21 @@ sub DoorBird_LastEvent_Image($$$) {
my $name = $hash->{NAME};
my $event = $param->{event};
my $timestamp = $param->{timestamp};
my $VideoEvent;
my $httpHeader;
my $ReadingImage;
if ($event =~ m/doorbell/ ){
$ReadingImage = "doorbell_snapshot_" . sprintf("%03d", $param->{doorbellNo});
$VideoEvent = "doorbell_" . sprintf("%03d", $param->{doorbellNo});
}
elsif ($event =~ m/motion/ ){
$ReadingImage = "motion_snapshot";
$VideoEvent = "motionsensor"
}
elsif ($event =~ m/keypad/ ){
$ReadingImage = "keypad_snapshot";
$VideoEvent = "keypad"
}
else {
### Create Log entry
@ -2474,9 +2581,9 @@ sub DoorBird_LastEvent_Image($$$) {
$ImageData =~ s{\n}{}g;
### Create Timestamp
my $httpHeader = $param->{httpheader};
$httpHeader =~ s/^[^_]*X-Timestamp: //;
$httpHeader =~ s/\n.*//g;
$httpHeader = $param->{httpheader};
$httpHeader =~ s/^[^_]*X-Timestamp: //;
$httpHeader =~ s/\n.*//g;
### If timestamp from history image has NOT been done since the timestamp from the event
if ((int($timestamp) - int($httpHeader)) > 0){
@ -2663,7 +2770,12 @@ sub DoorBird_LastEvent_Image($$$) {
readingsSingleUpdate($hash, $ReadingImage, "No image data", 1);
}
}
### If the attribute VideoDurationDoorbell has been set and therefore an video shall be recorded
if ($hash->{helper}{VideoDurationDoorbell} > 0){
### Call sub for Videorecording
DoorBird_Video_Request($hash, $hash->{helper}{VideoDurationDoorbell}, $VideoEvent, $httpHeader);
}
return;
}
####END####### Define Subfunction for LAST EVENT IMAGE REQUEST #################################################END#####
@ -3280,7 +3392,6 @@ sub DoorBird_History_Request_Parse($) {
Log3 $name, 2, $name. " : DoorBird_History_Request - close file error : " . $! . " - ". $ImageFileName;
}
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_History_Request - Index - motionsensor : " . $UrlIndex;
Log3 $name, 5, $name. " : DoorBird_History_Request - ImageData- motionsensor: " . length($ImageData);
@ -3311,7 +3422,169 @@ sub DoorBird_History_Request_Parse($) {
}
####END####### Define Subfunction for HISTORY IMAGE REQUEST ####################################################END#####
###START###### Define Subfunction for LIST FAVOURITES #########################################################START####
###START###### Define Subfunction for VIDEO REQUEST ###########################################################START####
sub DoorBird_Video_Request($$$$) {
my ($hash, $duration, $event, $timestamp) = @_;
### Obtain values from hash
my $name = $hash->{NAME};
my $url = $hash->{helper}{URL};
my $Method = "GET";
my $Header = "Accept: application/json";
my $VideoFileName;
my $ReadingVideo;
my $err;
my $data;
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request ___________________________________________________________";
Log3 $name, 5, $name. " : DoorBird_Video_Request - duration : " . $duration;
Log3 $name, 5, $name. " : DoorBird_Video_Request - event : " . $event;
Log3 $name, 5, $name. " : DoorBird_Video_Request - timestamp : " . $timestamp;
### Create name for Reading holding the filename for the event triggered video
if ($event =~ m/doorbell/ ){
Log3 $name, 5, $name. " : DoorBird_Video_Request - doorbell event old : " . $event;
### Extract doorbell pushbutton number from event
my $DoorbellNo = $event =~ s/doorbell_//;
### Reset event back to doorbell without pushbutton number
$event = "doorbell";
$ReadingVideo = "doorbell_video_" . sprintf("%03d", $DoorbellNo);
Log3 $name, 5, $name. " : DoorBird_Video_Request - doorbellevent new : " . $event;
Log3 $name, 5, $name. " : DoorBird_Video_Request - DoorbellNo : " . $DoorbellNo;
}
elsif ($event =~ m/motionsensor/ ){
$ReadingVideo = "motion_video";
}
elsif ($event =~ m/keypad/ ){
$ReadingVideo = "keypad_video";
}
else {
### Create Log entry
Log3 $name, 2, $name. " : DoorBird_LastEvent_Image - Unknown event. Breaking up";
### Exit sub
return
}
Log3 $name, 3, $name. " : DoorBird_Video_Request - ReadingVideo : " . $ReadingVideo;
### Create complete command URL for DoorBird depending on whether SessionIdSecurity has been enabled (>0) or disabled (=0)
my $UrlPrefix = "http://" . $url . "/bha-api/";
my $UrlPostfix;
if ($hash->{helper}{SessionIdSec} > 0) {
$UrlPostfix = "?sessionid=" . $hash->{helper}{SessionId};
}
else {
my $username = DoorBird_credential_decrypt($hash->{helper}{".USER"});
my $password = DoorBird_credential_decrypt($hash->{helper}{".PASSWORD"});
$UrlPostfix = "?http-user=". $username . "&http-password=" . $password;
}
my $CommandURL = $UrlPrefix . "video.cgi" . $UrlPostfix;
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - CommandURL : " . $CommandURL ;
### Create Timestamp
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime($timestamp);
my $VideoFileTimeStamp = sprintf ( "%04d%02d%02d-%02d%02d%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);
### Update STATE of device
readingsSingleUpdate($hash, "state", "Retrieving video", 1);
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - hash - VideoFileDir : " . $hash->{helper}{VideoFileDir};
### If attribute to video directory has been set
if ($hash->{helper}{VideoFileDir} ne "") {
### Get current working directory
my $cwd = getcwd();
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - working directory : " . $cwd;
### If the path is given as UNIX file system format
if ($cwd =~ /\//) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - file system format : LINUX";
### 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};
}
### 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/) {
$VideoFileName .= $VideoFileTimeStamp . "_" . $event . ".mpeg";
}
else {
$VideoFileName .= "/" . $VideoFileTimeStamp . "_" . $event . ".mpeg";
}
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - VideoFileName : " . $VideoFileName;
### Create command for shell
my $ShellCommand = "timeout " . $duration . " ffmpeg -hide_banner -loglevel panic -re -i '" . $CommandURL . "' -filter:v setpts=4.0*PTS -y " . $VideoFileName . " &";
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - ShellCommand : " . $ShellCommand;
### Pass shell command to shell and continue with the code below
eval {
system($ShellCommand) or die "Could not execute" . $ShellCommand . " ". $@;
};
### If error message appered
if ( $@ ) {
# $ErrorMessage = $@;
}
### Write Last video into reading
readingsSingleUpdate($hash, $ReadingVideo, $VideoFileName, 1);
}
### If the path is given as Windows file system format
if ($hash->{helper}{VideoFileDir} =~ /\\/) {
### Log Entry for debugging purposes
Log3 $name, 5, $name. " : DoorBird_Video_Request - 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};
}
### 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/) {
$VideoFileName .= $VideoFileTimeStamp . "_" . $event . ".mpeg";
}
else {
$VideoFileName .= "\\" . $VideoFileTimeStamp . "_" . $event . ".mpeg";
}
### 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.";
}
}
### If attribute to video directory has NOT been set
else {
### Log Entry for debugging purposes
Log3 $name, 2, $name . " : DoorBird_Video_Request - Could not open directory for video files. See commandref for attribute \"VideoFileDir\".";
}
return;
}
####END####### Define Subfunction for VIDEO REQUEST ############################################################END#####
##START###### Define Subfunction for LIST FAVOURITES #########################################################START####
sub DoorBird_List_Favorites($$) {
my ($hash, $option) = @_;
my $name = $hash->{NAME};