Merge pull request #6 from CoolTuxNet/patch-cooltux
Anmerkungen und Codeanalyse
This commit is contained in:
commit
23d037f2a5
@ -25,7 +25,7 @@
|
||||
##########################################################################
|
||||
# $Id: 98_Matrix.pm 14063 2022-11-12 12:52:00Z Man-fred $
|
||||
|
||||
package FHEM::Devices::Matrix;
|
||||
package FHEM::Matrix;
|
||||
use strict;
|
||||
use warnings;
|
||||
use HttpUtils;
|
||||
@ -33,8 +33,8 @@ use FHEM::Meta;
|
||||
use GPUtils qw(GP_Export GP_Import);
|
||||
|
||||
use JSON;
|
||||
use vars qw(%data);
|
||||
use FHEM::Core::Authentication::Passwords qw(:ALL);
|
||||
use vars qw(%data); #(CoolTux) sollte auch nicht nötig sein da Du es in dem Package nichts verwendest
|
||||
# use FHEM::Core::Authentication::Passwords qw(:ALL); #(CoolTux) Kann raus da Du es ja hier nicht verwendest
|
||||
require FHEM::Devices::Matrix::Matrix;
|
||||
|
||||
#-- Run before package compilation
|
||||
|
@ -18,6 +18,8 @@ use JSON;
|
||||
#use vars qw(%data);
|
||||
use FHEM::Core::Authentication::Passwords qw(:ALL);
|
||||
|
||||
use experimental qw /switch/; #(CoolTux) - als Ersatz für endlos lange elsif Abfragen
|
||||
|
||||
# strftime
|
||||
# RemoveInternalTimer
|
||||
# readingFnAttributes
|
||||
@ -54,7 +56,10 @@ sub Attr_List{
|
||||
}
|
||||
|
||||
sub Define {
|
||||
my ($hash, $def) = @_;
|
||||
#(CoolTux) bei einfachen übergaben nimmt man die Daten mit shift auf
|
||||
my $hash = shift;
|
||||
my $def = shift;
|
||||
|
||||
my @param = split('[ \t]+', $def);
|
||||
my $name = $param[0]; #$param[0];
|
||||
|
||||
@ -63,6 +68,7 @@ sub Define {
|
||||
if(int(@param) < 1) {
|
||||
return "too few parameters: define <name> Matrix <server> <user>";
|
||||
}
|
||||
|
||||
$hash->{name} = $param[0];
|
||||
$hash->{server} = $param[2];
|
||||
$hash->{user} = $param[3];
|
||||
@ -70,52 +76,87 @@ sub Define {
|
||||
$hash->{helper}->{passwdobj} = FHEM::Core::Authentication::Passwords->new($hash->{TYPE});
|
||||
#$hash->{helper}->{i18} = Get_I18n();
|
||||
$hash->{NOTIFYDEV} = "global";
|
||||
Startproc($hash) if($init_done);
|
||||
|
||||
Startproc($hash) if($init_done); #(CoolTux) Wie startet Startproc() wenn $init_done 0 ist. Dann bleibt das Modul stehen und macht nichts mehr
|
||||
# es empfiehlt sich hier in der NotifyFn das globale Event INITIALIZED abzufangen.
|
||||
# Ok gerade gesehen hast Du gemacht!!!
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
sub Undef {
|
||||
my ($hash, $arg) = @_;
|
||||
my $hash = shift;
|
||||
my $arg = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
# undef $data
|
||||
$data{MATRIX}{"$name"} = undef;
|
||||
$hash->{helper}->{passwdobj}->setDeletePassword($name);
|
||||
$data{MATRIX}{"$name"} = undef; #(CoolTux) Bin mir gerade nicht sicher woher das $data kommt
|
||||
# meinst Du das %data aus main? Das ist für User. Wenn Du als Modulentwickler
|
||||
# etwas zwischenspeichern möchtest dann in $hash->{helper}
|
||||
|
||||
$hash->{helper}->{passwdobj}->setDeletePassword($name); #(CoolTux) das ist nicht nötig,
|
||||
# du löschst jedesmal den Eintrag wenn FHEM beendet wird.
|
||||
# Es sollte eine DeleteFn geben da kannst Du das rein machen
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
sub Startproc {
|
||||
my ($hash) = @_;
|
||||
my $hash = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
Log3($name, 4, "$name : Matrix::Startproc $hash ".AttrVal($name,'matrixPoll','-1'));
|
||||
# Update necessary?
|
||||
Log3($name, 1, "$name: Start V".$hash->{ModuleVersion}." -> V".$Module_Version) if ($hash->{ModuleVersion});
|
||||
|
||||
$hash->{ModuleVersion} = $Module_Version;
|
||||
$language = AttrVal('global','language','EN');
|
||||
$data{MATRIX}{"$name"}{"softfail"} = 1;
|
||||
|
||||
Login($hash) if (AttrVal($name,'matrixPoll',0) == 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub Login {
|
||||
my ($hash) = @_;
|
||||
my $hash = shift;
|
||||
|
||||
Log3($hash->{NAME}, 4, "$hash->{NAME} : Matrix::Login $hash");
|
||||
|
||||
return PerformHttpRequest($hash, 'login', '');
|
||||
}
|
||||
|
||||
##########################
|
||||
sub Notify($$)
|
||||
# sub Notify($$)
|
||||
#(CoolTux) Subroutine prototypes used. See page 194 of PBP (Subroutines::ProhibitSubroutinePrototypes)
|
||||
# Contrary to common belief, subroutine prototypes do not enable
|
||||
# compile-time checks for proper arguments. Don't use them.
|
||||
sub Notify
|
||||
{
|
||||
my ($hash, $dev) = @_;
|
||||
my $hash = shift;
|
||||
my $dev = shift;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
my $devName = $dev->{NAME};
|
||||
|
||||
return "" if(IsDisabled($name));
|
||||
|
||||
my $events = deviceEvents($dev,1);
|
||||
|
||||
return if( !$events );
|
||||
|
||||
if(($devName eq "global") && grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
|
||||
#if(($devName eq "global") && grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
|
||||
#(CoolTux) unnötige Klammern, und vielleicht bisschen übersichtlicher versuchen :-)
|
||||
if ( $devName eq "global"
|
||||
&& grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
|
||||
{
|
||||
Log3($name, 4, "$name : Matrix::Notify $hash");
|
||||
Startproc($hash);
|
||||
}
|
||||
|
||||
|
||||
#(CoolTux) bin mir nicht sicher wieso die Schleife. Nötig ist sie aber egal wofür gedacht nicht.
|
||||
foreach my $event (@{$events}) {
|
||||
$event = "" if(!defined($event));
|
||||
### Writing log entry
|
||||
@ -129,25 +170,41 @@ sub Notify($$)
|
||||
#
|
||||
# processing $event with further code
|
||||
}
|
||||
return undef;
|
||||
|
||||
return; #(CoolTux) es reicht nur return. Wichtig jede sub muss immer mit return enden
|
||||
}
|
||||
|
||||
#############################################################################################
|
||||
# called when the device gets renamed, copy from telegramBot
|
||||
# in this case we then also need to rename the key in the token store and ensure it is recoded with new name
|
||||
sub Rename($$) {
|
||||
my ($new,$old) = @_;
|
||||
sub Rename {
|
||||
my $new = shift;
|
||||
my $old = shift;
|
||||
|
||||
my $hash = $defs{$new};
|
||||
|
||||
$data{MATRIX}{"$new"} = $data{MATRIX}{"$old"};
|
||||
$data{MATRIX}{"$old"} = undef;
|
||||
$hash->{helper}->{passwdobj}->setRename($new,$old);
|
||||
#$data{MATRIX}{"$old"} = undef; (CoolTux) Wenn ein Hash nicht mehr benötigt wird dann delete
|
||||
delete $data{MATRIX}{"$old"}
|
||||
|
||||
my ($passResp,$passErr);
|
||||
($passResp,$passErr) = $hash->{helper}->{passwdobj}->setRename($new,$old); #(CoolTux) Es empfiehlt sich ab zu fragen ob der Wechsel geklappt hat
|
||||
|
||||
Log3($name, 1, "$name : Matrix::Rename - error while change the password hash after rename - $passErr")
|
||||
if ( !defined($passResp)
|
||||
&& defined($passErr) );
|
||||
|
||||
Log3($name, 1, "$name : Matrix::Rename - change password hash after rename successfully")
|
||||
if ( defined($passResp)
|
||||
&& !defined($passErr) );
|
||||
|
||||
#my $nhash = $defs{$new};
|
||||
return;
|
||||
}
|
||||
|
||||
sub I18N {
|
||||
my $value = shift;
|
||||
|
||||
my $def = {
|
||||
'EN' => {
|
||||
'require2' => 'requires 2 arguments'
|
||||
@ -166,22 +223,32 @@ sub Get {
|
||||
my $value = join(" ", @args);
|
||||
#$cmd = '?' if (!$cmd);
|
||||
|
||||
if ($cmd eq "wellknown") {
|
||||
#(CoolTux) Eine endlos Lange elsif Schlange ist nicht zu empfehlen, besser mit switch arbeiten
|
||||
# Im Modulkopf use experimental qw /switch/; verwenden
|
||||
given ($cmd) {
|
||||
when ('wellknown') {
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
elsif ($cmd eq "logintypes") {
|
||||
|
||||
when ('logintypes') {
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
elsif ($cmd eq "sync") {
|
||||
$data{MATRIX}{"$name"}{"softfail"} = 0;
|
||||
|
||||
when ('sync') {
|
||||
$data{MATRIX}{"$name"}{"softfail"} = 0; #(CoolTux) Bin mir gerade nicht sicher woher das $data kommt
|
||||
# meinst Du das %data aus main? Das ist für User. Wenn Du als Modulentwickler
|
||||
# etwas zwischenspeichern möchtest dann in $hash->{helper}
|
||||
$data{MATRIX}{"$name"}{"hardfail"} = 0;
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
elsif ($cmd eq "filter") {
|
||||
|
||||
when ('filter') {
|
||||
return qq("get Matrix $cmd" needs a filterId to request);
|
||||
return PerformHttpRequest($hash, $cmd, $value);
|
||||
}
|
||||
return "Unknown argument $cmd, choose one of logintypes filter sync wellknown";
|
||||
|
||||
default { return "Unknown argument $cmd, choose one of logintypes filter sync wellknown"; }
|
||||
}
|
||||
}
|
||||
|
||||
sub Set {
|
||||
@ -192,49 +259,89 @@ sub Set {
|
||||
#Log3($name, 5, "Set $hash->{NAME}: $name - $cmd - $value");
|
||||
#return "set $name needs at least one argument" if (int(@$param) < 3);
|
||||
|
||||
if ($cmd eq "msg") {
|
||||
#(CoolTux) Eine endlos Lange elsif Schlange ist nicht zu empfehlen, besser mit switch arbeiten
|
||||
# Im Modulkopf use experimental qw /switch/; verwenden
|
||||
|
||||
# if ($cmd eq "msg") {
|
||||
# return PerformHttpRequest($hash, $cmd, $value);
|
||||
# }
|
||||
# elsif ($cmd eq "pollFullstate") {
|
||||
# readingsSingleUpdate($hash, $cmd, $value, 1); # Readings erzeugen
|
||||
# }
|
||||
# elsif ($cmd eq "password") {
|
||||
# my ($erg,$err) = $hash->{helper}->{passwdobj}->setStorePassword($name,$value);
|
||||
# return undef;
|
||||
# }
|
||||
# elsif ($cmd eq "filter") {
|
||||
# return PerformHttpRequest($hash, $cmd, '');
|
||||
# }
|
||||
# elsif ($cmd eq "question") {
|
||||
# return PerformHttpRequest($hash, $cmd, $value);
|
||||
# }
|
||||
# elsif ($cmd eq "questionEnd") {
|
||||
# return PerformHttpRequest($hash, $cmd, $value);
|
||||
# }
|
||||
# elsif ($cmd eq "register") {
|
||||
# return PerformHttpRequest($hash, $cmd, ''); # 2 steps (ToDo: 3 steps empty -> dummy -> registration_token o.a.)
|
||||
# }
|
||||
# elsif ($cmd eq "login") {
|
||||
# return PerformHttpRequest($hash, $cmd, '');
|
||||
# }
|
||||
# elsif ($cmd eq "refresh") {
|
||||
# return PerformHttpRequest($hash, $cmd, '');
|
||||
# }
|
||||
# else {
|
||||
# return "Unknown argument $cmd, choose one of filter:noArg password question questionEnd pollFullstate:0,1 msg register login:noArg refresh:noArg";
|
||||
# }
|
||||
|
||||
given ($cmd) {
|
||||
when ('msg') {
|
||||
return PerformHttpRequest($hash, $cmd, $value);
|
||||
}
|
||||
elsif ($cmd eq "pollFullstate") {
|
||||
when ('pollFullstate') {
|
||||
readingsSingleUpdate($hash, $cmd, $value, 1); # Readings erzeugen
|
||||
}
|
||||
elsif ($cmd eq "password") {
|
||||
when ('password') {
|
||||
my ($erg,$err) = $hash->{helper}->{passwdobj}->setStorePassword($name,$value);
|
||||
return undef;
|
||||
return;
|
||||
}
|
||||
elsif ($cmd eq "filter") {
|
||||
when ('filter') {
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
elsif ($cmd eq "question") {
|
||||
when ('question') {
|
||||
return PerformHttpRequest($hash, $cmd, $value);
|
||||
}
|
||||
elsif ($cmd eq "questionEnd") {
|
||||
when ('questionEnd') {
|
||||
return PerformHttpRequest($hash, $cmd, $value);
|
||||
}
|
||||
elsif ($cmd eq "register") {
|
||||
when ('register') {
|
||||
return PerformHttpRequest($hash, $cmd, ''); # 2 steps (ToDo: 3 steps empty -> dummy -> registration_token o.a.)
|
||||
}
|
||||
elsif ($cmd eq "login") {
|
||||
when ('login') {
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
elsif ($cmd eq "refresh") {
|
||||
when ('refresh') {
|
||||
return PerformHttpRequest($hash, $cmd, '');
|
||||
}
|
||||
else {
|
||||
return "Unknown argument $cmd, choose one of filter:noArg password question questionEnd pollFullstate:0,1 msg register login:noArg refresh:noArg";
|
||||
}
|
||||
|
||||
#return "$opt set to $value. Try to get it.";
|
||||
default {
|
||||
return "Unknown argument $cmd, choose one of filter:noArg password question questionEnd pollFullstate:0,1 msg register login:noArg refresh:noArg";
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
sub Attr {
|
||||
my ($cmd,$name,$attr_name,$attr_value) = @_;
|
||||
|
||||
Log3($name, 4, "Attr - $cmd - $name - $attr_name - $attr_value");
|
||||
|
||||
if($cmd eq "set") {
|
||||
if ($attr_name eq "matrixQuestion_") {
|
||||
my @erg = split(/ /, $attr_value, 2);
|
||||
#$_[2] = "matrixQuestion_n";
|
||||
$_[2] = "matrixQuestion_n";
|
||||
return qq("attr $name $attr_name" ).I18N('require2') if (!$erg[1] || $erg[0] !~ /[0-9]/);
|
||||
$_[2] = "matrixQuestion_$erg[0]";
|
||||
$_[3] = $erg[1];
|
||||
@ -246,11 +353,15 @@ sub Attr {
|
||||
$_[3] = $erg[1];
|
||||
}
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
sub Get_Message($$$) {
|
||||
my($name, $def, $message) = @_;
|
||||
sub Get_Message {
|
||||
my $name = shift;
|
||||
my $def = shift;
|
||||
my $message = shift;
|
||||
|
||||
Log3($name, 3, "$name - $def - $message");
|
||||
my $q = AttrVal($name, "matrixQuestion_$def", "");
|
||||
my $a = AttrVal($name, "matrixAnswer_$def", "");
|
||||
@ -259,8 +370,16 @@ sub Get_Message($$$) {
|
||||
my @answers = split(':', $a);
|
||||
Log3($name, 3, "$name - $q - $a");
|
||||
my $pos = 0;
|
||||
my ($question, $answer);
|
||||
foreach $question (@questions){
|
||||
#my ($question, $answer);
|
||||
my $answer;
|
||||
|
||||
# foreach my $question (@questions){
|
||||
foreach my $question (@questions){ #(CoolTux) - Loop iterator is not lexical. See page 108 of PBP (Variables::RequireLexicalLoopIterators)perlcritic
|
||||
# This policy asks you to use `my'-style lexical loop iterator variables:
|
||||
|
||||
# foreach my $zed (...) {
|
||||
# ...
|
||||
# }
|
||||
Log3($name, 3, "$name - $question - $answers[$pos]");
|
||||
$answer = $answers[$pos] if ($message eq $question);
|
||||
if ($answer){
|
||||
@ -270,11 +389,18 @@ sub Get_Message($$$) {
|
||||
}
|
||||
$pos++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub PerformHttpRequest($$$)
|
||||
sub PerformHttpRequest
|
||||
{
|
||||
my ($hash, $def, $value) = @_;
|
||||
#(CoolTux) hier solltest Du überlegen das Du die einzelnen Anweisung nach der Bedingung in einzelne Funktionen auslagerst
|
||||
# Subroutine "PerformHttpRequest" with high complexity score
|
||||
my $hash = shift;
|
||||
my $def = shift;
|
||||
my $value = shift;
|
||||
|
||||
my $now = gettimeofday();
|
||||
my $name = $hash->{NAME};
|
||||
my $passwd = "";
|
||||
@ -424,12 +550,21 @@ sub PerformHttpRequest($$$)
|
||||
|
||||
Log3($name, 3, qq($name $param->{'msgnumber'} $def Request Busy/Sync $data{MATRIX}{"$name"}{"busy"} / $data{MATRIX}{"$name"}{"sync"}) );
|
||||
HttpUtils_NonblockingGet($param); # Starten der HTTP Abfrage. Es gibt keinen Return-Code.
|
||||
return undef;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub ParseHttpResponse($)
|
||||
sub ParseHttpResponse
|
||||
{
|
||||
my ($param, $err, $data) = @_;
|
||||
|
||||
#(CoolTux) hier solltest Du überlegen das Du die einzelnen Anweisung nach der Bedingung in einzelne Funktionen auslagerst
|
||||
# Subroutine "PerformHttpRequest" with high complexity score
|
||||
|
||||
my $param = shift;
|
||||
my $err = shift;
|
||||
my $data = shift;
|
||||
|
||||
|
||||
my $hash = $param->{hash};
|
||||
my $def = $param->{def};
|
||||
my $value = $param->{value};
|
||||
@ -593,6 +728,7 @@ sub ParseHttpResponse($)
|
||||
#m.relates_to
|
||||
}
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, 1);
|
||||
$data{MATRIX}{"$name"}{"busy"}--; # = $data{MATRIX}{"$name"}{"busy"} - 1; # queue is busy until response is received
|
||||
$data{MATRIX}{"$name"}{"sync"}-- if ($def eq "sync"); # possible next sync
|
||||
@ -632,4 +768,11 @@ sub ParseHttpResponse($)
|
||||
}
|
||||
}
|
||||
# Damit ist die Abfrage zuende.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
1; #(CoolTux) ein Modul endet immer mit 1;
|
||||
|
||||
__END__ #(CoolTux) Markiert im File das Ende des Programms. Danach darf beliebiger Text stehen. Dieser wird vom Perlinterpreter nicht berücksichtigt.
|
Loading…
Reference in New Issue
Block a user