diff --git a/fhem/FHEM/36_Shelly.pm b/fhem/FHEM/36_Shelly.pm index 3c6e7633b..6e22ed226 100644 --- a/fhem/FHEM/36_Shelly.pm +++ b/fhem/FHEM/36_Shelly.pm @@ -38,7 +38,7 @@ use vars qw{%attr %defs}; sub Log($$); #-- globals on start -my $version = "1.81"; +my $version = "2.0"; #-- these we may get on request my %gets = ( @@ -63,17 +63,43 @@ my %setsrol = ( "open:noArg" => "O", "stop:noArg" => "S", "config" => "K", - "password" => "W", - "pct:slider,0,1,100" => "P", + "password" => "P", + "pct:slider,0,1,100" => "B", "zero:noArg" => "Z" ); +my %setsrgbww = ( + "on" => "O", + "off" => "F", + "on-for-timer" => "T", + "off-for-timer" => "E", + "config" => "K", + "password" => "P", + "pct" => "B", +); + +my %setsrgbwc = ( + "on" => "O", + "off" => "F", + "on-for-timer" => "T", + "off-for-timer" => "E", + "config" => "K", + "password" => "P", + "rgbw" => "A", + "hsv" => "H", + "rgb:colorpicker,HSV" => "R", + "white:slider,0,1,100" => "W" +); + my %shelly_models = ( - #(relays,rollers,meters) - "shelly1" => [1,0,0,], - "shelly2" => [2,1,1], - "shellyplug" => [1,0,1], - "shelly4" => [4,0,4] + #(relays,rollers,dimmers,meters) + "shelly1" => [1,0,0,0], + "shelly1pm" => [1,0,0,1], + "shelly2" => [2,1,0,1], + "shelly2.5" => [2,1,0,2], + "shellyplug" => [1,0,0,1], + "shelly4" => [4,0,0,4], + "shellyrgbw" => [0,0,4,1] ); my %shelly_regs = ( @@ -82,7 +108,8 @@ my %shelly_regs = ( "btn_type=momentary|toggle\x{27f6}type of local button\nobstacle_mode=disabled|while_opening|while_closing|while_moving\x{27f6}when to watch\nobstacle_action=stop|reverse\x{27f6}what to do\n". "obstacle_power=<watt>\x{27f6}power threshold for detection\nobstacle_delay=<seconds>\x{27f6}delay after motor start to watch\n". "safety_mode=disabled|while_opening|while_closing|while_moving\x{27f6}safety mode=2nd button\nsafety_action=stop|pause|reverse\x{27f6}action when safety mode\n". - "safety_allowed_on_trigger=none|open|close|all\x{27f6}commands allowed in safety mode" + "safety_allowed_on_trigger=none|open|close|all\x{27f6}commands allowed in safety mode", + "rgbw" => "" ); ######################################################################################## @@ -104,7 +131,7 @@ sub Shelly_Initialize ($) { #$hash->{NotifyFn} = "Shelly_Notify"; #$hash->{InitFn} = "Shelly_Init"; - $hash->{AttrList}= "verbose model:".join(",",(keys %shelly_models))." mode:relay,roller defchannel maxtime maxpower interval pct100:open,closed shellyuser ". + $hash->{AttrList}= "verbose model:".join(",",(keys %shelly_models))." mode:relay,roller,white,color defchannel maxtime maxpower interval pct100:open,closed shellyuser ". $readingFnAttributes; } @@ -190,28 +217,36 @@ sub Shelly_Attr(@) { my $hash = $main::defs{$name}; my $ret; - my $model = AttrVal($name,"model","shelly2"); - my $mode = AttrVal($name,"mode","relay"); + my $model = AttrVal($name,"model","shelly1"); + my $mode = AttrVal($name,"mode",""); #-- temporary code delete $hash->{BLOCKED}; + delete $hash->{MOVING} + if( ($model !~ /shelly2.*/) || ($mode ne "roller") ); #--------------------------------------- if ( ($cmd eq "set") && ($attrName =~ /model/) ) { - Log 1,"[Shelly_Attr] =====> Attribute model=shelly2beta deprecated, please replace by model=shelly2" - if( $model eq "shelly2beta" ); my $regex = "((".join(")|(",(keys %shelly_models))."))"; if( $attrVal !~ /$regex/){ Log3 $name,1,"[Shelly_Attr] wrong value of model attribute, see documentation for possible values"; return } - #-- only one channel + #-- only one relay if( $shelly_models{$model}[0] == 1){ fhem("deletereading ".$name." relay_.*"); fhem("deletereading ".$name." overpower_.*"); + fhem("deletereading ".$name." button_.*"); + #-- no relay + }elsif( $shelly_models{$model}[0] == 0){ + fhem("deletereading ".$name." relay.*"); + fhem("deletereading ".$name." overpower.*"); + fhem("deletereading ".$name." button.*"); + #-- other number }else{ fhem("deletereading ".$name." relay"); - fhem("deletereading ".$name." overpower"); + fhem("deletereading ".$name." overpower"); + fhem("deletereading ".$name." button"); } #-- no rollers if( $shelly_models{$model}[1] == 0){ @@ -222,36 +257,74 @@ sub Shelly_Attr(@) { delete $hash->{MOVING}; delete $hash->{DURATION}; } + #-- no dimmers + if( $shelly_models{$model}[2] == 0){ + fhem("deletereading ".$name." L-.*"); + fhem("deletereading ".$name." rgb"); + fhem("deletereading ".$name." pct.*"); + } #-- always clear readings for meters - #if( $shelly_models{$model}[2] <= 1){ - fhem("deletereading ".$name." power.*"); - fhem("deletereading ".$name." overpower.*"); - #} + fhem("deletereading ".$name." power.*"); + fhem("deletereading ".$name." overpower.*"); + + #-- change attribute list for model 2/rgbw w. hidden AttrList + my $old = $modules{Shelly}{'AttrList'}; + my $new; + my $ind = index($old,"mode:")-1; + my $pre = substr($old,0,$ind); + my $pos = substr($old,$ind+31,length($old)-$ind-31); + + if( $model =~ /shelly2.*/ ){ + $new = $pre." mode:relay,roller ".$pos; + }elsif( $model eq "shellyrgbw" ){ + $new = $pre." mode:white,color ".$pos; + }else{ + $new = $pre." ".$pos; + } + $hash->{'.AttrList'} = $new; + #--------------------------------------- }elsif ( ($cmd eq "set") && ($attrName =~ /mode/) ) { - if( $model !~ /shelly2.*/ ){ - Log3 $name,1,"[Shelly_Attr] setting the mode attribute only works for model=shelly2"; + if( $model !~ /shelly(2|(rgb)).*/ ){ + Log3 $name,1,"[Shelly_Attr] setting the mode attribute only works for model=shelly2|shelly2.5|shellyrgbw"; return } - if( $attrVal !~ /((relay)|(roller))/){ - Log3 $name,1,"[Shelly_Attr] wrong mode value $attrVal"; - return; - }elsif( $attrVal eq "relay"){ - fhem("deletereading ".$name." position.*"); - fhem("deletereading ".$name." stop_reason.*"); - fhem("deletereading ".$name." last_dir.*"); - fhem("deletereading ".$name." pct.*"); - }elsif( $attrVal eq "roller"){ - fhem("deletereading ".$name." relay.*"); + if( $model =~ /shelly2.*/ ){ + fhem("deletereading ".$name." power.*"); fhem("deletereading ".$name." overpower.*"); - } + if( $attrVal !~ /((relay)|(roller))/){ + Log3 $name,1,"[Shelly_Attr] wrong mode value $attrVal, must be relay or roller"; + return; + }elsif( $attrVal eq "relay"){ + fhem("deletereading ".$name." position.*"); + fhem("deletereading ".$name." stop_reason.*"); + fhem("deletereading ".$name." last_dir.*"); + fhem("deletereading ".$name." pct.*"); + }elsif( $attrVal eq "roller"){ + fhem("deletereading ".$name." relay.*"); + } + }elsif( $model eq "shellyrgbw" ){ + fhem("deletereading ".$name." power.*"); + fhem("deletereading ".$name." overpower.*"); + if( $attrVal !~ /((white)|(color))/){ + Log3 $name,1,"[Shelly_Attr] wrong mode value $attrVal, must be white or color"; + return; + }elsif( $attrVal eq "color"){ + fhem("deletereading ".$name." pct.*"); + fhem("deletereading ".$name." state_.*"); + }elsif( $attrVal eq "white"){ + fhem("deletereading ".$name." L-.*"); + fhem("deletereading ".$name." rgb"); + fhem("deletereading ".$name." hsv"); + } + } Shelly_configure($hash,"settings?mode=".$attrVal); #--------------------------------------- }elsif ( ($cmd eq "set") && ($attrName eq "maxtime") ) { if( ($model !~ /shelly2.*/) || ($mode ne "roller" ) ){ - Log3 $name,1,"[Shelly_Attr] setting the maxtime attribute only works for model=shelly2 and mode=roller"; + Log3 $name,1,"[Shelly_Attr] setting the maxtime attribute only works for model=shelly2/2.5 and mode=roller"; return } Shelly_configure($hash,"settings?maxtime=".$attrVal); @@ -259,7 +332,7 @@ sub Shelly_Attr(@) { #--------------------------------------- }elsif ( ($cmd eq "set") && ($attrName eq "pct100") ) { if( ($model !~ /shelly2.*/) || ($mode ne "roller" ) ){ - Log3 $name,1,"[Shelly_Attr] setting the pct100 attribute only works for model=shelly2 and mode=roller"; + Log3 $name,1,"[Shelly_Attr] setting the pct100 attribute only works for model=shelly2/2.5 and mode=roller"; return } @@ -363,28 +436,49 @@ sub Shelly_Set ($@) { $cmd = shift @a; $value = shift @a; - my $model = AttrVal($name,"model","shelly2"); - my $mode = AttrVal($name,"mode","relay"); + my $model = AttrVal($name,"model","shelly1"); + my $mode = AttrVal($name,"mode",""); my ($channel,$time); #-- we have a Shelly 1,4 or ShellyPlug switch type device #-- or we have a Shelly 2 switch type device - if( ($model eq "shelly1") || ($model eq "shelly4") || ($model eq "shellyplug") || (($model =~ /shelly2.*/) && ($mode eq "relay")) ){ + if( ($model =~ /shelly1.*/) || ($model eq "shelly4") || ($model eq "shellyplug") || (($model =~ /shelly2.*/) && ($mode eq "relay")) ){ #-- WEB asking for command list if( $cmd eq "?" ) { $newkeys = join(" ", sort keys %setssw); return "[Shelly_Set] Unknown argument " . $cmd . ", choose one of ".$newkeys; } - - if( $cmd =~ /^((on)|(off)).*/ ){ + #-- command received via web to register local changes of the device output + if( $cmd =~ /^out_((on)|(off))/){ + my $ison = $1; + #-- + my $subs = ($shelly_models{$model}[0] ==1) ? "" : "_".$value; + + readingsBeginUpdate($hash); + if($model =~ /shelly(1|(plug)).*/){ + readingsBulkUpdateIfChanged($hash,"state",$ison) + } + readingsBulkUpdate($hash,"relay".$subs,$ison); + readingsEndUpdate($hash,1); + #-- Call status after switch. + InternalTimer(int(gettimeofday()+1.5), "Shelly_status", $hash,0); + + #-- command received via web to register local changes of the device input + }elsif( $cmd =~ /^button_((on)|(off))/){ + my $ison = $1; + #-- + my $subs = ($shelly_models{$model}[0] ==1) ? "" : "_".$value; + readingsSingleUpdate( $hash, "button".$subs, $ison, 1 ) + #-- now real commands + }elsif( $cmd =~ /^((on)|(off)).*/ ){ $channel = $value; if( $cmd =~ /(.*)-for-timer/ ){ $time = $value; $channel = shift @a; } if( $shelly_models{$model}[0] == 1){ - $channel = 0 + $channel = 0 }else{ if( !defined($channel) || ($channel !~ /[0123]/) || $channel >= $shelly_models{$model}[0] ){ if( !defined($channel) ){ @@ -466,6 +560,109 @@ sub Shelly_Set ($@) { Shelly_updown($hash,$cmd); } + #-- we have a Shelly rgbw type device in white mode + }elsif( ($model =~ /shellyrgbw.*/) && ($mode eq "white")){ + if( $cmd eq "?" ) { + $newkeys = join(" ", sort keys %setsrgbww); + return "[Shelly_Set] Unknown argument " . $cmd . ", choose one of ".$newkeys; + } + + if( $cmd =~ /^((on)|(off)).*/ ){ + $channel = $value; + if( $cmd =~ /(.*)-for-timer/ ){ + $time = $value; + $channel = shift @a; + } + if( !defined($channel) || ($channel !~ /[0123]/) || $channel >= $shelly_models{$model}[3] ){ + if( !defined($channel) ){ + $channel = AttrVal($name,"defchannel",undef); + if( !defined($channel) ){ + $msg = "Error: wrong channel $channel given and defchannel attribute not set properly"; + Log3 $name, 1,"[Shelly_Set] ".$msg; + return $msg; + }else{ + Log3 $name, 4,"[Shelly_Set] switching default channel $channel"; + } + } + } + if( $cmd =~ /(.*)-for-timer/ ){ + $cmd = $1; + if( $time !~ /\d+/ ){ + $msg = "Error: wrong time spec $time, must be "; + Log3 $name, 1,"[Shelly_Set] ".$msg; + return $msg; + } + $cmd = $cmd."&timer=$time"; + } + Shelly_dim($hash,"white/$channel","?turn=".$cmd); + #Shelly_onoff($hash,"white/$channel","?turn=".$cmd); + + }elsif( $cmd eq "pct" ){ + #$channel = $value; + $channel = shift @a; + if( !defined($channel) || ($channel !~ /[0123]/) || $channel >= $shelly_models{$model}[3] ){ + if( !defined($channel) ){ + $channel = AttrVal($name,"defchannel",undef); + if( !defined($channel) ){ + $msg = "Error: wrong channel $channel given and defchannel attribute not set properly"; + Log3 $name, 1,"[Shelly_Set] ".$msg; + return $msg; + }else{ + Log3 $name, 4,"[Shelly_Set] dimming default channel $channel"; + } + } + } + #TODO check value + Shelly_dim($hash,"white/$channel","?brightness=".$value); + } + #-- we have a Shelly rgbw type device in color mode + }elsif( ($model =~ /shellyrgbw.*/) && ($mode eq "color")){ + my $channel = $value; + #-- WEB asking for command list + if( $cmd eq "?" ) { + $newkeys = join(" ", sort keys %setsrgbwc); + return "[Shelly_Set] Unknown argument " . $cmd . ", choose one of ".$newkeys; + } + + if( $cmd =~ /^((on)|(off)).*/ ){ + $channel = 0; + + if( $cmd =~ /(.*)-for-timer/ ){ + $time = $value; + $cmd = $1; + if( $time !~ /\d+/ ){ + $msg = "Error: wrong time spec $time, must be "; + Log3 $name, 1,"[Shelly_Set] ".$msg; + return $msg; + } + $cmd = $cmd."&timer=$time"; + } + Shelly_dim($hash,"color/0","?turn=".$cmd); + #Shelly_onoff($hash,"color/0","?turn=".$cmd); + } + + if( $cmd eq "hsv" ){ + my($hue,$saturation,$value)=split(',',$value); + my ($red,$green,$blue)=Color::hsv2rgb($hue,$saturation,$value); + $cmd=sprintf("red=%d&green=%d&blue=%d",int($red*255+0.5),int($green*255+0.5),int($blue*255+0.5)); + Shelly_dim($hash,"color/0","?".$cmd); + }elsif( $cmd eq "rgb" ){ + my $red=hex(substr($value,0,2)); + my $green=hex(substr($value,2,2)); + my $blue=hex(substr($value,4,2)); + $cmd=sprintf("red=%d&green=%d&blue=%d",$red,$green,$blue); + Shelly_dim($hash,"color/0","?".$cmd); + }elsif( $cmd eq "rgbw" ){ + my $red=hex(substr($value,0,2)); + my $green=hex(substr($value,2,2)); + my $blue=hex(substr($value,4,2)); + my $white=hex(substr($value,4,2)); + $cmd=sprintf("red=%d&green=%d&blue=%d&white=%d",$red,$green,$blue,$white); + Shelly_dim($hash,"color/0","?".$cmd); + }elsif( $cmd eq "white" ){ + $cmd=sprintf("white=%d",$value); + Shelly_dim($hash,"color/0","?".$cmd); + } } #-- configuration register @@ -484,8 +681,12 @@ sub Shelly_Set ($@) { return $msg; } my $pre = "settings/"; - if( ($model eq "shelly2") && ($mode eq "roller") ){ + if( ($model =~ /shelly2.*/) && ($mode eq "roller") ){ $pre .= "roller/$chan?"; + }elsif( ($model eq "shellyrgbw") && ($mode eq "white") ){ + $pre .= "white/$chan?"; + }elsif( ($model eq "shellyrgbw") && ($mode eq "color") ){ + $pre .= "color/$chan?"; }else{ $pre .= "relay/$chan?"; $v = Shelly_configure($hash,$pre.$reg."=".$val); @@ -577,7 +778,7 @@ sub Shelly_pwd($){ return undef; } - + ######################################################################################## # # Shelly_status - Retrieve data from device @@ -625,30 +826,30 @@ sub Shelly_pwd($){ return; } - my $model = AttrVal($name,"model","shelly2"); - my $mode = AttrVal($name,"mode","relay"); - + my $model = AttrVal($name,"model","shelly1"); + my $mode = AttrVal($name,"mode",""); + my $channels = $shelly_models{$model}[0]; my $rollers = $shelly_models{$model}[1]; - my $meters = $shelly_models{$model}[2]; + my $dimmers = $shelly_models{$model}[2]; + my $meters = $shelly_models{$model}[3]; my ($subs,$ison,$overpower,$rpower,$rstate,$power,$rstopreason,$rcurrpos,$position,$rlastdir,$pct,$pctnormal); readingsBeginUpdate($hash); readingsBulkUpdateIfChanged($hash,"network","connected",1); - #-- we have a Shelly 1, Shelly 4, Shelly 2 or ShellyPlug switch type device - if( ($model eq "shelly1") || ($model eq "shellyplug") || ($model eq "shelly4") || (($model =~ /shelly2.*/) && ($mode eq "relay")) ){ + #-- we have a Shelly 1/1pw, Shelly 4, Shelly 2/2.5 or ShellyPlug switch type device + if( ($model =~ /shelly1.*/) || ($model eq "shellyplug") || ($model eq "shelly4") || (($model =~ /shelly2.*/) && ($mode eq "relay")) ){ for( my $i=0;$i<$channels;$i++){ $subs = (($channels == 1) ? "" : "_".$i); $ison = $jhash->{'relays'}[$i]{'ison'}; - $ison =~ s/0/off/; - $ison =~ s/1/on/; + $ison =~ s/0|(false)/off/; + $ison =~ s/1|(true)/on/; $overpower = $jhash->{'relays'}[$i]{'overpower'}; - readingsBulkUpdateIfChanged($hash,"relay".$subs,$ison); readingsBulkUpdateIfChanged($hash,"overpower".$subs,$overpower); - if($model eq "shelly1"){ + if($model =~ /shelly(1|(plug)).*/){ readingsBulkUpdateIfChanged($hash,"state",$ison) }else{ readingsBulkUpdateIfChanged($hash,"state","OK"); @@ -690,12 +891,12 @@ sub Shelly_pwd($){ #-- we have data from the device, take that one if( defined($rcurrpos) && ($rcurrpos =~ /\d\d?\d?/) ){ $pct = $pctnormal ? $rcurrpos : 100-$rcurrpos; - $position = ($rcurrpos==100) ? "open" : ($rcurrpos==0 ? "closed" : $pct); + $position = ($rcurrpos==100) ? "open" : ($rcurrpos==0 ? "closed" : $pct); #-- we have no data from the device }else{ - Log3 $name,1,"[Shelly_status] device $name with model=$model returns no blind position, consider chosing a different model=shelly2" - if( $model ne "shelly2" ); + Log3 $name,1,"[Shelly_status] device $name with model=$model returns no blind position, consider chosing a different model=shelly2/2.5" + if( $model !~ /shelly2.*/ ); $pct = ReadingsVal($name,"pct",undef); #-- we have a reading if( defined($pct) && $pct =~ /\d\d?\d?/ ){ @@ -716,7 +917,6 @@ sub Shelly_pwd($){ } } } - readingsBulkUpdateIfChanged($hash,"state".$subs,$rstate); readingsBulkUpdateIfChanged($hash,"pct".$subs,$pct); readingsBulkUpdateIfChanged($hash,"position".$subs,$position); @@ -724,6 +924,48 @@ sub Shelly_pwd($){ readingsBulkUpdateIfChanged($hash,"stop_reason".$subs,$rstopreason); readingsBulkUpdateIfChanged($hash,"last_dir".$subs,$rlastdir); } + #-- we have a Shelly RGBW white device + }elsif( $model eq "shellyrgbw" && $mode eq "white" ){ + for( my $i=0;$i<$dimmers;$i++){ + $subs = (($dimmers == 1) ? "" : "_".$i); + $ison = $jhash->{'lights'}[$i]{'ison'}; + $ison =~ s/0|(false)/off/; + $ison =~ s/1|(true)/on/; + my $bri = $jhash->{'lights'}[$i]{'brightness'}; + $power = $jhash->{'lights'}[$i]{'power'}; + $overpower = $jhash->{'lights'}[$i]{'overpower'}; + + readingsBulkUpdateIfChanged($hash,"state".$subs,$ison); + readingsBulkUpdateIfChanged($hash,"pct".$subs,$bri); + readingsBulkUpdateIfChanged($hash,"power".$subs,$power); + readingsBulkUpdateIfChanged($hash,"overpower".$subs,$overpower); + } + readingsBulkUpdateIfChanged($hash,"state","OK"); + + #-- we have a Shelly RGBW color device + }elsif( $model eq "shellyrgbw" && $mode eq "color" ){ + $ison = $jhash->{'lights'}[0]{'ison'}; + $ison =~ s/0|(false)/off/; + $ison =~ s/1|(true)/on/; + $overpower = $jhash->{'lights'}[0]{'overpower'}; + my $red = $jhash->{'lights'}[0]{'red'}; + my $green = $jhash->{'lights'}[0]{'green'}; + my $blue = $jhash->{'lights'}[0]{'blue'}; + my $white = $jhash->{'lights'}[0]{'white'}; + my $rgb = sprintf("%X%X%X", $red,$green,$blue); + + readingsBulkUpdateIfChanged($hash,"rgb",$rgb); + readingsBulkUpdateIfChanged($hash,"L-red",$red); + readingsBulkUpdateIfChanged($hash,"L-green",$green); + readingsBulkUpdateIfChanged($hash,"L-blue",$blue); + readingsBulkUpdateIfChanged($hash,"L-white",$white); + readingsBulkUpdateIfChanged($hash,"overpower",$overpower); + readingsBulkUpdateIfChanged($hash,"state",$ison); + for( my $i=0;$i<$meters;$i++){ + $subs = ($meters == 1) ? "" : "_".$i; + $power = $jhash->{'meters'}[$i]{'power'}; + readingsBulkUpdateIfChanged($hash,"power".$subs,$power); + } } #-- common to all Shelly models my $hasupdate = $jhash->{'update'}{'has_update'}; @@ -756,6 +998,97 @@ sub Shelly_pwd($){ return undef; } +######################################################################################## +# +# Shelly_dim - Set Shelly dimmer state +# acts as callable program Shelly_dim($hash,$channel,$cmd) +# and as callback program Shelly_dim($hash,$channel,$cmd,$err,$data) +# +# Parameter hash, channel = 0,1 cmd = command +# +######################################################################################## + + sub Shelly_dim { + my ($hash, $channel, $cmd, $err, $data) = @_; + my $name = $hash->{NAME}; + my $url; + my $state = $hash->{READINGS}{state}{VAL}; + my $net = $hash->{READINGS}{network}{VAL}; + return + if( $net ne "connected" ); + + my $model = AttrVal($name,"model",""); + my $creds = Shelly_pwd($hash); + + if ( $hash && !$err && !$data ){ + $url = "http://$creds".$hash->{TCPIP}."/$channel$cmd"; + Log3 $name, 5,"[Shelly_dim] Issue a non-blocking call to $url"; + HttpUtils_NonblockingGet({ + url => $url, + callback=>sub($$$){ Shelly_dim($hash,$channel,$cmd,$_[1],$_[2]) } + }); + return undef; + }elsif ( $hash && $err ){ + #Log3 $name, 1,"[Shelly_dim] has error $err"; + readingsSingleUpdate($hash,"state","Error",1); + return; + } + Log3 $name, 5,"[Shelly_dim] has obtained data $data"; + + my $json = JSON->new->utf8; + my $jhash = eval{ $json->decode( $data ) }; + if( !$jhash ){ + if( ($model =~ /shellyrgbw.*/) && ($data =~ /Device mode is not dimmer!/) ){ + Log3 $name,1,"[Shelly_dim] Device $name is not a dimmer"; + readingsSingleUpdate($hash,"state","Error",1); + return + }else{ + Log3 $name,1,"[Shelly_dim] has invalid JSON data"; + readingsSingleUpdate($hash,"state","Error",1); + return; + } + } + + my $ison = $jhash->{'ison'}; + my $bright = $jhash->{'brightness'}; + my $hastimer = $jhash->{'has_timer'}; + my $overpower = $jhash->{'overpower'}; + + if( $cmd =~ /\?turn=((on)|(off))/ ){ + my $cmd2 = $1; + $ison =~ s/0|(false)/off/; + $ison =~ s/1|(true)/on/; + #-- timer command + if( index($cmd,"&") ne "-1"){ + $cmd = substr($cmd,0,index($cmd,"&")); + if( $hastimer ne "1" ){ + Log3 $name,1,"[Shelly_dim] returns with problem, timer not set"; + } + } + if( $ison ne $cmd2 ) { + Log3 $name,1,"[Shelly_dim] returns without success, cmd=$cmd but ison=$ison"; + } + }elsif( $cmd =~ /\?brightness=(.*)/){ + my $cmd2 = $1; + if( $bright ne $cmd2 ) { + Log3 $name,1,"[Shelly_dim] returns without success, desired brightness $cmd, but device brightness=$bright"; + } + } + if( defined($overpower) && $overpower eq "1") { + Log3 $name,1,"[Shelly_dim] switched off automatically because of overpower signal"; + } + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash,"overpower",$overpower) + if( $shelly_models{$model}[3] > 0); + readingsEndUpdate($hash,1); + + #-- Call status after switch. + InternalTimer(int(gettimeofday()+1.5), "Shelly_status", $hash,0); + + return undef; +} + ######################################################################################## # # Shelly_updown - Move roller blind @@ -895,8 +1228,8 @@ sub Shelly_updown2($){ my $hastimer = $jhash->{'has_timer'}; my $overpower = $jhash->{'overpower'}; - $ison =~ s/0/off/; - $ison =~ s/1/on/; + $ison =~ s/0|(false)/off/; + $ison =~ s/1|(true)/on/; $cmd =~ s/\?turn=//; #-- timer command @@ -916,14 +1249,14 @@ sub Shelly_updown2($){ my $subs = ($shelly_models{$model}[0] ==1) ? "" : "_".$channel; readingsBeginUpdate($hash); - if($model eq "shelly1"){ + if($model =~ /shelly(1|(plug)).*/){ readingsBulkUpdateIfChanged($hash,"state",$ison) }else{ readingsBulkUpdate($hash,"state","OK"); } readingsBulkUpdate($hash,"relay".$subs,$ison); readingsBulkUpdate($hash,"overpower".$subs,$overpower) - if( $shelly_models{$model}[2] > 0); + if( $shelly_models{$model}[3] > 0); readingsEndUpdate($hash,1); #-- Call status after switch. @@ -981,7 +1314,7 @@ sub Shelly_updown2($){ my $power = $jhash->{'power'}; #-- - my $subs = ($shelly_models{$model}[2] ==1) ? "" : "_".$channel; + my $subs = ($shelly_models{$model}[3] ==1) ? "" : "_".$channel; readingsSingleUpdate($hash,"power".$subs,$power,1); return undef; @@ -997,35 +1330,42 @@ sub Shelly_updown2($){

Shelly