2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 03:06:37 +00:00

49_IPCAM: added templates, improved logging

git-svn-id: https://svn.fhem.de/fhem/trunk@23834 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
delmar 2021-02-26 21:39:44 +00:00
parent e92955c5c5
commit 11c0a0569d
3 changed files with 108 additions and 77 deletions

View File

@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide. # 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. # Do not insert empty lines here, update check depends on it.
- feature: 49_IPCAM: added templates, improved logging
- feature: 73_DoorBird: Maximum Size of files stored for Image, Video & Audio - feature: 73_DoorBird: Maximum Size of files stored for Image, Video & Audio
- bugfix: 49_SSCam: solve JS error, remove sscam_tooltip.js - bugfix: 49_SSCam: solve JS error, remove sscam_tooltip.js
- bugfix: 55_DWD_OpenData: no smartmatch warning (forum #118669) - bugfix: 55_DWD_OpenData: no smartmatch warning (forum #118669)

View File

@ -3,6 +3,7 @@
################################################################ ################################################################
# #
# (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de) # (c) 2012 Copyright: Martin Fischer (m_fischer at gmx dot de)
# 2021 Martin Gutenbrunner
# All rights reserved # All rights reserved
# #
# This script is free software; you can redistribute it and/or modify # This script is free software; you can redistribute it and/or modify
@ -26,9 +27,36 @@ package main;
use strict; use strict;
use warnings; use warnings;
sub IPCAM_getSnapshot($); #####################################
sub IPCAM_guessFileFormat($); sub
sub IPCAM_getScheme($); IPCAM_Initialize($$)
{
my ($hash) = @_;
$hash->{DefFn} = "IPCAM::Define";
$hash->{UndefFn} = "IPCAM::Undef";
$hash->{GetFn} = "IPCAM::Get";
$hash->{SetFn} = "IPCAM::Set";
$hash->{AttrList} = "basicauth delay credentials path pathCmd pathPanTilt query snapshots storage timestamp:0,1 ".
"cmdPanLeft cmdPanRight cmdTiltUp cmdTiltDown cmdStep ".
"cmdPos01 cmdPos02 cmdPos03 cmdPos04 cmdPos05 cmdPos06 cmdPos07 cmdPos08 ".
"cmdPos09 cmdPos10 cmdPos11 cmdPos12 cmdPos13 cmdPos14 cmdPos15 cmdPosHome ".
"cmd01 cmd02 cmd03 cmd04 cmd05 cmd06 cmd07 cmd08 ".
"cmd09 cmd10 cmd11 cmd12 cmd13 cmd14 cmd15 ".
"model do_not_notify:1,0 showtime:1,0 scheme:http,https ".
"loglevel:0,1,2,3,4,5,6 disable:0,1 ".
$readingFnAttributes;
}
package IPCAM;
use strict;
use warnings;
use SetExtensions;
use GPUtils qw(:all);
sub getSnapshot($);
sub guessFileFormat($);
sub getScheme($);
my %gets = ( my %gets = (
"image" => "", "image" => "",
@ -44,30 +72,32 @@ my %sets = (
"raw" => "", "raw" => "",
); );
##################################### ## Import der FHEM Funktionen
sub BEGIN {
IPCAM_Initialize($$) GP_Import(qw(
{ readingsSingleUpdate
my ($hash) = @_; readingsBulkUpdate
readingsBulkUpdateIfChanged
$hash->{DefFn} = "IPCAM_Define"; readingsBeginUpdate
$hash->{UndefFn} = "IPCAM_Undef"; readingsEndUpdate
$hash->{GetFn} = "IPCAM_Get"; readingsDelete
$hash->{SetFn} = "IPCAM_Set"; Log3
$hash->{AttrList} = "basicauth delay credentials path pathCmd pathPanTilt query snapshots storage timestamp:0,1 ". RemoveInternalTimer
"cmdPanLeft cmdPanRight cmdTiltUp cmdTiltDown cmdStep ". InternalTimer
"cmdPos01 cmdPos02 cmdPos03 cmdPos04 cmdPos05 cmdPos06 cmdPos07 cmdPos08 ". makeReadingName
"cmdPos09 cmdPos10 cmdPos11 cmdPos12 cmdPos13 cmdPos14 cmdPos15 cmdPosHome ". AttrVal
"cmd01 cmd02 cmd03 cmd04 cmd05 cmd06 cmd07 cmd08 ". gettimeofday
"cmd09 cmd10 cmd11 cmd12 cmd13 cmd14 cmd15 ". attr
"do_not_notify:1,0 showtime:1,0 scheme:http,https ". TimeNow
"loglevel:0,1,2,3,4,5,6 disable:0,1 ". GetFileFromURLQuiet
$readingFnAttributes; SetExtensions
} AttrTemplate_Set
))
};
##################################### #####################################
sub sub
IPCAM_Define($$) { Define($$) {
my ($hash, $def) = @_; my ($hash, $def) = @_;
# define <name> IPCAM <camip:port> # define <name> IPCAM <camip:port>
@ -90,10 +120,10 @@ IPCAM_Define($$) {
##################################### #####################################
sub sub
IPCAM_Undef($$) { Undef($$) {
my ($hash, $name) = @_; my ($hash, $name) = @_;
delete($modules{IPCAM}{defptr}{$hash->{NAME}}); delete($main::modules{IPCAM}{defptr}{$hash->{NAME}});
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
return undef; return undef;
@ -101,19 +131,17 @@ IPCAM_Undef($$) {
##################################### #####################################
sub sub
IPCAM_Set($@) { Set($$$@) {
my ($hash, @a) = @_; my ($hash, $name, $cmd, @args) = @_;
my $name = $hash->{NAME};
my @camCmd; my @camCmd;
# check argument my $list = join(' ', sort keys %sets);
return "Unknown argument $a[1], choose one of ".join(" ", sort keys %sets)
if(!defined($sets{$a[1]}));
shift @a; Log3 $name, 4, "IPCAM ($name) - set: name:$name cmd:$cmd list:$list";
my $cmd = $a[0];
shift @a; # check argument
my @args = @a; return AttrTemplate_Set($hash, $list, $name, $cmd, @args)
if(!defined($sets{$cmd}));
if($cmd eq "pan" || $cmd eq "tilt") { if($cmd eq "pan" || $cmd eq "tilt") {
@ -135,8 +163,8 @@ IPCAM_Set($@) {
"'attr $name cmdStep <your_camera_command>'" "'attr $name cmdStep <your_camera_command>'"
if(defined($args[1]) && !defined(AttrVal($name,"cmdStep",undef))); if(defined($args[1]) && !defined(AttrVal($name,"cmdStep",undef)));
push(@camCmd,$attr{$name}{"cmd".ucfirst($cmd).ucfirst($args[0])}); push(@camCmd,AttrVal($name,"cmd".ucfirst($cmd).ucfirst($args[0]), undef));
push(@camCmd,$attr{$name}{"cmdStep"}."=".$args[1]) push(@camCmd,AttrVal($name,"cmdStep", undef)."=".$args[1])
if(defined($args[1])); if(defined($args[1]));
} elsif($cmd eq "pos") { } elsif($cmd eq "pos") {
@ -151,9 +179,9 @@ IPCAM_Set($@) {
my $arg = ($args[0] =~ /\d+/) ? sprintf("cmdPos%02d",$args[0]) : "cmdPosHome"; my $arg = ($args[0] =~ /\d+/) ? sprintf("cmdPos%02d",$args[0]) : "cmdPosHome";
return "Command for '$cmd $args[0]' is not defined. Please add this attribute first: " . return "Command for '$cmd $args[0]' is not defined. Please add this attribute first: " .
"'attr $name $arg <your_camera_command>'" "'attr $name $arg <your_camera_command>'"
if(!defined($attr{$name}{$arg})); if(!defined(AttrVal($name,$arg,undef)));
push(@camCmd,$attr{$name}{$arg}); push(@camCmd,AttrVal($name,$arg, undef));
} elsif($cmd eq "cmd") { } elsif($cmd eq "cmd") {
@ -167,9 +195,9 @@ IPCAM_Set($@) {
my $arg = sprintf("cmd%02d",$args[0]); my $arg = sprintf("cmd%02d",$args[0]);
return "Command for '$cmd $args[0]' is not defined. Please add this attribute first: " . return "Command for '$cmd $args[0]' is not defined. Please add this attribute first: " .
"'attr $name $arg <your_camera_command>'" "'attr $name $arg <your_camera_command>'"
if(!defined($attr{$name}{$arg})); if(!defined(AttrVal($name,$arg,undef)));
push(@camCmd,$attr{$name}{$arg}); push(@camCmd,AttrVal($name,$arg, undef));
} elsif($cmd eq "raw") { } elsif($cmd eq "raw") {
@ -184,9 +212,9 @@ IPCAM_Set($@) {
if(@camCmd) { if(@camCmd) {
my $camAuth = $hash->{AUTHORITY}; my $camAuth = $hash->{AUTHORITY};
my $basicauth = (defined($attr{$name}{basicauth}) ? $attr{$name}{basicauth} : undef); my $basicauth = AttrVal($name,'basicauth', undef);
my $camURI; my $camURI;
my $camPath = (defined($attr{$name}{path}) ? $attr{$name}{path} : undef); my $camPath = AttrVal($name, 'path', undef);
my $camQuery = join("&",@camCmd); my $camQuery = join("&",@camCmd);
if(($cmd eq "pan" || $cmd eq "tilt" || $cmd =~ /pos/) && if(($cmd eq "pan" || $cmd eq "tilt" || $cmd =~ /pos/) &&
@ -203,7 +231,7 @@ IPCAM_Set($@) {
return "Missing a path value for camURI. Please set attribute 'path', 'pathCmd' and/or 'pathPanTilt' first." return "Missing a path value for camURI. Please set attribute 'path', 'pathCmd' and/or 'pathPanTilt' first."
if(!$camPath && $cmd ne "raw"); if(!$camPath && $cmd ne "raw");
my $scheme = IPCAM_getScheme($hash); my $scheme = getScheme($hash);
if($basicauth) { if($basicauth) {
$camURI = "$scheme://$basicauth" . "@" . "$camAuth/$camPath"; $camURI = "$scheme://$basicauth" . "@" . "$camAuth/$camPath";
@ -221,7 +249,7 @@ IPCAM_Set($@) {
if(defined($attr{$name}{credentials})) { if(defined($attr{$name}{credentials})) {
if(!open(CFG, $attr{$name}{credentials})) { if(!open(CFG, $attr{$name}{credentials})) {
Log 1, "IPCAM $name Cannot open credentials file: $attr{$name}{credentials}"; Log3 $name, 0, "IPCAM ($name) - Cannot open credentials file: $attr{$name}{credentials}";
return undef; return undef;
} }
my @cfg = <CFG>; my @cfg = <CFG>;
@ -233,9 +261,9 @@ IPCAM_Set($@) {
} }
} }
Log3 $name, 4, "IPCAM ($name) - set $cmd requesting $camURI";
my $camret = GetFileFromURLQuiet($camURI); my $camret = GetFileFromURLQuiet($camURI);
Log 5, "ipcam return:$camret"; Log3 $name, 5, "IPCAM ($name) - return:$camret";
} }
return undef; return undef;
@ -243,14 +271,14 @@ IPCAM_Set($@) {
##################################### #####################################
sub sub
IPCAM_Get($@) { Get($@) {
my ($hash, @a) = @_; my ($hash, @a) = @_;
my $modpath = $attr{global}{modpath}; my $modpath = $attr{global}{modpath};
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $seqImages; my $seqImages;
my $seqDelay; my $seqDelay;
my $seqWait; my $seqWait;
my $storage = (defined($attr{$name}{storage}) ? $attr{$name}{storage} : "$modpath/www/snapshots"); my $storage = AttrVal($name,'storage',"$modpath/www/snapshots");
# check syntax # check syntax
return "argument is missing @a" return "argument is missing @a"
@ -274,7 +302,7 @@ IPCAM_Get($@) {
if(! -d $storage) { if(! -d $storage) {
my $ret = mkdir "$storage"; my $ret = mkdir "$storage";
if($ret == 0) { if($ret == 0) {
Log 1, "ipcam Error while creating: $storage: $!"; Log3 $name, 0, "IPCAM ($name) - Error while creating: $storage: $!";
return "Error while creating storagepath $storage: $!"; return "Error while creating storagepath $storage: $!";
} }
} }
@ -284,8 +312,8 @@ IPCAM_Get($@) {
if($arg eq "image") { if($arg eq "image") {
$seqImages = int(defined($attr{$name}{snapshots}) ? $attr{$name}{snapshots} : 1); $seqImages = int(AttrVal($name,'snapshots',1));
$seqDelay = int(defined($attr{$name}{delay}) ? $attr{$name}{delay} : 0); $seqDelay = int(AttrVal($name,'delay',0));
$seqWait = 0; $seqWait = 0;
# housekeeping after number of sequence has changed # housekeeping after number of sequence has changed
@ -295,13 +323,13 @@ IPCAM_Get($@) {
my $n = $r; my $n = $r;
$n =~ s/snapshot//; $n =~ s/snapshot//;
delete $readings->{$r} if( $r =~ m/snapshot/ && int($n) > $seqImages); delete $readings->{$r} if( $r =~ m/snapshot/ && int($n) > $seqImages);
Log 5, "IPCAM $name remove old reading: $r"; Log3 $name, 5, "IPCAM ($name) - remove old reading: $r";
} }
} }
$hash->{READINGS}{snapshots}{VAL} = 0; $hash->{READINGS}{snapshots}{VAL} = 0;
for (my $i=0;$i<$seqImages;$i++) { for (my $i=0;$i<$seqImages;$i++) {
InternalTimer(gettimeofday()+$seqWait, "IPCAM_getSnapshot", $hash, 0); InternalTimer(gettimeofday()+$seqWait, "IPCAM::getSnapshot", $hash, 0);
$seqWait = $seqWait + $seqDelay; $seqWait = $seqWait + $seqDelay;
} }
return undef; return undef;
@ -320,7 +348,7 @@ IPCAM_Get($@) {
##################################### #####################################
sub sub
IPCAM_getSnapshot($) { getSnapshot($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $camAuth = $hash->{AUTHORITY}; my $camAuth = $hash->{AUTHORITY};
@ -335,11 +363,11 @@ IPCAM_getSnapshot($) {
my $dateTime; my $dateTime;
my $modpath = $attr{global}{modpath}; my $modpath = $attr{global}{modpath};
my $seq = int(defined($hash->{SEQ}) ? $hash->{SEQ} : 0); my $seq = int(defined($hash->{SEQ}) ? $hash->{SEQ} : 0);
my $seqImages = int(defined($attr{$name}{snapshots}) ? $attr{$name}{snapshots} : 1); my $seqImages = int(AttrVal($name,'snapshots',1));
my $seqF; my $seqF;
my $seqL = length($seqImages); my $seqL = length($seqImages);
my $storage = (defined($attr{$name}{storage}) ? $attr{$name}{storage} : "$modpath/www/snapshots"); my $storage = AttrVal($name,'storage',"$modpath/www/snapshots");
my $basicauth = (defined($attr{$name}{basicauth}) ? $attr{$name}{basicauth} : undef); my $basicauth = AttrVal($name,'basicauth', undef);
my $timestamp; my $timestamp;
#if(!$storage) { #if(!$storage) {
@ -351,11 +379,11 @@ IPCAM_getSnapshot($) {
$camQuery = $attr{$name}{query} $camQuery = $attr{$name}{query}
if(defined($attr{$name}{query}) && $attr{$name}{query} ne ""); if(defined($attr{$name}{query}) && $attr{$name}{query} ne "");
my $scheme = IPCAM_getScheme($hash); my $uriScheme = getScheme($hash);
if($basicauth) { if($basicauth) {
$camURI = "$scheme://$basicauth" . "@" . "$camAuth/$camPath"; $camURI = "$uriScheme://$basicauth" . "@" . "$camAuth/$camPath";
} else { } else {
$camURI = "$scheme://$camAuth/$camPath"; $camURI = "$uriScheme://$camAuth/$camPath";
} }
$camURI .= "?$camQuery" if($camQuery); $camURI .= "?$camQuery" if($camQuery);
@ -363,7 +391,7 @@ IPCAM_getSnapshot($) {
if(defined($attr{$name}{credentials})) { if(defined($attr{$name}{credentials})) {
if(!open(CFG, $attr{$name}{credentials})) { if(!open(CFG, $attr{$name}{credentials})) {
Log 1, "IPCAM $name Cannot open credentials file: $attr{$name}{credentials}"; Log3 $name, 0, "IPCAM ($name) - Cannot open credentials file: $attr{$name}{credentials}";
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
return undef; return undef;
} }
@ -381,19 +409,21 @@ IPCAM_getSnapshot($) {
$timestamp =~ s/ /_/g; $timestamp =~ s/ /_/g;
$timestamp =~ s/(:|-)//g; $timestamp =~ s/(:|-)//g;
Log3 $name, 3, "IPCAM ($name) - getSnapshot URI: $camURI";
$snapshot = GetFileFromURLQuiet($camURI); $snapshot = GetFileFromURLQuiet($camURI);
# Log3 $name, 5, "IPCAM ($name) - getSnapshot snapshot: $snapshot";
$imageFormat = IPCAM_guessFileFormat(\$snapshot); $imageFormat = guessFileFormat(\$snapshot);
my @imageTypes = qw(JPEG PNG GIF TIFF BMP ICO PPM XPM XBM SVG); my @imageTypes = qw(JPEG PNG GIF TIFF BMP ICO PPM XPM XBM SVG);
if( ! grep { $_ eq "$imageFormat"} @imageTypes) { if( ! grep { $_ eq "$imageFormat"} @imageTypes) {
Log 1, "IPCAM $name Wrong or not supported image format: $imageFormat"; Log3 $name, 1, "IPCAM ($name) - Wrong or not supported image format: $imageFormat";
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
return undef; return undef;
} }
Log GetLogLevel($name,5), "IPCAM $name Image Format: $imageFormat"; Log3 $name, 4, "IPCAM ($name) - Image Format: $imageFormat";
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
if($seq < $seqImages) { if($seq < $seqImages) {
@ -408,33 +438,33 @@ IPCAM_getSnapshot($) {
$imageFile = $name."_snapshot_".$seqF.".".lc($imageFormat); $imageFile = $name."_snapshot_".$seqF.".".lc($imageFormat);
} }
if(!open(FH, ">$storage/$lastSnapshot")) { if(!open(FH, ">$storage/$lastSnapshot")) {
Log 1, "IPCAM $name Can't write $storage/$lastSnapshot: $!"; Log3 $name, 0, "IPCAM ($name) - Can't write $storage/$lastSnapshot: $!";
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
return undef; return undef;
} }
print FH $snapshot; print FH $snapshot;
close(FH); close(FH);
Log 5, "IPCAM $name snapshot $storage/$lastSnapshot written."; Log3 $name, 4, "IPCAM ($name) - snapshot $storage/$lastSnapshot written.";
if(!open(FH, ">$storage/$imageFile")) { if(!open(FH, ">$storage/$imageFile")) {
Log 1, "IPCAM $name Can't write $storage/$imageFile: $!"; Log3 $name, 0, "IPCAM ($name) - Can't write $storage/$imageFile: $!";
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
return undef; return undef;
} }
print FH $snapshot; print FH $snapshot;
close(FH); close(FH);
Log 5, "IPCAM $name snapshot $storage/$imageFile written."; Log3 $name, 4, "IPCAM ($name) - snapshot $storage/$imageFile written.";
readingsBulkUpdate($hash,"last",$lastSnapshot); readingsBulkUpdate($hash,"last",$lastSnapshot, 1);
$hash->{STATE} = "last: $dateTime"; $hash->{STATE} = "last: $dateTime";
$hash->{READINGS}{"snapshot$seqF"}{TIME} = $dateTime; $hash->{READINGS}{"snapshot$seqF"}{TIME} = $dateTime;
$hash->{READINGS}{"snapshot$seqF"}{VAL} = $imageFile; $hash->{READINGS}{"snapshot$seqF"}{VAL} = $imageFile;
} }
Log GetLogLevel($name,4), "IPCAM $name image: $imageFile"; Log3 $name, 4, "IPCAM ($name) - image: $imageFile";
if($seq == $seqImages) { if($seq == $seqImages) {
readingsBulkUpdate($hash,"snapshots",$seq); readingsBulkUpdate($hash,"snapshots",$seq,1 );
$seq = 0; $seq = 0;
} }
readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1)); readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
@ -445,7 +475,7 @@ IPCAM_getSnapshot($) {
##################################### #####################################
sub sub
IPCAM_getScheme($) { getScheme($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -454,7 +484,7 @@ IPCAM_getScheme($) {
##################################### #####################################
sub sub
IPCAM_guessFileFormat($) { guessFileFormat($) {
my ($src) = shift; my ($src) = shift;
my $header; my $header;
my $srcHeader; my $srcHeader;

View File

@ -260,7 +260,7 @@ FHEM/46_TRX_WEATHER.pm KernSani RFXTRX
FHEM/47_OBIS.pm gvzdus Sonstige Systeme FHEM/47_OBIS.pm gvzdus Sonstige Systeme
FHEM/48_MieleAtHome.pm choenig Sonstige Systeme FHEM/48_MieleAtHome.pm choenig Sonstige Systeme
FHEM/49_Arlo.pm maluk Sonstige Systeme FHEM/49_Arlo.pm maluk Sonstige Systeme
FHEM/49_IPCAM.pm mfr69bs Sonstiges FHEM/49_IPCAM.pm delmar Sonstiges
FHEM/49_SSCam.pm DS_Starter Sonstiges FHEM/49_SSCam.pm DS_Starter Sonstiges
FHEM/49_SSCamSTRM.pm DS_Starter Sonstiges FHEM/49_SSCamSTRM.pm DS_Starter Sonstiges
FHEM/49_TBot_List.pm viegener Unterstützende Dienste FHEM/49_TBot_List.pm viegener Unterstützende Dienste