diff --git a/fhem/FHEM/88_xs1Bridge.pm b/fhem/FHEM/88_xs1Bridge.pm index e680051ca..3a961ec36 100644 --- a/fhem/FHEM/88_xs1Bridge.pm +++ b/fhem/FHEM/88_xs1Bridge.pm @@ -26,12 +26,14 @@ eval "use JSON;1" or $missingModul .= "JSON "; use Net::Ping; # Ping Test Verbindung +#$| = 1; #Puffern abschalten, Hilfreich für PEARL WARNINGS Search + sub xs1Bridge_Initialize($) { my ($hash) = @_; $hash->{WriteFn} = "xs1Bridge_Write"; - $hash->{Clients} = ":xs1Device:"; - $hash->{MatchList} = { "1:xs1Device" => '[A][k][t][o][r]_[0-6][0-9].*|[S][e][n][s][o][r]_[0-6][0-9].*' }; ## https://regex101.com/ Testfunktion + $hash->{Clients} = ":xs1Dev:"; + $hash->{MatchList} = { "1:xs1Dev" => '[x][s][1][D][e][v][#][A][k][t][o][r]#[0-6][0-9].*|[x][s][1][D][e][v][#][S][e][n][s][o][r]#[0-6][0-9].*' }; ## https://regex101.com/ Testfunktion $hash->{DefFn} = "xs1Bridge_Define"; $hash->{AttrFn} = "xs1Bridge_Attr"; @@ -39,7 +41,10 @@ sub xs1Bridge_Initialize($) { $hash->{AttrList} = "debug:0,1 ". "disable:0,1 ". "ignore:0,1 ". - "interval:30,60,180,360 "; + "interval:30,60,180,360 ". + "update_only_difference:0,1 ". + "view_Device_name:0,1 ". + "view_Device_function:0,1 "; ##$readingFnAttributes; ## die Standardattribute von FHEM foreach my $d(sort keys %{$modules{xs1Bridge}{defptr}}) { @@ -53,6 +58,9 @@ sub xs1Bridge_Define($$) { my $name = $hash->{NAME}; ## Der Definitionsname, mit dem das Gerät angelegt wurde. my $typ = $hash->{TYPE}; ## Der Modulname, mit welchem die Definition angelegt wurde. my $debug = AttrVal($hash->{NAME},"debug",0); + my $viewDeviceName = AttrVal($hash->{NAME},"view_Device_name",0); + my $viewDeviceFunction = AttrVal($hash->{NAME},"view_Device_function",0); + my $update_only_difference = AttrVal($hash->{NAME},"update_only_difference",0); return "Usage: define $name " if(@arg != 3); return "Cannot define xs1Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul ); @@ -64,7 +72,7 @@ sub xs1Bridge_Define($$) { if (&xs1Bridge_Ping == 1) { ## IP - Check $hash->{STATE} = "Initialized"; ## Der Status des Modules nach Initialisierung. $hash->{TIME} = time(); ## Zeitstempel, derzeit vom anlegen des Moduls - $hash->{VERSION} = "1.06"; ## Version + $hash->{VERSION} = "1.09"; ## Version $hash->{BRIDGE} = 1; # Attribut gesetzt @@ -91,17 +99,17 @@ sub xs1Bridge_Attr(@) { my $typ = $hash->{TYPE}; my $interval = 0; my $debug = AttrVal($hash->{NAME},"debug",0); + my $viewDeviceName = AttrVal($hash->{NAME},"view_Device_name",0); + my $viewDeviceFunction = AttrVal($hash->{NAME},"view_Device_function",0); + my $update_only_difference = AttrVal($hash->{NAME},"update_only_difference",0); # $cmd - Vorgangsart - kann die Werte "del" (löschen) oder "set" (setzen) annehmen # $name - Gerätename # $attrName/$attrValue sind Attribut-Name und Attribut-Wert - Debug " $typ: xs1_Attr | Attributes $attrName = $attrValue" if($debug); - if ($cmd eq "set") { ## Handling bei set .. attribute RemoveInternalTimer($hash); ## Timer löschen - Debug " $typ: xs1_Attr | Cmd:$cmd | RemoveInternalTimer" if($debug); - + Debug " $typ: Attr | Cmd:$cmd | RemoveInternalTimer" if($debug); if ($attrName eq "interval") { ## Abfrage Attribute if (($attrValue !~ /^\d*$/) || ($attrValue < 10)) ## Bildschirmausgabe - Hinweis Wert zu klein { @@ -116,17 +124,63 @@ sub xs1Bridge_Attr(@) { elsif ($attrValue eq "0") { ## Handling bei attribute disable 0 readingsSingleUpdate($hash, "state", "active", 1); } + }elsif ($attrName eq "view_Device_function") { + if ($attrValue eq "1") { ## Handling bei attribute disable 1 + Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue"; + } + elsif ($attrValue eq "0") { ## Handling bei attribute disable 0 + Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue"; + } + }elsif ($attrName eq "view_Device_name") { + if ($attrValue eq "1") { ## Handling bei attribute disable 1 + Log3 $name, 3, "$typ: Attribut view_Device_name $cmd to $attrValue"; + } + elsif ($attrValue eq "0") { ## Handling bei attribute disable 0 + Log3 $name, 3, "$typ: Attribut view_Device_name $cmd to $attrValue"; + for my $i (0..64) { + delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS}); + delete $hash->{READINGS}{"Sensor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS}); + } + } + }elsif ($attrName eq "update_only_difference") { + if ($attrValue eq "1") { ## Handling bei attribute disable 1 + Log3 $name, 3, "$typ: Attribut update_only_difference $cmd to $attrValue"; + } + elsif ($attrValue eq "0") { ## Handling bei attribute disable 0 + Log3 $name, 3, "$typ: Attribut update_only_difference $cmd to $attrValue"; + for my $i (0..64) { + delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS}); + } + } } } if ($cmd eq "del") { ## Handling bei del ... attribute if ($attrName eq "disable" && !defined $attrValue) { readingsSingleUpdate($hash, "state", "active", 1); - Debug " $typ: xs1_Attr | Cmd:$cmd | $attrName=$attrValue" if($debug); + Debug " $typ: Attr | Cmd:$cmd | $attrName=$attrValue" if($debug); } - if ($attrName eq "interval") { + elsif ($attrName eq "interval") { RemoveInternalTimer($hash); - Debug " $typ: xs1_Attr | Cmd:$cmd | $attrName" if($debug); + Debug " $typ: Attr | Cmd:$cmd | $attrName" if($debug); + } + elsif ($attrName eq "view_Device_function") { + Log3 $name, 3, "$typ: Attribut view_Device_function delete"; + for my $i (0..64) { + for my $i2 (1..4) { + delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_function_".$i2} if($hash->{READINGS}); + } + } + } + elsif ($attrName eq "view_Device_name") { + Log3 $name, 3, "$typ: Attribut view_Device_name delete"; + for my $i (0..64) { + delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS}); + delete $hash->{READINGS}{"Sensor_".sprintf("%02d", $i)."_name"} if($hash->{READINGS}); + } + } + elsif ($attrName eq "update_only_difference") { + Log3 $name, 3, "$typ: Attribut update_only_difference delete"; } } @@ -134,7 +188,7 @@ sub xs1Bridge_Attr(@) { if ($hash->{STATE} eq "active") { RemoveInternalTimer($hash); InternalTimer(gettimeofday()+$interval, "xs1Bridge_GetUpDate", $hash); - Debug " $typ: xs1_Attr | RemoveInternalTimer + InternalTimer" if($debug); + Debug " $typ: Attr | RemoveInternalTimer + InternalTimer" if($debug); } return undef; } @@ -145,7 +199,7 @@ sub xs1Bridge_Delete($$) { return undef; } -sub xs1Bridge_Ping() { ## Check before Define +sub xs1Bridge_Ping() { ## Check IP before Define my ($hash) = @_; my $name = $hash->{NAME}; my $typ = $hash->{TYPE}; @@ -186,82 +240,167 @@ sub xs1Bridge_GetUpDate() { my $debug = AttrVal($hash->{NAME},"debug",0); my $disable = AttrVal($name, "disable", 0); my $interval = AttrVal($name, "interval", 60); + my $viewDeviceName = AttrVal($hash->{NAME},"view_Device_name",0); + my $viewDeviceFunction = AttrVal($hash->{NAME},"view_Device_function",0); + my $update_only_difference = AttrVal($hash->{NAME},"update_only_difference",0); if (AttrVal($hash->{NAME},"disable",0) == 0) { RemoveInternalTimer($hash); InternalTimer(gettimeofday()+$interval, "xs1Bridge_GetUpDate", $hash); Debug "\n ------------- ERROR CHECK - START -------------" if($debug); - Debug " $typ: xs1Bridge_GetUpDate | RemoveInternalTimer + InternalTimer" if($debug); + Debug " $typ: GetUpDate | RemoveInternalTimer + InternalTimer" if($debug); #Log3 $name, 3, "$typ: xs1Bridge_GetUpDate | RemoveInternalTimer + InternalTimer"; if ($state eq "Initialized") { - readingsSingleUpdate($hash, "state", "active", 1); + readingsSingleUpdate($hash, "state", "active", 0); } - my $xs1_check = "-"; + my $xs1Dev_check = "ERROR"; - if($modules{xs1Device} && $modules{xs1Device}{LOADED}) { ## Check Modul - Debug " $typ: xs1Bridge_GetUpDate | Modul xs1Device loaded" if($debug); - $xs1_check = "ok"; + #if($modules{xs1Dev} && $modules{xs1Dev}{LOADED}) { ## Check Modul vorhanden + geladen + if($modules{xs1Dev}) { ## Check Modul vorhanden + $xs1Dev_check = "ok"; + Debug " $typ: GetUpDate | Modul xs1Dev_check = $xs1Dev_check" if($debug); } else { - Debug " $typ: xs1Bridge_GetUpDate | Modul xs1Device can´t load! Please check it to be available!" if($debug); + Debug " $typ: GetUpDate ERROR | Modul xs1Dev not existent! Please check it to be available!" if($debug); + #Log3 $name, 3, "$typ: GetUpDate | xs1Dev_check = $xs1Dev_check"; } ### JSON Abfrage - Schleife - for my $i (0..4) { + for my $i (0..3) { my $adress = "http://".$hash->{xs1_ip}.$cmd.$cmdtyp[$i]; - Debug " $typ: xs1Bridge_GetUpDate | Adresse: $adress" if($debug); + Debug " $typ: GetUpDate | Adresse: $adress" if($debug); my $ua = LWP::UserAgent->new; ## CHECK JSON Adresse -> JSON-query, sonst FHEM shutdown my $resp = $ua->request(HTTP::Request->new(GET => $adress)); + Debug " $typ: GetUpDate | Adresse HTTP request Code: ".$resp->code if($debug); if ($resp->code != "200") { ## http://search.cpan.org/~oalders/HTTP-Message-6.13/lib/HTTP/Status.pm - Log3 $name, 3, "$typ: xs1Bridge_GetUpDate | HTTP GET error code ".$resp->code." -> no JSON-query"; - if ($i == 0 || $i == 1 || $i == 2 || $i == 3) {last}; ## ERROR JSON-query -> Abbruch schleife + Log3 $name, 3, "$typ: GetUpDate | cmdtyp=".$cmdtyp[$i]." - HTTP GET error code ".$resp->code." -> no JSON-query"; + last; ## ERROR JSON-query -> Abbruch schleife } - my ($json) = get( $adress ) =~ /[^(]*[}]/g; ## cut cname( + ) am Ende von Ausgabe -> ARRAY Struktur - my $json_utf8 = eval {encode_utf8( $json )}; ## UTF-8 character Bearbeitung, da xs1 TempSensoren ERROR - my $decoded = eval {decode_json( $json_utf8 )}; - - if ($i <= 1 ) { ### xs1 Aktoren / Sensoren + my $json; + my $json_utf8; + my $decoded; + + if (defined($adress)) { + ($json) = get( $adress ) =~ /[^(]*[}]/g; ## cut cname( + ) am Ende von Ausgabe -> ARRAY Struktur als Antwort vom xs1 + $json_utf8 = eval {encode_utf8( $json )}; ## UTF-8 character Bearbeitung, da xs1 TempSensoren ERROR + $decoded = eval {decode_json( $json_utf8 )}; ## auswertbares ARAAY + } else { + Log3 $name, 3, "$typ: Adresse:$adress undefined"; + last; + } + + if ($i <= 1 ) { ### xs1 Aktoren / Sensoren + #my $resp = $ua->request(HTTP::Request->new(GET => $adress)); ## CHECK JSON Adresse -> JSON-query, sonst FHEM shutdown + if ($resp->code != "200") { ## http://search.cpan.org/~oalders/HTTP-Message-6.13/lib/HTTP/Status.pm + Log3 $name, 3, "$typ: GetUpDate | cmdtyp=".$cmdtyp[$i]." - HTTP GET error code ".$resp->code." -> no JSON-query"; + last; ## ERROR JSON-query -> Abbruch schleife + } + + #Log3 $name, 3, "$typ: GetUpDate | adresse=".$adress; + + my $data; my @array = @{ $decoded->{$arrayname[$i]} }; - foreach my $f ( @array ) { + foreach my $f ( @array ) { if ($f->{"type"} ne "disabled") { - Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"} if($debug); - my $data = "-"; - if ($i == 0) ### xs1 Aktoren nur update bei differenten Wert - { - my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}), "unknown"); ## Readings Wert - my $newState = $f->{"value"}; ## ARRAY Wert xs1 aktuell - Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." oldState=$oldState newState=$newState" if($debug); - if ($oldState ne $newState) { - readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , $f->{"value"}, 1); - $data = $readingsname[$i]."_".sprintf("%02d", $f->{"id"})."_".$f->{"type"}."_".$f->{"value"}; + my $xs1Dev = "xs1Dev"; + + ### Aktoren spezifisch + my $xs1_function1 = "-"; + my $xs1_function2 = "-"; + my $xs1_function3 = "-"; + my $xs1_function4 = "-"; + + if ($i == 0) { + ### xs1 Aktoren nur update bei differenten Wert + if ($update_only_difference == 1) { + my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}), "unknown"); ## Readings Wert + my $newState = $f->{"value"}; ## ARRAY Wert xs1 aktuell + + Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." oldState=$oldState newState=$newState" if($debug); + + if ($oldState ne $newState) { + readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , $f->{"value"}, 0); + } + } + + ### xs1 Aktoren / Funktion != disable + my @array2 = @{ $decoded->{'actuator'}->[($f->{"id"})-1]->{$arrayname[4]} }; + my $i2 = 0; ## Funktionscounter + + foreach my $f2 ( @array2 ) { + $i2 = $i2+1; + + if ($viewDeviceFunction == 1) { + my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $f->{"id"})."_".$arrayname[4]."_".$i2, "unknown"); ## Readings Wert + my $newState = $f2->{'type'}; ## ARRAY Wert xs1 aktuell + + if ($f2->{"type"} ne "disabled") { ## Funktion != function -> type disable + if ($oldState ne $newState) { + readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"})."_".$arrayname[4]."_".$i2 , $f2->{"type"} , 0); + } + } + } else { + if ($f2->{"type"} ne "disabled") { ## Funktion != function -> type disable + + if ($i2 == 1) { + $xs1_function1 = $f2->{"type"}; + }elsif ($i2 == 2) { + $xs1_function2 = $f2->{"type"}; + }elsif ($i2 == 3) { + $xs1_function3 = $f2->{"type"}; + }elsif ($i2 == 4) { + $xs1_function4 = $f2->{"type"}; + } + } + } } } - else - { - readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , $f->{"value"}, 1); - $data = $readingsname[$i]."_".sprintf("%02d", $f->{"id"})."_".$f->{"type"}."_".$f->{"value"}; + + ### Value der Aktoren | Sensoren + if ($i == 1 || $i == 0 && $update_only_difference == 0) { # Aktoren | Sensoren im intervall + readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , $f->{"value"}, 0); + $data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $f->{"id"})."#".$f->{"type"}."#".$f->{"value"}."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"}; + } elsif ($i == 0 && $update_only_difference == 1) { # Aktoren separat wenn update_only_difference Option aktiv für xs1Bridge + $data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $f->{"id"})."#".$f->{"type"}."#".$f->{"value"}."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"}; } - if ($xs1_check eq "ok") { - Debug " $typ: Dispatch -> $data" if($debug); - Dispatch($hash,$data,undef); ## Dispatch an xs1Device Modul + + ### Ausgaben je Typ unterschiedlich !!! + Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"}." | "."F1 $xs1_function1 | F2 $xs1_function2 | F3 $xs1_function3 | F4 $xs1_function4" if($debug == 1 && $i == 0); + Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"} if($debug == 1 && $i != 0); + + ### Namen der Aktoren | Sensoren + if ($viewDeviceName == 1) { + readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"})."_name" , $f->{"name"} , 0); + } + + ### Dispatch an xs1Device Modul + if ($xs1Dev_check eq "ok") { + #Log3 $name, 3, " $typ: GetUpDate | Dispatch -> $data"; + Debug " $typ: GetUpDate | Dispatch -> $data" if($debug); + Dispatch($hash,$data,undef) if($data); } } } - - } elsif ($i == 2) { ### xs1 Info´s + } elsif ($i == 2) { ### xs1 Info´s + #my $resp = $ua->request(HTTP::Request->new(GET => $adress)); ## CHECK JSON Adresse -> JSON-query, sonst FHEM shutdown + if ($resp->code != "200") { ## http://search.cpan.org/~oalders/HTTP-Message-6.13/lib/HTTP/Status.pm + Log3 $name, 3, "$typ: GetUpDate | cmdtyp=".$cmdtyp[$i]." - HTTP GET error code ".$resp->code." -> no JSON-query"; + last; ## ERROR JSON-query -> Abbruch schleife + } + my $features; my $features_i=0; while (defined $decoded->{'info'}{'features'}->[$features_i]) { - $features.= $decoded->{'info'}{'features'}->[$features_i]." "; - $features_i++; + $features.= $decoded->{'info'}{'features'}->[$features_i]." "; + $features_i++; } - my @xs1_readings = ("xs1_devicename","xs1_bootloader","xs1_hardware","xs1_features","xs1_firmware","xs1_mac","xs1_uptime"); + my @xs1_readings = ("xs1_devicename","xs1_bootloader","xs1_hardware","xs1_features","xs1_firmware","xs1_mac","xs1_start"); my @xs1_decoded = ($decoded->{'info'}{'devicename'} , $decoded->{'info'}{'bootloader'} , $decoded->{'info'}{'hardware'} , $features , $decoded->{'info'}{'firmware'} , $decoded->{'info'}{'mac'} , FmtDateTime(time()-($decoded->{'info'}{'uptime'}))); - # xs1_uptime wird teilweise je nach Laufzeit mit aktualisiert (+-1 Sekunde) -> Systemabhängig + # xs1_start wird teilweise je nach Laufzeit mit aktualisiert (+-1 Sekunde) -> Systemabhängig my $i2 = 0; readingsBeginUpdate($hash); @@ -273,7 +412,7 @@ sub xs1Bridge_GetUpDate() { readingsBulkUpdate($hash, $xs1_readings[$i2] , $xs1_decoded[$i2]); } } - readingsEndUpdate($hash, 1); + readingsEndUpdate($hash, 0); Debug " $typ: xs1_devicename: ".$decoded->{'info'}{'devicename'} if($debug); Debug " $typ: xs1_bootloader: ".$decoded->{'info'}{'bootloader'} if($debug); @@ -281,45 +420,34 @@ sub xs1Bridge_GetUpDate() { Debug " $typ: xs1_features: ".$features if($debug); Debug " $typ: xs1_firmware: ".$decoded->{'info'}{'firmware'} if($debug); Debug " $typ: xs1_mac: ".$decoded->{'info'}{'mac'} if($debug); - Debug " $typ: xs1_uptime: ".$decoded->{'info'}{'uptime'} if($debug); + Debug " $typ: xs1_start: ".$decoded->{'info'}{'uptime'} if($debug); - } elsif ($i == 3) { ### xs1 Timers + } elsif ($i == 3) { ### xs1 Timers + #my $resp = $ua->request(HTTP::Request->new(GET => $adress)); ## CHECK JSON Adresse -> JSON-query, sonst FHEM shutdown + if ($resp->code != "200") { ## http://search.cpan.org/~oalders/HTTP-Message-6.13/lib/HTTP/Status.pm + Log3 $name, 3, "$typ: GetUpDate | cmdtyp=".$cmdtyp[$i]." - HTTP GET error code ".$resp->code." -> no JSON-query"; + last; ## ERROR JSON-query -> Abbruch schleife + } + my @array = @{ $decoded->{$arrayname[$i]} }; foreach my $f ( @array ) { my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}), "unknown"); ## Readings Wert - my $newState = FmtDateTime($f->{"next"}); ## ARRAY Wert xs1 aktuell + my $newState = FmtDateTime($f->{"next"}); ## ARRAY Wert xs1 aktuell if ($f->{"type"} ne "disabled") { - if ($oldState ne $newState) { ## Update Reading nur bei Wertänderung - readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , FmtDateTime($f->{"next"}), 1); + if ($oldState ne $newState) { ## Update Reading nur bei Wertänderung + readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $f->{"id"}) , FmtDateTime($f->{"next"}), 0); } Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"name"}." | ".$f->{"type"}." | ". $f->{"next"} if($debug); } - elsif($oldState ne "unknown") { ## deaktive Timer mit Wert werden als Reading entfernt - Log3 $name, 3, "$typ: xs1Bridge_GetUpDate | ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." is deactive in xs1"; + elsif($oldState ne "unknown") { ## deaktive Timer mit Wert werden als Reading entfernt + Log3 $name, 3, "$typ: GetUpDate | ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." is deactive in xs1"; delete $defs{$name}{READINGS}{$readingsname[$i]."_".sprintf("%02d", $f->{"id"})}; } } - } elsif ($i == 4) { ### xs1 Aktoren / Funktion != disable - my @array2 = @{ $decoded->{$arrayname[0]} }; - foreach my $f2 ( @array2 ) { - - if ($f2->{"type"} ne "disabled") { ## Funktion != actuator -> type disable - my @array = @{ $decoded->{'actuator'}->[($f2->{"id"})-1]->{$arrayname[$i]} }; - my $i3 = 0; ## Funktionscounter - - foreach my $f3 ( @array ) { - $i3 = $i3+1; - if ($f3->{"type"} ne "disabled") { ## Funktion != function -> type disable - Debug " $typ: ".$readingsname[0]."_".sprintf("%02d", $f2->{"id"})." | ".$f2->{"type"}." | ".$arrayname[$i]."_".$i3." | ".$f3->{"type"} if($debug); - #readingsSingleUpdate($hash, $readingsname[0]."_".sprintf("%02d", $f2->{"id"})."_".$arrayname[$i]."_".$i3 , $f3->{"type"} , 1); - } - } - } - } } - - if ($i < 4) { + + if ($i < 3) { Debug "\n ------------- ERROR CHECK - SUB -------------" if($debug); } ### Schleifen Ende ### @@ -331,11 +459,49 @@ sub xs1Bridge_GetUpDate() { sub xs1Bridge_Write($) ## Zustellen von Daten via IOWrite() vom logischen zum physischen Modul { - my ($hash, $Aktor_ID, $cmd) = @_; + my ($hash, $Aktor_ID, $xs1_typ, $cmd) = @_; my $name = $hash->{NAME}; my $typ = $hash->{TYPE}; + my $xs1_ip = $hash->{xs1_ip}; - Log3 $name, 3, "$typ: xs1Bridge_Write | Aktor_ID=$Aktor_ID, cmd=$cmd"; + Log3 $name, 3, "$typ: Write | Device=$Aktor_ID xs1_typ=$xs1_typ cmd=$cmd Parameter for xs1"; + + ## http://xmodulo.com/how-to-send-http-get-or-post-request-in-perl.html + ## Anfrage (Client -> XS1): http://192.168.1.242/control?callback=cname&cmd=set_state_actuator&number=1&value=50 + + $Aktor_ID = substr($Aktor_ID, 1,2); + + if ($xs1_typ eq "switch") { + Log3 $name, 3, "$typ: Write | xs1_typ=$xs1_typ cmd=$cmd"; + + if ($cmd eq "off") { + $cmd = 0; + } elsif ($cmd eq "on") { + $cmd = 100; + } + } elsif ($xs1_typ eq "dimmer") { + Log3 $name, 3, "$typ: Write | xs1_typ=$xs1_typ cmd=$cmd"; + + } + + my $json; + my $json_utf8; + my $decoded; + my $xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&value=$cmd"; + + my $ua = LWP::UserAgent->new; ## CHECK JSON Adresse -> JSON-query, sonst FHEM shutdown + my $resp = $ua->request(HTTP::Request->new(GET => $xs1cmd)); + + if ($resp->code != "200") { ## http://search.cpan.org/~oalders/HTTP-Message-6.13/lib/HTTP/Status.pm + Log3 $name, 3, "$typ: Write | cmd=".$xs1cmd." - HTTP GET error code ".$resp->code." -> no Control possible"; + return undef; + } else { + Log3 $name, 3, "$typ: Write | Send to xs1 -> $xs1cmd"; + + ($json) = get( $xs1cmd ) =~ /[^(]*[}]/g; ## cut cname( + ) am Ende von Ausgabe -> ARRAY Struktur als Antwort vom xs1 + $json_utf8 = eval {encode_utf8( $json )}; ## UTF-8 character Bearbeitung, da xs1 TempSensoren ERROR + $decoded = eval {decode_json( $json_utf8 )}; ## auswertbares ARAAY + } } sub xs1Bridge_Undef($$) @@ -345,6 +511,7 @@ sub xs1Bridge_Undef($$) RemoveInternalTimer($hash); Log3 $name, 3, "$typ: Device with Name: $name delete"; + delete $modules{xs1Bridge}{defptr}{BRIDGE} if( defined($modules{xs1Bridge}{defptr}{BRIDGE}) ); return undef; } @@ -357,7 +524,7 @@ sub xs1Bridge_Undef($$) =pod =item summary Connection of the device xs1 from EZControl -=item summary_DE Anbindung des Gerates xs1 der Firma EZControl +=item summary_DE Anbindung des Gerätes xs1 der Firma EZControl =begin html @@ -366,7 +533,8 @@ sub xs1Bridge_Undef($$) With this module you can read out the device xs1 from EZcontrol. There will be actors | Sensors | Timer | Information read from xs1 and written in readings. With each read only readings are created or updated, which are also defined and active in xs1. Actor | Sensor or timer definitions which are deactivated in xs1 are NOT read.

- The module was developed based on the firmware version v4-Beta of the xs1. There may be errors due to different adjustments within the manufacturer's firmware.

+ The module was developed based on the firmware version v4-Beta of the xs1. There may be errors due to different adjustments within the manufacturer's firmware.
+ Testet firmware: v4.0.0.5326 (Beta)

Define
@@ -403,19 +571,33 @@ sub xs1Bridge_Undef($$) For actuators, only different states are updated in the set interval.
Sensors are always updated in intervals, regardless of the status.
(Default, interval 60) +
+
  • update_only_difference (0,1)
    + The actuators defined in xs1 are only updated when the value changes.
    + (Default, update_only_difference 0)

  • +
  • view_Device_name (0,1)
    + The actor names defined in xs1 are read as Reading.
    + (Default, view_Device_name 0)
    +

  • +
  • view_Device_function (0,1)
    + The actuator functions defined in xs1 are read out as Reading.
    + (Default, view_Device_function 0)


  • explanation: @@ -430,7 +612,8 @@ sub xs1Bridge_Undef($$) Es werden Aktoren | Sensoren | Timer | Informationen vom xs1 ausgelesen und in Readings geschrieben. Bei jedem Auslesen werden nur Readings angelegt bzw. aktualisiert, welche auch im xs1 definiert und aktiv sind. Aktor | Sensor bzw. Timer Definitionen welche deaktiviert sind im xs1, werden NICHT ausgelesen.

    - Das Modul wurde entwickelt basierend auf dem Firmwarestand v4-Beta des xs1. Es kann aufgrund von unterschiedlichen Anpassungen innerhalb der Firmware des Herstellers zu Fehlern kommen.

    + Das Modul wurde entwickelt basierend auf dem Firmwarestand v4-Beta des xs1. Es kann aufgrund von unterschiedlichen Anpassungen innerhalb der Firmware des Herstellers zu Fehlern kommen.
    + Getestete Firmware: v4.0.0.5326 (Beta)

    Define
    @@ -467,19 +650,33 @@ sub xs1Bridge_Undef($$) Bei Aktoren werden nur unterschiedliche Zustände aktualisiert im eingestellten Intervall.
    Sensoren werden unabhängig vom Zustand immer im Intervall aktualisiert.
    (Default, interval 60) +
    +
  • update_only_difference (0,1)
    + Die Aktoren welche im xs1 definiert wurden, werden nur bei Wertänderung aktualisiert.
    + (Default, update_only_difference 0)

  • +
  • view_Device_name (0,1)
    + Die Aktor Namen welche im xs1 definiert wurden, werden als Reading ausgelesen.
    + (Default, view_Device_name 0)
    +

  • +
  • view_Device_function (0,1)
    + Die Aktor Funktionen welche im xs1 definiert wurden, werden als Reading ausgelesen.
    + (Default, view_Device_function 0)


  • Erläuterung: