stellt einen einzelnen ausgang des PiFace als device bereit, mit schnellerem polling als die readingsProxy variante die in der doku vorgeschlagen wird.
# $Id: 55_PIOUT.pm 5251 2014-06-04 11:33:00Z Florian Duesterwald $
update:
# $Id: 39_PIOUT.pm 5301 2014-06-20 18:00:00Z Florian Duesterwald $
####################################################################################################
#
# 39_PIOUT.pm
#
# quick&dirty hack based on 55_PIFACE.pm 5251 2014-03-18 04:35:17Z klaus-schauer $
#
# An FHEM Perl module to control RaspberryPi extension board PIOUT
#
# The PIOUT 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,
# so only the read, write and internal pull-up commands are implemented.
#
# Please read commandref for details on prerequisits!
# Depends on wiringPi library from http://wiringpi.com
#
# maintainer: klaus.schauer (see MAINTAINER.txt)
#
# This file is part of fhem.
#
# Fhem is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# Fhem is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################
package main;
use strict;
use warnings;
use Time::HiRes qw(gettimeofday);
sub PIOUT_Define($$);
sub PIOUT_Undefine($$);
sub PIOUT_Set($@);
sub PIOUT_Get($@);
sub PIOUT_Notify(@);
sub PIOUT_Attr(@);
my $outPinBase = 200;
sub PIOUT_Initialize($){
my ($hash) = @_;
$hash->{DefFn} = "PIOUT_Define";
$hash->{UndefFn} = "PIOUT_Undefine";
$hash->{SetFn} = "PIOUT_Set";
$hash->{GetFn} = "PIOUT_Get";
$hash->{NotifyFn} = "PIOUT_Notify";
$hash->{AttrFn} = "PIOUT_Attr";
$hash->{AttrList} = $readingFnAttributes .
" defaultState:0,1,last,off pollInterval:0.01,0.1,0.2,0.3,0.4,0.5,1,2,3,4,5,10,off" .
" disable:0,1 disabledForIntervals" .
" portMode:tri,up";
}
sub PIOUT_Define($$){
my ($hash, $def) = @_;
my @args = split("[ \t]+", $def);
my $menge = int(@args);
if (int(@args) < 2)
{
return "Define: to less arguments. Usage:\n" .
"define <name> PIOUT <PortNo.>";
}
my $name = $args[0];
readingsSingleUpdate($hash, "pin", $args[2], 1);
# my $name = $hash->{NAME};
$hash->{NOTIFYDEV} = "global";
Log3($name, 3, "PIOUT $name active");
readingsSingleUpdate($hash, "state", "active",1);
#wait 1 minute before first poll
InternalTimer(gettimeofday() + 60, "PIOUT_GetUpdate", $hash, 0);
return;
}
sub PIOUT_Undefine($$){
my($hash, $name) = @_;
RemoveInternalTimer($hash);
return;
}
sub PIOUT_Set($@) {
my ($hash, @a) = @_;
my $name = $hash->{NAME};
if (IsDisabled($name)) {
Log3 $name, 4, "PIOUT $name set commands disabled.";
return;
}
#Log 3, "PIOUT set L.100 a[0]:".$a[0].": a[1]:".$a[1]." pin:".ReadingsVal($name,"pin","err");
my $val = $a[1];
my $usage = "Unknown argument ".$val.", choose one of 0:noArg 1:noArg off:noArg on:noArg";
return $usage if ( @a < 2 );
return $usage if $val eq "?";
my ($adr, $cmd);
if(lc($val) eq "on"){$val=1;}elsif(lc($val) eq "off"){$val=0;}
if(!(($val eq 0) or ($val eq 1))){$val="?";}
return $usage if $val eq "?";
my $pin = ReadingsVal($name, "pin", "");
$adr = $outPinBase + $pin;
Log3($name, 3, "PIOUT $name set port ".$pin." ".$val);
$cmd = "/usr/local/bin/gpio -p write $adr $val";
$cmd = `$cmd`;
# $hash->{STATE}=$val;
PIOUT_Get($hash);
readingsSingleUpdate($hash, 'state', $val, 1);
return;
}
sub PIOUT_Get($@){
my ($hash, @a) = @_;
my $name = $hash->{NAME};
my $pin = ReadingsVal($name, "pin", "");
my $adr = $outPinBase + 8 + $pin;
my $cmd = '/usr/local/bin/gpio -p read '.$adr;
my $val = `$cmd`;
$val =~ s/\n//g;
$val =~ s/\r//g;
my ( $triggerEventVar ) = 0;
if($hash->{STATE} ne $val){
$triggerEventVar=1;
}
#Log 3, "PIOUT L.132 $name val:".$val.": a";
readingsSingleUpdate($hash, 'state', $val, $triggerEventVar); #0: without event trigger
return;
}
sub PIOUT_Notify(@) {
my ($hash, $dev) = @_;
my $name = $hash->{NAME};
if ($dev->{NAME} eq "global" && grep (m/^INITIALIZED$/,@{$dev->{CHANGED}})){
Log3($name, 3, "PIOUT $name initialized");
PIOUT_Restore_Outports_State($hash);
PIOUT_GetUpdate($hash);
}
return;
}
sub PIOUT_GetUpdate($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my $pollInterval = AttrVal($name, "pollInterval", "off");
if ($pollInterval ne "off") {
InternalTimer(gettimeofday() + ($pollInterval), "PIOUT_GetUpdate", $hash, 1);
PIOUT_Get($hash);
}
return;
}
sub PIOUT_Attr(@) {
my ($cmd, $name, $attrName, $attrVal) = @_;
my $hash = $defs{$name};
if ($attrName eq "pollInterval") {
if (!defined $attrVal) {
#RemoveInternalTimer($hash);
} elsif ($attrVal eq "off" || ( $attrVal >= 0.01 and $attrVal <= 10 ) ) {
PIOUT_GetUpdate($hash);
} else {
#RemoveInternalTimer($hash);
Log3($name, 3, "PIOUT $name attribute-value [$attrName] = $attrVal wrong, use seconds >0.1 as float");
CommandDeleteAttr(undef, "$name pollInterval");
}
} elsif ($attrName eq "defaultState") {
if (!defined $attrVal){
} elsif ($attrVal !~ m/^(last|off|[01])$/) {
Log3($name, 3, "PIOUT $name attribute-value [$attrName] = $attrVal wrong");
CommandDeleteAttr(undef, "$name defaultState");
}
}
return;
}
sub PIOUT_Restore_Outports_State($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my @cmd = ($name, 0, 0);
my $defaultState = AttrVal($name, "defaultState", "off");
if ($defaultState ne "off") {
$cmd[1] = ReadingsVal($name,"pin",0);
if ($defaultState eq "last") {
$cmd[2] = ReadingsVal($name, "state", 0);
} elsif ($defaultState == 1) {
$cmd[2] = 1;
} else {
$cmd[2] = 0;
}
PIOUT_Set($hash, @cmd);
}
return;
}
1;
=pod
=begin html
<a name="PIOUT"></a>
<h3>PIOUT</h3>
<ul>
The PIOUT module managed the <a href=http://www.raspberrypi.org/>Raspberry Pi</a> extension board <a href=http://www.PIOUT.org.uk/products/PIOUT_digital/>PIOUT Digital</a>.<br>
PIOUT controls the output ports 0..7.
<ul>
<li>The relays 0 and 1 have corresponding output port 0 and 1.</li>
</ul>
The status of the ports can be displayed periodically. The update of the states via interrupt is not supported.<br>
PIOUT is tested with the Raspbian OS.<br><br>
<b>Preparatory Work</b><br>
The use of PIOUT module requires some preparatory work.
<ul>
<br>
<li>Module needs tools from <a href=http://wiringpi.com>Wiring Pi</a>. Install it with<br>
<code>git clone git://git.drogon.net/wiringPi<br>
cd wiringPi<br>
./build</code><br>
</li>
<li>PIOUT Digital need the SPI pins on the Raspberry Pi to be enabled in order to function.
Start <code>sudo raspi-config</code>, select <code>Option 8 Advanced Options</code>
and set the <code>A5 SPI</code> option to "Yes".
</li>
<li>The function of the PIOUT Digital can be tested at OS command line. For example:<br>
<code>gpio -p readall</code><br>
<code>gpio -p read 208</code><br>
<code>gpio -p write 209 0</code> or <code>gpio -p write 209 1</code><br>
</li>
</ul>
<br>
<a name="PIOUTdefine"></a>
<b>Define</b>
<ul><br>
<code>define <name> PIOUT <portnumber></code><br>
</ul><br>
<a name="PIOUTset"></a>
<b>Set</b><br/>
<ul>
<br/>
<code>set <name> <value></code>
<br/><br/>
<ul>
<li>set single port n to 1 (on) or 0 (off)<br/><br/>
Examples:<br/>
set <name> 1 => set port 3 on<br/>
set <name> on => set port 3 on<br/>
set <name> 0 => set port 3 on<br/>
set <name> Off => set port 5 off<br/></li>
<br/>
</ul>
</ul>
<br>
<a name="PIOUTget"></a>
<b>Get</b><br/>
<ul>
<br/>
<code>get <name> </code>
<br/><br/>
<ul>
<li>get state of single port<br/><br/>
Example:<br/>
get <name> => get state of port 3<br/>
</li>
</ul>
</ul>
<br>
<a name="PIOUTattr"></a>
<b>Attributes</b><br/><br/>
<ul>
<li><a name="PIOUT_defaultState">defaultState</a> last|off|0|1,
[defaultState] = off is default.<br>
Restoration of the status of the output port after a Fhem reboot.
</li>
<li><a href="#PIOUT_disable">disable</a> 0|1<br>
If applied set commands will not be executed.
</li>
<li><a href="#PIOUT_disabledForIntervals">disabledForIntervals</a> HH:MM-HH:MM HH:MM-HH-MM...<br>
Space separated list of HH:MM tupels. If the current time is between
the two time specifications, set commands will not be executed. Instead of
HH:MM you can also specify HH or HH:MM:SS. To specify an interval
spawning midnight, you have to specify two intervals, e.g.:
<ul>
23:00-24:00 00:00-01:00
</ul>
</li>
<li><a name="PIOUT_pollInterval">pollInterval</a> off|0.01,0.1,0.2,0.3,0.4,0.5,1,2,3,4,5,10,
[pollInterval] = off is default.<br>
Define the polling interval of the input ports in seconds.
</li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
<br>
<b>Generated Readings/Events:</b>
<br/><br/>
<ul>
<li><out0..out7>: 0|1<br>
state of output port</li>
<li>state: active|error</li><br>
</ul>
</ul>
=end html
=cut