diff --git a/fhem/FHEM/36_Shelly.pm b/fhem/FHEM/36_Shelly.pm
index 06e16b01d..b725457ba 100644
--- a/fhem/FHEM/36_Shelly.pm
+++ b/fhem/FHEM/36_Shelly.pm
@@ -65,6 +65,7 @@
# 5.17 Add: Roller devices: 'set ... position' equivalent to 'pct'
# 5.18 Bug Fix: function of all Gen1 relay devices
# 5.19 change back: roller devices: use 'set ... pct' as command
+# 5.20 Bug Fix: suppress status calls for disabled devices
package main;
@@ -83,7 +84,7 @@ sub Log($$);
sub Shelly_Set ($@);
#-- globals on start
-my $version = "5.19 11.01.2024";
+my $version = "5.20 24.01.2024";
my $defaultINTERVAL = 60;
my $secndIntervalMulti = 4; # Multiplier for 'long update'
@@ -610,6 +611,17 @@ my %si_units = (
"ISO" => [ "kJ", 3.6, 0 ]
);
+my %peripherals = (
+ # Peripheral type => Component Type
+ "analog_in" => "input",
+ "digital_in" => "input",
+ "dht22" => "humidity",
+ "ds18b20" => "temperature",
+ "voltmeter" => "voltmeter"
+);
+
+
+
########################################################################################
#
# Shelly_Initialize
@@ -868,7 +880,7 @@ if(0){
######################################################################################
readingsSingleUpdate($hash,"state","initialized",1);
- InternalTimer(gettimeofday()+6, "Refresh", $hash);
+ InternalTimer(time()+6, "Refresh", $hash);
delete($attr{$hash->{NAME}}{mode}) if( $shelly_models{$model}[8]<2 ); # no multi-mode device
delete($hash->{helper}{Sets}); # build up the sets-dropdown with next refresh
return;
@@ -1331,10 +1343,11 @@ sub Shelly_Attr(@) {
Log3 $name,1,"[Shelly_Attr] $name\: $error model=shelly2/2.5/plus2/pro2 and mode=roller"; ##R
return $error;
}
- # perform an update of the position related readings
- RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+1, "Shelly_status", $hash); ##ü
-
+ if($init_done){
+ # perform an update of the position related readings
+ RemoveInternalTimer($hash,"Shelly_status");
+ InternalTimer(time()+1, "Shelly_status", $hash); ##ü
+ }
#---------------------------------------
}elsif( $attrName =~ /Energymeter/ ){
if($cmd eq "set" ){
@@ -1498,12 +1511,12 @@ sub Shelly_Attr(@) {
$hash->{CMD}="Check";
}
}
- # calling Shelly_webhook() via timer, otherwise settings are not available
- Log3 $name,3,"[Shelly_Attr:webhook] we will call Shelly_webhook for device $name, command is ".$hash->{CMD};
- RemoveInternalTimer($hash,"Shelly_webhook");
- InternalTimer(gettimeofday()+3, "Shelly_webhook", $hash, 0);
-
-
+ if( $hash->{INTERVAL} != 0 ){
+ # calling Shelly_webhook() via timer, otherwise settings are not available
+ Log3 $name,3,"[Shelly_Attr:webhook] we will call Shelly_webhook for device $name, command is ".$hash->{CMD};
+ RemoveInternalTimer($hash,"Shelly_webhook");
+ InternalTimer(time()+3, "Shelly_webhook", $hash, 0);
+ }
#---------------------------------------
}elsif( $attrName eq "interval" ){
if( $cmd eq "set" ){
@@ -1511,7 +1524,7 @@ sub Shelly_Attr(@) {
if( $model eq "shellypro3em" && $attrVal > 0 ){
# restart the 2nd timer (only when stopped)
# adjust the timer to one second after the full minute
- InternalTimer(int((gettimeofday()+60)/60)*60+1, "Shelly_shelly", $hash, 1)
+ InternalTimer(int((time()+60)/60)*60+1, "Shelly_shelly", $hash, 1)
if( AttrVal($name,"interval",-1) == 0 );
# adjust the 1st timer to 60
@@ -1524,9 +1537,9 @@ sub Shelly_Attr(@) {
}elsif( $cmd eq "del" ){
$hash->{INTERVAL}=60;
}
- if($init_done) {
+ if($init_done){
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Shelly_status", $hash, 0)
+ InternalTimer(time()+$hash->{INTERVAL}, "Shelly_status", $hash, 0)
if( $hash->{INTERVAL} != 0 );
}
#---------------------------------------
@@ -1781,7 +1794,7 @@ sub Shelly_Set ($@) {
readingsBulkUpdateMonitored($hash, "input$subs\_actionS",$fhem_events{$cmd}, 1 );
# after a second, the pushbuttons state is back to OFF resp. 'unknown', call status of inputs
RemoveInternalTimer($hash,"Shelly_inputstatus");
- InternalTimer(gettimeofday()+1.4, "Shelly_inputstatus", $hash,1);
+ InternalTimer(time()+1.4, "Shelly_inputstatus", $hash,1);
}elsif( $signal eq "touch" ){ # devices with an touch-display
#$subs = ($shelly_models{$model}[5] == 1) ? "" : "_".$value;
readingsBulkUpdateMonitored($hash, "touch", $isWhat, 1 );
@@ -1840,7 +1853,7 @@ sub Shelly_Set ($@) {
#-- Call status after switch.n
if( $signal !~ /^(Active_Power|Voltage|Current|apower|voltage|current)/ ){
RemoveInternalTimer($hash,"Shelly_status"); Log3 $name,6,"shelly_set 1715 removed Timer Shelly_status, now calling in 1.5 sec";
- InternalTimer(gettimeofday()+1.5, "Shelly_status", $hash);
+ InternalTimer(time()+1.5, "Shelly_status", $hash);
}
return undef;
}
@@ -2109,7 +2122,7 @@ sub Shelly_Set ($@) {
$hash->{DURATION} = 0;
$hash->{CMD}=$cmd;
RemoveInternalTimer($hash,"Shelly_Set");
- InternalTimer(gettimeofday()+1.0, "Shelly_Set", $hash, 1);
+ InternalTimer(time()+1.0, "Shelly_Set", $hash, 1);
$cmd = "?go=stop";
#-- is moving !!!
@@ -2265,12 +2278,12 @@ sub Shelly_Set ($@) {
if( $hash->{INTERVAL} ){
Log3 $name,2,"[Shelly_Set] Starting cyclic timers for $name ($model)";
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
+ InternalTimer(time()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
RemoveInternalTimer($hash,"Shelly_shelly");
- InternalTimer(gettimeofday()+$defaultINTERVAL*$secndIntervalMulti, "Shelly_shelly", $hash,0);
+ InternalTimer(time()+$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);
+ InternalTimer(int((time()+60)/60)*60+1, "Shelly_EMData", $hash,0);
Log3 $name,2,"[Shelly_Set] Starting cyclic EM-Data timers for $name";
}
}else{
@@ -2282,11 +2295,11 @@ sub Shelly_Set ($@) {
if( $hash->{INTERVAL} ){
Log3 $name,2,"[Shelly_Set] Starting cyclic timers for $name";
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
+ InternalTimer(time()+$hash->{INTERVAL}, "Shelly_status", $hash, 0);
RemoveInternalTimer($hash,"Shelly_shelly");
- InternalTimer(gettimeofday()+$defaultINTERVAL*$secndIntervalMulti, "Shelly_shelly", $hash,0);
+ InternalTimer(time()+$defaultINTERVAL*$secndIntervalMulti, "Shelly_shelly", $hash,0);
RemoveInternalTimer($hash,"Shelly_EMData");
- InternalTimer(int((gettimeofday()+60)/60)*60+1, "Shelly_EMData", $hash,0);
+ InternalTimer(int((time()+60)/60)*60+1, "Shelly_EMData", $hash,0);
}else{
Log3 $name,2,"[Shelly_Set] No timer started for $name";
}
@@ -2646,6 +2659,7 @@ sub Shelly_inputstatus {
sub Shelly_status {
my ($hash, $comp, $err, $data) = @_;
my $name = $hash->{NAME};
+return if( $hash->{INTERVAL} == 0 );
my $state = $hash->{READINGS}{state}{VAL};
my $model = AttrVal($name,"model","generic");
@@ -2660,7 +2674,7 @@ sub Shelly_status {
RemoveInternalTimer($hash,"Shelly_status");
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);
+ InternalTimer(time()+$interval, "Shelly_status", $hash, 1);
}
# in any cases check for error in non blocking call
@@ -2782,7 +2796,7 @@ sub Shelly_status {
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)
+ InternalTimer(time()+$next, "Shelly_status", $hash, 1)
if( $hash->{INTERVAL} != 0 );
return undef;
}
@@ -2802,7 +2816,7 @@ sub Shelly_shelly {
my ($hash) = @_;
my $name = $hash->{NAME};
my $state = $hash->{READINGS}{state}{VAL};
-
+return if( $hash->{INTERVAL} == 0 );
my $model = AttrVal($name,"model","generic");
my $creds = Shelly_pwd($hash);
my $url = "http://$creds".$hash->{TCPIP};
@@ -2866,10 +2880,10 @@ sub Shelly_shelly {
# updates at every multiple of 60 seconds
$offset = $hash->{INTERVAL}<=60 ? 60 : int($hash->{INTERVAL}/60)*60 ;
# adjust to get readings 2sec after full minute
- $offset = $offset + 2 - gettimeofday() % 60;
+ $offset = $offset + 2 - time() % 60;
}
Log3 $name,4,"[Shelly_shelly] $name: long update in $offset seconds, Timer is Shelly_shelly"; #4
- InternalTimer(gettimeofday()+$offset, "Shelly_shelly", $hash, 1);
+ InternalTimer(time()+$offset, "Shelly_shelly", $hash, 1);
return undef;
}
@@ -3837,7 +3851,7 @@ sub Shelly_EMData {
#-- cyclic update nevertheless
RemoveInternalTimer($hash,"Shelly_EMData");
# adjust timer to one second after full minute
- my $Tupdate = int((gettimeofday()+60)/60)*60+1;
+ my $Tupdate = int((time()+60)/60)*60+1;
Log3 $name,4,"[Shelly_EMData] $name: next EMData update at $Tupdate = ".strftime("%H:%M:%S",localtime($Tupdate) )." Timer is Shelly_EMdata";
InternalTimer($Tupdate, "Shelly_EMData", $hash, 1)
if( $hash->{INTERVAL} != 0 );
@@ -4241,9 +4255,9 @@ sub shelly_energy_fmt {
#-- Call status after switch.
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+0.5, "Shelly_status", $hash,0);
+ InternalTimer(time()+0.5, "Shelly_status", $hash,0);
my $duration=ReadingsNum($name,"transition",10000)/1000;
- InternalTimer(gettimeofday()+$duration, "Shelly_status2", $hash,0);
+ InternalTimer(time()+$duration, "Shelly_status2", $hash,0);
return undef;
}
@@ -4322,9 +4336,9 @@ sub shelly_energy_fmt {
#-- perform first update after starting of drive
$hash->{DURATION} = 5 if( !$hash->{DURATION} ); # duration not provided by Gen2
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+0.5, "Shelly_status", $hash); # update after starting
+ InternalTimer(time()+0.5, "Shelly_status", $hash); # update after starting
# next update after expected stopping of drive + offset (at least 1 sec)
- InternalTimer(gettimeofday()+$hash->{DURATION}+1.5, "Shelly_status2", $hash,1);
+ InternalTimer(time()+$hash->{DURATION}+1.5, "Shelly_status2", $hash,1);
}
return undef;
}
@@ -4363,14 +4377,14 @@ sub Shelly_status2($){
if( $hash && !$err && !$data ){
my $callback;
my $url = "http://$creds".$hash->{TCPIP};
-if($shelly_models{$model}[4]<2){
- $url .= "/relay/$channel$cmd";
- $callback="/relay/$channel$cmd";
-}else{ # eg Wall-Display
- $cmd =~ /\?id=(\d)/;
- $callback = $url."/rpc/Switch.GetStatus?id=".$1;
- $url .= $cmd;
-}
+ if($shelly_models{$model}[4]<2){
+ $url .= "/relay/$channel$cmd";
+ $callback="/relay/$channel$cmd";
+ }else{ # eg Wall-Display
+ $cmd =~ /\?id=(\d)/;
+ $callback = $url."/rpc/Switch.GetStatus?id=".$1;
+ $url .= $cmd;
+ }
Log3 $name,4,"[Shelly_onoff] issue a non-blocking call to $url; callback to Shelly_onoff with command $callback";
HttpUtils_NonblockingGet({
url => $url,
@@ -4455,7 +4469,7 @@ if($shelly_models{$model}[4]<2){
$onofftimer = ($onofftimer % $hash->{INTERVAL}) + 0.5; #modulus
}
RemoveInternalTimer($hash,"Shelly_status");
- InternalTimer(gettimeofday()+$onofftimer, "Shelly_status", $hash,0);
+ InternalTimer(time()+$onofftimer, "Shelly_status", $hash,0);
return undef;
}
@@ -4475,6 +4489,7 @@ if($shelly_models{$model}[4]<2){
sub Shelly_webhook {
my ($hash, $cmd, $err, $data) = @_;
my $name = $hash->{NAME};
+return if( $hash->{INTERVAL} == 0 );
my $state = $hash->{READINGS}{state}{VAL};
my $net = $hash->{READINGS}{network}{VAL};
@@ -5055,6 +5070,7 @@ Shelly_readingsBulkUpdate($$$@) # derived from fhem.pl readingsBulkUpdateIfChang
return undef;
}
+
#
@@ -5125,6 +5141,8 @@ Shelly_readingsBulkUpdate($$$@) # derived from fhem.pl readingsBulkUpdateIfChang
This is the only way to set the password for the Shelly web interface.
For Shelly devices first gen, the attribute 'shellyuser' must be defined
+ To remove a password, use:
+ set <name> password
set <name> reboot
@@ -5664,6 +5682,9 @@ Shelly_readingsBulkUpdate($$$@) # derived from fhem.pl readingsBulkUpdateIfChang
set <name> password <password>
set <name> password
Hinweis: Beim Umbenennen des Devices mit 'rename' geht das Passwort verloren