diff --git a/contrib/inputevent/89_inputevent.pm b/contrib/inputevent/89_inputevent.pm new file mode 100644 index 000000000..c109d4caf --- /dev/null +++ b/contrib/inputevent/89_inputevent.pm @@ -0,0 +1,234 @@ +package main; +########################### +# 89_inputevent.pm +# Modul for FHEM +# +# contributed by Dirk Hoffmann 2010-2011 +# $Id: 89_inputEvent.pm,v 0.2 2011/11/27 19:16:16 dirkho Exp $ +# +# +# Linux::Input wird benötigt +########################### +use strict; +use Switch; +use warnings; + +use IO::Select; +use Linux::Input; + +use vars qw{%attr %defs}; +sub Log($$); +our $FH; +#################################### +# INPUTEVENT_Initialize +# Implements Initialize function +# +sub INPUTEVENT_Initialize($) { + my ($hash) = @_; + Log 1, "INPUT/Event Initialize"; + + # Provider + $hash->{ReadFn} = "INPUTEVENT_Read"; + $hash->{ReadyFn} = "INPUTEVENT_Ready"; + + # Consumer + $hash->{DefFn} = "INPUTEVENT_Define"; + $hash->{UndefFn} = "INPUTEVENT_Undef"; + + $hash->{SetFn} = "INPUTEVENT_Set"; + $hash->{AttrList}= "model:EVENT loglevel:0,1,2,3,4,5"; + + $hash->{READINGS}{uTIME} = 0; + $hash->{READINGS}{lastCode} = 0; +} + +##################################### +# INPUTEVENT_Define +# Implements DefFn function +# +sub INPUTEVENT_Define($$) { + my ($hash, $def) = @_; + my ($name, undef, $dev, $msIgnore) = split("[ \t][ \t]*", $def); + + if (!$msIgnore) { + $msIgnore = 175; + } + + delete $hash->{fh}; + delete $hash->{FD}; + + my $fileno; + + if($dev eq "none") { + Log 1, "Input device is none, commands will be echoed only"; + return undef; + } + + Log 4, "Opening input device at $dev. Repeated commands within $msIgnore miliseconds was ignored."; + + if ($dev=~/^\/dev\/input/) { + my $OS=$^O; + if ($OS eq 'MSWin32') { + my $logMsg = "Input devices only avilable under Linux OS at this time."; + Log 1, $logMsg; + return $logMsg; + } else { + if ($@) { + my $logMsg = "Error using Modul Linux::Input"; + $hash->{STATE} = $logMsg; + Log 1, $logMsg; + return $logMsg . " Can't open Linux::Input $@\n"; + } + + my $devObj = Linux::Input->new($dev); + if (!$devObj) { + my $logMsg = "Error opening device"; + $hash->{STATE} = "error opening device"; + Log 1, $logMsg . " $dev"; + return "Can't open Device $dev: $^E\n"; + } + + my $select = IO::Select->new($devObj->fh); + + foreach my $fh ($select->handles) { + $fileno = $fh->fileno; + } + + $selectlist{"$name.$dev"} = $hash; + $hash->{fh} = $devObj->fh; + $hash->{FD} = $fileno; + $hash->{SelectObj} = $select; + $hash->{STATE} = "Opened"; + $hash->{DeviceName}=$name; + $hash->{msIgnore}=$msIgnore; + Log 4, "$name connected to device $dev"; + } + + } else { + my $logMsg = "$dev is no device and not implemented"; + $hash->{STATE} = $logMsg; + Log 1, $logMsg; + return $logMsg; + } + + return undef; +} + +##################################### +# implements UnDef-Function +# +sub INPUTEVENT_Undef($$) { + my ($hash, $arg) = @_; + my $name = $hash->{NAME}; + my $fh = $hash->{fh}; + delete $hash->{fh}; + $hash->{STATE}='Closed'; + + if ($fh) { + $fh->close(); + } + + Log 5, "$name shutdown complete"; + return undef; +} + +##################################### +# INPUTEVENT_Set +# implement SetFn +# currently nothing to set +# +sub INPUTEVENT_Ready($$) { + my ($hash, $dev) = @_; + my $select= $hash->{SelectObj}; + + return ($select->can_read(0)); +} + +##################################### +# INPUTEVENT_Set +# implement SetFn +# currently nothing to set +# +sub INPUTEVENT_Set($@) { + my ($hash, @a) = @_; + my $name=$a[0]; + my $msg = "$name => No Set function implemented"; + + Log 1,$msg; + return $msg; +} + +##################################### +# INPUTEVENT_Read +# Implements ReadFn, called from global select +# +sub INPUTEVENT_Read($$) { + my ($hash) = @_; + + my $fh = $hash->{fh}; + my $select= $hash->{SelectObj}; + my $name = $hash->{NAME}; + + my $message = undef; + + if( $select->can_read(0) ){ + $fh->read($message,16); + + INPUTEVENT_Parse($hash, $message); + } + + return 1; +} + +##################################### +# INPUTEVENT_Parse +# decodes complete frame +# called directly from INPUTEVENT_Read +sub INPUTEVENT_Parse($$) { + my ($hash, $msg) = @_; + my $name = $hash->{NAME}; + my $message; + + my ($b0,$b1,$b2,$b3,$b4,$b5,$b6,$b7,$b8,$b9,$b10,$b11,$b12,$b13,$b14,$b15) = + map {$_ & 0x7F} unpack("U*",$msg); + + my $sec = sprintf('%10s', $b0 + $b1*256 + $b2*256*256 + $b3*256*256*256); + my $ySec = sprintf('%06s', $b4 + $b5*256 + $b6*256*256); + my $type = $b8; + my $code = $b10; + my $value = sprintf('%07s', $b12 + $b13*256 + $b14*256*256); + + if ($type eq 4 && $code eq 3) { + $message = "$name => $sec.$ySec, type: $type, code: $code, value: $value"; + + # Set $ignoreUSecs => µSec sice last command. + my $uTime = $sec * 1000000 + $ySec; + my $ignoreUSecs = $uTime - $hash->{READINGS}{uTIME}; + $hash->{READINGS}{uTIME} = $uTime; + + #Log 4, $hash->{READINGS}{lastCode} . " _ " . $value . " | " . $hash->{READINGS}{uTIME} . " --- " . $uTime . " +++ " . $ignoreUSecs; + + # IR-codes was repeated with short delay. So we ignor commands the next µSeconds set in the define command. (Default 175000) + if (($ignoreUSecs > ($hash->{msIgnore} * 1000)) || ($hash->{READINGS}{lastCode} ne $value)) { + $hash->{READINGS}{LAST}{VAL} = unpack('H*',$msg); + $hash->{READINGS}{LAST}{TIME} = TimeNow(); + $hash->{READINGS}{RAW}{TIME} = time(); + $hash->{READINGS}{RAW}{VAL} = unpack('H*',$msg); + $hash->{READINGS}{lastCode} = $value; + + Log 4, $message; + + DoTrigger($name, $message); + } + } +} + + +##################################### +sub INPUTEVENT_List($$) { + my ($hash,$msg) = @_; + $msg = INPUTEVENT_Get($hash,$hash->{NAME},'list'); + return $msg; +} + +1; diff --git a/contrib/inputevent/inputevent.txt b/contrib/inputevent/inputevent.txt new file mode 100644 index 000000000..64869de32 --- /dev/null +++ b/contrib/inputevent/inputevent.txt @@ -0,0 +1,21 @@ +InputEvent - Linux InputEvent handling für fhem +=============================================== +Von Dirk Hoffmann + +V0.1 + +InputEvent ist ein Modul für FHEM um auf Linux Input Events zu reagieren. +Damit ist es möglich z.B. auf Tastatur Ereignisse zu reagieren. + +Ich benutze InpuEvent um FHEM mit einer Infrarotfernbedienung an einer DVB-S Karte +zu koppeln. Damit lassen sich über FHEM z.B. Befehle an alle unterstützen Geräte +Senden. + +in der Datei sample.conf ist eine Beispielkonfiguration enthalten. + +History +----------- +V0.1 - Initiale Version + +V0.2 - Events werden jetzt nur noch einmal innerhalb einer bestimmten Zeit ausgeführt + (Siehe sample.conf) diff --git a/contrib/inputevent/sample.conf b/contrib/inputevent/sample.conf new file mode 100644 index 000000000..2798b1b24 --- /dev/null +++ b/contrib/inputevent/sample.conf @@ -0,0 +1,42 @@ +### Sample Settings for DVB-IR-Remote +# +# the code can be found in output of command evtest /dev/input/eventX +# Sampleoutput : +# ~> evtest /dev/input/eventX +# +# Event: time 1322401114.481388, type 4 (Misc), code 3 (?), value 1900585 +# Event: time 1322401114.481396, type 4 (Misc), code 4 (?), value 41 +# Event: time 1322401114.595003, type 4 (Misc), code 3 (?), value 1900585 +# Event: time 1322401114.595006, type 4 (Misc), code 4 (?), value 41 + +# Define the inputevent handler +# The input device +# | Miliseconds between repeated commands ignored (Default 150) +# | | +define DVB_Remote inputevent /dev/input/event4 160 +attr DVB_Remote comment DVB-Remote IR Receiver at /dev/input/event4. Repeated commands within 150 miliseconds was ignored. + +# Define a FS20 actor +define st1 FS20 44444444 1111 +attr st1 follow-on-for-timer +attr st1 comment Steckdose 1 +attr st1 model FS20 ST-2 + +# Define some notify handler to receive the remote commands + +# Sample settings for FS20 Device st1 Steckdose 1 +# The IR-Code (see above) +# | +# | +define xsight_st1_off notify DVB_Remote.*value:.*1900586 set st1 off +define xsight_st1_on notify DVB_Remote.*value:.*1900585 set st1 on + +# Wohnzimmer Licht 1 +define xsight_wzLicht1_off notify DVB_Remote.*value:.*1900570 set wzLicht1 off +define xsight_wzLicht1_on notify DVB_Remote.*value:.*1900569 set wzLicht1 on +define xsight_wzLicht1_dim06 notify DVB_Remote.*value:.*1900590 set wzLicht1 dim06%% +define xsight_wzLicht1_dim25 notify DVB_Remote.*value:.*1900589 set wzLicht1 dim25%% +define xsight_wzLicht1_dim43 notify DVB_Remote.*value:.*1900574 set wzLicht1 dim43%% +define xsight_wzLicht1_dim62 notify DVB_Remote.*value:.*1900573 set wzLicht1 dim62%% +define xsight_wzLicht1_dim81 notify DVB_Remote.*value:.*1900558 set wzLicht1 dim81%% +define xsight_wzLicht1_dim100 notify DVB_Remote.*value:.*1900557 set wzLicht1 dim100%% diff --git a/contrib/inputevent/vdr-plugin-remote.diff b/contrib/inputevent/vdr-plugin-remote.diff new file mode 100644 index 000000000..1b0f40e09 --- /dev/null +++ b/contrib/inputevent/vdr-plugin-remote.diff @@ -0,0 +1,18 @@ +diff -upr remote/remote.c remote_patched/remote.c +--- remote/remote.c 2010-09-27 00:42:45.273924974 +0200 ++++ remote_patched/remote.c 2010-09-27 00:58:26.477924549 +0200 +@@ -268,14 +268,7 @@ cRemoteDevInput::cRemoteDevInput(const c + polldelay = repeatdelay = repeatfreq = repeattimeout = 0; + } + +- // grab device if possible (kernel 2.6) +-#ifndef EVIOCGRAB +- // required if an old /usr/include/linux/input.h is used with a new kernel :-( +-#define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ +-#endif + data[0] = 1; +- if (ioctl(f, EVIOCGRAB, data) == 0) +- dsyslog("%s: exclusive access granted", name); + + // setup keymap + const char *setupStr = GetSetup();