From 366571bb95b50548cd0e30340e304aae6da57fc1 Mon Sep 17 00:00:00 2001
From: "klaus.schauer" <>
Date: Wed, 22 May 2019 19:28:00 +0000
Subject: [PATCH] 55_PIFACE: Now wiringPi V2.46 is supported. Various
optimizations
git-svn-id: https://svn.fhem.de/fhem/trunk@19446 2b470e98-0d58-463d-a4d8-8e2adae1ed80
---
fhem/FHEM/55_PIFACE.pm | 200 ++++++++++++++++++++++-------------------
1 file changed, 110 insertions(+), 90 deletions(-)
diff --git a/fhem/FHEM/55_PIFACE.pm b/fhem/FHEM/55_PIFACE.pm
index 4403269c3..7d321d03e 100644
--- a/fhem/FHEM/55_PIFACE.pm
+++ b/fhem/FHEM/55_PIFACE.pm
@@ -6,8 +6,8 @@
# An FHEM Perl module to control RaspberryPi extension board PiFace
#
# The PiFace is an add-on board for the Raspberry Pi featuring 8 open-collector outputs,
-# with 2 relays and 8 inputs (with 4 on-board buttons).
-# These functions are fairly well fixed in the hardware,
+# with 2 relays and 8 inputs (with 4 on-board buttons).
+# These functions are fairly well fixed in the hardware,
# so only the read, write and internal pull-up commands are implemented.
#
# Please read commandref for details on prerequisits!
@@ -74,7 +74,7 @@ sub PIFACE_Initialize($){
" watchdog:on,off,silent watchdogInterval";
}
-sub PIFACE_Define($$){
+sub PIFACE_Define($$) {
my ($hash, $def) = @_;
my $name = $hash->{NAME};
$hash->{NOTIFYDEV} = "global";
@@ -83,28 +83,28 @@ sub PIFACE_Define($$){
return;
}
-sub PIFACE_Undefine($$){
+sub PIFACE_Undefine($$) {
my($hash, $name) = @_;
RemoveInternalTimer($hash);
return;
}
sub PIFACE_Set($@) {
- my ($hash, @a) = @_;
+ my ($hash, @a) = @_;
my $name = $hash->{NAME};
if (IsDisabled($name)) {
- Log3 $name, 4, "PIFACE $name set commands disabled.";
+ Log3 $name, 4, "PIFACE $name set commands disabled.";
return;
}
my $port = $a[1];
my $val = $a[2];
- my ($adr, $cmd, $i, $j, $k);
+ my ($adr, $cmd, $i, $j, $k);
my $usage = "Unknown argument $port, choose one of all 0:0,1 1:0,1 2:0,1 3:0,1 4:0,1 5:0,1 6:0,1 7:0,1 ";
- return $usage if $port eq "?";
+ return $usage if ($port eq "?");
if ($port ne "all") {
$adr = $base + $port;
Log3($name, 3, "PIFACE $name set port $port $val");
- $cmd = "$gpioCmd -p write $adr $val";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 write $adr $val";
$cmd = `$cmd`;
readingsSingleUpdate($hash, 'out'.$port, $val, 1);
} else {
@@ -116,7 +116,7 @@ sub PIFACE_Set($@) {
$k = ($k) ? 1 : 0;
Log3($name, 3, "PIFACE $name set port $i $k");
$adr = $base + $i;
- $cmd = "$gpioCmd -p write $adr $k";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 write $adr $k";
$cmd = `$cmd`;
readingsBulkUpdate($hash, 'out'.$i, $k);
}
@@ -125,7 +125,7 @@ sub PIFACE_Set($@) {
return;
}
-sub PIFACE_Get($@){
+sub PIFACE_Get($@) {
my ($hash, @a) = @_;
my $name = $hash->{NAME};
my $port = $a[1];
@@ -136,18 +136,23 @@ sub PIFACE_Get($@){
return $usage if $port eq "?";
if ($port eq "all") {
PIFACE_Read_Inports(1, $hash);
- PIFACE_Read_Outports(1, $hash);
+ PIFACE_Read_Outports(1, $hash);
+ Log3($name, 3, "PIFACE $name get port $port");
} elsif ($port eq "in") {
- PIFACE_Read_Inports(0, $hash);
+ PIFACE_Read_Inports(1, $hash);
+ Log3($name, 3, "PIFACE $name get port $port");
} elsif ($port eq "out") {
- PIFACE_Read_Outports(0, $hash);
+ PIFACE_Read_Outports(1, $hash);
+ Log3($name, 3, "PIFACE $name get port $port");
} else {
- $adr = $base + $port;
- $cmd = "$gpioCmd -p read $adr";
+ # get state of in port
+ $adr = $base + 8 + $port;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read $adr";
$val = `$cmd`;
$val =~ s/\n//g;
$val =~ s/\r//g;
- readingsSingleUpdate($hash, 'in'.$port, $val, 1);
+ readingsSingleUpdate($hash, 'in' . $port, $val, 1);
+ Log3($name, 3, "PIFACE $name get port in$port");
}
return;
}
@@ -155,59 +160,61 @@ sub PIFACE_Get($@){
sub PIFACE_Attr(@) {
my ($cmd, $name, $attrName, $attrVal) = @_;
my $hash = $defs{$name};
-
+ return undef if (!$init_done);
if ($attrName eq "pollInterval") {
if (!defined $attrVal) {
- #RemoveInternalTimer($hash);
+ #RemoveInternalTimer($hash);
} elsif ($attrVal eq "off" || ($attrVal =~ m/^\d+?$/ && $attrVal > 0 && $attrVal < 11)) {
PIFACE_GetUpdate($hash);
} else {
- #RemoveInternalTimer($hash);
+ #RemoveInternalTimer($hash);
Log3($name, 3, "PIFACE $name attribute-value [$attrName] = $attrVal wrong");
CommandDeleteAttr(undef, "$name pollInterval");
}
-
+
} elsif ($attrName eq "defaultState") {
if (!defined $attrVal){
-
- } elsif ($attrVal !~ m/^(last|off|[01])$/) {
+
+ } elsif ($attrVal !~ m/^last|off|[01]$/) {
Log3($name, 3, "PIFACE $name attribute-value [$attrName] = $attrVal wrong");
CommandDeleteAttr(undef, "$name defaultState");
}
-
- } elsif ($attrName =~ m/^portMode/) {
- my $port = substr($attrName, 8, 1);
- my $adr = $base + $port;
+
+ } elsif ($attrName =~ m/^portMode(.)/) {
+ my $port = $1;
+ #my $port = substr($attrName, 8, 1);
+ my $adr = $base + 8 + $port;
my $portMode = $attrVal;
my $val;
$portMode = "tri" if (!defined $attrVal);
- if ($attrVal !~ m/^(tri|up)$/) {
+ if ($attrVal !~ m/^tri|up$/) {
$portMode = "tri" ;
Log3($name, 3, "PIFACE $name attribute-value [$attrName] = $attrVal wrong");
- CommandDeleteAttr(undef, "$name $port");
+ CommandDeleteAttr(undef, "$name portMode$port");
}
- $cmd = "$gpioCmd -p mode $adr $portMode";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 mode $adr $portMode";
$val = `$cmd`;
- $cmd = "$gpioCmd -p read $adr";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read $adr";
$val = `$cmd`;
$val =~ s/\n//g;
$val =~ s/\r//g;
readingsSingleUpdate($hash, 'in' . $port, $val, 1);
-
+
} elsif ($attrName eq "watchdog") {
if (!defined $attrVal) {
$attrVal = "off" ;
CommandDeleteReading(undef, "$name watchdog");
}
- if ($attrVal !~ m/^(on|off|silent)$/) {
+ if ($attrVal !~ m/^on|off|silent$/) {
Log3($name, 3, "PIFACE $name attribute-value [$attrName] = $attrVal wrong");
CommandDeleteAttr(undef, "$name watchdog");
}
- if ($attrVal =~ m/^(on|silent)$/) {
+ if ($attrVal =~ m/^on|silent$/) {
readingsSingleUpdate($hash, 'watchdog', 'start', 1);
+ $attr{$name}{$attrName} = $attrVal;
PIFACE_Watchdog($hash);
}
-
+
} elsif ($attrName eq "watchdogInterval") {
if ($attrVal !~ m/^\d+$/ || $attrVal < 10) {
Log3($name, 3, "PIFACE $name attribute-value [$attrName] = $attrVal wrong");
@@ -219,14 +226,15 @@ sub PIFACE_Attr(@) {
sub PIFACE_Notify(@) {
my ($hash, $dev) = @_;
- my $name = $hash->{NAME};
- if ($dev->{NAME} eq "global" && grep (m/^INITIALIZED$/,@{$dev->{CHANGED}})){
- Log3($name, 3, "PIFACE $name initialized");
+ my $name = $hash->{NAME};
+ if ($dev->{NAME} eq "global" && grep (m/^INITIALIZED|REREADCFG$/,@{$dev->{CHANGED}})){
+ PIFACE_Restore_Inports_Mode($hash);
PIFACE_Restore_Outports_State($hash);
- PIFACE_Read_Inports(0, $hash);
- PIFACE_Read_Outports(0, $hash);
- PIFACE_GetUpdate($hash);
+ #PIFACE_Read_Inports(0, $hash);
+ #PIFACE_Read_Outports(0, $hash);
+ PIFACE_GetUpdate($hash);
PIFACE_Watchdog($hash);
+ Log3($name, 3, "PIFACE $name initialized");
}
return;
}
@@ -237,15 +245,15 @@ sub PIFACE_Read_Outports($$){
my ($cmd, $i, $port, $val);
readingsBeginUpdate($hash);
for($i=0; $i<8; $i++){
- $port = $base + $i + 8;
- $cmd = "$gpioCmd -p read $port";
+ $port = $base + $i;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read $port";
$val = `$cmd`;
$val =~ s/\n//g;
$val =~ s/\r//g;
if ($updateMode == 1){
readingsBulkUpdate($hash, 'out'.$i, $val);
} else {
- readingsBulkUpdate($hash, 'out'.$i, $val) if(ReadingsVal($name, 'out'.$i, '') ne $val);
+ readingsBulkUpdateIfChanged($hash, 'out'.$i, $val);
}
}
readingsEndUpdate($hash, 1);
@@ -258,15 +266,15 @@ sub PIFACE_Read_Inports($$){
my ($cmd, $i, $j, $port, $portMode, $val);
readingsBeginUpdate($hash);
for($i=0; $i<8; $i++){
- $port = $base + $i;
- $cmd = "$gpioCmd -p read $port";
+ $port = $base + 8 + $i;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read $port";
$val = `$cmd`;
$val =~ s/\n//g;
$val =~ s/\r//g;
if ($updateMode == 1) {
readingsBulkUpdate($hash, 'in'.$i, $val);
} else {
- readingsBulkUpdate($hash, 'in'.$i, $val) if(ReadingsVal($name, 'in'.$i, '') ne $val);
+ readingsBulkUpdateIfChanged($hash, 'in'.$i, $val);
}
}
readingsEndUpdate($hash, 1);
@@ -284,9 +292,9 @@ sub PIFACE_Restore_Outports_State($) {
if ($defaultState eq "last") {
$cmd[2] = ReadingsVal($name, "out" . $port, 0);
} elsif ($defaultState == 1) {
- $cmd[2] = 1;
+ $cmd[2] = 1;
} else {
- $cmd[2] = 0;
+ $cmd[2] = 0;
}
PIFACE_Set($hash, @cmd);
}
@@ -295,8 +303,21 @@ sub PIFACE_Restore_Outports_State($) {
return;
}
-sub
-PIFACE_GetUpdate($) {
+sub PIFACE_Restore_Inports_Mode($) {
+ my ($hash) = @_;
+ my $name = $hash->{NAME};
+ my ($cmd, $port, $portMode, $valIn);
+ for (my $i = 0; $i <= 7; $i++) {
+ $port = $base + 8 + $i;
+ $portMode = AttrVal($name, "portMode" . $i, "tri");
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 mode $port $portMode";
+ $valIn = `$cmd`;
+ }
+ PIFACE_Read_Inports(1, $hash);
+ return;
+}
+
+sub PIFACE_GetUpdate($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my $pollInterval = AttrVal($name, "pollInterval", "off");
@@ -304,48 +325,47 @@ PIFACE_GetUpdate($) {
InternalTimer(gettimeofday() + $pollInterval, "PIFACE_GetUpdate", $hash, 1);
PIFACE_Read_Inports(0, $hash);
PIFACE_Read_Outports(0, $hash);
- }
+ }
return;
}
-sub
-PIFACE_Watchdog($) {
+sub PIFACE_Watchdog($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my ($cmd, $port, $portMode, $valIn, $valOut0, $valOut1);
my $watchdog = AttrVal($name, "watchdog", undef);
my $watchdogInterval = AttrVal($name, "watchdogInterval", 60);
$watchdogInterval = 10 if ($watchdogInterval !~ m/^\d+$/ || $watchdogInterval < 10);
-
+
if (!defined $watchdog) {
CommandDeleteReading(undef, "$name watchdog");
-
- } elsif ($watchdog =~ m/^(on|silent)$/) {
+
+ } elsif ($watchdog =~ m/^on|silent$/) {
InternalTimer(gettimeofday() + $watchdogInterval, "PIFACE_Watchdog", $hash, 1);
for (my $i=0; $i<7; $i++) {
- $port = $base + $i;
- $portMode = AttrVal($name, "portMode" . $i, "tri");
- $cmd = "$gpioCmd -p mode $port $portMode";
+ $port = $base + 8 + $i;
+ $portMode = AttrVal($name, "portMode" . $i, "tri");
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 mode $port $portMode";
$valIn = `$cmd`;
- }
- $cmd = "$gpioCmd -p mode 207 up";
+ }
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 mode 215 up";
$valIn = `$cmd`;
- $cmd = "$gpioCmd -p read 207";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read 215";
$valIn = `$cmd`;
$valIn =~ s/\n//g;
$valIn =~ s/\r//g;
- $cmd = "$gpioCmd -p write 207 0";
- $cmd = `$cmd`;
- $cmd = "$gpioCmd -p read 215";
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 write 207 0";
+ $cmd = `$cmd`;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read 207";
$valOut0 = `$cmd`;
$valOut0 =~ s/\n//g;
- $valOut0 =~ s/\r//g;
- $cmd = "$gpioCmd -p write 207 1";
- $cmd = `$cmd`;
- $cmd = "$gpioCmd -p read 215";
+ $valOut0 =~ s/\r//g;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 write 207 1";
+ $cmd = `$cmd`;
+ $cmd = "$gpioCmd -x mcp23s17:200:0:0 read 207";
$valOut1 = `$cmd`;
$valOut1 =~ s/\n//g;
- $valOut1 =~ s/\r//g;
+ $valOut1 =~ s/\r//g;
if ($valIn == 0 && $valOut0 == 0 && $valOut1 == 1) {
readingsSingleUpdate($hash, "state", "active", 1) if (ReadingsVal($name, "state", undef) ne "active");
readingsSingleUpdate($hash, ".watchdogRestart", 0, 1);
@@ -356,39 +376,39 @@ PIFACE_Watchdog($) {
readingsSingleUpdate($hash, "watchdog", "ok", 1) if (ReadingsVal($name, "watchdog", undef) ne "ok");
}
} else {
- if ($watchdog eq "on") {
+ if ($watchdog eq "on") {
Log3($name, 3, "PIFACE $name Watchdog error");
- readingsSingleUpdate($hash, "watchdog", "error", 1);
+ readingsSingleUpdate($hash, "watchdog", "error", 1);
} elsif ($watchdog eq "silent") {
- my $watchdogRestart = ReadingsVal($name, ".watchdogRestart", undef);
+ my $watchdogRestart = ReadingsVal($name, ".watchdogRestart", undef);
if (!defined($watchdogRestart) || $watchdogRestart == 0) {
Log3($name, 3, "PIFACE $name Watchdog Fhem restart");
- readingsSingleUpdate($hash, "watchdog", "restart", 1);
- readingsSingleUpdate($hash, ".watchdogRestart", 1, 1);
+ readingsSingleUpdate($hash, "watchdog", "restart", 1);
+ readingsSingleUpdate($hash, ".watchdogRestart", 1, 1);
CommandSave(undef, undef);
CommandShutdown(undef, "restart");
} elsif ($watchdogRestart == 1) {
Log3($name, 3, "PIFACE $name Watchdog OS restart");
readingsSingleUpdate($hash, "watchdog", "restart", 1);
- readingsSingleUpdate($hash, ".watchdogRestart", 2, 1);
+ readingsSingleUpdate($hash, ".watchdogRestart", 2, 1);
CommandSave(undef, undef);
$cmd = 'shutdown -r now';
#$cmd = 'sudo /sbin/shutdown -r now';
#$cmd = 'sudo /sbin/shutdown -r now > /dev/null 2>&1';
- $cmd = `$cmd`;
+ $cmd = `$cmd`;
} elsif ($watchdogRestart == 2) {
$attr{$name}{watchdog} = "off";
Log3($name, 3, "PIFACE $name Watchdog error");
Log3($name, 3, "PIFACE $name Watchdog deactivated");
- CommandDeleteReading(undef, "$name .watchdogRestart");
+ CommandDeleteReading(undef, "$name .watchdogRestart");
readingsSingleUpdate($hash, "watchdog", "error", 1);
readingsSingleUpdate($hash, "state", "error",1);
CommandSave(undef, undef);
}
}
- }
+ }
} else {
- Log3($name, 3, "PIFACE $name Watchdog off");
+ Log3($name, 3, "PIFACE $name Watchdog off");
readingsSingleUpdate($hash, "watchdog", "off", 1);
}
return;
@@ -414,7 +434,7 @@ PIFACE_Watchdog($) {
The module can be periodically monitored by a watchdog function.
The ports can be read and controlled individually by the function readingsProxy.
PIFACE is tested with the Raspbian OS.
-
+
Preparatory Work
The use of PIFACE module requires some preparatory work. The module needs the Wiring Pi tool.
A5 SPI
option to "Yes".
gpio -p readall
gpio -p read 200
gpio -p write 201 0
or gpio -p write 201 1
gpio -x mcp23s17:200:0:0 readall
gpio -x mcp23s17:200:0:0 read 200
gpio -x mcp23s17:200:0:0 write 201 0
or gpio -x mcp23s17:200:0:0 write 201 1
A6 SPI
option to "Yes".
gpio -p readall
gpio -p read 200
gpio -p write 201 0
or gpio -p write 201 1
gpio -x mcp23s17:200:0:0 readall
gpio -x mcp23s17:200:0:0 read 200
gpio -x mcp23s17:200:0:0 write 201 0
or gpio -x mcp23s17:200:0:0 write 201 1