2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-01-31 12:49:34 +00:00

88_xs1Bridge: revised perlcritic

88_xs1Dev: revised perlcritic & fixed match (Forum #85137 #msg1204419)

git-svn-id: https://svn.fhem.de/fhem/trunk@25799 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
HomeAuto_User 2022-03-08 19:48:45 +00:00
parent 878e081c84
commit 289c7ca5e1
2 changed files with 1291 additions and 1277 deletions

View File

@ -7,7 +7,6 @@
# - Port Check ???
# - Sendeausgabe im LOG anpassen
#
#
#################################################################
package main;
@ -18,182 +17,193 @@ use strict;
use warnings; # Warnings
use Net::Ping;
my $missingModul = "";
my $missingModul = '';
my $xs1_ConnectionTry = 1; # disable Funktion sobald 10x keine Verbindung (Schutzabschaltung)
my $xs1_id;
eval "use Encode qw(encode encode_utf8 decode_utf8);1" or $missingModul .= "Encode ";
eval "use JSON;1" or $missingModul .= "JSON ";
eval "use Net::Ping;1" or $missingModul .= "Net::Ping ";
eval {use Encode qw(encode encode_utf8 decode_utf8);1} or $missingModul .= 'Encode ';
eval {use JSON;1} or $missingModul .= 'JSON ';
eval {use Net::Ping;1} or $missingModul .= 'Net::Ping ';
#$| = 1; #Puffern abschalten, Hilfreich für PEARL WARNINGS Search
sub xs1Bridge_Initialize($) {
##########################
sub xs1Bridge_Initialize {
my ($hash) = @_;
$hash->{WriteFn} = "xs1Bridge_Write";
$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->{WriteFn} = 'xs1Bridge_Write';
$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";
$hash->{UndefFn} = "xs1Bridge_Undef";
$hash->{AttrList} = "debug:0,1,2 ".
"ignore:0,1 ".
"update_only_difference:0,1 ".
"view_Device_name:0,1 ".
"view_Device_function:0,1 ".
"xs1_blackl_aktor ".
"xs1_blackl_sensor ".
"xs1_control:0,1 ".
"xs1_interval:0,30,60,180,360 ";
$hash->{DefFn} = 'xs1Bridge_Define';
$hash->{AttrFn} = 'xs1Bridge_Attr';
$hash->{UndefFn} = 'xs1Bridge_Undef';
$hash->{AttrList} = 'debug:0,1,2 '.
'ignore:0,1 '.
'update_only_difference:0,1 '.
'view_Device_function:0,1 '.
'view_Device_name:0,1 '.
'xs1_blackl_aktor '.
'xs1_blackl_sensor '.
'xs1_control:0,1 '.
'xs1_interval:0,30,60,180,360 ';
##$readingFnAttributes; ## die Standardattribute von FHEM
foreach my $d(sort keys %{$modules{xs1Bridge}{defptr}}) {
my $hash = $modules{xs1Bridge}{defptr}{$d};
$hash = $modules{xs1Bridge}{defptr}{$d};
}
return;
}
sub xs1Bridge_Define($$) {
##########################
sub xs1Bridge_Define {
my ($hash, $def) = @_;
my @arg = split("[ \t][ \t]*", $def);
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);
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);
# 0 1 2
return "Usage: define <NAME> $name <IP>" if(@arg != 3);
#return "Usage: define <NAME> $name <IP> <PORT>" if(@arg != 4);
return "Your IP is not valid. Please Check!" if not($arg[2] =~ /[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}/s);
#return "Your PORT is not valid. Please Check!" if not($arg[3] =~ /[0-9]{2,5}/s);
return 'Your IP is not valid. Please Check!' if not($arg[2] =~ /[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}/s);
#return 'Your PORT is not valid. Please Check!' if not($arg[3] =~ /[0-9]{2,5}/s);
return "Cannot define xs1Bridge device. Perl modul ${missingModul}is missing." if ( $missingModul );
my $xs1check = 0;
if(!defined $modules{xs1Bridge}) {
my $p = Net::Ping->new("tcp", 2);
my $p = Net::Ping->new('tcp', 2);
if(!($p->ping("$arg[2]", 2))) {
$xs1check = 1;
}
$p->close();
return "Your IP is not reachable. Please Check!" if ($xs1check == 1);
return 'Your IP is not reachable. Please Check!' if ($xs1check == 1);
}
# Parameter Define
my $xs1_ip = $arg[2]; ## Zusatzparameter 1 bei Define - ggf. nur in Sub
$hash->{xs1_ip} = $xs1_ip;
$hash->{STATE} = "Initialized"; ## Der Status des Modules nach Initialisierung.
$hash->{TIME} = time(); ## Zeitstempel, derzeit vom anlegen des Moduls
$hash->{VERSION} = "1.26"; ## Version
$hash->{BRIDGE} = 1;
$hash->{STATE} = 'Initialized'; ## Der Status des Modules nach Initialisierung.
$hash->{TIME} = time(); ## Zeitstempel, derzeit vom anlegen des Moduls
$hash->{VERSION} = '1.27'; ## Version
# Attribut gesetzt
$attr{$name}{xs1_interval} = "60" if( not defined( $attr{$name}{xs1_interval} ) );
$attr{$name}{room} = "xs1" if( not defined( $attr{$name}{room} ) );
$attr{$name}{xs1_control} = "0" if( not defined( $attr{$name}{xs1_control} ) );
if( not defined( $attr{$name}{xs1_control} ) ) { $attr{$name}{xs1_control} = '0'; }
if( not defined( $attr{$name}{xs1_interval} ) ) { $attr{$name}{xs1_interval} = '60'; }
$modules{xs1Bridge}{defptr}{BRIDGE} = $hash;
InternalTimer(gettimeofday()+$attr{$name}{xs1_interval}, "xs1Bridge_GetUpDate", $hash); ## set Timer
InternalTimer(gettimeofday()+$attr{$name}{xs1_interval}, 'xs1Bridge_GetUpDate', $hash); ## set Timer
#Log3 $name, 3, "$typ: IODev defined with xs1_ip: $xs1_ip";
if(!defined($defs{'FileLog_xs1Bridge'})) { ## Logfile existent check
Log3 $name, 4, "$typ: FileLog_xs1Bridge ist NICHT definiert";
fhem("define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log ".$arg[0]); ## Logfile define
fhem("attr FileLog_xs1Bridge room xs1"); ## Logfile in xs1 room
fhem('define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log '.$arg[0]); ## Logfile define
} else {
Log3 $name, 4, "$typ: FileLog_xs1Bridge ist definiert";
}
return undef;
return;
}
sub xs1Bridge_Attr(@) {
##########################
sub xs1Bridge_Attr {
my ($cmd,$name,$attrName,$attrValue) = @_;
my $hash = $defs{$name};
my $typ = $hash->{TYPE};
my $debug = AttrVal($hash->{NAME},"debug",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
my $xs1_interval = 0;
my @string_attrValue;
my @string_attrValue = split(",",$attrValue) if (defined $attrValue); ## for Check Blacklist
@string_attrValue = split(',',$attrValue) if (defined $attrValue); ## for Check Blacklist
my $length = scalar @string_attrValue; ## for Check Blacklist
# $cmd - Vorgangsart - kann die Werte "del" (löschen) oder "set" (setzen) annehmen
# $name - Gerätename
# $attrName/$attrValue sind Attribut-Name und Attribut-Wert
#### Handling bei set .. attribute
if ($cmd eq "set") {
if ($cmd eq 'set') {
RemoveInternalTimer($hash); ## Timer löschen
Debug " $typ: Attr | Cmd:$cmd | RemoveInternalTimer" if($debug == 2);
if ($attrName eq "xs1_interval" && $attrValue == 0) { ## Handling xs1_interval == 0
### xs1_interval == 0 ###
if ($attrName eq 'xs1_interval' && $attrValue == 0) {
RemoveInternalTimer($hash);
readingsSingleUpdate($hash, "state", "deactive", 1);
}elsif ($attrName eq "xs1_interval" && $attrValue >= 30) { ## Handling xs1_interval >= 30
readingsSingleUpdate($hash, 'state', 'deactive', 1);
### xs1_interval >= 30 ###
} elsif ($attrName eq 'xs1_interval' && $attrValue >= 30) {
$xs1_ConnectionTry = 1;
my $xs1_interval = $attrValue;
InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
readingsSingleUpdate($hash, "state", "active", 1);
### Ansicht xs1_Device_function ###
}elsif ($attrName eq "view_Device_function") {
if ($attrValue eq "1") { ## Handling view_Device_function 1
$xs1_interval = $attrValue;
InternalTimer(gettimeofday()+$xs1_interval, 'xs1Bridge_GetUpDate', $hash);
readingsSingleUpdate($hash, 'state', 'active', 1);
### view_Device_function ###
} elsif ($attrName eq 'view_Device_function') {
if ($attrValue eq '1') {
#Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue";
} elsif ($attrValue eq '0') {
#Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue";
}
elsif ($attrValue eq "0") { ## Handling view_Device_function 0
#Log3 $name, 3, "$typ: Attribut view_Device_function $cmd to $attrValue";
}
### Ansicht xs1_Device_name ###
}elsif ($attrName eq "view_Device_name") {
if ($attrValue eq "1") { ## Handling view_Device_name 1
### view_Device_name ###
} elsif ($attrName eq 'view_Device_name') {
if ($attrValue eq '1') {
#Log3 $name, 3, "$typ: Attribut view_Device_name $cmd to $attrValue";
}
elsif ($attrValue eq "0") { ## Handling view_Device_name 0
} elsif ($attrValue eq '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});
if ($hash->{READINGS}) {
if ($hash->{READINGS}{'Aktor_'.sprintf("%02d", $i).'_name'}) { delete $hash->{READINGS}{'Aktor_'.sprintf("%02d", $i).'_name'}; }
if ($hash->{READINGS}{'Sensor_'.sprintf("%02d", $i).'_name'}) { delete $hash->{READINGS}{'Sensor_'.sprintf("%02d", $i).'_name'}; }
}
}
### Wertaenderung nur bei Difference ###
}elsif ($attrName eq "update_only_difference") {
if ($attrValue eq "1") { ## Handling update_only_difference 1
}
### update_only_difference - Wertaenderung nur bei Difference ###
} elsif ($attrName eq 'update_only_difference') {
if ($attrValue eq '1') {
#Log3 $name, 3, "$typ: Attribut update_only_difference $cmd to $attrValue";
}
elsif ($attrValue eq "0") { ## Handling update_only_difference 0
} elsif ($attrValue eq '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});
delete $hash->{READINGS}{'Aktor_'.sprintf("%02d", $i).'_name'} if($hash->{READINGS});
}
}
### xs1 - steuern ###
}elsif ($attrName eq "xs1_control") {
if ($attrValue eq "1") { ## Handling xs1_control 1
} elsif ($attrName eq 'xs1_control') {
if ($attrValue eq '1') {
if(! $modules{xs1Dev}) { ## Check Modul vorhanden
$attr{$name}{xs1_control} = "0";
return "Module xs1Dev is non-existent or still under development. Please wait"
$attr{$name}{xs1_control} = '0';
return 'Module xs1Dev is non-existent or still under development. Please wait'
}
}
### Blacklist - Aktor / Sensor ###
}elsif ($attrName eq "xs1_blackl_aktor") { ## Handling xs1_blackl_aktor
} elsif ($attrName eq 'xs1_blackl_aktor') {
for (my $x = 0; $x < $length ; $x++) {
if ($string_attrValue[$x] =~ /^[1-9]{1}\d*/ && $string_attrValue[$x] <65) {
## RICHTIG ##
} else {
return "The comma separated value must only 1 to 64";
return 'The comma separated value must only 1 to 64';
}
}
Log3 $name, 4, "$typ: Attribut xs1_blackl_aktor $attrValue";
}elsif ($attrName eq "xs1_blackl_sensor") { ## Handling xs1_blackl_sensor
} elsif ($attrName eq 'xs1_blackl_sensor') {
for (my $x = 0; $x < $length ; $x++) {
if ($string_attrValue[$x] =~ /^[1-9]{1}\d*/ && $string_attrValue[$x] <65) {
## RICHTIG ##
} else {
return "The comma separated value must only 1 to 64";
return 'The comma separated value must only 1 to 64';
}
}
Log3 $name, 4, "$typ: Attribut xs1_blackl_sensor $attrValue";
@ -201,52 +211,54 @@ sub xs1Bridge_Attr(@) {
}
#### Handling bei del ... attribute
if ($cmd eq "del") {
if ($attrName eq "xs1_interval") { ## Handling deleteattr xs1_interval
if ($cmd eq 'del') {
if ($attrName eq 'xs1_interval') {
RemoveInternalTimer($hash);
readingsSingleUpdate($hash, "state", "deactive", 1);
readingsSingleUpdate($hash, 'state', 'deactive', 1);
Debug " $typ: Attr | Cmd:$cmd | $attrName" if($debug == 2);
}
elsif ($attrName eq "view_Device_function") { ## Handling deleteattr view_Device_function
} 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});
delete $hash->{READINGS}{'Aktor_'.sprintf("%02d", $i).'_function_'.$i2} if($hash->{READINGS});
}
}
}
elsif ($attrName eq "view_Device_name") { ## Handling deleteattr view_Device_name
} 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});
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") {
} elsif ($attrName eq 'update_only_difference') {
Log3 $name, 3, "$typ: Attribut update_only_difference delete";
}
}
#### Handling bei state active
if ($hash->{STATE} eq "active") {
if ($hash->{STATE} eq 'active') {
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
InternalTimer(gettimeofday()+$xs1_interval, 'xs1Bridge_GetUpDate', $hash);
Debug " $typ: Attr | RemoveInternalTimer + InternalTimer" if($debug == 2);
}
return undef;
return;
}
sub xs1Bridge_GetUpDate() {
##########################
sub xs1Bridge_GetUpDate {
my ($hash) = @_;
my $name = $hash->{NAME};
my $typ = $hash->{TYPE};
my $state = $hash->{STATE};
my $xs1_ip = $hash->{xs1_ip};
my $xs1_uptimeStart = $hash->{helper}{xs1_uptimeStart};
my $xs1_uptimeOld = $hash->{helper}{xs1_uptimeOld};
my $xs1_uptimeNew = $hash->{helper}{xs1_uptimeNew};
my $def;
my $xs1_uptimeNew = $hash->{helper}{xs1_uptimeNew};
my $xs1_uptimeOld = $hash->{helper}{xs1_uptimeOld};
my $xs1_uptimeStart = $hash->{helper}{xs1_uptimeStart};
#http://x.x.x.x/control?callback=cname&cmd=...
#get_list_actuators - list all actuators i0
@ -255,37 +267,36 @@ sub xs1Bridge_GetUpDate() {
#get_config_info - list all device info´s i2
#get_protocol_info - list protocol info´s
my $cmd = "/control?callback=cname&cmd=";
my @cmdtyp = ("get_list_actuators","get_list_sensors","get_config_info","get_list_timers","get_list_actuators");
my @arrayname = ("actuator","sensor","info","timer","function");
my @readingsname = ("Aktor","Sensor","","Timer","");
my $cmd = '/control?callback=cname&cmd=';
my @cmdtyp = ('get_list_actuators','get_list_sensors','get_config_info','get_list_timers','get_list_actuators');
my @arrayname = ('actuator','sensor','info','timer','function');
my @readingsname = ('Aktor','Sensor','','Timer','');
my $debug = AttrVal($hash->{NAME},"debug",0);
my $xs1_interval = AttrVal($name, "xs1_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);
my $xs1_control = AttrVal($hash->{NAME},"xs1_control",0);
my $xs1_blackl_aktor = AttrVal($hash->{NAME},"xs1_blackl_aktor",0);
my $xs1_blackl_sensor = AttrVal($hash->{NAME},"xs1_blackl_sensor",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
my $update_only_difference = AttrVal($hash->{NAME},'update_only_difference',0);
my $viewDeviceFunction = AttrVal($hash->{NAME},'view_Device_function',0);
my $viewDeviceName = AttrVal($hash->{NAME},'view_Device_name',0);
my $xs1_blackl_aktor = AttrVal($hash->{NAME},'xs1_blackl_aktor',0);
my $xs1_blackl_sensor = AttrVal($hash->{NAME},'xs1_blackl_sensor',0);
my $xs1_control = AttrVal($hash->{NAME},'xs1_control',0);
my $xs1_interval = AttrVal($name, 'xs1_interval', 60);
#### xs1Bridge xs1_interval >= 10 -> aktiviert zum auslesen
if ($xs1_interval >= 10 && $xs1_ConnectionTry <= 5) {
RemoveInternalTimer($hash); ## Timer löschen
InternalTimer(gettimeofday()+$xs1_interval, "xs1Bridge_GetUpDate", $hash);
Debug " -------------- ERROR CHECK - START --------------" if($debug == 2 || $debug == 1);
InternalTimer(gettimeofday()+$xs1_interval, 'xs1Bridge_GetUpDate', $hash);
Debug ' -------------- ERROR CHECK - START --------------' if($debug == 2 || $debug == 1);
Debug " $typ: GetUpDate | RemoveInternalTimer + InternalTimer" if($debug == 2);
#Log3 $name, 3, "$typ: xs1Bridge_GetUpDate | RemoveInternalTimer + InternalTimer";
if ($state eq "Initialized") {
readingsSingleUpdate($hash, "state", "active", 1);
if ($state eq 'Initialized') {
readingsSingleUpdate($hash, 'state', 'active', 1);
}
my $xs1Dev_check = "ERROR";
my $xs1Dev_check = 'ERROR';
#if($modules{xs1Dev} && $modules{xs1Dev}{LOADED}) { ## Check Modul vorhanden + geladen
if($modules{xs1Dev}) { ## Check Modul vorhanden
$xs1Dev_check = "ok";
$xs1Dev_check = 'ok';
Debug " $typ: GetUpDate | Modul xs1Dev_check = $xs1Dev_check" if($debug == 2);
} else {
Debug " $typ: GetUpDate ERROR | Modul xs1Dev not existent! Please check it to be available!" if($debug == 2);
@ -296,28 +307,28 @@ sub xs1Bridge_GetUpDate() {
for my $i (0..3) {
#### HTTP Requests #### Start ####
my $connection;
my $Http_err = "";
my $Http_data = "";
my $Http_err = '';
my $Http_data = '';
my $param = {
url => "http://".$xs1_ip.$cmd.$cmdtyp[$i],
url => 'http://'.$xs1_ip.$cmd.$cmdtyp[$i],
timeout => 3,
method => "GET", # Lesen von Inhalten
method => 'GET', # Lesen von Inhalten
};
#HttpUtils_BlockingGet($param);
($Http_err, $Http_data) = HttpUtils_BlockingGet($param);
#### HTTP Requests #### END ####
my $adress = "http://".$xs1_ip.$cmd.$cmdtyp[$i];
my $adress = 'http://'.$xs1_ip.$cmd.$cmdtyp[$i];
my $decoded;
my $json;
my $json_utf8;
my $decoded;
Debug " $typ: GetUpDate | Adresse: $adress | xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err eq "");
Debug " $typ: GetUpDate | HTTP request: ".$Http_err."| xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err ne "");
Debug " $typ: GetUpDate | Adresse: $adress | xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err eq '');
Debug " $typ: GetUpDate | HTTP request: ".$Http_err."| xs1_ConnectionTry=$xs1_ConnectionTry" if($debug == 1 && $Http_err ne '');
#### HTTP Requests, ERROR
if ($Http_err ne "") {
if ($Http_err ne '') {
# ERROR Message
# http://192.168.2.5/control?callback=cname&cmd=get_list_actuators: Can't connect(1) to http://192.168.2.5:80: IO::Socket::INET: connect: No route to host
# http://192.168.2.5/control?callback=cname&cmd=get_config_info: empty answer received
@ -327,9 +338,9 @@ sub xs1Bridge_GetUpDate() {
Log3 $name, 3, "$typ: GetUpDate | Try=$xs1_ConnectionTry loop=$i | Error: ".$Http_err;
$xs1_ConnectionTry++;
last; ## Abbruch Schleife
}
#### HTTP Requests, OK dann ARRAY Verarbeitung
elsif ($Http_data ne "") {
} elsif ($Http_data ne '') {
($json) = $Http_data =~ /[^(]*[}]/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 )};
@ -354,25 +365,25 @@ sub xs1Bridge_GetUpDate() {
$xs1_id = $i3;
#### Test ob Aktoren / Sensoren auf xs1_blackl
if ($f->{"type"} ne "disabled" && is_in_array($hash,$xs1_id,$i) == 0) {
my $xs1Dev = "xs1Dev";
if ($f->{'type'} ne 'disabled' && is_in_array($hash,$xs1_id,$i) == 0) {
my $xs1Dev = 'xs1Dev';
#### Aktoren spezifisch
my $xs1_function1 = "-";
my $xs1_function2 = "-";
my $xs1_function3 = "-";
my $xs1_function4 = "-";
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", $i3), "unknown"); ## Readings Wert
my $newState = sprintf("%.1f" , $f->{"value"}); ## ARRAY Wert xs1 aktuell
my $oldState = ReadingsVal($name, $readingsname[$i].'_'.sprintf("%02d", $i3), 'unknown'); ## Readings Wert
my $newState = sprintf("%.1f" , $f->{'value'}); ## ARRAY Wert xs1 aktuell
Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." oldState=$oldState newState=$newState" if($debug == 2);
Debug " $typ: ".$readingsname[$i].'_'.sprintf("%02d", $i3)." oldState=$oldState newState=$newState" if($debug == 2);
if ($oldState ne $newState) {
readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3) , $newState, 0);
readingsSingleUpdate($hash, $readingsname[$i].'_'.sprintf("%02d", $i3) , $newState, 0);
}
}
@ -385,31 +396,31 @@ sub xs1Bridge_GetUpDate() {
#### xs1 Option - Ansicht Funktionsname
if ($viewDeviceFunction == 1) {
my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $i3)."_".$arrayname[4]."_".$i2, "unknown"); ## Readings Wert
my $oldState = ReadingsVal($name, $readingsname[$i].'_'.sprintf("%02d", $i3).'_'.$arrayname[4].'_'.$i2, 'unknown'); ## Readings Wert
my $newState = $f2->{'type'}; ## ARRAY Wert xs1 aktuell
if ($oldState ne "unknown" && $newState eq "disabled") { ## FunktionReading del bei disable
Debug " $typ: "."Aktor_".sprintf("%02d", $i3)."_function_".$i2." are disabled" if($debug == 2);
delete $hash->{READINGS}{"Aktor_".sprintf("%02d", $i3)."_function_".$i2} if($hash->{READINGS});
if ($oldState ne 'unknown' && $newState eq 'disabled') { ## FunktionReading del bei disable
Debug " $typ: ".'Aktor_'.sprintf("%02d", $i3).'_function_'.$i2.' are disabled' if($debug == 2);
delete $hash->{READINGS}{'Aktor_'.sprintf("%02d", $i3).'_function_'.$i2} if($hash->{READINGS});
}
if ($f2->{"type"} ne "disabled") { ## Funktion != function -> type disable
if ($f2->{'type'} ne 'disabled') { ## Funktion != function -> type disable
if ($oldState ne $newState) {
readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3)."_".$arrayname[4]."_".$i2 , $f2->{"type"} , 1);
readingsSingleUpdate($hash, $readingsname[$i].'_'.sprintf("%02d", $i3).'_'.$arrayname[4].'_'.$i2 , $f2->{'type'} , 1);
}
}
}
#### Funktion != function -> type disable
if ($f2->{"type"} ne "disabled") {
if ($f2->{'type'} ne 'disabled') {
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"};
$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'};
}
}
}
@ -417,74 +428,74 @@ sub xs1Bridge_GetUpDate() {
#### Value der Aktoren | Sensoren
if ($i == 1 || $i == 0 && $update_only_difference == 0) { # Aktoren | Sensoren im intervall - Format 0.0 bzw. 37.0 wie aus xs1
readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3) , sprintf("%.1f" , $f->{"value"}), 0);
$xs1_data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $i3)."#".$f->{"type"}."#".sprintf("%.1f" , $f->{"value"})."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"};
readingsSingleUpdate($hash, $readingsname[$i].'_'.sprintf("%02d", $i3) , sprintf("%.1f" , $f->{'value'}), 0);
$xs1_data = $xs1Dev.'#'.$readingsname[$i].'#'.sprintf("%02d", $i3).'#'.$f->{'type'}.'#'.sprintf("%.1f" , $f->{'value'}).'#'."$xs1_function1".'#'."$xs1_function2".'#'."$xs1_function3".'#'."$xs1_function4".'#'.$f->{'name'};
} elsif ($i == 0 && $update_only_difference == 1){ # Aktoren | nur bei DIFF - Format 0.0 bzw. 37.0 wie aus xs1
$xs1_data = $xs1Dev."#".$readingsname[$i]."#".sprintf("%02d", $i3)."#".$f->{"type"}."#".sprintf("%.1f" , $f->{"value"})."#"."$xs1_function1"."#"."$xs1_function2"."#"."$xs1_function3"."#"."$xs1_function4"."#".$f->{"name"};
$xs1_data = $xs1Dev.'#'.$readingsname[$i].'#'.sprintf("%02d", $i3).'#'.$f->{'type'}.'#'.sprintf("%.1f" , $f->{'value'}).'#'."$xs1_function1".'#'."$xs1_function2".'#'."$xs1_function3".'#'."$xs1_function4".'#'.$f->{'name'};
}
#### Ausgaben je Typ unterschiedlich !!!
Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"}." | "."F1 $xs1_function1 | F2 $xs1_function2 | F3 $xs1_function3 | F4 $xs1_function4" if($debug == 2 && $i == 0);
Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $i3)." | ".$f->{"type"}." | ".$f->{"name"}." | ". $f->{"value"} if($debug == 2 && $i != 0);
Debug " $typ: ".$readingsname[$i].'_'.sprintf("%02d", $i3).' | '.$f->{'type'}.' | '.$f->{'name'}.' | '. $f->{'value'}.' | '."F1 $xs1_function1 | F2 $xs1_function2 | F3 $xs1_function3 | F4 $xs1_function4" if($debug == 2 && $i == 0);
Debug " $typ: ".$readingsname[$i].'_'.sprintf("%02d", $i3).' | '.$f->{'type'}.' | '.$f->{'name'}.' | '. $f->{'value'} if($debug == 2 && $i != 0);
### Ansicht Namen der Aktoren | Sensoren als Readings
if ($viewDeviceName == 1) {
my $oldState = ReadingsVal($name, $readingsname[$i]."_".sprintf("%02d", $i3)."_name", "unknown"); ## Readings Wert
my $newState = $f->{"name"}; ## ARRAY Wert xs1 aktuell
my $oldState = ReadingsVal($name, $readingsname[$i].'_'.sprintf("%02d", $i3).'_name', 'unknown'); ## Readings Wert
my $newState = $f->{'name'}; ## ARRAY Wert xs1 aktuell
if ($oldState ne $newState) { ## Namen nur bei Änderung schreiben
#Log3 $name, 3, "$typ: GetUpDate | newState=$newState ne oldState=$oldState";
readingsSingleUpdate($hash, $readingsname[$i]."_".sprintf("%02d", $i3)."_name" , $f->{"name"} , 1);
readingsSingleUpdate($hash, $readingsname[$i].'_'.sprintf("%02d", $i3).'_name' , $f->{'name'} , 1);
}
}
### Dispatch an xs1Device Modul
if ($xs1Dev_check eq "ok" && $xs1_control == 1) {
if ($xs1Dev_check eq 'ok' && $xs1_control == 1) {
Debug " $typ: GetUpDate | Dispatch: $xs1_data" if($debug == 2);
Dispatch($hash,$xs1_data,undef) if($xs1_data);
}
} else {
#### ID bzw. Speicherplatz xs1 ist disabled | Reading are delete
delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)} if($hash->{READINGS});
delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)."_name"} if($hash->{READINGS});
delete $hash->{READINGS}{$readingsname[$i].'_'.sprintf("%02d", $i3)} if($hash->{READINGS});
delete $hash->{READINGS}{$readingsname[$i].'_'.sprintf('%02d', $i3).'_name'} if($hash->{READINGS});
### Erweiterung v1.20 ### Device | Logfile | SVG löschen wenn in xs1 disable - TEST
my $delDevice = "xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3);
my $delDevice = 'xs1Dev_'.$readingsname[$i].'_'.sprintf("%02d", $i3);
if (defined($defs{"xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
if (defined($defs{'xs1Dev_'.$readingsname[$i].'_'.sprintf("%02d", $i3)})) {
#Log3 $name, 3, "$typ: GetUpDate | for delete $delDevice";
fhem("delete ".$delDevice); ## delete Device
fhem('delete '.$delDevice); ## delete Device
}
if (defined($defs{"SVG_xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
if (defined($defs{'SVG_xs1Dev_'.$readingsname[$i].'_'.sprintf("%02d", $i3)})) {
#Log3 $name, 3, "$typ: GetUpDate | for delete FileLog_$delDevice";
fhem("delete SVG_".$delDevice); ## delete FileLog_Device
fhem('delete SVG_'.$delDevice); ## delete FileLog_Device
}
if (defined($defs{"FileLog_xs1Dev_".$readingsname[$i]."_".sprintf("%02d", $i3)})) {
if (defined($defs{'FileLog_xs1Dev_'.$readingsname[$i].'_'.sprintf("%02d", $i3)})) {
#Log3 $name, 3, "$typ: GetUpDate | for delete FileLog_$delDevice";
fhem("delete FileLog_".$delDevice); ## delete FileLog_Device
fhem('delete FileLog_'.$delDevice); ## delete FileLog_Device
}
### Erweiterung v1.20 ### Device | Logfile | SVG löschen wenn in xs1 disable - TEST ### ENDE ###
if ($i == 0) {
for my $count (1..4) {
delete $hash->{READINGS}{$readingsname[$i]."_".sprintf("%02d", $i3)."_function_".$count} if($hash->{READINGS});
}
delete $hash->{READINGS}{$readingsname[$i].'_'.sprintf("%02d", $i3).'_function_'.$count} if($hash->{READINGS});
}
}
}
}
#### xs1 Info´s nur bei uptime Änderung als Readings
elsif ($i == 2) {
} elsif ($i == 2) {
my $features;
my $features_i=0;
my @xs1_readings = ("xs1_start","xs1_devicename","xs1_bootloader","xs1_hardware","xs1_features","xs1_firmware","xs1_mac","xs1_dhcp");
my @xs1_readings = ('xs1_start','xs1_devicename','xs1_bootloader','xs1_hardware','xs1_features','xs1_firmware','xs1_mac','xs1_dhcp');
my @xs1_decoded = (FmtDateTime(time()-($decoded->{'info'}{'uptime'})) , $decoded->{'info'}{'devicename'} , $decoded->{'info'}{'bootloader'} , $decoded->{'info'}{'hardware'} , $features , $decoded->{'info'}{'firmware'} , $decoded->{'info'}{'mac'} , $decoded->{'info'}{'autoip'});
my $oldState = ReadingsVal($name, $xs1_readings[0], "2000-01-01 03:33:33"); ## Readings Wert
my $oldState = ReadingsVal($name, $xs1_readings[0], '2000-01-01 03:33:33'); ## Readings Wert
my @oldstate = split (/[-,:,\s\/]/, $oldState); ## Split $year, $month, $mday, $hour, $min, $sec
$oldState = fhemTimeGm($oldstate[5], $oldstate[4], $oldstate[3], $oldstate[2], $oldstate[1]-1, $oldstate[0]-1900); ## Verarbeitung $sec, $min, $hour, $mday, $month-1, $year-1900
@ -498,14 +509,14 @@ sub xs1Bridge_GetUpDate() {
for my $i2 (0..7) {
if ($i2 == 4) {
while (defined $decoded->{'info'}{'features'}->[$features_i]) {
$features.= $decoded->{'info'}{'features'}->[$features_i]." ";
$features.= $decoded->{'info'}{'features'}->[$features_i].' ';
$features_i++;
}
$xs1_decoded[4] = $features; ## ARRAY Wert xs1_decoded wird definiert
}
if (defined $xs1_decoded[$i2]) {
readingsBulkUpdate($hash, $xs1_readings[$i2] , $xs1_decoded[$i2]);
Debug " $typ: ".$xs1_readings[$i2].": ".$xs1_decoded[$i2] if($debug == 2);
Debug " $typ: ".$xs1_readings[$i2].': '.$xs1_decoded[$i2] if($debug == 2);
} else {
Log3 $name, 3, "$typ: GetUpDate | ARRAY-ERROR xs1 -> no Data in loop $i|$i2";
last;
@ -513,28 +524,28 @@ sub xs1Bridge_GetUpDate() {
}
readingsEndUpdate($hash, 1);
}
}
#### xs1 Timers als Readings
elsif ($i == 3) {
} elsif ($i == 3) {
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 $oldState = ReadingsVal($name, $readingsname[$i].'_'.sprintf("%02d", $f->{'id'}), 'unknown'); ## Readings Wert
my $newState = FmtDateTime($f->{'next'}); ## ARRAY Wert xs1 aktuell
if ($f->{"type"} ne "disabled") {
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);
readingsSingleUpdate($hash, $readingsname[$i].'_'.sprintf("%02d", $f->{'id'}) , FmtDateTime($f->{'next'}), 1);
}
Debug " $typ: ".$readingsname[$i]."_".sprintf("%02d", $f->{"id"})." | ".$f->{"name"}." | ".$f->{"type"}." | ". $f->{"next"} if($debug == 2);
} 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"})};
Debug " $typ: ".$readingsname[$i].'_'.sprintf("%02d", $f->{'id'}).' | '.$f->{'name'}.' | '.$f->{'type'}.' | '. $f->{'next'} if($debug == 2);
} 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'})};
}
}
}
if ($i < 2) {
Debug " --------------- ERROR CHECK - SUB --------------- " if($debug == 2);
Debug ' --------------- ERROR CHECK - SUB --------------- ' if($debug == 2);
}
### Schleifen Ende ###
}
@ -544,20 +555,23 @@ sub xs1Bridge_GetUpDate() {
}
if ($xs1_ConnectionTry == 6) { ## Abschaltung xs1 nach 5 Verbindungsversuchen
$attr{$name}{xs1_interval} = "0";
readingsSingleUpdate($hash, "state", "deactive", 1);
$attr{$name}{xs1_interval} = '0';
readingsSingleUpdate($hash, 'state', 'deactive', 1);
RemoveInternalTimer($hash); ## Timer löschen
Log3 $name, 3, "$typ: GetUpDate | connection ERROR -> xs1 set to disable! Device not reachable after 5 attempts";
}
return;
}
sub xs1Bridge_Write($) ## Zustellen von Daten via IOWrite() vom logischen zum physischen Modul
{
##########################
sub xs1Bridge_Write { ## Zustellen von Daten via IOWrite() vom logischen zum physischen Modul
my ($hash, $Aktor_ID, $xs1_typ, $cmd, $cmd2) = @_;
my $name = $hash->{NAME};
my $typ = $hash->{TYPE};
my $xs1_ip = $hash->{xs1_ip};
my $debug = AttrVal($hash->{NAME},"debug",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
## Anfrage (Client -> XS1): http://192.168.1.242/control?callback=cname&cmd=set_state_actuator&number=1&value=100
@ -581,15 +595,17 @@ sub xs1Bridge_Write($) ## Zustellen von Daten via IOWrite() vom logischen zum
$Aktor_ID = substr($Aktor_ID, 1,2);
my $xs1cmd;
my $valuenew;
#### xs1 Typ switch || shutter || timerswitch - Anpassung Sendebefehl
if ($xs1_typ eq "switch" || $xs1_typ eq "shutter" || $xs1_typ eq "timerswitch") {
if ($xs1_typ eq 'switch' || $xs1_typ eq 'shutter' || $xs1_typ eq 'timerswitch') {
$xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&$cmd2";
} elsif ($xs1_typ eq "dimmer") {
if ($cmd eq "off") {
} elsif ($xs1_typ eq 'dimmer') {
if ($cmd eq 'off') {
$cmd = 0;
}
$xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&$cmd2" if ($cmd2 =~ /[f][u][n][c][t][i][o][n][=]./);
my $valuenew = substr($cmd2,3,length($cmd2)-3) if ($cmd2 !~ /[f][u][n][c][t][i][o][n][=]./);
$valuenew = substr($cmd2,3,length($cmd2)-3) if ($cmd2 !~ /[f][u][n][c][t][i][o][n][=]./);
#Log3 $name, 3, "$typ: Write | Check cmd=$cmd cmd2=$cmd2 valuenew=$valuenew";
$xs1cmd = "http://$xs1_ip/control?callback=cname&cmd=set_state_actuator&number=$Aktor_ID&value=$valuenew" if ($cmd2 !~ /[f][u][n][c][t][i][o][n][=]./);
} else {
@ -600,28 +616,31 @@ sub xs1Bridge_Write($) ## Zustellen von Daten via IOWrite() vom logischen zum
### HTTP Requests #### Start ####
my $connection;
my $Http_err = "";
my $Http_err = '';
my $Http_data;
my $param = {
url => "$xs1cmd",
timeout => 3,
method => "GET", # Lesen von Inhalten
method => 'GET', # Lesen von Inhalten
};
($Http_err, $Http_data) = HttpUtils_BlockingGet($param);
### HTTP Requests #### END ####
if ($Http_err ne "") {
if ($Http_err ne '') {
($Http_err) = $Http_err =~ /[:]\s.*/g;
Log3 $name, 3, "$typ: Write | no Control possible | Error".$Http_err;
return undef;
} elsif ($Http_data ne "") {
return;
} elsif ($Http_data ne '') {
Debug " $typ: Write | Send to xs1 -> $xs1cmd" if($debug == 1); ## Kontrolle Sendebefehl
}
return;
}
sub xs1Bridge_Undef($$)
{
##########################
sub xs1Bridge_Undef {
my ( $hash, $name) = @_;
my $typ = $hash->{TYPE};
@ -637,24 +656,27 @@ sub xs1Bridge_Undef($$)
}
}
return undef;
return;
}
##########################
# eigene Sub
sub is_in_array($$$)
{
my ( $hash,$xs1_id,$i) = @_;
sub is_in_array {
my ($hash,$xs1_id,$i) = @_;
my $name = $hash->{NAME};
my $typ = $hash->{TYPE};
my $xs1_blackl;
my $xs1_blackl = AttrVal($hash->{NAME},"xs1_blackl_aktor",0) if ($i eq 0);
$xs1_blackl = AttrVal($hash->{NAME},"xs1_blackl_sensor",0) if ($i eq 1);
if ($i == 0) {
$xs1_blackl = AttrVal($hash->{NAME},'xs1_blackl_aktor',0);
} elsif ($i == 1) {
$xs1_blackl = AttrVal($hash->{NAME},'xs1_blackl_sensor',0);
}
my @attr_array=split(/,/,$xs1_blackl);
if ( grep( /^$xs1_id$/, @attr_array ) ) {
if ( grep { /^$xs1_id$/ } @attr_array ) {
#Log3 $name, 3, "$typ: is_in_array | id=$xs1_id auf xs1_blackl Aktoren" if ($i eq 0);
#Log3 $name, 3, "$typ: is_in_array | id=$xs1_id auf xs1_blackl Sensoren" if ($i eq 1);
return 1;
@ -663,7 +685,6 @@ sub is_in_array($$$)
#Log3 $name, 3, "$typ: is_in_array | id=$xs1_id NICHT auf xs1_blackl Sensoren" if ($i eq 1);
return 0;
}
}
##########################
@ -687,9 +708,8 @@ sub is_in_array($$$)
<br><br>
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.<br>
Testet firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br>
<br><ul>
Testet firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br><br>
<ul>
<u>Currently implemented types of xs1 for processing: </u><br>
<li>Aktor: dimmer, switch, shutter, timerswitch</li>
<li>Sensor: barometer, counter, counterdiff, light, motion, other, rain, rain_1h, rain_24h, rainintensity, remotecontrol, uv_index, waterdetector, winddirection, windgust, windspeed, windvariance</li>
@ -714,10 +734,13 @@ sub is_in_array($$$)
define EZcontrol_xs1 xs1Bridge admin:secret@192.168.1.45<br>
</ul>
</ul><br>
<b>Set</b>
<ul>N/A</ul><br>
<b>Get</b><br>
<ul>N/A</ul><br>
<a name="xs1_attr"></a>
<b>Attributes</b>
<ul>
@ -727,7 +750,8 @@ sub is_in_array($$$)
</li><br>
<li>update_only_difference (0,1)<br>
The actuators defined in xs1 are only updated when the value changes.<br>
(Default, update_only_difference 0)</li><br>
(Default, update_only_difference 0)
</li><br>
<li>view_Device_name (0,1)<br>
The actor names defined in xs1 are read as Reading.<br>
(Default, view_Device_name 0)<br>
@ -755,6 +779,7 @@ sub is_in_array($$$)
</li><br>
</li><br><br>
</ul>
<b>explanation:</b>
<ul>
<li>various Readings:</li>
@ -775,7 +800,8 @@ sub is_in_array($$$)
(This can happen more often with DLAN.)<br><br></li>
<li>If the device has not been connected after 5 connection attempts, the module will switch on < disable > !</li><br>
<li>Create logfile automatically after define | scheme: <code>define FileLog_xs1Bridge FileLog ./log/xs1Bridge-%Y-%m.log &lt;name&gt;</code><br>
The following values are recorded in logfile: Timer | xs1-status information</li>
The following values are recorded in logfile: Timer | xs1-status information
</li>
</ul>
</ul>
=end html
@ -789,10 +815,10 @@ sub is_in_array($$$)
<br><br>
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.<br>
Getestete Firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br>
Getestete Firmware: v4.0.0.5326 (Beta) @me | v3.0.0.4493 @ForumUser<br><br>
<ul>
<u>Derzeit implementierte Typen des xs1 zur Verarbeitung:</u><br>
<br><ul>
<u>Derzeit implementierte Typen des xs1 zur Verarbeitung: </u><br>
<li>Aktor: dimmer, switch, shutter, timerswitch</li>
<li>Sensor: barometer, counter, counterdiff, light, motion, other, rain, rain_1h, rain_24h, rainintensity, remotecontrol, uv_index, waterdetector, winddirection, windgust, windspeed, windvariance</li>
</ul><br><br>
@ -810,16 +836,20 @@ sub is_in_array($$$)
<li><code>&lt;User&gt;</code> ist der Administrator Benutzer admin (standard)</li>
<li><code>&lt;Passwort&gt;</code> ist das vergebene Administrator Passwort im xs1.</li>
</ul><br>
Beispiele:
<ul>
define EZcontrol_xs1 xs1Bridge 192.168.1.45<br>
define EZcontrol_xs1 xs1Bridge admin:geheim@192.168.1.45<br>
</ul>
</ul><br>
<b>Set</b>
<ul>N/A</ul><br>
<b>Get</b><br>
<ul>N/A</ul><br>
<a name="xs1_attr"></a>
<b>Attribute</b>
<ul>

View File

@ -17,38 +17,39 @@ use strict;
use warnings; # Warnings
use POSIX;
use Time::Local;
#use SetExtensions;
sub xs1Dev_Initialize($) {
########################
sub xs1Dev_Initialize {
my ($hash) = @_;
$hash->{Match} = "[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].*"; ## zum testen - https://regex101.com/
$hash->{DefFn} = "xs1Dev_Define";
$hash->{AttrFn} = "xs1Dev_Attr";
$hash->{ParseFn} = "xs1Dev_Parse";
$hash->{SetFn} = "xs1Dev_Set";
$hash->{UndefFn} = "xs1Dev_Undef";
$hash->{AttrList} = "debug:0,1 ".
"IODev ".
"useSetExtensions:0,1 ".
$hash->{Match} = '[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].*'; ## zum testen - https://regex101.com/
$hash->{DefFn} = 'xs1Dev_Define';
$hash->{AttrFn} = 'xs1Dev_Attr';
$hash->{ParseFn} = 'xs1Dev_Parse';
$hash->{SetFn} = 'xs1Dev_Set';
$hash->{UndefFn} = 'xs1Dev_Undef';
$hash->{AttrList} = 'debug:0,1 '.
'IODev '.
'ignore:0,1 '.
'useSetExtensions:0,1 '.
$readingFnAttributes;
$hash->{AutoCreate} = { "xs1Dev_Sensor_.*" => { GPLOT => "temp4hum4:Temp/Hum,", FILTER=>"%NAME", } };
$hash->{AutoCreate} = { 'xs1Dev_Sensor_.*' => { GPLOT => 'temp4hum4:Temp/Hum,', FILTER=>'%NAME', } };
return;
}
sub xs1Dev_Define($$) {
# $def --> Definition des Module
# $hash --> ARRAY des Module
########################
sub xs1Dev_Define {
my ($hash, $def) = @_;
my @arg = split("[ \t][ \t]*", $def);
#-----0------1------2----3----4
return "Usage: define <NAME> xs1Dev <Typ> <ID> | wrong number of arguments" if( @arg != 4);
return "Usage: define <NAME> xs1Dev <Typ> <ID> | wrong ID, must be 1-64" if ( $arg[3] <1 || $arg[3] >64);
return "Usage: define <NAME> xs1Dev <Typ> <ID> | wrong Typ, must be A or S" if ( $arg[2] ne "A" && $arg[2] ne "S");
return 'Usage: define <NAME> xs1Dev <Typ> <ID> | wrong number of arguments' if( @arg != 4);
return 'Usage: define <NAME> xs1Dev <Typ> <ID> | wrong ID, must be 1-64' if ( $arg[3] <1 || $arg[3] >64);
return 'Usage: define <NAME> xs1Dev <Typ> <ID> | wrong Typ, must be A or S' if ( $arg[2] ne 'A' && $arg[2] ne 'S');
splice( @arg, 1, 1 );
my $iodev;
@ -93,26 +94,22 @@ sub xs1Dev_Define($$) {
$hash->{ID} = $xs1_typ1.$xs1_ID; ## A02 || S05
$modules{xs1Dev}{defptr}{$xs1_typ1.$xs1_ID} = $hash; ## !!! Adresse rückwärts dem Hash zuordnen (für ParseFn)
my $debug = AttrVal($hash->{NAME},"debug",0);
AttrVal($hash->{NAME},"useSetExtensions",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
AttrVal($hash->{NAME},'useSetExtensions',0);
$hash->{STATE} = "Defined"; ## Der Status des Modules nach Initialisierung.
$hash->{STATE} = 'Defined'; ## Der Status des Modules nach Initialisierung.
$hash->{TIME} = time(); ## Zeitstempel, derzeit vom anlegen des Moduls
#$hash->{VERSION} = "1.17"; ## Version
$hash->{xs1_name} = "undefined"; ## Aktor | Sensor Name welcher def. im xs1
$hash->{xs1_typ} = "undefined"; ## xs1_Typ switch | hygrometer | temperature ...
$hash->{xs1_name} = 'undefined'; ## Aktor | Sensor Name welcher def. im xs1
$hash->{xs1_typ} = 'undefined'; ## xs1_Typ switch | hygrometer | temperature ...
if ($xs1_typ1 eq "A"){
$hash->{xs1_function1} = "undefined"; ## xs1_Funktion zugeordnete Funktion 1
$hash->{xs1_function2} = "undefined"; ## xs1_Funktion zugeordnete Funktion 2
$hash->{xs1_function3} = "undefined"; ## xs1_Funktion zugeordnete Funktion 3
$hash->{xs1_function4} = "undefined"; ## xs1_Funktion zugeordnete Funktion 4
if ($xs1_typ1 eq 'A'){
$hash->{xs1_function1} = 'undefined'; ## xs1_Funktion zugeordnete Funktion 1
$hash->{xs1_function2} = 'undefined'; ## xs1_Funktion zugeordnete Funktion 2
$hash->{xs1_function3} = 'undefined'; ## xs1_Funktion zugeordnete Funktion 3
$hash->{xs1_function4} = 'undefined'; ## xs1_Funktion zugeordnete Funktion 4
}
# Attribut gesetzt
$attr{$name}{room} = "xs1" if( not defined( $attr{$name}{room} ) );
AssignIoPort($hash,$iodev) if( !$hash->{IODev} ); ## sucht nach einem passenden IO-Gerät (physikalische Definition)
# alles mit IODev erst NACH AssignIoPort nutzbar !!!
@ -124,142 +121,149 @@ sub xs1Dev_Define($$) {
Log3 $name, 3, "xs1Dev: $name - no I/O Device, Please delete and restart FHEM.";
}
#$iodev = $hash->{IODev}->{NAME};
# if(defined($hash->{IODev}->{xs1_ip})) { ## IP von xs1Bridge - Device aus HASH
# $hash->{xs1_ip} = $hash->{IODev}->{xs1_ip};
# }
return undef;
return;
}
sub xs1Dev_Attr()
{
########################
sub xs1Dev_Attr {
my ($cmd,$name,$attrName,$attrValue) = @_;
my $hash = $defs{$name};
my $typ = $hash->{TYPE};
my $debug = AttrVal($hash->{NAME},"debug",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
#Debug " $name: Attr | Attributes $attrName = $attrValue" if($debug);
#### Handling bei set ... attribute
if ($cmd eq 'set' && $init_done == 1 ) {
Log3 $name, 4, "$name: set attribute $attrName to $attrValue";
}
#### Handling bei del ... attribute
if ($cmd eq 'del') {
Log3 $name, 3, "$name: $cmd attribute $attrName";
}
return;
}
sub xs1Dev_Set ($$@)
{
########################
sub xs1Dev_Set {
my ( $hash, $name, @args ) = @_;
my $xs1_ID = $hash->{ID};
my $typ = $hash->{TYPE}; ## xs1Dev
my $cmd = $args[0];
my $debug = AttrVal($hash->{NAME},"debug",0);
my $debug = AttrVal($hash->{NAME},'debug',0);
my $xs1_typ = $hash->{xs1_typ};
my $Aktor_ID = substr($xs1_ID,1,2); ## A01 zu 01
my $cmd2; ## notwendig für Switch Funktionsplatz xs1
my $cmdFound;
return "no set value specified" if(int(@args) < 1);
my %xs1_function = (); ## Funktionen in ARRAY schreiben
return 'no set value specified' if(int(@args) < 1);
my %setList = (); ## Funktionen als Liste
my %setListPos = (); ## Funktionen als Position|Funktion
my %xs1_function = (); ## Funktionen in ARRAY schreiben
Debug " -------------- ERROR CHECK - START --------------" if($debug && $cmd ne "?");
Debug ' -------------- ERROR CHECK - START --------------' if($debug && $cmd ne '?');
# http://192.168.2.5/control?callback=cname&cmd=set_state_actuator&number=7&function=1
if (substr($xs1_ID,0,1) eq "A" && $xs1_typ ne "undefined") { ## nur bei Aktoren und nicht "undefined"
if (substr($xs1_ID,0,1) eq 'A' && $xs1_typ ne 'undefined') { ## nur bei Aktoren und nicht 'undefined'
for (my $d = 0; $d < 4; $d++) {
if ($hash->{"xs1_function".($d+1)} ne "-") {
if ($hash->{"xs1_function".($d+1)} eq "dim_up") { ## FHEM Mod xs1 dim_up -> FHEM dimup
$xs1_function{"dimup:noArg"} = ($d+1);
} elsif ($hash->{"xs1_function".($d+1)} eq "dim_down") { ## FHEM Mod xs1 dim_down -> FHEM dimdown
$xs1_function{"dimdown:noArg"} = ($d+1);
} elsif (exists $xs1_function{$hash->{"xs1_function".($d+1)}.":noArg"}){ ## CHECK ob Funktion bereits exists
$xs1_function{$hash->{"xs1_function".($d+1)}."_".($d+1).":noArg"} = ($d+1);
if ($hash->{'xs1_function'.($d+1)} ne '-') {
if ($hash->{'xs1_function'.($d+1)} eq 'dim_up') { ## FHEM Mod xs1 dim_up -> FHEM dimup
$xs1_function{'dimup:noArg'} = ($d+1);
} elsif ($hash->{'xs1_function'.($d+1)} eq 'dim_down') { ## FHEM Mod xs1 dim_down -> FHEM dimdown
$xs1_function{'dimdown:noArg'} = ($d+1);
} elsif (exists $xs1_function{$hash->{'xs1_function'.($d+1)}.':noArg'}){ ## CHECK ob Funktion bereits exists
$xs1_function{$hash->{'xs1_function'.($d+1)}.'_'.($d+1).':noArg'} = ($d+1);
} else {
$xs1_function{$hash->{"xs1_function".($d+1)}.":noArg"} = ($d+1); ## xs1 Standardbezeichnung Funktion
$xs1_function{$hash->{'xs1_function'.($d+1)}.':noArg'} = ($d+1); ## xs1 Standardbezeichnung Funktion
}
}
}
if ($xs1_typ eq "dimmer"){ #bei dimmer Typ, dim hinzufügen FHEM
$xs1_function{"dim"} = (5);
if ($xs1_typ eq 'dimmer'){ #bei dimmer Typ, dim hinzufügen FHEM
$xs1_function{'dim'} = (5);
}
while ( (my $k,my $v) = each %xs1_function ) {
if ($v > 0 && $v < 7) {
$setListPos{$v."|".$k} = $k;
$setListPos{$v.'|'.$k} = $k;
#Debug " $name: Set | $k|$v" if($debug && $cmd ne "?");
}
}
my $setList = join(" ", keys %xs1_function);
my $setListAll = join(" ", keys %setListPos);
my $setList = join(' ', keys %xs1_function);
my $setListAll = join(' ', keys %setListPos);
my $cmdFound = index($setListAll, $cmd.":"); ## check cmd in setListAll - Zuordnung Platz
my $cmdFound2 = "";
my $cmdFound = index($setListAll, $cmd.':'); ## check cmd in setListAll - Zuordnung Platz
my $cmdFound2 = '';
if ($cmdFound >= 0) { #$cmd für Sendebefehl anpassen
$cmdFound2 = substr($setListAll,$cmdFound-2,1);
$cmd2 = "function=".$cmdFound2;
$cmd2 = 'function='.$cmdFound2;
} else {
$cmd2 = $cmd.$args[1] if (defined $args[1]);
}
### dimmer - spezifisch dim hinzufügen FHEM + value Check
if ($xs1_typ eq "dimmer" && $cmd eq "dim") {
if ($xs1_typ eq 'dimmer' && $cmd eq 'dim') {
if (not defined $args[1]) {
return "dim value arguments failed";
return 'dim value arguments failed';
} elsif ($args[1] !~ /[a-zA-Z]/ && $args[1] <= 1 || $args[1] !~ /[a-zA-Z]/ && $args[1] >= 99) {
return "dim value must be 1 to 99";
return 'dim value must be 1 to 99';
} elsif ($args[1] =~ /[a-zA-Z]/) {
return "wrong dim value format! only value from 1 to 99";
return 'wrong dim value format! only value from 1 to 99';
} else {
$cmd = $cmd.$args[1]."%"; ## FHEM state mod --> anstatt nur dim --> dim47%
$cmd = $cmd.$args[1].'%'; ## FHEM state mod --> anstatt nur dim --> dim47%
}
}
Debug " $name: Set | xs1_typ=$xs1_typ cmd=$cmd setListAll=$setListAll cmdFound=$cmdFound cmdFound2=$cmdFound2" if($debug && $cmd ne "?");
Debug " $name: Set | xs1_typ=$xs1_typ cmd=$cmd setListAll=$setListAll cmdFound=$cmdFound cmdFound2=$cmdFound2" if($debug && $cmd ne '?');
if(AttrVal($name,"useSetExtensions",undef) || AttrVal($name,"useSetExtensions","0")) {
if(AttrVal($name,'useSetExtensions',undef) || AttrVal($name,'useSetExtensions',0)) {
$cmd =~ s/([.?*])/\\$1/g;
if($setList !~ m/\b$cmd\b/) {
Debug " $name: Set | useSetExtensions check" if($debug && $cmd ne "?");
if ($setList !~ m/\b$cmd\b/) {
Debug " $name: Set | useSetExtensions check" if($debug && $cmd ne '?');
unshift @args, $name;
return SetExtensions($hash, $setList, $name, @args);
}
SetExtensionsCancel($hash);
} else {
return "Unknown argument ?, choose one of $setList" if($args[0] eq "?");
return "Unknown argument ?, choose one of $setList" if($args[0] eq '?');
}
#Debug " $name: Set | xs1_typ=$xs1_typ (after mod) cmd=$cmd" if($debug && $cmd ne "?");
if(defined($hash->{IODev}->{NAME})) {
if ($xs1_typ eq "switch" || $xs1_typ eq "dimmer" || $xs1_typ eq "shutter" || $xs1_typ eq "timerswitch" && $cmd ne "?") {
Debug " $name: Set IOWrite | xs1_ID=$xs1_ID xs1_typ=$xs1_typ cmd=$cmd cmd2=$cmd2" if($debug && $xs1_typ ne "temperature" && $xs1_typ ne "hygrometer");
if (defined($hash->{IODev}->{NAME})) {
if ($xs1_typ eq 'switch' || $xs1_typ eq 'dimmer' || $xs1_typ eq 'shutter' || $xs1_typ eq 'timerswitch' && $cmd ne '?') {
Debug " $name: Set IOWrite | xs1_ID=$xs1_ID xs1_typ=$xs1_typ cmd=$cmd cmd2=$cmd2" if($debug && $xs1_typ ne 'temperature' && $xs1_typ ne 'hygrometer');
#Log3 $name, 3, "$name: Set IOWrite | xs1_ID=$xs1_ID xs1_typ=$xs1_typ cmd=$cmd cmd2=$cmd2 IODev=$hash->{IODev}->{NAME}";
Log3 $name, 3, "$typ set $name $cmd";
IOWrite($hash, $xs1_ID, $xs1_typ, $cmd, $cmd2);
readingsSingleUpdate($hash, "state", $cmd , 1);
readingsSingleUpdate($hash, 'state', $cmd , 1);
}
#else {
#Log3 $name, 2, "$name: Device NOT SUPPORTED for Dispatch. In xs1 disabled.";
#}
} else {
return "no IODev define. Please define xs1Bridge.";
return 'no IODev define. Please define xs1Bridge.';
}
#Debug " $name: Set | xs1_ID=$xs1_ID xs1_typ=$xs1_typ" if($debug);
Debug " -------------- ERROR CHECK - END --------------" if($debug);
Debug ' -------------- ERROR CHECK - END --------------' if($debug);
}
return undef;
return;
}
sub xs1Dev_Parse($$) ## Input Data from 88_xs1Bridge
{
########################
sub xs1Dev_Parse { ## Input Data from 88_xs1Bridge
my ( $io_hash, $data) = @_; ## $io_hash = ezControl -> def. Name von xs1Bridge
my ($xs1Dev,$xs1_readingsname,$xs1_ID,$xs1_typ2,$xs1_value,$xs1_f1,$xs1_f2,$xs1_f3,$xs1_f4,$xs1_name) = split("#", $data);
my ($xs1Dev,$xs1_readingsname,$xs1_ID,$xs1_typ2,$xs1_value,$xs1_f1,$xs1_f2,$xs1_f3,$xs1_f4,$xs1_name) = split('#', $data);
my $xs1_typ1 = substr($xs1_readingsname,0,1); ## A || S
my $def = $modules{xs1Dev}{defptr}{$xs1_typ1.$xs1_ID};
@ -272,62 +276,57 @@ sub xs1Dev_Parse($$) ## Input Data from 88_xs1Bridge
my $name = $hash->{NAME}; ## xs1Dev_Aktor_01
my $typ = $hash->{TYPE}; ## xs1Dev
$typ = "xs1Dev" if (!$def); ## Erstanlegung
$typ = 'xs1Dev' if (!$def); ## Erstanlegung
###### Define and values update ######
#Log3 $typ, 3, "$typ: Parse | Data: $xs1Dev | $xs1_readingsname | $xs1_ID | $xs1_typ2 | $xs1_value | $xs1_typ1" if (!$def);
#Log3 $typ, 3, "$typ: Parse | Data: $xs1Dev | $xs1_readingsname | $xs1_ID | $xs1_typ2 | $xs1_value | $xs1_typ1";
if(!$def) {
# "UNDEFINED xs1Dev_Aktor_12 xs1Dev A 12"
Log3 $name, 3, "$typ: Unknown device ".$xs1Dev."_".$xs1_readingsname."_"."$xs1_ID $xs1_ID $xs1_typ1 , please define it";
return "UNDEFINED xs1Dev"."_".$xs1_readingsname."_"."$xs1_ID xs1Dev $xs1_typ1 $xs1_ID";
Log3 $name, 3, "$typ: Unknown device ".$xs1Dev.'_'.$xs1_readingsname.'_'."$xs1_ID $xs1_ID $xs1_typ1 , please define it";
return 'UNDEFINED xs1Dev'.'_'.$xs1_readingsname.'_'."$xs1_ID xs1Dev $xs1_typ1 $xs1_ID"; ## "UNDEFINED xs1Dev_Aktor_12 xs1Dev A 12"
} else {
#Log3 $name, 3, "$typ: device $xs1_readingsname"."_"."$xs1_ID xs1_value:$xs1_value xs1_typ2:$xs1_typ2";
#Log3 $name, 3, "$typ: device $xs1_readingsname".'_'."$xs1_ID xs1_value:$xs1_value xs1_typ2:$xs1_typ2";
AssignIoPort($hash, $io_hash); ## sucht nach einem passenden IO-Gerät (physikalische Definition)
if ($xs1_readingsname eq "Aktor") { ## zugeordnete xs1_Funktionen
if ($xs1_readingsname eq 'Aktor') { ## zugeordnete xs1_Funktionen
$hash->{xs1_function1} = $xs1_f1;
$hash->{xs1_function2} = $xs1_f2;
$hash->{xs1_function3} = $xs1_f3;
$hash->{xs1_function4} = $xs1_f4;
}
readingsBeginUpdate($hash);
#### Typ switch | on | off mod for FHEM Default
if ($xs1_typ2 eq "switch") {
if ($xs1_value == 0) { $xs1_value = "off"; }
elsif ($xs1_value == 100) { $xs1_value = "on"; }
readingsSingleUpdate($hash, "state", $xs1_value ,1); # Aktor | Sensor Update value
if ($xs1_typ2 eq 'switch') {
if ($xs1_value == 0) { $xs1_value = 'off'; }
elsif ($xs1_value == 100) { $xs1_value = 'on'; }
readingsBulkUpdate($hash, 'state', $xs1_value); # Aktor | Sensor Update value
## RegEx devStateIcon da Symbole nicht gleich benannt -> dim_up | dim_down
if ($hash->{xs1_function1} eq "dim_up" || $hash->{xs1_function2} eq "dim_up" || $hash->{xs1_function3} eq "dim_up" || $hash->{xs1_function4} eq "dim_up" ||
$hash->{xs1_function1} eq "dim_down" || $hash->{xs1_function2} eq "dim_down" || $hash->{xs1_function3} eq "dim_down" || $hash->{xs1_function4} eq "dim_down" ) {
$attr{$name}{devStateIcon} = "dim_up:dimup dim_down:dimdown" if( not defined( $attr{$name}{devStateIcon} ) );
if ($hash->{xs1_function1} eq 'dim_up' || $hash->{xs1_function2} eq 'dim_up' || $hash->{xs1_function3} eq 'dim_up' || $hash->{xs1_function4} eq 'dim_up' ||
$hash->{xs1_function1} eq 'dim_down' || $hash->{xs1_function2} eq 'dim_down' || $hash->{xs1_function3} eq 'dim_down' || $hash->{xs1_function4} eq 'dim_down' ) {
$attr{$name}{devStateIcon} = 'dim_up:dimup dim_down:dimdown' if( not defined( $attr{$name}{devStateIcon} ) );
}
}
#### Typ temperature
elsif ($xs1_typ2 eq "temperature") {
my $xs1_value_new = "T: ".$xs1_value; ## temperature mod for FHEM Default
} elsif ($xs1_typ2 eq 'temperature') {
my $xs1_value_new = 'T: '.$xs1_value; ## temperature mod for FHEM Default
readingsBulkUpdate($hash, 'state', $xs1_value_new);
readingsBulkUpdate($hash, 'temperature', $xs1_value);
readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "state", $xs1_value_new);
readingsBulkUpdate($hash, "temperature", $xs1_value);
readingsEndUpdate($hash, 1);
}
#### Typ hygrometer
elsif ($xs1_typ2 eq "hygrometer") {
my $xs1_value_new = "H: ".$xs1_value; ## hygrometer mod for FHEM Default
} elsif ($xs1_typ2 eq 'hygrometer') {
my $xs1_value_new = 'H: '.$xs1_value; ## hygrometer mod for FHEM Default
readingsBulkUpdate($hash, 'state', $xs1_value_new);
readingsBulkUpdate($hash, 'humidity', $xs1_value);
readingsBeginUpdate($hash);
readingsBulkUpdate($hash, "state", $xs1_value_new);
readingsBulkUpdate($hash, "humidity", $xs1_value);
readingsEndUpdate($hash, 1);
}
#### Typ dimmer
elsif ($xs1_typ2 eq "dimmer") {
} elsif ($xs1_typ2 eq 'dimmer') {
## RegEx devStateIcon da Symbole nicht durchweg von 0 - 100 | dim_up | dim_down
$attr{$name}{devStateIcon} = "dim0[1-6]\\D%:dim06% dim[7-9]\\D|dim[1][0-2]%:dim12% dim[1][3-8]%:dim18% \n"
."dim[1][9]|dim[2][0-5]%:dim25% dim[2][6-9]|dim[3][0-1]%:dim31% dim[3][2-7]%:dim37% \n"
@ -336,106 +335,91 @@ sub xs1Dev_Parse($$) ## Input Data from 88_xs1Bridge
."dim[7][6-9]|dim[8][0-1]%:dim81% dim[8][2-7]%:dim87% dim[8][8-9]|dim[9][0-3]%:dim93% \n"
."dim[9][4-9]|dim[1][0][0]%:dim100% dim[_][u][p]:dimup dim[_][d][o]:dimdown" if( not defined( $attr{$name}{devStateIcon} ) );
if ($xs1_value ne "0.0") {
$xs1_value = "dim".sprintf("%02d", $xs1_value)."%";
} elsif ($xs1_value eq "0.0") {
$xs1_value = "off";
if ($xs1_value ne '0.0') {
$xs1_value = 'dim'.sprintf("%02d", $xs1_value).'%';
} elsif ($xs1_value eq '0.0') {
$xs1_value = 'off';
}
readingsSingleUpdate($hash, "state", $xs1_value ,1);
}
readingsBulkUpdate($hash, 'state', $xs1_value);
#### Typ shutter | on | off mod for FHEM Default
elsif ($xs1_typ2 eq "shutter") {
if ($xs1_value == 0) { $xs1_value = "off"; }
elsif ($xs1_value == 100) { $xs1_value = "on"; }
readingsSingleUpdate($hash, "state", $xs1_value ,1);
}
} elsif ($xs1_typ2 eq 'shutter') {
if ($xs1_value == 0) { $xs1_value = 'off'; }
elsif ($xs1_value == 100) { $xs1_value = 'on'; }
readingsBulkUpdate($hash, 'state', $xs1_value);
#### Typ timerswitch | on | off mod for FHEM Default
elsif ($xs1_typ2 eq "timerswitch") {
if ($xs1_value == 0) { $xs1_value = "off"; }
elsif ($xs1_value == 100) { $xs1_value = "on"; }
readingsSingleUpdate($hash, "state", $xs1_value ,1);
}
elsif ($xs1_typ2 eq "barometer") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "pressure", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "P: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "rain") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "rain", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "R: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "rain_1h") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "rain_calc_h", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "R: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "rain_24h") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "rain_calc_d", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "R: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "winddirection") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "Winddirection", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "D: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "windspeed") {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "Windspeed", $xs1_value ,1);
readingsSingleUpdate($hash, "state", "W: ".$xs1_value ,1);
readingsEndUpdate($hash, 1);
}
elsif ($xs1_typ2 eq "counter" || $xs1_typ2 eq "counterdiff" || $xs1_typ2 eq "fencedetector" || $xs1_typ2 eq "gas_consump" || $xs1_typ2 eq "gas_peak" ||
$xs1_typ2 eq "light" || $xs1_typ2 eq "motion" || $xs1_typ2 eq "other" || $xs1_typ2 eq "rainintensity" || $xs1_typ2 eq "remotecontrol" ||
$xs1_typ2 eq "uv_index" || $xs1_typ2 eq "waterdetector" || $xs1_typ2 eq "waterlevel" || $xs1_typ2 eq "windgust" || $xs1_typ2 eq "windvariance" ||
$xs1_typ2 eq "wtr_consump" || $xs1_typ2 eq "wtr_peak") {
readingsSingleUpdate($hash, "state", $xs1_value ,1);
}
} elsif ($xs1_typ2 eq 'timerswitch') {
if ($xs1_value == 0) { $xs1_value = 'off'; }
elsif ($xs1_value == 100) { $xs1_value = 'on'; }
readingsBulkUpdate($hash, 'state', $xs1_value);
} elsif ($xs1_typ2 eq 'barometer') {
readingsBulkUpdate($hash, 'pressure', $xs1_value);
readingsBulkUpdate($hash, 'state', 'P: '.$xs1_value);
} elsif ($xs1_typ2 eq 'rain') {
readingsBulkUpdate($hash, 'rain', $xs1_value);
readingsBulkUpdate($hash, 'state', 'R: '.$xs1_value);
} elsif ($xs1_typ2 eq 'rain_1h') {
readingsBulkUpdate($hash, 'rain_calc_h', $xs1_value);
readingsBulkUpdate($hash, 'state', 'R: '.$xs1_value);
} elsif ($xs1_typ2 eq 'rain_24h') {
readingsBulkUpdate($hash, 'rain_calc_d', $xs1_value);
readingsBulkUpdate($hash, 'state', 'R: '.$xs1_value);
} elsif ($xs1_typ2 eq 'winddirection') {
readingsBulkUpdate($hash, 'Winddirection', $xs1_value);
readingsBulkUpdate($hash, 'state', 'D: '.$xs1_value);
} elsif ($xs1_typ2 eq 'windspeed') {
readingsBulkUpdate($hash, 'Windspeed', $xs1_value);
readingsBulkUpdate($hash, 'state', 'W: '.$xs1_value);
} elsif ($xs1_typ2 eq 'counter' || $xs1_typ2 eq 'counterdiff' || $xs1_typ2 eq 'fencedetector' || $xs1_typ2 eq 'gas_consump' || $xs1_typ2 eq 'gas_peak' ||
$xs1_typ2 eq 'light' || $xs1_typ2 eq 'motion' || $xs1_typ2 eq 'other' || $xs1_typ2 eq 'rainintensity' || $xs1_typ2 eq 'remotecontrol' ||
$xs1_typ2 eq 'uv_index' || $xs1_typ2 eq 'waterdetector' || $xs1_typ2 eq 'waterlevel' || $xs1_typ2 eq 'windgust' || $xs1_typ2 eq 'windvariance' ||
$xs1_typ2 eq 'wtr_consump' || $xs1_typ2 eq 'wtr_peak') {
readingsBulkUpdate($hash, 'state', $xs1_value);
### Fenstermelder = windowopen | Tuermelder = dooropen --> 0 zu / 100 offen | mod for FHEM Default
elsif ($xs1_typ2 eq "dooropen" || $xs1_typ2 eq "windowopen") {
if ($xs1_value == 0.0) { $xs1_value = "closed";} elsif ($xs1_value == 100.0) { $xs1_value = "Open"; }
readingsBeginUpdate($hash);
if ($xs1_typ2 eq "windowopen") {
readingsSingleUpdate($hash, "Window", $xs1_value ,1);
}
if ($xs1_typ2 eq "dooropen") {
readingsSingleUpdate($hash, "Door", $xs1_value ,1);
}
} elsif ($xs1_typ2 eq 'dooropen' || $xs1_typ2 eq 'windowopen') {
if ($xs1_value == 0.0) { $xs1_value = 'closed';} elsif ($xs1_value == 100.0) { $xs1_value = 'Open'; }
if ($xs1_typ2 eq 'windowopen') { readingsBulkUpdate($hash, 'Window', $xs1_value); }
if ($xs1_typ2 eq 'dooropen') { readingsBulkUpdate($hash, 'Door', $xs1_value); }
my $value = Value($name);
my $OldValue = OldValue($name);
if ($value ne $OldValue) {
readingsSingleUpdate($hash, "Previous", $xs1_value ,0);
}
readingsSingleUpdate($hash, "state", $xs1_value ,0);
readingsEndUpdate($hash, 1);
if ($value ne $OldValue) { readingsBulkUpdate($hash, 'Previous', $xs1_value ,0); }
readingsBulkUpdate($hash, 'state', $xs1_value);
### alles andere ...
} else {
readingsBeginUpdate($hash);
readingsSingleUpdate($hash, "state", $xs1_value ,0);
readingsEndUpdate($hash, 1);
readingsBulkUpdate($hash, 'state', $xs1_value);
}
readingsEndUpdate($hash, 1);
}
return $name;
}
sub xs1Dev_Undef($$)
{
########################
sub xs1Dev_Undef {
my ( $hash, $name) = @_;
my $typ = $hash->{TYPE};
delete($modules{xs1Dev}{defptr}{$hash->{ID}});
Log3 $name, 3, "$typ: Device with Name $name delete";
return undef;
return;
}
########################
# Eval-Rückgabewert für erfolgreiches
# Laden des Moduls
1;