2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-09 20:57:11 +00:00

36_Shelly.pm:bug fix undefined values on restart

git-svn-id: https://svn.fhem.de/fhem/trunk@28117 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Starkstrombastler 2023-10-31 22:21:38 +00:00
parent 8f95c63d6a
commit 51e879e252
2 changed files with 44 additions and 27 deletions

View File

@ -1,5 +1,6 @@
# 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.
- bugfix: 36_Shelly: undefinded values on restart
- bugfix: 36_Shelly: Refresh: removed fixed name of FHEMWEB device
Gen.2: on/off-for-timer
update interval of GetStatus call

View File

@ -34,6 +34,8 @@
# 5.03 Bug Fix: Refresh: removed fixed name of FHEMWEB device
# Bug Fix: Gen.2: on/off-for-timer
# Bug Fix: update interval of GetStatus call
# 5.04 Bug Fix: undefined values on restart
# Energymeter activated
package main;
@ -48,7 +50,10 @@ use vars qw{%attr %defs};
sub Log($$);
#-- globals on start
my $version = "5.03 31.10.2023";
my $version = "5.04 01.11.2023";
my $defaultINTERVAL = 60;
my $secndIntervalMulti = 4; # Multiplier for 'long update'
#-- support differtent readings-names for energy & power metering
my %mapping = (
@ -394,7 +399,8 @@ my %shelly_events = ( # events, that can be used by webhooks; key is mode, value
"roller" => ["cover.stopped","cover.opening","cover.closing","cover.open","cover.closed"],
"switch" => ["input.toggle_on","input.toggle_off"], # for input instances of type switch
"button" => ["input.button_push","input.button_longpush","input.button_doublepush","input.button_triplepush"], # for input instances of type button
"emeter" => ["em.active_power_change","em.voltage_change","em.current_change"]
"emeter" => ["em.active_power_change","em.voltage_change","em.current_change"],
"touch" => ["input.touch_swipe_up","input.touch_swipe_down","input.touch_multi_touch"]
);
my %fhem_events = ( # events, that can be used by webhooks; key is shelly-event, value is event
@ -432,22 +438,32 @@ my %fhem_events = ( # events, that can be used by webhooks; key is shelly-event,
"btn2_longpush_url" => "long_push 1",
#Gen 2
#relay
"switch.on" => "out_on",
"switch.off" => "out_off",
#roller
"cover.stopped" => "stopped",
"cover.opening" => "opening",
"cover.closing" => "closing",
"cover.open" => "is_open",
"cover.closed" => "is_closed",
#switch
"input.toggle_on" => "button_on",
"input.toggle_off" => "button_off",
#button
"input.button_push" => "single_push",
"input.button_longpush" => "long_push",
"input.button_doublepush" => "double_push",
"input.button_triplepush" => "triple_push",
#touch
"input.touch_swipe_up" => "swipe_up",
"input.touch_swipe_down" => "swipe_down",
"input.touch_multi_touch" => "multi_touch",
#emeter
"em.active_power_change" => "Active_Power",
"em.voltage_change" => "Voltage",
"em.current_change" => "Current",
# translations
"S" => "single_push",
"L" => "long_push",
"SS" => "double_push",
@ -645,7 +661,7 @@ sub Shelly_Define($$) {
my $dev = $a[2];
$hash->{TCPIP} = $dev;
$hash->{INTERVAL} = AttrVal($hash->{NAME},"interval",60); # Updates each minute, if not set as attribute
$hash->{INTERVAL} = AttrVal($hash->{NAME},"interval",$defaultINTERVAL); # Updates each minute, if not set as attribute
$modules{Shelly}{defptr}{$a[0]} = $hash;
@ -877,16 +893,14 @@ sub Shelly_get_model {
$AttrList =~ s/$attributes{'input'}/""/e;
}
if( !$mode && $shelly_models{$model}[0]<2 ){
# delete 'defchannel' from attribute list for single-mode devices with less than 2 relays
$AttrList =~ s/\sdefchannel//;
}elsif( ($mode ne "roller" && $shelly_models{$model}[0]>1) || #more than one relay
($mode ne "relay" && $shelly_models{$model}[1]>1) || #more than one roller
($mode eq "white" && $shelly_models{$model}[2]>1) ){ #more than one dimmer
# we have multiple channel and need attribute 'defchannel'
if( defined($mode) && $mode eq "relay" && $shelly_models{$model}[0]>1 ){ #more than one relay
}elsif( defined($mode) && $mode eq "roller" && $shelly_models{$model}[1]>1 ){ #more than one roller
}elsif( defined($mode) && $mode eq "white" && $shelly_models{$model}[2]>1 ){ #more than one dimmer
}elsif( $shelly_models{$model}[0]>1 || $shelly_models{$model}[1]>1 || $shelly_models{$model}[2]>1 ){ # we have single mode but multiple channel
}else{
# delete 'defchannel' from attribute list
$AttrList =~ s/\sdefchannel//;
Log3 $name,4,"[Shelly_get_model] deleted defchannel from device $name: model=$model, mode=". (!$mode?"not defined":$mode);
}
if( $shelly_models{$model}[4]==0 && $model ne "shellybulb" ){ # 1st Gen
@ -1707,7 +1721,7 @@ sub Shelly_Set ($@) {
if( IsInt($value) && $value >= 0){ # see 99_Utils.pm
$hash->{INTERVAL}=int($value);
}elsif( $value == -1 ){
$value=AttrVal($name,"interval",60);
$value=AttrVal($name,"interval",$defaultINTERVAL);
$hash->{INTERVAL}=$value;
}else{
my $msg = "Value is not an positve integer";
@ -1721,7 +1735,7 @@ sub Shelly_Set ($@) {
RemoveInternalTimer($hash,"Shelly_status");
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
RemoveInternalTimer($hash,"Shelly_shelly");
InternalTimer(gettimeofday()+120, "Shelly_shelly", $hash,0);
InternalTimer(gettimeofday()+$defaultINTERVAL*$secndIntervalMulti, "Shelly_shelly", $hash,0);
if( $model eq "shellypro3em" ){
RemoveInternalTimer($hash,"Shelly_EMData");
InternalTimer(int((gettimeofday()+60)/60)*60+1, "Shelly_EMData", $hash,0);
@ -1738,7 +1752,7 @@ sub Shelly_Set ($@) {
RemoveInternalTimer($hash,"Shelly_status");
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
RemoveInternalTimer($hash,"Shelly_shelly");
InternalTimer(gettimeofday()+120, "Shelly_shelly", $hash,0);
InternalTimer(gettimeofday()+$defaultINTERVAL*$secndIntervalMulti, "Shelly_shelly", $hash,0);
RemoveInternalTimer($hash,"Shelly_EMData");
InternalTimer(int((gettimeofday()+60)/60)*60+1, "Shelly_EMData", $hash,0);
}else{
@ -2376,6 +2390,7 @@ sub Shelly_status {
my $state = $hash->{READINGS}{state}{VAL};
my $model = AttrVal($name,"model","generic");
my $creds = Shelly_pwd($hash);
my $url = "http://$creds".$hash->{TCPIP};
my $timeout = AttrVal($name,"timeout",4);
@ -2384,7 +2399,7 @@ sub Shelly_status {
if ( $hash && $err && $hash->{INTERVAL} != 0 ){ ## ($err || $data )
#-- cyclic update nevertheless
RemoveInternalTimer($hash,"Shelly_status");
my $interval=minNum(120,$hash->{INTERVAL});
my $interval=minNum($hash->{INTERVAL},$defaultINTERVAL*$secndIntervalMulti);
Log3 $name,3,"[Shelly_status] $name: Error in callback, update in $interval seconds";
InternalTimer(gettimeofday()+$interval, "Shelly_status", $hash, 1);
}
@ -2469,14 +2484,14 @@ sub Shelly_status {
readingsBulkUpdateIfChanged($hash,"network","<html>connected to <a href=\"http://".$hash->{TCPIP}."\">".$hash->{TCPIP}."</a></html>",1);
readingsEndUpdate($hash,1);
}
my $next; # Time offset in seconds for next update
if( !$is2G ){
$next=Shelly_proc1G($hash,$jhash);
}else{
$next=Shelly_proc2G($hash,$comp,$jhash);
}
Log3 $name,4,"[Shelly_status] $name: proc.G returned with value=$next for comp $comp"; #4
Log3 $name,4,"[Shelly_status] $name: proc.G returned with value=$next for comp ".(defined($comp)?$comp:"none"); #4
return undef if( $next == -1 );
#-- cyclic update (or update close to on/off-for-timer command)
@ -2487,8 +2502,7 @@ sub Shelly_status {
$next = 0.75*$hash->{INTERVAL};
}
Log3 $name,4,"[Shelly_status] $name: next update for comp=$comp in $next seconds "; #4
Log3 $name,4,"[Shelly_status] $name: next update in $next seconds".(defined($comp)?" for Comp=$comp":""); #4
RemoveInternalTimer($hash,"Shelly_status");
InternalTimer(gettimeofday()+$next, "Shelly_status", $hash, 1)
if( $hash->{INTERVAL} != 0 );
@ -2560,7 +2574,7 @@ sub Shelly_shelly {
return undef
if( $hash->{INTERVAL} == 0 );
my $offset = 120; #$hash->{INTERVAL};
my $offset = maxNum($hash->{INTERVAL},$defaultINTERVAL)*$secndIntervalMulti; #$hash->{INTERVAL};
if( $model eq "shellypro3em" ){
# updates at every multiple of 60 seconds
$offset = $hash->{INTERVAL}<=60 ? 60 : int($hash->{INTERVAL}/60)*60 ;
@ -3646,7 +3660,7 @@ sub Shelly_EMData {
$hash->{helper}{Energymeter_F}=$active_energy_i-$return_energy_i;
if(0){ # calculate the suppliers meter value
if(1){ # calculate the suppliers meter value
foreach my $EM ( "F","P","R" ){
if( defined(AttrVal($name,"Energymeter_$EM",undef)) ){
$reading = "Total_Energymeter_$EM";
@ -3987,7 +4001,7 @@ if(0){
sub Shelly_interval($){
my ($hash) =@_;
$hash->{INTERVAL} = AttrVal($hash->{name},"interval",60);
$hash->{INTERVAL} = AttrVal($hash->{NAME},"interval",$defaultINTERVAL);
Log3 $hash->{NAME},3,"[Shelly_interval] interval reset to ".$hash->{INTERVAL};
Shelly_status($hash);
}
@ -4198,7 +4212,7 @@ if(1){
my $eventsCount=0; # number of events
my ($component,$element);
foreach $component ( $mode, "input", "emeter" ){
foreach $component ( $mode, "input", "emeter", "touch" ){
Log3 $name,5,"[Shelly_webhook] $name: check number of components for component=$component";
if( $component eq "relay" ){
$compCount = $shelly_models{$model}[0];
@ -4210,6 +4224,8 @@ if(1){
$compCount = abs($shelly_models{$model}[5]); # number of inputs on ShellyPlug is -1, because it's a button, not an wired input
}elsif( $component eq "emeter" && $model eq "shellypro3em" ){
$compCount = 1;
}elsif( $component eq "touch" && $model =~ /walldisplay/ ){
$compCount = 1;
}elsif( $component eq "white" && $model eq "shellybulb" ){
$compCount = 1;
}else{
@ -4260,14 +4276,14 @@ if(1){
# only first emeter-action (activ power) is enabled
$URL =~ s/enable\=true/enable\=false/ if( $e > 0 );
}
}
} if($name eq "Y199"){Debug $URL.$urls;}else{
Log3 $name,5,"[Shelly_webhook] $name $cmd component=$element count=$c event=$e";
Log3 $name,5,"[Shelly_webhook] issue a non-blocking call to \n$URL$urls";
HttpUtils_NonblockingGet({
url => $URL.$urls,
timeout => $timeout,
callback => sub($$$){ Shelly_webhook($hash,$cmd,$_[1],$_[2]) }
});
}); }
}
}
}
@ -4327,7 +4343,7 @@ if(1){ # first of all, get number of webhooks
$current_url = $jhash->{'hooks'}[0]{'urls'}[0]; # get the first webhook url from shelly
$current_url =~ m/.*:([0-9]*)\/.*/;
my $fhemwebport = $1;
Log3 $name,1,"[Shelly_webhook] We have found a webhook with port no $fhemwebport on $name, but the webhook attribute is none or not set";
Log3 $name,4,"[Shelly_webhook] We have found a webhook with port no $fhemwebport on $name, but the webhook attribute is none or not set";
return;
}
@ -4555,7 +4571,7 @@ sub Shelly_error_handling {
my ($hash, $func, $err) = @_;
my $name = $hash->{NAME};
readingsBeginUpdate($hash);
Log3 $name,1,"[$func] device $name has error \"$err\" ";
Log3 $name,2,"[$func] device $name has error \"$err\" ";
if( $err =~ /timed out/ ){
if( $err =~ /read/ ){
$err = "Error: Timeout reading";
@ -4578,7 +4594,7 @@ sub Shelly_error_handling {
}else{
$err = "Error";
}
Log3 $name,1,"[Shelly_error_handling] Device $name has Error \'$err\' ";
Log3 $name,1,"[$func] Device $name has Error \'$err\' ";
readingsBulkUpdate($hash,"network_disconnects",ReadingsNum($name,"network_disconnects",0)+1) if( ReadingsVal($name,"state","") ne $err );
readingsBulkUpdateMonitored($hash,"state",$err, 1 );
readingsEndUpdate($hash,1);