Hallo Martin,
hier https://forum.fhem.de/index.php?topic=145558.0 (https://forum.fhem.de/index.php?topic=145558.0) habe ich auch auf das Problem aufmerksam gemacht.
Ab 10_CUL_HM.pm Zeile 1638
elsif ($evnt =~ m/^(DELETED|RENAMED) (.*?) ?/){
my ($cmd,$ent,$new) =split(" ",$evnt." ");
# $ent no longer exist
# $new is the renamed (if rename)
if (($evnt eq "DELETED" && $defs{$ent}{TYPE} eq "CUL_HM")
wurde nicht beachtet, dass der gelöschtet device hash gelöscht ist und schon der Versuch
'$defs{$ent}{TYPE} eq "CUL_HM"'
erzeugt einen ghost hash auf den DELETED Trigger hin.
Und das nicht nur für HM devices, sondern generell bei Nutzung von 'delete' und geladenem CUL_HM!
Die HM-device spezifische Funktionalität kann in die UndefFn verlagert werden, denn diese wird von CommandDelete vorher mit noch existierendem device hash aufgerufen.
Insbesondere findet in der jetzigen Form auch kein 'remove' vom IO statt, wie es gedacht ist, als weiterer nicht funktionaler Effekt.
Und das primaryDevice wird nicht aktualisiert, weil die Abfrage scheitert. Umziehen darf das aber nicht, weil der device hash wirklich weg sein muss.
Vorschlag CUL_HM_Notify
sub CUL_HM_Notify(@) {###############################
my ($ntfy, $dev) = @_;
#$ntfy - whom to notify
#$dev - who changed
return if( $dev->{NAME} ne 'global'
||$dev->{NAME} eq $ntfy->{NAME}
);# no notification about myself
my $events = deviceEvents($dev, 0);
return if (!defined($events)); # Some previous notify deleted the array.
# my $cws = join(';#',@{$dev->{CHANGED}});
my ($cmd,$ent,$new,$count);
for my $evnt (@{$events}){
($cmd,$ent,$new) = split(" ",$evnt,3);
if ($cmd eq 'ATTR'){#ATTR
if( $new =~ /^ignore 1/ #ATTR ignore - was it the primary notification device?
&& $ent eq $modules{CUL_HM}{helper}{primary}){
$modules{CUL_HM}{helper}{primary} = ''; # force rescan
CUL_HM_primaryDev();
}
}
elsif ($cmd eq 'DELETEATTR'){
}
elsif ($cmd eq 'RENAMED'){
# $ent no longer exist
# $new is the renamed
if ($defs{$new}{TYPE} eq 'CUL_HM'){
CUL_HM_Rename($new,$ent);
CUL_HM_primaryDev() if ($ent eq $modules{CUL_HM}{helper}{primary});
$count++;
}
else{##------- update dependancies to IO devices used
my @culHmDevs = grep{$defs{$_}{DEF} =~ /^......$/} grep{$defs{$_}{TYPE} eq 'CUL_HM'} keys %defs;
## ------ correct IOList and IOGrp
{
my ($ea, $eaOld, $ios);
for my $vccu (grep{AttrVal($_,'IOList','') =~ /,?$ent/} @culHmDevs){# for each vccu
$ea = $eaOld = AttrVal($vccu,'IOList','');
$ea = join(',',grep{defined $defs{$_}}
map{my $foo = $_ ne $ent?$_:$new;$foo}
split(/,/,$ea));
for my $HMdef(grep{AttrVal($_,'IOgrp','') =~ /$vccu:.*$ent/} @culHmDevs){
if($ea){#vccu still operational
(undef,$ios) = split(/:/,AttrVal($HMdef,'IOgrp',''));
$ios = join(',',
grep{defined $defs{$_}}
map{my $foo = $_ ne $ent?$_:$new;$foo}
split(/,/,$ios)
);
$attr{$HMdef}{IOgrp} = "$vccu".($ios ? ":$ios" : '');
$count++;
}
else {# the vccu has no IO anymore - delete clients
CommandDeleteAttr(undef,"$HMdef IOgrp") ;
$count++;
}
}
if ($ea ne $eaOld) {
CommandAttr(undef,"$vccu IOList $ea");
$count++;
}
}
}
for my $HMdef (grep{AttrVal($_,'IODev',ReadingsVal($_,'IODev','')) eq $ent} @culHmDevs){# for each IODev
next if CUL_HM_notActivebyName($HMdef);
CommandAttr(undef,"$HMdef IODev $new");
$count++;
}
}
return ($count ? "CUL_HM: $count device(s) renamed or attributes changed due to $cmd event"
: undef);
}
elsif ($cmd eq 'DELETED'){
# $ent no longer exist
CUL_HM_primaryDev() if ($ent eq $modules{CUL_HM}{helper}{primary});
$count++;
my @culHmDevs = grep{$defs{$_}{DEF} =~ /^......$/} grep{$defs{$_}{TYPE} eq 'CUL_HM'} keys %defs;
## ------ correct IOList and IOGrp
{
my ($ea, $eaOld, $ios);
for my $vccu (grep{AttrVal($_,'IOList','') =~ /,?$ent/} @culHmDevs){# for each vccu
$ea = $eaOld = AttrVal($vccu,'IOList','');
$ea = join(',',grep{defined $defs{$_}}
map{my $foo = $_ ne $ent?$_:'';$foo}
split(/,/,$ea));
for my $HMdef (grep{AttrVal($_,'IOgrp','') =~ /$vccu:.*$ent/} @culHmDevs){
if($ea){#vccu still operational
(undef,$ios) = split(/:/,AttrVal($HMdef,'IOgrp',''));
$ios = join(',',
grep{defined $defs{$_}}
map{my $foo = $_ ne $ent?$_:'';$foo}
split(/,/,$ios)
);
$attr{$HMdef}{IOgrp} = "$vccu".($ios ? ":$ios" : '');
$count++;
}
else {# the vccu has no IO anymore - delete clients
CommandDeleteAttr(undef,"$HMdef IOgrp") ;
$count++;
}
}
if ($ea ne $eaOld) {
CommandAttr(undef,"$vccu IOList $ea");
$count++;
}
}
}
for my $HMdef (grep{AttrVal($_,'IODev',ReadingsVal($_,'IODev','')) eq $ent} @culHmDevs){# for each IODev
next if CUL_HM_notActivebyName($HMdef);
CUL_HM_assignIO($defs{$HMdef});
$count++;
}
return ($count ? "CUL_HM: $count device(s) attributes changed due to $cmd event"
: undef);
}
elsif ($cmd eq 'REREADCFG'){
Log3($ntfy,0,'[FAILURE] CUL_HM does not reliably support rereadcfg any longer! Restart FHEM instead.');
delete $modules{CUL_HM}{helper}{initDone};
CUL_HM_updateConfig('startUp');
InternalTimer(1,\&CUL_HM_setupHMLAN, 'initHMLAN', 0);
}
elsif ($cmd eq 'INITIALIZED'){
if (!$modules{CUL_HM}{helper}{initDone}){# grep the first initialize
CUL_HM_updateConfig('startUp');
InternalTimer(1,\&CUL_HM_setupHMLAN, 'initHMLAN', 0);#start asap once FHEM is operational
}
}
# elsif ($cmd eq 'DEFINED' ){ Log 1,"Info --- $dev->{NAME} -->$ntfy->{NAME} : $evnt";}
# elsif ($cmd eq 'SHUTDOWN'){ Log 1,"Info --- $dev->{NAME} -->$ntfy->{NAME} : $evnt";}#SHUTDOWN|DELAYEDSHUTDOWN
# elsif ($cmd eq 'SAVE' ){ Log 1,"Info --- $dev->{NAME} -->$ntfy->{NAME} : $evnt";}
# elsif ($cmd eq 'MODIFIED'){ Log 1,"Info --- $dev->{NAME} -->$ntfy->{NAME} : $evnt";}
# else { Log 1,"Info --- $dev->{NAME} -->$ntfy->{NAME} : $evnt";}
}
return;
}
Vorschlag CUL_HM_Undef
sub CUL_HM_Undef($$) {###############################
my ($hash, $name) = @_;
my $HMid = $hash->{DEF};
CUL_HM_unQEntity($name,'qReqConf');
CUL_HM_unQEntity($name,'qReqStat');
CUL_HM_complConfigTestRm($name);
my $devName = $hash->{device};
my $chn = substr($HMid,6,2);
if ($chn){# delete a channel
if ( $devName
&& defined(my $devHash = $defs{$devName})) {
delete $devHash->{"channel_$chn"};
$devHash->{helper}{role}{chn} = 1 if($chn eq '01');# return chan 01 role
CUL_HM_hmInitMsg($devHash);
}
delete $hash->{helper}{mId};
}
else{# delete a device
CommandDelete(undef,$hash->{$_}) for (grep(/^channel_/,keys %{$hash}));
if ( defined($hash->{IODev}) #noansi: not possible in DELETED notify
&& ( $hash->{IODev}{helper}{VTS_AES}
|| ( defined($hash->{IODev}{TYPE})
&& $hash->{IODev}{TYPE} =~ /^HM(?:LAN|UARTLGW)$/s) )
) {
IOWrite($hash, '', 'remove:'.CUL_HM_hash2Id($hash));
}
}
delete($modules{CUL_HM}{defptr}{$HMid});
delete $modules{CUL_HM}{helper}{primary} if (devspec2array('TYPE=CUL_HM') == 1);
return;
}