88_Itach_IRDevice.pm 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. ##############################################
  2. # $Id: 88_Itach_IRDevice.pm 10723 2016-02-04 18:13:54Z ulimaass $
  3. # 88_Itach_IRDevice
  4. #
  5. ################################################################
  6. #
  7. # Copyright notice
  8. #
  9. # (c) 2014 Copyright: Ulrich Maass
  10. #
  11. # This file is part of fhem.
  12. #
  13. # Fhem is free software: you can redistribute it and/or modify
  14. # it under the terms of the GNU General Public License as published by
  15. # the Free Software Foundation, either version 2 of the License, or
  16. # (at your option) any later version.
  17. #
  18. # Fhem is distributed in the hope that it will be useful,
  19. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. # GNU General Public License for more details.
  22. #
  23. # You should have received a copy of the GNU General Public License
  24. # along with fhem. If not, see <http://www.gnu.org/licenses/>.
  25. #
  26. # Disclaimer: The Author takes no responsibility whatsoever
  27. # for damages potentially done by this program.
  28. #
  29. ################################################################################
  30. #
  31. # This module serves as frontend to 10_Itach_IR
  32. #
  33. ################################################################################
  34. package main;
  35. use strict;
  36. use warnings;
  37. #########################
  38. # Forward declaration
  39. sub IIRD_Define();
  40. sub IIRD_Attr(@);
  41. sub IIRD_Set($@);
  42. sub IIRD_Get($@);
  43. sub IIRD_getDeviceCommands($);
  44. sub IIRD_send($$$);
  45. sub IIRD_getIRcode($$);
  46. sub IIRD_clearIRcodes($@);
  47. #####################################
  48. # Initialize module
  49. sub
  50. Itach_IRDevice_Initialize($)
  51. {
  52. my ($hash) = @_;
  53. $hash->{GetFn} = "IIRD_Get";
  54. $hash->{SetFn} = "IIRD_Set";
  55. $hash->{AttrFn} = "IIRD_Attr";
  56. $hash->{DefFn} = "IIRD_Define";
  57. $hash->{AttrList} = "verbose:0,1,2,3,4,5,6 IODev";
  58. }
  59. #####################################
  60. # Initialize every new instance
  61. sub
  62. IIRD_Define() {
  63. my ($hash, $def) = @_;
  64. my $ret;
  65. my ($name, $type, $file, $iodev) = split("[ \t]+", $def);
  66. return "Usage: define <name> ItachIRDevice <IR-config-file>" if(!$file);
  67. #should check if file exists
  68. $hash->{STATE} = "Initialized";
  69. $hash->{FILE} = $file if ($file);
  70. AssignIoPort($hash,$iodev) if( !$hash->{IODev} );
  71. if(defined($hash->{IODev}->{NAME})) {
  72. Log3 $name, 4, "$name: I/O device is " . $hash->{IODev}->{NAME};
  73. } else {
  74. my $ret = "$name: no I/O device";
  75. Log3 $name, 1, $ret;
  76. }
  77. my $cmdret= CommandAttr(undef,"$name room ItachIR") if (!AttrVal($name,'room',undef));
  78. return $ret;
  79. }
  80. #####################################
  81. # Ensure .IRcodes is created from scratch after an attribute value has been changed
  82. sub
  83. IIRD_Attr(@)
  84. {
  85. my @a = @_;
  86. my $hash = $defs{$a[1]};
  87. delete $hash->{'.IRcodes'}; # reset IRcodes so they will be loaded anew
  88. return;
  89. }
  90. #####################################
  91. # Digest set-commands
  92. sub
  93. IIRD_Set($@)
  94. {
  95. my ($hash, @a) = @_;
  96. my ($nam,$cmd,$par)=@a;
  97. return if (!defined($cmd));
  98. if ($cmd eq '?') {
  99. return "Unknown argument $cmd choose one of rereadIRfile seqsingle ". IIRD_getDeviceCommands($hash);
  100. } elsif ($cmd eq 'rereadIRfile') {
  101. IIRD_clearIRcodes($hash);
  102. IIRD_getDeviceCommands($hash);
  103. } else {
  104. IIRD_send($hash,$cmd,$par);
  105. }
  106. return undef;
  107. }
  108. #####################################
  109. # Digest get-commands
  110. sub
  111. IIRD_Get($@)
  112. {
  113. my ($hash, @a) = @_;
  114. my $arg = (defined($a[1]) ? $a[1] : ""); #command
  115. my $name = $hash->{NAME};
  116. ## get htmlcode
  117. if($arg eq "validcommands") {
  118. my @vc = split(' ',IIRD_getDeviceCommands($hash));
  119. return join(' ', sort @vc);
  120. } else {
  121. return "Unknown argument $arg choose one of validcommands";
  122. }
  123. }
  124. #####################################
  125. # Send commands to ItachIR
  126. sub
  127. IIRD_send($$$) {
  128. my ($hash,$cmd,$par)=@_;
  129. my $IRcode;
  130. my $name=$hash->{NAME};
  131. if ($cmd eq 'seqsingle') {
  132. for (my $i=0;$i<length($par);$i++) {
  133. $IRcode .= IIRD_getIRcode($hash,substr($par,$i,1)).';';
  134. }
  135. $IRcode =~ s/;$//; #delete final ;
  136. $cmd.=' '.$par;
  137. } else {
  138. $IRcode = IIRD_getIRcode($hash,$cmd);
  139. }
  140. Log3 $name, 5, "IIRD136 Writing $name, $cmd, $IRcode";
  141. my $ret = IOWrite($hash, $name, $cmd, $IRcode) if (defined($IRcode));
  142. readingsSingleUpdate($hash,"state",$cmd,1);
  143. RemoveInternalTimer($hash);
  144. InternalTimer(gettimeofday()+7200, "IIRD_clearIRcodes", $hash, 0); # delete hash->{'.IRcodes'} 2 hours after last use
  145. }
  146. #####################################
  147. # Get IRcode
  148. sub
  149. IIRD_getIRcode($$) {
  150. my ($hash,$cmd)=@_;
  151. my $nam=$hash->{NAME};
  152. my $scmd = $cmd;
  153. $scmd =~ s/^0$/chr0/;
  154. if (!$hash->{'.IRcodes'} || !$hash->{'.IRcodes'}{$scmd}) {
  155. IIRD_getDeviceCommands($hash);
  156. if (!$hash->{'.IRcodes'} || !$hash->{'.IRcodes'}{$scmd}) {
  157. Log3 $nam, 3, "No IRcode defined for device $nam, command $cmd";
  158. return undef;
  159. }
  160. }
  161. return $hash->{'.IRcodes'}{$scmd};
  162. }
  163. #####################################
  164. ## get all defined commands of device
  165. sub
  166. IIRD_getDeviceCommands($) {
  167. my $hash = shift;
  168. my $ret;
  169. my $filename=$hash->{FILE};
  170. if (!$hash->{'.IRcodes'}) {
  171. my $filename = AttrVal('global','modpath','.').'/'.$filename;
  172. Log3 $hash->{NAME}, 5, "Reading $filename ...";
  173. # open IR-file
  174. if (! open(IRCODES, "< $filename")) {
  175. Log3 $hash->{NAME}, 1, "Cannot open file $filename : $!";
  176. } else {
  177. # read commands from IR-file
  178. my $line;
  179. while (defined ($line = <IRCODES>)) {
  180. $line =~ m/^\[(.*)\]\s(.*)/;
  181. $ret .= $1.' ';
  182. my $scmd = $1;
  183. my $IR = $2;
  184. $scmd =~ s/^0$/chr0/;
  185. $hash->{'.IRcodes'}{$scmd} = $IR;
  186. next;
  187. }
  188. }
  189. } else {
  190. foreach my $cmd (keys %{$hash->{'.IRcodes'}}) {
  191. $cmd =~ s/^chr0$/0/;
  192. $ret .= $cmd . ' ' if (defined($cmd));
  193. }
  194. }
  195. $ret =~ s/ $//; #delete final blank
  196. return $ret;
  197. }
  198. #####################################
  199. # Delete IRcodes from hash to save memory
  200. sub
  201. IIRD_clearIRcodes($@) {
  202. my $hash = shift;
  203. delete $hash->{'.IRcodes'};
  204. return undef;
  205. }
  206. 1;
  207. =pod
  208. =begin html
  209. <a name="Itach_IRDevice"></a>
  210. <h3>Itach_IRDevice</h3>
  211. <ul>
  212. Itach IR is a physical device that serves to emit Infrared (IR) commands, hence it is a general IR remote control that can be controlled via WLAN (WF2IR) or LAN (IP2IR).<br>
  213. Using the iLearn-Software that ships with every Itach IR, record the IR-squences per original remotecontrol-button and store all these IR-codes as an IR-config-file.
  214. This IR-config-file can then be used directly with this module. All commands stored in the IR-config-file will be available immediately for use.<br>
  215. For more information, check the <a href="http://www.fhemwiki.de/wiki/ITach">Wiki page</a>.<br>
  216. <a name="Itach_IRDevicedefine"></a><br>
  217. <b>Define</b>
  218. <ul>
  219. <code>define &lt;name&gt; Itach_IRDevice &lt;IR-config-file&gt;</code><br>
  220. Store the IR-config-file in the same directory where fhem.cfg resides.<br>
  221. <b>Hint:</b> define an <a href="#Itach_IR">Itach_IR</a> device first!<br>
  222. Example:<br>
  223. <code>define IR_mac Itach_IRDevice IR-codes-mac.txt</code><br>
  224. <code>define IR_amp Itach_IRDevice IR-codes-media-amplifier.txt</code>
  225. </ul>
  226. <a name="Itach_IRDeviceset"></a><br>
  227. <b>Set</b><br>
  228. <code>set &lt;name&gt; &lt;command&gt; [&lt;parameter&gt;]</code><br><br>
  229. The list of available commands depends on the content of the IR-config-file.
  230. <br>There are only two module specific commands:
  231. <ul>
  232. <li><code>set &lt;name&gt; rereadIRfile</code><br>
  233. For performance reasons, the IR-config-File is read into memory upon definition of the device. If you change the configuration within that file, use this set-command to read its content into fhem once again.</li>
  234. <li><code>set &lt;name&gt; seqsingle &lt;parameter&gt;</code><br>
  235. Will send the digits of a sequence one after the other. Useful when you have a sequence of digits to be sent, e.g. 123. Each digit must be a valid command in your IR-config-file.</li>
  236. </ul>
  237. <a name="Itach_IRDeviceget"></a><br>
  238. <b>Get</b>
  239. <ul>
  240. <li><code>get &lt;name&gt; validcommands</code><br>
  241. Lists the valid commands for this device according to your IR-config-file.</li>
  242. </ul>
  243. <a name="Itach_IRDeviceattr"></a><br>
  244. <b>Attributes</b>
  245. <ul>
  246. <li><a href="#verbose">verbose</a></li>
  247. <li><a href="#IODev">IODev</a><br>
  248. Needs to be stated if more than one ItachIR-device is part of your fhem-configuration.</li>
  249. </ul>
  250. </ul>
  251. =end html
  252. =cut