mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-02-01 07:19:24 +00:00
36_Shelly.pm: Neue Version 2.0 mit diversen Verbesserungen, unterstützt weitere Shelly-Aktoren
git-svn-id: https://svn.fhem.de/fhem/trunk@19432 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
4c360bed7d
commit
e3c37bfb77
@ -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 <integer>";
|
||||
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 <integer>";
|
||||
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($){
|
||||
<a name="Shelly"></a>
|
||||
<h3>Shelly</h3>
|
||||
<ul>
|
||||
<p> FHEM module to communicate with a Shelly switch/roller actuator</p>
|
||||
<p> FHEM module to communicate with a Shelly switch/roller actuator/RGBW controller</p>
|
||||
<a name="Shellydefine"></a>
|
||||
<h4>Define</h4>
|
||||
<p>
|
||||
<code>define <name> Shelly <IP address></code>
|
||||
<br />Defines the Shelly device. </p>
|
||||
Notes: <ul>
|
||||
<li>The attribute <code>model</code> <b>must</b> be set</li>
|
||||
<li>The attribute <code>model</code> <b>must</b> be set</li>
|
||||
<li>This module needs the JSON package</li>
|
||||
<li>In Shelly switch devices one may set URL values that are "hit" when the input or output status changes. Here one must set
|
||||
<ul>
|
||||
<li> For <i>Button switched ON url</i>: http://<FHEM IP address>:<Port>/fhem?cmd=set%20$lt;Devicename>%20<b>button_on</b>%20[<channel>]</li>
|
||||
<li> For <i>Button switched OFF url</i>: http://<FHEM IP address>:<Port>/fhem?cmd=set%20$lt;Devicename>%20<b>button_off</b>%20[<channel>]</li>
|
||||
<li> For <i>Output switched ON url</i>: http://<FHEM IP address>:<Port>/fhem?cmd=set%20$lt;Devicename>%20<b>out_on</b>%20[<channel>]</li>
|
||||
<li> For <i>Output switched OFF url</i>: http://<FHEM IP address>:<Port>/fhem?cmd=set%20$lt;Devicename>%20<b>out_off</b>%20[<channel>]</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
<a name="Shellyset"></a>
|
||||
<h4>Set</h4>
|
||||
For Shelly all Shelly devices
|
||||
For all Shelly devices
|
||||
<ul>
|
||||
<li><a name="shelly_sconfig"></a>
|
||||
<code>set <name> config <registername> [<channel>] <value></code>
|
||||
<br />set the value of a configuration register</li>
|
||||
<li><a name="shelly_password">password <password></a><br>This is the only way to set the password for the Shelly web interface</li>
|
||||
</ul>
|
||||
For Shelly switching devices (mode=relay for model=shelly2, standard for all other models)
|
||||
For Shelly switching devices (model=shelly1|shelly1pm|shelly4|shellyplug or (model=shelly2/2.5 and mode=relay))
|
||||
<ul>
|
||||
<li><a name="shelly_onoff"></a>
|
||||
<code>set <name> on|off [<channel>] </code>
|
||||
<br />switches channel <channel> on or off. Channel numbers are 0 and 1 for model=shelly2, 0..3 model=shelly4. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
<br />switches channel <channel> on or off. Channel numbers are 0 and 1 for model=shelly2/2.5, 0..3 for model=shelly4. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
<li><a name="shelly_onofftimer"></a>
|
||||
<code>set <name> on-for-timer|off-for-timer <time> [<channel>] </code>
|
||||
<br />switches <channel> on or off for <time> seconds. Channel numbers are 0 and 1 for model=shelly2, 0..3 model=shelly4. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
<br />switches <channel> on or off for <time> seconds. Channel numbers are 0 and 1 for model=shelly2/2.5, and 0..3 model=shelly4. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
</ul>
|
||||
<br/>For Shelly roller blind devices (mode=roller for model=shelly2)
|
||||
<br/>For Shelly roller blind devices (model=shelly2/2.5 and mode=roller)
|
||||
<ul>
|
||||
<li><a name="shelly_updown"></a>
|
||||
<code>set <name> open|closed|stop </code>
|
||||
@ -1035,7 +1375,40 @@ sub Shelly_updown2($){
|
||||
<br />drives the roller blind to a partially closed position (100=open, 0=closed)</li>
|
||||
<li><a name="shelly_zero"></a>
|
||||
<code>set <name> zero </code>
|
||||
<br />calibration of roller device (only for model=shelly2)</li>
|
||||
<br />calibration of roller device (only for model=shelly2/2.5)</li>
|
||||
</ul>
|
||||
<br/>For Shelly dimmer devices (model=shellyrgbw and mode=white)
|
||||
<ul>
|
||||
<li><a name="shelly_onoff"></a>
|
||||
<code>set <name> on|off [<channel>] </code>
|
||||
<br />switches channel <channel> on or off. Channel numbers are 0..3 for model=shellyrgbw. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
<li><a name="shelly_onofftimer"></a>
|
||||
<code>set <name> on-for-timer|off-for-timer <time> [<channel>] </code>
|
||||
<br />switches <channel> on or off for <time> seconds. Channel numbers 0..3 for model=shellyrgbw. If the channel parameter is omitted, the module will switch the channel defined in the defchannel attribute.</li>
|
||||
<li><a name="shelly_brightness"></a>
|
||||
<code>set <name> pct <0..100> [<channel>] </code>
|
||||
<br />percent value to set brightness value. Channel numbers 0..3 for model=shellyrgbw. If the channel parameter is omitted, the module will dim the channel defined in the defchannel attribute.</li>
|
||||
</ul>
|
||||
<br/>For Shelly RGBW devices (model=shellyrgbw and mode=color)
|
||||
<ul>
|
||||
<li><a name="shelly_onoff"></a>
|
||||
<code>set <name> on|off</code>
|
||||
<br />switches device <channel> on or off</li>
|
||||
<li><a name="shelly_onofftimer"></a>
|
||||
<code>set <name> on-for-timer|off-for-timer <time></code>
|
||||
<br />switches device on or off for <time> seconds. </li>
|
||||
<li><a name="shelly_hsv"></a>
|
||||
<code>set <name> hsv <hue value 0..360><saturation value 0..1><brightness value 0..1> </code>
|
||||
<br />6-digit hex string to set the color.</li>
|
||||
<li><a name="shelly_rgb"></a>
|
||||
<code>set <name> rgb <rrggbb> </code>
|
||||
<br />6-digit hex string to set the color.</li>
|
||||
<li><a name="shelly_rgbw"></a>
|
||||
<code>set <name> rgbw <rrggbbww> </code>
|
||||
<br />8-digit hex string to set the color and white value</li>
|
||||
<li><a name="shelly_white"></a>
|
||||
<code>set <name> white <integer></code>
|
||||
<br /> number 0..255 to set the white value </li>
|
||||
</ul>
|
||||
<a name="Shellyget"></a>
|
||||
<h4>Get</h4>
|
||||
@ -1057,20 +1430,20 @@ sub Shelly_updown2($){
|
||||
<h4>Attributes</h4>
|
||||
<ul>
|
||||
<li><a name="shelly_shellyuser"><code>attr <name> shellyuser <shellyuser></code><br>username for addressing the Shelly web interface</li>
|
||||
<li><a name="shelly_model"><code>attr <name> model shelly1|shelly2|shelly4|shellyplug </code></a>
|
||||
<li><a name="shelly_model"><code>attr <name> model shelly1|shelly1pm|shelly2|shelly2.5|shelly4|shellyplug|shellyrgbw </code></a>
|
||||
<br />type of the Shelly device</li>
|
||||
<li><a name="shelly_mode"><code>attr <name> mode relay|roller (only for model=shelly2)</code></a>
|
||||
<li><a name="shelly_mode"><code>attr <name> mode relay|roller (only for model=shelly2/2.5) mode white|color (only for model=shellyrgbw)</code></a>
|
||||
<br />type of the Shelly device</li>
|
||||
<li><a name="shelly_interval">
|
||||
<code><interval></code>
|
||||
<br />Update interval for reading in seconds. The default is 60 seconds, a value of 0 disables the automatic update. </li>
|
||||
</ul>
|
||||
<br/>For Shelly switching devices (mode=relay for model=shelly2, standard for all other models)
|
||||
<br/>For Shelly switching devices (mode=relay for model=shelly2/2.5, standard for all other switching models)
|
||||
<ul>
|
||||
<li><a name="shelly_defchannel"><code>attr <name> defchannel <integer> </code></a>
|
||||
<br />only for model=shelly2|shelly4 or multi-channel switches: Which channel will be switched, if a command is received without channel number</li>
|
||||
<br />only for model=shelly2|shelly2.5|shelly4 or multi-channel switches: Which channel will be switched, if a command is received without channel number</li>
|
||||
</ul>
|
||||
<br/>For Shelly roller blind devices (mode=roller for model=shelly2)
|
||||
<br/>For Shelly roller blind devices (mode=roller for model=shelly2/2.5)
|
||||
<ul>
|
||||
<li><a name="shelly_maxtime"><code>attr <name> maxtime <float> </code></a>
|
||||
<br />time needed for a complete drive upward or downward</li>
|
||||
@ -1094,5 +1467,4 @@ sub Shelly_updown2($){
|
||||
Absichtlich keine deutsche Dokumentation vorhanden, die englische Version gibt es hier: <a href="commandref.html#Shelly">Shelly</a>
|
||||
</ul>
|
||||
=end html_DE
|
||||
|
||||
=cut
|
Loading…
Reference in New Issue
Block a user