52_I2C_PCF8574.pm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. ##############################################
  2. # $Id: 52_I2C_PCF8574.pm 12059 2016-08-22 21:14:59Z klauswitt $
  3. package main;
  4. use strict;
  5. use warnings;
  6. use SetExtensions;
  7. use Scalar::Util qw(looks_like_number);
  8. my %setsP = (
  9. 'off' => 0,
  10. 'on' => 1,
  11. );
  12. sub I2C_PCF8574_Initialize($) {
  13. my ($hash) = @_;
  14. #$hash->{Match} = ".*";
  15. $hash->{DefFn} = "I2C_PCF8574_Define";
  16. $hash->{InitFn} = 'I2C_PCF8574_Init';
  17. $hash->{AttrFn} = "I2C_PCF8574_Attr";
  18. $hash->{SetFn} = "I2C_PCF8574_Set";
  19. $hash->{StateFn} = "I2C_PCF8574_State";
  20. $hash->{GetFn} = "I2C_PCF8574_Get";
  21. $hash->{UndefFn} = "I2C_PCF8574_Undef";
  22. $hash->{ParseFn} = "I2C_PCF8574_Parse";
  23. $hash->{I2CRecFn} = "I2C_PCF8574_I2CRec";
  24. $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:1,0 showtime:1,0 ".
  25. "poll_interval OnStartup ".
  26. "InputPorts:multiple-strict,0,1,2,3,4,5,6,7 ".
  27. "$readingFnAttributes";
  28. }
  29. ###################################
  30. sub I2C_PCF8574_Set($@) { #
  31. my ($hash, @a) = @_;
  32. my $name =$a[0];
  33. my $cmd = $a[1];
  34. my $val = $a[2];
  35. my @inports = sort(split( " ",AttrVal($name, "InputPorts", "")));
  36. my %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cwrite" );
  37. if ( $cmd && $cmd =~ m/^P(ort|)((0|)[0-7])(,(P|)(ort|)((0|)[0-7])){0,7}$/i) {
  38. return "wrong value: $val for \"set $name $cmd\" use one of: off, on"
  39. unless(exists($setsP{$val}));
  40. my @scmd = split(",", $cmd);
  41. my $msg = undef;
  42. foreach (@scmd) {
  43. $_ =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren
  44. $msg .= (defined $msg ? "," : "") . "Port" . $_ if ( $_ ~~ @inports ); #Pruefen ob entsprechender Port Input ist
  45. }
  46. return "$name error: $msg is defined as input" if $msg;
  47. my $sbyte = 0;
  48. foreach (0..7) {
  49. if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt
  50. $sbyte += 1 << (1 * $_);
  51. } elsif( $_ ~~ @scmd ) { #Port der geaendert werden soll
  52. $sbyte += $setsP{$val} << (1 * $_);
  53. } else { #alle anderen Portwerte werden den Readings entnommen
  54. $sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_); #->sonst aus dem Reading holen
  55. }
  56. }
  57. $sendpackage{data} = $sbyte;
  58. } elsif ( $cmd && $cmd eq "setfromreading" ) {
  59. my $sbyte = 0;
  60. foreach (0..7) {
  61. if ($_ ~~ @inports) { #Port der als Input konfiguriert ist wird auf 1 gesetzt
  62. $sbyte += 1 << (1 * $_);
  63. } else { #alle anderen Portwerte werden den Readings entnommen
  64. $sbyte += $setsP{ReadingsVal($name,'Port'.$_,"off")} << (1 * $_);
  65. }
  66. }
  67. $sendpackage{data} = $sbyte;
  68. } else {
  69. my $list = undef;
  70. foreach (0..7) {
  71. next if ( $_ ~~ @inports ); #Inputs ueberspringen
  72. $list .= "Port" . $_ . ":" . join(',', (sort { $setsP{ $a } <=> $setsP{ $b } } keys %setsP) ) . " ";
  73. }
  74. return "Unknown argument $a[1], choose one of " . $list if defined $list;
  75. return "Unknown argument $a[1]";
  76. }
  77. return "$name: no IO device defined" unless ($hash->{IODev});
  78. my $phash = $hash->{IODev};
  79. my $pname = $phash->{NAME};
  80. CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
  81. ##########################################################
  82. # IOWrite($hash, \%sendpackage);
  83. ##########################################################
  84. ##########################################################
  85. # Look for all devices with the same code, and set state, timestamp
  86. #my $code = "$hash->{I2C_Address} $hash->{BTN}";
  87. #my $code = "$hash->{NAME} $hash->{I2C_Address}";
  88. #my $tn = TimeNow();
  89. #my $defptr = $modules{I2C_PCF8574}{defptr}{$code};
  90. #foreach my $n (keys %{ $defptr }) {
  91. # readingsSingleUpdate($defptr->{$n}, "state", $v, 1);
  92. # }
  93. ##########################################################
  94. return undef;
  95. }
  96. ###################################
  97. sub I2C_PCF8574_Get($@) {
  98. my ($hash, @a) = @_;
  99. my $name =$a[0];
  100. my %sendpackage = ();
  101. #%sendpackage = ( direction => "i2cread", id => (defined( $hash->{ID} )? $hash->{ID} : "00"), i2caddress => $hash->{I2C_Address});
  102. %sendpackage = ( i2caddress => $hash->{I2C_Address}, direction => "i2cread");
  103. return "$name: no IO device defined" unless ($hash->{IODev});
  104. #neu: ueber CallFn auf eigene Funktion
  105. my $phash = $hash->{IODev};
  106. my $pname = $phash->{NAME};
  107. CallFn($pname, "I2CWrtFn", $phash, \%sendpackage);
  108. #alt: fuer IOWrite
  109. #IOWrite($hash, \%sendpackage);
  110. }
  111. ###################################
  112. sub I2C_PCF8574_Attr(@) { #
  113. my ($command, $name, $attr, $val) = @_;
  114. my $hash = $defs{$name};
  115. my $msg = '';
  116. if ($command && $command eq "set" && $attr && $attr eq "IODev") {
  117. if ($main::init_done and (!defined ($hash->{IODev}) or $hash->{IODev}->{NAME} ne $val)) {
  118. main::AssignIoPort($hash,$val);
  119. my @def = split (' ',$hash->{DEF});
  120. I2C_PCF8574_Init($hash,\@def) if (defined ($hash->{IODev}));
  121. }
  122. }
  123. if ($attr eq 'poll_interval') {
  124. if ( defined($val) ) {
  125. if ( looks_like_number($val) && $val > 0) {
  126. RemoveInternalTimer($hash);
  127. InternalTimer(1, 'I2C_PCF8574_Poll', $hash, 0);
  128. } else {
  129. $msg = "$hash->{NAME}: Wrong poll intervall defined. poll_interval must be a number > 0";
  130. }
  131. } else {
  132. RemoveInternalTimer($hash);
  133. }
  134. } elsif ($attr && $attr eq "InputPorts") {
  135. if ( defined($val) ) {
  136. my @inp = split(" ", $val);
  137. foreach (@inp) {
  138. $msg = "wrong value: $_ for \"set $name $attr\" use space separated numbers 0-7" unless ($_ >= 0 && $_ < 8);
  139. }
  140. }
  141. } elsif ($attr && $attr eq "OnStartup") {
  142. if (defined $val) {
  143. foreach (split (/,/,$val)) {
  144. my @pair = split (/=/,$_);
  145. $msg = "wrong value: $_ for \"attr $hash->{NAME} $attr\" use comma separated <port>=on|off|last where <port> = 0 - 7"
  146. unless ( scalar(@pair) == 2 && ($pair[0] =~ m/^[0-7]$/i && ( $pair[1] eq "last" || exists($setsP{$pair[1]}) ) ) );
  147. }
  148. }
  149. }
  150. return $msg
  151. }
  152. ###################################
  153. sub I2C_PCF8574_Define($$) { #
  154. my ($hash, $def) = @_;
  155. my @a = split("[ \t]+", $def);
  156. $hash->{STATE} = 'defined';
  157. if ($main::init_done) {
  158. eval { I2C_PCF8574_Init( $hash, [ @a[ 2 .. scalar(@a) - 1 ] ] ); };
  159. return I2C_PCF8574_Catch($@) if $@;
  160. }
  161. return undef;
  162. }
  163. ###################################
  164. sub I2C_PCF8574_Init($$) { #
  165. my ( $hash, $args ) = @_;
  166. #my @a = split("[ \t]+", $args);
  167. my $name = $hash->{NAME};
  168. if (defined $args && int(@$args) != 1) {
  169. return "Define: Wrong syntax. Usage:\n" .
  170. "define <name> I2C_PCA9532 <i2caddress>";
  171. }
  172. if (defined (my $address = shift @$args)) {
  173. $hash->{I2C_Address} = $address =~ /^0.*$/ ? oct($address) : $address;
  174. } else {
  175. return "$name I2C Address not valid";
  176. }
  177. #fuer die Nutzung von IOWrite
  178. #my $code = ( defined( $hash->{ID} )? $hash->{ID} : "00" ) . " " . $hash->{I2C_Address};
  179. #my $ncode = 1;
  180. #my $name = $a[0];
  181. #$hash->{CODE}{$ncode++} = $code;
  182. #$modules{I2C_PCF8574}{defptr}{$code}{$name} = $hash;
  183. AssignIoPort($hash);
  184. $hash->{STATE} = 'Initialized';
  185. I2C_PCF8574_Set($hash, $name, "setfromreading");
  186. return;
  187. }
  188. ###################################
  189. sub I2C_PCF8574_Catch($) {
  190. my $exception = shift;
  191. if ($exception) {
  192. $exception =~ /^(.*)( at.*FHEM.*)$/;
  193. return $1;
  194. }
  195. return undef;
  196. }
  197. ###################################
  198. sub I2C_PCF8574_State($$$$) { #reload readings at FHEM start
  199. my ($hash, $tim, $sname, $sval) = @_;
  200. Log3 $hash, 4, "$hash->{NAME}: $sname kann auf $sval wiederhergestellt werden $tim";
  201. if ($sname =~ m/^Port[0-7]$/i) {
  202. my $po = $sname; #noch ändern
  203. $po =~ tr/[a-zA-Z]//d; #Nummer aus String extrahieren
  204. my @inports = sort(split(/ /,AttrVal($hash->{NAME}, "InputPorts", "")));
  205. unless ( $po ~~ @inports) {
  206. my %onstart = split /[,=]/, AttrVal($hash->{NAME}, "OnStartup", "");
  207. if ( exists($onstart{$po}) && exists($setsP{$onstart{$po}})) {
  208. Log3 $hash, 5, "$hash->{NAME}: $sname soll auf $onstart{$po} gesetzt werden";
  209. readingsSingleUpdate($hash,$sname, $onstart{$po}, 1);
  210. } else {
  211. Log3 $hash, 5, "$hash->{NAME}: $sname soll auf Altzustand: $sval gesetzt werden";
  212. $hash->{READINGS}{$sname}{VAL} = $sval;
  213. $hash->{READINGS}{$sname}{TIME} = $tim;
  214. }
  215. } else {
  216. Log3 $hash, 5, "$hash->{NAME}: $sname ist Eingang";
  217. }
  218. }
  219. return undef;
  220. }
  221. ###################################
  222. sub I2C_PCF8574_Undef($$) { #
  223. my ($hash, $name) = @_;
  224. if ( defined (AttrVal($hash->{NAME}, "poll_interval", undef)) ) {
  225. RemoveInternalTimer($hash);
  226. }
  227. #foreach my $c (keys %{ $hash->{CODE} } ) {
  228. # $c = $hash->{CODE}{$c};
  229. # my $c = ( defined( $hash->{ID} )? $hash->{ID} : "00" ) . " " . $hash->{I2C_Address};
  230. # As after a rename the $name my be different from the $defptr{$c}{$n}
  231. # we look for the hash.
  232. # foreach my $dname (keys %{ $modules{I2C_PCF8574}{defptr}{$c} }) {
  233. # delete($modules{I2C_PCF8574}{defptr}{$c}{$dname})
  234. # if($modules{I2C_PCF8574}{defptr}{$c}{$dname} == $hash);
  235. # }
  236. # }
  237. return undef;
  238. }
  239. ###################################
  240. sub I2C_PCF8574_Poll($) { #for attr poll_intervall -> readout pin values
  241. my ($hash) = @_;
  242. my $name = $hash->{NAME};
  243. # Read values
  244. I2C_PCF8574_Get($hash, $name);
  245. my $pollInterval = AttrVal($hash->{NAME}, 'poll_interval', 0);
  246. if ($pollInterval > 0) {
  247. InternalTimer(gettimeofday() + ($pollInterval * 60), 'I2C_PCF8574_Poll', $hash, 0);
  248. }
  249. }
  250. ###################################
  251. sub I2C_PCF8574_I2CRec($@) { # ueber CallFn vom physical aufgerufen
  252. my ($hash, $clientmsg) = @_;
  253. my $name = $hash->{NAME};
  254. my $phash = $hash->{IODev};
  255. my $pname = $phash->{NAME};
  256. while ( my ( $k, $v ) = each %$clientmsg ) { #erzeugen von Internals fuer alle Keys in $clientmsg die mit dem physical Namen beginnen
  257. $hash->{$k} = $v if $k =~ /^$pname/ ;
  258. }
  259. my $sval;
  260. if ($clientmsg->{direction} && $clientmsg->{$pname . "_SENDSTAT"} && $clientmsg->{$pname . "_SENDSTAT"} eq "Ok") {
  261. readingsBeginUpdate($hash);
  262. if ($clientmsg->{direction} eq "i2cread" && defined($clientmsg->{received})) { # =~ m/^(0x|)[0-9A-F]{1,2}$/xi) {
  263. foreach (0..7) {
  264. #$sval = hex($clientmsg->{received}) & (1 << $_);
  265. $sval = $clientmsg->{received} & (1 << $_);
  266. $sval = $sval == 0 ? "off" :"on";
  267. readingsBulkUpdate($hash, 'Port'.$_ , $sval) if (ReadingsVal($name,'Port'.$_,"") ne $sval);
  268. }
  269. readingsBulkUpdate($hash, 'state', $clientmsg->{received});
  270. } elsif ($clientmsg->{direction} eq "i2cwrite" && defined($clientmsg->{data})) { # =~ m/^(0x|)[0-9A-F]{1,2}$/xi) {
  271. my @inports = sort(split( " ",AttrVal($name, "InputPorts", "")));
  272. foreach (0..7) {
  273. #$sval = hex($clientmsg->{data}) & (1 << $_);
  274. $sval = $clientmsg->{data} & (1 << $_);
  275. $sval = $sval == 0 ? "off" :"on";
  276. readingsBulkUpdate($hash, 'Port'.$_ , $sval) unless (ReadingsVal($name,'Port'.$_,"") eq $sval || $_ ~~ @inports );
  277. }
  278. readingsBulkUpdate($hash, 'state', $clientmsg->{data});
  279. }
  280. #readingsBulkUpdate($hash, 'state', join(" ", $clientmsg->{received}));
  281. readingsEndUpdate($hash, 1);
  282. }
  283. }
  284. ###################################
  285. sub I2C_PCF8574_Parse($$) { #wird ueber dispatch vom physical device aufgerufen (dispatch wird im mom nicht verwendet)
  286. my ($hash, $msg) = @_;
  287. my($sid, $addr, @msg) = split(/ /,$msg);
  288. #Log3 $hash, 4, "Vom Netzerparse $hash->{NAME}: sid: $sid, Msg: @msg";
  289. my $def = $modules{I2C_PCF8574}{defptr}{"$sid $addr"};
  290. if($def) {
  291. my @list;
  292. foreach my $n (keys %{ $def }) {
  293. my $lh = $def->{$n}; # Hash bekommen
  294. $n = $lh->{NAME}; # It may be renamed
  295. return "" if(IsIgnored($n)); # Little strange.
  296. ################################################
  297. my $cde = join(" ",@msg);
  298. my $sval;
  299. readingsBeginUpdate($lh);
  300. if ( int(@msg) == 1) {
  301. for (my $i = 0; $i < 8; $i++) {
  302. #$sval = hex($cde) & (1 << $i);
  303. $sval = $cde & (1 << $i);
  304. $sval = $sval == 0 ? "0" :"1";
  305. readingsBulkUpdate($lh, 'P'.$i , $sval) if (ReadingsVal($n,'P'.$i,2) ne $sval);
  306. }
  307. }
  308. readingsBulkUpdate($lh, 'state', join(" ", @msg));
  309. readingsEndUpdate($lh, 1);
  310. ################################################
  311. Log3 $n, 4, "I2C_PCF8574 $n $cde";
  312. push(@list, $n);
  313. }
  314. return @list;
  315. } else {
  316. Log3 $hash, 3, "I2C_PCF8574 Unknown device $addr Id $sid";
  317. #return "UNDEFINED I2C_PCF8574_$addr$sid I2C_PCF8574 $addr $sid";
  318. }
  319. }
  320. ###################################
  321. 1;
  322. =pod
  323. =item device
  324. =item summary controls/reads GPIOs from an via I2C connected PCF8574 port extender
  325. =item summary_DE steuern/lesen der GPIOs eines &uuml;ber I2C angeschlossenen PCF8574
  326. =begin html
  327. <a name="I2C_PCF8574"></a>
  328. <h3>I2C_PCF8574</h3>
  329. (en | <a href="commandref_DE.html#I2C_PCF8574">de</a>)
  330. <ul>
  331. <a name="I2C_PCF8574"></a>
  332. Provides an interface to the PCA9532 8 channel port extender IC. On Raspberry Pi the Interrupt Pin can be connected to an GPIO and <a href="#RPI_GPIO">RPI_GPIO</a> can be used to get the port values if an interrupt occurs.<br>
  333. The I2C messages are send through an I2C interface module like <a href="#RPII2C">RPII2C</a>, <a href="#FRM">FRM</a>
  334. or <a href="#NetzerI2C">NetzerI2C</a> so this device must be defined first.<br>
  335. <b>attribute IODev must be set</b><br>
  336. <a name="I2C_PCF8574Define"></a><br>
  337. <b>Define</b>
  338. <ul>
  339. <code>define &lt;name&gt; I2C_PCF8574 &lt;I2C Address&gt;</code><br>
  340. where <code>&lt;I2C Address&gt;</code> is without direction bit<br>
  341. </ul>
  342. <a name="I2C_PCF8574Set"></a>
  343. <b>Set</b>
  344. <ul>
  345. <code>set &lt;name&gt; &lt;port[,port[...]]&gt; &lt;value&gt;</code><br><br>
  346. <ul>
  347. <li><code>&lt;port&gt;</code> is one of Port0 to Port7 and <code>&lt;value&gt;</code> is one of:<br>
  348. <ul>
  349. <code>
  350. off<br>
  351. on<br>
  352. </code>
  353. </ul>
  354. </li>
  355. </ul>
  356. <br>
  357. Example:
  358. <ul>
  359. <code>set mod1 Port4 on</code><br>
  360. <code>set mod1 Port4,Port6 off</code><br>
  361. <code>set mod1 Port4,6 on</code><br>
  362. </ul><br>
  363. </ul>
  364. <a name="I2C_PCF8574Get"></a>
  365. <b>Get</b>
  366. <ul>
  367. <code>get &lt;name&gt;</code>
  368. <br><br>
  369. refreshes all readings
  370. </ul><br>
  371. <a name="I2C_PCF8574Attr"></a>
  372. <b>Attributes</b>
  373. <ul>
  374. <li>poll_interval<br>
  375. Set the polling interval in minutes to query the GPIO's level<br>
  376. Default: -, valid values: decimal number<br><br>
  377. </li>
  378. <li>InputPorts<br>
  379. Space separated list of Portnumers that are used as Inputs<br>
  380. Ports in this list can't be written<br>
  381. Default: no, valid values: 0 1 2 .. 7<br><br>
  382. </li>
  383. <li>OnStartup<br>
  384. Comma separated list of output ports and their desired state after start<br>
  385. Without this atribut all output ports will set to last state<br>
  386. Default: -, valid values: &lt;port&gt;=on|off|last where &lt;port&gt; = 0 - 7<br><br>
  387. </li>
  388. <li><a href="#IODev">IODev</a></li>
  389. <li><a href="#ignore">ignore</a></li>
  390. <li><a href="#do_not_notify">do_not_notify</a></li>
  391. <li><a href="#showtime">showtime</a></li>
  392. </ul>
  393. <br>
  394. </ul>
  395. =end html
  396. =begin html_DE
  397. <a name="I2C_PCF8574"></a>
  398. <h3>I2C_PCF8574</h3>
  399. (<a href="commandref.html#I2C_PCF8574">en</a> | de)
  400. <ul>
  401. <a name="I2C_PCF8574"></a>
  402. Erm&ouml;glicht die Verwendung eines PCF8574 I2C 8 Bit Portexenders.
  403. Auf einem Raspberry Pi kann der Interrupt Pin des PCF8574 mit einem GPIO verbunden werden und &uml;ber die Interrupt Funktionen von <a href="#RPI_GPIO">RPI_GPIO</a> l&aml;sst sich dann ein get f&uuml;r den PCF8574 bei Pegel&aml;nderung ausl&oml;sen.<br>
  404. I2C-Botschaften werden &uuml;ber ein I2C Interface Modul wie beispielsweise das <a href="#RPII2C">RPII2C</a>, <a href="#FRM">FRM</a>
  405. oder <a href="#NetzerI2C">NetzerI2C</a> gesendet. Daher muss dieses vorher definiert werden.<br>
  406. <b>Das Attribut IODev muss definiert sein.</b><br>
  407. <a name="I2C_PCF8574Define"></a><br>
  408. <b>Define</b>
  409. <ul>
  410. <code>define &lt;name&gt; I2C_PCF8574 &lt;I2C Address&gt;</code><br>
  411. Der Wert <code>&lt;I2C Address&gt;</code> ist ohne das Richtungsbit<br>
  412. </ul>
  413. <a name="I2C_PCF8574Set"></a>
  414. <b>Set</b>
  415. <ul>
  416. <code>set &lt;name&gt; &lt;port[,port[...]]&gt; &lt;value&gt;</code><br><br>
  417. <ul>
  418. <li><code>&lt;port&gt;</code> kann Port0 bis Port7 annehmen und <code>&lt;value&gt;</code> folgende Werte:<br>
  419. <ul>
  420. <code>
  421. off<br>
  422. on<br>
  423. </code>
  424. </ul>
  425. </li>
  426. </ul>
  427. <br>
  428. Beispiel:
  429. <ul>
  430. <code>set mod1 Port4 on</code><br>
  431. <code>set mod1 Port4,Port6 off</code><br>
  432. <code>set mod1 Port4,6 on</code><br>
  433. </ul><br>
  434. </ul>
  435. <a name="I2C_PCF8574Get"></a>
  436. <b>Get</b>
  437. <ul>
  438. <code>get &lt;name&gt;</code>
  439. <br><br>
  440. Aktualisierung aller Werte
  441. </ul><br>
  442. <a name="I2C_PCF8574Attr"></a>
  443. <b>Attribute</b>
  444. <ul>
  445. <li>poll_interval<br>
  446. Aktualisierungsintervall aller Werte in Minuten.<br>
  447. Standard: -, g&uuml;ltige Werte: Dezimalzahl<br><br>
  448. </li>
  449. <li>InputPorts<br>
  450. Durch Leerzeichen getrennte Portnummern die als Inputs genutzt werden.<br>
  451. Ports in dieser Liste k&ouml;nnen nicht geschrieben werden.<br>
  452. Standard: no, g&uuml;ltige Werte: 0 1 2 .. 7<br><br>
  453. </li>
  454. <li>OnStartup<br>
  455. Durch Komma getrennte Output Ports und ihr gew&uuml;nschter Status nach dem Start.<br>
  456. Ohne dieses Attribut werden alle Ausg&auml;nge nach dem Start auf den letzten Status gesetzt.<br>
  457. Standard: -, g&uuml;ltige Werte: &lt;port&gt;=on|off|last wobei &lt;port&gt; = 0 - 7<br><br>
  458. </li>
  459. <li><a href="#IODev">IODev</a></li>
  460. <li><a href="#ignore">ignore</a></li>
  461. <li><a href="#do_not_notify">do_not_notify</a></li>
  462. <li><a href="#showtime">showtime</a></li>
  463. </ul>
  464. <br>
  465. </ul>
  466. =end html_DE
  467. =cut