2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-08 01:14:19 +00:00

52_I2C_PCF8574: replaced smartmatch, enhanced compatibility with FRM

git-svn-id: https://svn.fhem.de/fhem/trunk@13601 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
klausw 2017-03-05 01:36:56 +00:00
parent 210fd5cab0
commit ca47564cdc

View File

@ -17,43 +17,54 @@ sub I2C_PCF8574_Initialize($) {
#$hash->{Match} = ".*"; #$hash->{Match} = ".*";
$hash->{DefFn} = "I2C_PCF8574_Define"; $hash->{DefFn} = "I2C_PCF8574_Define";
$hash->{InitFn} = 'I2C_PCF8574_Init'; $hash->{InitFn} = 'I2C_PCF8574_Init';
$hash->{AttrFn} = "I2C_PCF8574_Attr"; $hash->{AttrFn} = "I2C_PCF8574_Attr";
$hash->{SetFn} = "I2C_PCF8574_Set"; $hash->{SetFn} = "I2C_PCF8574_Set";
$hash->{StateFn} = "I2C_PCF8574_State"; $hash->{StateFn} = "I2C_PCF8574_State";
$hash->{GetFn} = "I2C_PCF8574_Get"; $hash->{GetFn} = "I2C_PCF8574_Get";
$hash->{UndefFn} = "I2C_PCF8574_Undef"; $hash->{UndefFn} = "I2C_PCF8574_Undef";
$hash->{ParseFn} = "I2C_PCF8574_Parse"; #$hash->{ParseFn} = "I2C_PCF8574_Parse";
$hash->{I2CRecFn} = "I2C_PCF8574_I2CRec"; $hash->{I2CRecFn} = "I2C_PCF8574_I2CRec";
$hash->{AttrList} = "IODev do_not_notify:1,0 ignore:1,0 showtime:1,0 ". $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:1,0 showtime:1,0 ".
"poll_interval OnStartup ". "poll_interval OnStartup ".
"InputPorts:multiple-strict,0,1,2,3,4,5,6,7 ". "InputPorts:multiple-strict,0,1,2,3,4,5,6,7 ".
"InvrtPorts:multiple-strict,0,1,2,3,4,5,6,7 ".
"$readingFnAttributes"; "$readingFnAttributes";
} }
################################### ###################################
sub I2C_PCF8574_Set($@) { # sub I2C_PCF8574_Set($@) { #
my ($hash, @a) = @_; my ($hash, @a) = @_;
my $name =$a[0]; my $name =$a[0];
my $cmd = $a[1]; my $cmd = $a[1];
my $val = $a[2]; my $val = $a[2];
my @inports = sort(split( " ",AttrVal($name, "InputPorts", "")));
my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cwrite" ); my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cwrite" );
if ( $cmd && $cmd =~ m/^P(ort|)((0|)[0-7])(,(P|)(ort|)((0|)[0-7])){0,7}$/i) { if ( $cmd && $cmd =~ m/^P(ort|)((0|)[0-7])(,(P|)(ort|)((0|)[0-7])){0,7}$/i) {
return "wrong value: $val for \"set $name $cmd\" use one of: off, on" return "wrong value: $val for \"set $name $cmd\" use one of: off, on"
unless(exists($setsP{$val})); unless(exists($setsP{$val}));
my @scmd = split(",", $cmd); my @scmd = split(",", $cmd);
my $scms = 0;
my $msg = undef; my $msg = undef;
foreach (@scmd) { foreach (@scmd) {
$_ =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren $_ =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren
$msg .= (defined $msg ? "," : "") . "Port" . $_ if ( $_ ~~ @inports ); #Pruefen ob entsprechender Port Input ist $msg .= (defined $msg ? "," : "") . "Port" . $_ if ( ((1 << $_) & $hash->{helper}{InputPorts}) != 0 ); #Pruefen ob entsprechender Port Input ist
$scms |= 1 << $_;
#Log3 $hash, 1, "$hash->{NAME} test: $_|$scms|@scmd|";
} }
return "$name error: $msg is defined as input" if $msg; return "$name error: $msg is defined as input" if $msg;
my $sbyte = 0; my $sbyte = 0;
foreach (0..7) { foreach (0..7) {
if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt #if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt
$sbyte += 1 << (1 * $_); ##if ( grep { $_ eq $clientAddress} @inports ) { #test
} elsif( $_ ~~ @scmd ) { #Port der geaendert werden soll # $sbyte += 1 << (1 * $_);
#} elsif( $_ ~~ @scmd ) { #Port der geaendert werden soll
# $sbyte += $setsP{$val} << (1 * $_);
#} else { #alle anderen Portwerte werden den Readings entnommen
# $sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_); #->sonst aus dem Reading holen
#}
if( ((1 << $_) & $scms) != 0 ) { #Port der geaendert werden soll
$sbyte += $setsP{$val} << (1 * $_); $sbyte += $setsP{$val} << (1 * $_);
Log3 $hash, 5, "$hash->{NAME} Port$_ soll auf $val gesetzt werden";
} else { #alle anderen Portwerte werden den Readings entnommen } else { #alle anderen Portwerte werden den Readings entnommen
$sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_); #->sonst aus dem Reading holen $sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_); #->sonst aus dem Reading holen
} }
@ -62,41 +73,38 @@ sub I2C_PCF8574_Set($@) { #
} elsif ( $cmd && $cmd eq "setfromreading" ) { } elsif ( $cmd && $cmd eq "setfromreading" ) {
my $sbyte = 0; my $sbyte = 0;
foreach (0..7) { foreach (0..7) {
if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt #if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt
$sbyte += 1 << (1 * $_); # $sbyte += 1 << (1 * $_);
} else { #alle anderen Portwerte werden den Readings entnommen #} else { #alle anderen Portwerte werden den Readings entnommen
$sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_); $sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_);
} #}
} }
$sendpackage{data} = $sbyte; $sendpackage{data} = $sbyte;
} else { } else {
my $list = undef; my $list = undef;
foreach (0..7) { foreach (0..7) {
next if ( $_ ~~ @inports ); #Inputs ueberspringen #next if ( $_ ~~ @inports ); #Inputs ueberspringen
next if ( ((1 << $_) & $hash->{helper}{InputPorts}) != 0 ); #Inputs ueberspringen ohne Smartmatch
$list .= "Port" . $_ . ":" . join(',', (sort { $setsP{ $a } <=> $setsP{ $b } } keys %setsP) ) . " "; $list .= "Port" . $_ . ":" . join(',', (sort { $setsP{ $a } <=> $setsP{ $b } } keys %setsP) ) . " ";
} }
return "Unknown argument $a[1], choose one of " . $list if defined $list; return "Unknown argument $a[1], choose one of " . $list if defined $list;
return "Unknown argument $a[1]"; return "Unknown argument $a[1]";
} }
Log3 $hash, 5, "$hash->{NAME} Output: 0b" . sprintf("%08b",$sendpackage{data});
Log3 $hash, 5, "$hash->{NAME} Inverts: 0b" . sprintf("%08b",$hash->{helper}{InvrtPorts});
Log3 $hash, 5, "$hash->{NAME} Inputs: 0b" . sprintf("%08b",$hash->{helper}{InputPorts});
$sendpackage{data} = ($sendpackage{data} ^ ($hash->{helper}{InvrtPorts} ||= 0) ) | ($hash->{helper}{InputPorts} ||= 0);
Log3 $hash, 5, "$hash->{NAME} Result: 0b" . sprintf("%08b",$sendpackage{data});
return "$name: no IO device defined" unless ($hash->{IODev}); return "$name: no IO device defined" unless ($hash->{IODev});
my $phash = $hash->{IODev}; my $phash = $hash->{IODev};
my $pname = $phash->{NAME}; my $pname = $phash->{NAME};
CallFn($pname, "I2CWrtFn", $phash, \%sendpackage); CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
########################################################## I2C_PCF8574_Get($hash, $name) if $phash->{TYPE} ne "RPII2C"; # Bei allen IODevs ausser RPII2C Daten zuruecklesen, da diese sondt nicht aktualisiert werden
# IOWrite($hash, \%sendpackage); #Log3 $hash, 1, "$hash->{NAME} IODev Typ: $phash->{TYPE}";
########################################################## #%sendpackage = ();
#%sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread");
########################################################## #CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
# Look for all devices with the same code, and set state, timestamp return undef;
#my $code = "$hash->{I2C_Address} $hash->{BTN}";
#my $code = "$hash->{NAME} $hash->{I2C_Address}";
#my $tn = TimeNow();
#my $defptr = $modules{I2C_PCF8574}{defptr}{$code};
#foreach my $n (keys %{ $defptr }) {
# readingsSingleUpdate($defptr->{$n}, "state", $v, 1);
# }
##########################################################
return undef;
} }
################################### ###################################
sub I2C_PCF8574_Get($@) { sub I2C_PCF8574_Get($@) {
@ -106,18 +114,15 @@ sub I2C_PCF8574_Get($@) {
#%sendpackage = ( direction => "i2cread", id => (defined( $hash->{ID} )? $hash->{ID} : "00"), i2caddress => $hash->{I2C_Address}); #%sendpackage = ( direction => "i2cread", id => (defined( $hash->{ID} )? $hash->{ID} : "00"), i2caddress => $hash->{I2C_Address});
%sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread"); %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread");
return "$name: no IO device defined" unless ($hash->{IODev}); return "$name: no IO device defined" unless ($hash->{IODev});
#neu: ueber CallFn auf eigene Funktion
my $phash = $hash->{IODev}; my $phash = $hash->{IODev};
my $pname = $phash->{NAME}; my $pname = $phash->{NAME};
CallFn($pname, "I2CWrtFn", $phash, \%sendpackage); CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
#alt: fuer IOWrite
#IOWrite($hash, \%sendpackage);
} }
################################### ###################################
sub I2C_PCF8574_Attr(@) { # sub I2C_PCF8574_Attr(@) { #
my ($command, $name, $attr, $val) = @_; my ($command, $name, $attr, $val) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
my $msg = ''; my $msg = undef;
if ($command && $command eq "set" && $attr && $attr eq "IODev") { if ($command && $command eq "set" && $attr && $attr eq "IODev") {
if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) { if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) {
main::AssignIoPort($hash,$val); main::AssignIoPort($hash,$val);
@ -138,12 +143,36 @@ sub I2C_PCF8574_Attr(@) { #
} }
} elsif ($attr && $attr eq "InputPorts") { } elsif ($attr && $attr eq "InputPorts") {
if ( defined($val) ) { if ( defined($val) ) {
my @inp = split(" ", $val); my @tmp = split(/\D+/, $val);
foreach (@inp) { my $tmpattr;
$msg = "wrong value: $_ for \"set $name $attr\" use space separated numbers 0-7" unless ($_ >= 0 && $_ < 8); foreach (@tmp) {
if ($_ =~ /^[0-7]$/) {
$tmpattr += 1 << (1 * $_);
} else {
$msg = "wrong value: $_ for \"attr $name $attr\" use comma separated numbers 0-7";
}
} }
$hash->{helper}{$attr} = $tmpattr unless defined $msg;
} else {
$hash->{helper}{$attr} = 0;
} }
} elsif ($attr && $attr eq "OnStartup") { } elsif ($attr && $attr eq "InvrtPorts") {
if ( defined($val) ) {
my @tmp = split(/\D+/, $val);
my $tmpattr;
foreach (@tmp) {
if ($_ =~ /^[0-7]$/) {
$tmpattr += 1 << (1 * $_);
} else {
$msg = "wrong value: $_ for \"attr $name $attr\" use comma separated numbers 0-7";
}
}
$hash->{helper}{$attr} = $tmpattr unless defined $msg;
} else {
#delete $hash->{helper}{$attr} if defined $hash->{helper}{$attr};
$hash->{helper}{$attr} = 0;
}
}elsif ($attr && $attr eq "OnStartup") {
if (defined $val) { if (defined $val) {
foreach (split (/,/,$val)) { foreach (split (/,/,$val)) {
my @pair = split (/=/,$_); my @pair = split (/=/,$_);
@ -159,6 +188,8 @@ sub I2C_PCF8574_Define($$) { #
my ($hash, $def) = @_; my ($hash, $def) = @_;
my @a = split("[ \t]+", $def); my @a = split("[ \t]+", $def);
$hash->{STATE} = 'defined'; $hash->{STATE} = 'defined';
$hash->{helper}{InvrtPorts} = 0;
$hash->{helper}{InputPorts} = 0;
if ($main::init_done) { if ($main::init_done) {
eval { I2C_PCF8574_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); }; eval { I2C_PCF8574_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); };
return I2C_PCF8574_Catch($@) if $@; return I2C_PCF8574_Catch($@) if $@;
@ -174,45 +205,34 @@ sub I2C_PCF8574_Init($$) { #
return "Define: Wrong syntax. Usage:\n" . return "Define: Wrong syntax. Usage:\n" .
"define <name> I2C_PCA9532 <i2caddress>"; "define <name> I2C_PCA9532 <i2caddress>";
} }
if (defined (my $address = shift @$args)) {
if (defined (my $address = shift @$args)) { $hash->{I2C_Address} = $address =~ /^0.*$/ ? oct($address) : $address;
$hash->{I2C_Address} = $address =~ /^0.*$/ ? oct($address) : $address; } else {
} else { return "$name I2C Address not valid";
return "$name I2C Address not valid"; }
} AssignIoPort($hash);
#fuer die Nutzung von IOWrite
#my $code = ( defined( $hash->{ID} )? $hash->{ID} : "00" ) . " " . $hash->{I2C_Address};
#my $ncode = 1;
#my $name = $a[0];
#$hash->{CODE}{$ncode++} = $code;
#$modules{I2C_PCF8574}{defptr}{$code}{$name} = $hash;
AssignIoPort($hash);
$hash->{STATE} = 'Initialized'; $hash->{STATE} = 'Initialized';
I2C_PCF8574_Set($hash, $name, "setfromreading"); I2C_PCF8574_Set($hash, $name, "setfromreading");
return; return;
} }
################################### ###################################
sub I2C_PCF8574_Catch($) { sub I2C_PCF8574_Catch($) {
my $exception = shift; my $exception = shift;
if ($exception) { if ($exception) {
$exception =~ /^(.*)( at.*FHEM.*)$/; $exception =~ /^(.*)( at.*FHEM.*)$/;
return $1; return $1;
} }
return undef; return undef;
} }
################################### ###################################
sub I2C_PCF8574_State($$$$) { #reload readings at FHEM start sub I2C_PCF8574_State($$$$) { #reload readings at FHEM start
my ($hash, $tim, $sname, $sval) = @_; my ($hash, $tim, $sname, $sval) = @_;
Log3 $hash, 4, "$hash->{NAME}: $sname kann auf $sval wiederhergestellt werden $tim"; Log3 $hash, 4, "$hash->{NAME}: $sname kann auf $sval wiederhergestellt werden $tim";
if ($sname =~ m/^Port[0-7]$/i) { if ($sname =~ m/^Port[0-7]$/i) {
my $po = $sname; #noch ändern my $po = $sname; #noch <EFBFBD>ndern
$po =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren $po =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren
#my @inports = sort(split(/\D+/,AttrVal($hash->{NAME}, "InputPorts", "")));
my @inports = sort(split(/ /,AttrVal($hash->{NAME}, "InputPorts", ""))); unless ( ((1 << $po) & $hash->{helper}{InputPorts}) != 0 ) {
unless ( $po ~~ @inports) {
my %onstart = split /[,=]/, AttrVal($hash->{NAME}, "OnStartup", ""); my %onstart = split /[,=]/, AttrVal($hash->{NAME}, "OnStartup", "");
if ( exists($onstart{$po}) && exists($setsP{$onstart{$po}})) { if ( exists($onstart{$po}) && exists($setsP{$onstart{$po}})) {
Log3 $hash, 5, "$hash->{NAME}: $sname soll auf $onstart{$po} gesetzt werden"; Log3 $hash, 5, "$hash->{NAME}: $sname soll auf $onstart{$po} gesetzt werden";
@ -222,7 +242,6 @@ sub I2C_PCF8574_State($$$$) { #reload readings at FHEM start
$hash->{READINGS}{$sname}{VAL} = $sval; $hash->{READINGS}{$sname}{VAL} = $sval;
$hash->{READINGS}{$sname}{TIME} = $tim; $hash->{READINGS}{$sname}{TIME} = $tim;
} }
} else { } else {
Log3 $hash, 5, "$hash->{NAME}: $sname ist Eingang"; Log3 $hash, 5, "$hash->{NAME}: $sname ist Eingang";
} }
@ -231,107 +250,90 @@ sub I2C_PCF8574_State($$$$) { #reload readings at FHEM start
} }
################################### ###################################
sub I2C_PCF8574_Undef($$) { # sub I2C_PCF8574_Undef($$) { #
my ($hash, $name) = @_; my ($hash, $name) = @_;
if ( defined (AttrVal($hash->{NAME}, "poll_interval", undef)) ) { RemoveInternalTimer($hash) if ( defined (AttrVal($hash->{NAME}, "poll_interval", undef)) );
RemoveInternalTimer($hash); return undef;
}
#foreach my $c (keys %{ $hash->{CODE} } ) {
# $c = $hash->{CODE}{$c};
# my $c = ( defined( $hash->{ID} )? $hash->{ID} : "00" ) . " " . $hash->{I2C_Address};
# As after a rename the $name my be different from the $defptr{$c}{$n}
# we look for the hash.
# foreach my $dname (keys %{ $modules{I2C_PCF8574}{defptr}{$c} }) {
# delete($modules{I2C_PCF8574}{defptr}{$c}{$dname})
# if($modules{I2C_PCF8574}{defptr}{$c}{$dname} == $hash);
# }
# }
return undef;
} }
################################### ###################################
sub I2C_PCF8574_Poll($) { #for attr poll_intervall -> readout pin values sub I2C_PCF8574_Poll($) { # for attr poll_intervall -> readout pin values
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; I2C_PCF8574_Get($hash, $hash->{NAME}); # Read values
# Read values my $pollInterval = AttrVal($hash->{NAME}, 'poll_interval', 0);
I2C_PCF8574_Get($hash, $name); InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_PCF8574_Poll', $hash, 0) if ($pollInterval > 0);
my $pollInterval = AttrVal($hash->{NAME}, 'poll_interval', 0);
if ($pollInterval > 0) {
InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_PCF8574_Poll', $hash, 0);
}
} }
################################### ###################################
sub I2C_PCF8574_I2CRec($@) { # ueber CallFn vom physical aufgerufen sub I2C_PCF8574_I2CRec($@) { # ueber CallFn vom physical aufgerufen
my ($hash, $clientmsg) = @_; my ($hash, $clientmsg) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $phash = $hash->{IODev}; my $phash = $hash->{IODev};
my $pname = $phash->{NAME}; my $pname = $phash->{NAME};
while ( my ( $k, $v ) = each %$clientmsg ) { #erzeugen von Internals fuer alle Keys in $clientmsg die mit dem physical Namen beginnen while ( my ( $k, $v ) = each %$clientmsg ) { #erzeugen von Internals fuer alle Keys in $clientmsg die mit dem physical Namen beginnen
$hash->{$k} = $v if $k =~ /^$pname/ ; $hash->{$k} = $v if $k =~ /^$pname/ ;
} }
my $sval; my $sval;
if ($clientmsg->{direction} && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") { if ($clientmsg->{direction} && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
if ($clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received})) { # =~ m/^(0x|)[0-9A-F]{1,2}$/xi) { if ($clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received})) {
readingsBulkUpdate($hash, 'state', $clientmsg->{received});
$clientmsg->{received} ^= $hash->{helper}{InvrtPorts};
foreach (0..7) { foreach (0..7) {
#$sval = hex($clientmsg->{received}) & (1 << $_);
$sval = $clientmsg->{received} & (1 << $_); $sval = $clientmsg->{received} & (1 << $_);
$sval = $sval == 0 ? "off" :"on"; $sval = $sval == 0 ? "off" :"on";
readingsBulkUpdate($hash, 'Port'.$_ , $sval) if (ReadingsVal($name,'Port'.$_,"") ne $sval); readingsBulkUpdate($hash, 'Port'.$_ , $sval) if (ReadingsVal($name,'Port'.$_,"") ne $sval);
} }
readingsBulkUpdate($hash, 'state', $clientmsg->{received}); } elsif ($clientmsg->{direction} eq "i2cwrite" && defined($clientmsg->{data})) {
} elsif ($clientmsg->{direction} eq "i2cwrite" && defined($clientmsg->{data})) { # =~ m/^(0x|)[0-9A-F]{1,2}$/xi) { #my @inports = sort(split( /\D+/,AttrVal($name, "InputPorts", "")));
my @inports = sort(split( " ",AttrVal($name, "InputPorts", ""))); readingsBulkUpdate($hash, 'state', $clientmsg->{data});
foreach (0..7) { $clientmsg->{data} ^= $hash->{helper}{InvrtPorts};
#$sval = hex($clientmsg->{data}) & (1 << $_); foreach (0..7) {
$sval = $clientmsg->{data} & (1 << $_); $sval = $clientmsg->{data} & (1 << $_);
$sval = $sval == 0 ? "off" :"on"; $sval = $sval == 0 ? "off" :"on";
readingsBulkUpdate($hash, 'Port'.$_ , $sval) unless (ReadingsVal($name,'Port'.$_,"") eq $sval || $_ ~~ @inports ); readingsBulkUpdate($hash, 'Port'.$_ , $sval) unless (ReadingsVal($name,'Port'.$_,"") eq $sval);# || $_ ~~ @inports );
} }
readingsBulkUpdate($hash, 'state', $clientmsg->{data}); }
readingsEndUpdate($hash, 1);
} }
#readingsBulkUpdate($hash, 'state', join(" ", $clientmsg->{received}));
readingsEndUpdate($hash, 1);
}
} }
################################### ###################################
sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen (dispatch wird im mom nicht verwendet) #sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen (dispatch wird im mom nicht verwendet)
my ($hash, $msg) = @_; # my ($hash, $msg) = @_;
my($sid, $addr, @msg) = split(/ /,$msg); # my($sid, $addr, @msg) = split(/ /,$msg);
#Log3 $hash, 4, "Vom Netzerparse $hash->{NAME}: sid: $sid, Msg: @msg"; # #Log3 $hash, 4, "Vom Netzerparse $hash->{NAME}: sid: $sid, Msg: @msg";
#
my $def = $modules{I2C_PCF8574}{defptr}{"$sid $addr"}; # my $def = $modules{I2C_PCF8574}{defptr}{"$sid $addr"};
if($def) { # if($def) {
my @list; # my @list;
foreach my $n (keys %{ $def }) { # foreach my $n (keys %{ $def }) {
my $lh = $def->{$n}; # Hash bekommen # my $lh = $def->{$n}; # Hash bekommen
$n = $lh->{NAME}; # It may be renamed # $n = $lh->{NAME}; # It may be renamed
return "" if(IsIgnored($n)); # Little strange. # return "" if(IsIgnored($n)); # Little strange.
################################################ # ################################################
my $cde = join(" ",@msg); # my $cde = join(" ",@msg);
my $sval; # my $sval;
readingsBeginUpdate($lh); # readingsBeginUpdate($lh);
if ( int(@msg) == 1) { # if ( int(@msg) == 1) {
for (my $i = 0; $i < 8; $i++) { # for (my $i = 0; $i < 8; $i++) {
#$sval = hex($cde) & (1 << $i); # #$sval = hex($cde) & (1 << $i);
$sval = $cde & (1 << $i); # $sval = $cde & (1 << $i);
$sval = $sval == 0 ? "0" :"1"; # $sval = $sval == 0 ? "0" :"1";
readingsBulkUpdate($lh, 'P'.$i , $sval) if (ReadingsVal($n,'P'.$i,2) ne $sval); # readingsBulkUpdate($lh, 'P'.$i , $sval) if (ReadingsVal($n,'P'.$i,2) ne $sval);
} # }
} # }
readingsBulkUpdate($lh, 'state', join(" ", @msg)); # readingsBulkUpdate($lh, 'state', join(" ", @msg));
readingsEndUpdate($lh, 1); # readingsEndUpdate($lh, 1);
################################################ # ################################################
Log3 $n, 4, "I2C_PCF8574 $n $cde"; # Log3 $n, 4, "I2C_PCF8574 $n $cde";
#
push(@list, $n); # push(@list, $n);
} # }
return @list; # return @list;
#
} else { # } else {
Log3 $hash, 3, "I2C_PCF8574 Unknown device $addr Id $sid"; # Log3 $hash, 3, "I2C_PCF8574 Unknown device $addr Id $sid";
#return "UNDEFINED I2C_PCF8574_$addr$sid I2C_PCF8574 $addr $sid"; # #return "UNDEFINED I2C_PCF8574_$addr$sid I2C_PCF8574 $addr $sid";
} # }
#
} #}
################################### ###################################
1; 1;
@ -396,9 +398,13 @@ sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen
Default: -, valid values: decimal number<br><br> Default: -, valid values: decimal number<br><br>
</li> </li>
<li>InputPorts<br> <li>InputPorts<br>
Space separated list of Portnumers that are used as Inputs<br> Comma separated list of Portnumers that are used as Inputs<br>
Ports in this list can't be written<br> Ports in this list can't be written<br>
Default: no, valid values: 0 1 2 .. 7<br><br> Default: -, valid values: 0 - 7<br><br>
</li>
<li>InvrtPorts<br>
Comma separated list of Portnumers that will be inverted<br>
Default: -, valid values: 0 - 7<br><br>
</li> </li>
<li>OnStartup<br> <li>OnStartup<br>
Comma separated list of output ports and their desired state after start<br> Comma separated list of output ports and their desired state after start<br>
@ -473,9 +479,13 @@ sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen
Standard: -, g&uuml;ltige Werte: Dezimalzahl<br><br> Standard: -, g&uuml;ltige Werte: Dezimalzahl<br><br>
</li> </li>
<li>InputPorts<br> <li>InputPorts<br>
Durch Leerzeichen getrennte Portnummern die als Inputs genutzt werden.<br> Durch Komma getrennte Portnummern die als Inputs genutzt werden.<br>
Ports in dieser Liste k&ouml;nnen nicht geschrieben werden.<br> Ports in dieser Liste k&ouml;nnen nicht geschrieben werden.<br>
Standard: no, g&uuml;ltige Werte: 0 1 2 .. 7<br><br> Standard: -, g&uuml;ltige Werte: 0 - 7<br><br>
</li>
<li>InvrtPorts<br>
Durch Komma getrennte Portnummern die invertiert werden.<br>
Standard: -, g&uuml;ltige Werte: 0 - 7<br><br>
</li> </li>
<li>OnStartup<br> <li>OnStartup<br>
Durch Komma getrennte Output Ports und ihr gew&uuml;nschter Status nach dem Start.<br> Durch Komma getrennte Output Ports und ihr gew&uuml;nschter Status nach dem Start.<br>
@ -492,4 +502,4 @@ sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen
=end html_DE =end html_DE
=cut =cut