39_PIOUT.pm quick&dirty hack für einzelnen PiFace out-port als Device

Begonnen von epsrw1, 19 Mai 2014, 19:28:21

Vorheriges Thema - Nächstes Thema

epsrw1

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 $
Ich habe keine Ahnung, aber davon wenigstens ganz viel

epsrw1

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 &lt;name&gt; PIOUT &lt;portnumber&gt;</code><br>
    </ul><br>

<a name="PIOUTset"></a>
<b>Set</b><br/>
<ul>
<br/>
<code>set &lt;name&gt; &lt;value&gt;</code>
<br/><br/>
<ul>
<li>set single port n to 1 (on) or 0 (off)<br/><br/>
Examples:<br/>
set &lt;name&gt; 1 =&gt; set port 3 on<br/>
set &lt;name&gt; on =&gt; set port 3 on<br/>
set &lt;name&gt; 0 =&gt; set port 3 on<br/>
set &lt;name&gt; Off =&gt; set port 5 off<br/></li>
<br/>
</ul>

</ul>
<br>

<a name="PIOUTget"></a>
<b>Get</b><br/>
<ul>
<br/>
<code>get &lt;name&gt; </code>
<br/><br/>
<ul>
<li>get state of single port<br/><br/>
Example:<br/>
get &lt;name&gt; =&gt; 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>&lt;out0..out7&gt;: 0|1<br>
state of output port</li>
<li>state: active|error</li><br>
</ul>

</ul>

=end html
=cut
Ich habe keine Ahnung, aber davon wenigstens ganz viel