00_TUL.pm 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359
  1. ##############################################
  2. # $Id: 00_TUL.pm 15260 2017-10-14 18:48:39Z andi291 $
  3. # ABU 20150916 removed print: simpleWriteDate, cleaned init
  4. # ABU 20150918 fixed deprecated warning, fixed warning related to hex-conversion in simple-write
  5. # ABU 20151123 added error-label in getGroup. Responsible for error-handling, if knxd is not accesible
  6. # ABU 20151213 changed message-check in decode_tpuart() to avoid ignore while receiving repeated messages
  7. # ABU 20160308 remoced set, get. Changed loglevel to verbose. Added KNX/EIB-Split. Added EIB-backward-compatibility.
  8. # ABU 20160309 fixed log2
  9. # ABU 20160310 repaired dispatch events - inform EIB, only is useEIB is set
  10. # ABU 20160515 removed compatibility flag for EIB
  11. # ABU 20160516 added log entry for non-compatibility of tul
  12. # ABU 20160613 changed log entry for startup
  13. # ABU 20161108 added knxd. Added doku as well. Added summary. Treat it like eibd. See thread #58375
  14. # ABU 20170102 fixed write-mechanism, added mod for extended adressing (thx to its2bit)
  15. # ABU 20170110 removed mod for extended adressing
  16. # ABU 20170427 reintegrated mechanism for extenden GAD-Support
  17. # ABU 20170427 cleaned logs
  18. # ABU 20171006 deactivated default-log-entry
  19. # ABU 20171006 EIB requires different handling of extended GAD --> added
  20. package main;
  21. use strict;
  22. use warnings;
  23. use Time::HiRes qw(gettimeofday);
  24. sub TUL_Attr(@);
  25. sub TUL_Clear($);
  26. sub TUL_Parse($$$$$);
  27. sub TUL_Read($);
  28. sub TUL_Ready($);
  29. sub TUL_Write($$$);
  30. sub TUL_OpenDev($$);
  31. sub TUL_CloseDev($);
  32. sub TUL_SimpleWrite(@);
  33. sub TUL_SimpleRead($);
  34. sub TUL_Disconnected($);
  35. sub TUL_Shutdown($);
  36. my %gets = ( # Name, Data to send to the TUL, Regexp for the answer
  37. "raw" => ["r", '.*'],
  38. );
  39. my %sets = (
  40. "raw" => "",
  41. );
  42. my $clients = ":KNX:EIB:";
  43. my %matchList = (
  44. "2:KNX" => "^C.*",
  45. "3:EIB" => "^B.*",
  46. );
  47. my $useEIB = '0';
  48. sub
  49. TUL_Initialize($)
  50. {
  51. my ($hash) = @_;
  52. # Provider
  53. $hash->{ReadFn} = "TUL_Read";
  54. $hash->{WriteFn} = "TUL_Write";
  55. $hash->{ReadyFn} = "TUL_Ready";
  56. # Normal devices
  57. $hash->{DefFn} = "TUL_Define";
  58. $hash->{UndefFn} = "TUL_Undef";
  59. $hash->{StateFn} = "TUL_SetState";
  60. $hash->{AttrFn} = "TUL_Attr";
  61. $hash->{AttrList}= "do_not_notify:1,0 " .
  62. "dummy:1,0 " .
  63. "showtime:1,0 " .
  64. "verbose:0,1,2,3,4,5 " .
  65. "useEIB:1,0 ";
  66. $hash->{ShutdownFn} = "TUL_Shutdown";
  67. }
  68. #####################################
  69. sub
  70. TUL_Define($$)
  71. {
  72. my ($hash, $def) = @_;
  73. my @a = split("[ \t][ \t]*", $def);
  74. if(@a < 4)
  75. {
  76. my $msg = "wrong syntax: define <name> TUL <devicename> <device addr> [<line def in hex>]";
  77. return $msg;
  78. }
  79. TUL_CloseDev($hash);
  80. my $name = $a[0];
  81. my $dev = $a[2];
  82. my $devaddr = tul_str2hex($a[3]);
  83. my $linedef = substr(tul_str2hex($a[4]),0,2) if(@a > 4);
  84. if($dev eq "none")
  85. {
  86. Log3 ($name, 1, "device is none, commands will be echoed only");
  87. $attr{$name}{dummy} = 1;
  88. return undef;
  89. }
  90. #Set attributes in order to control backward-compatibility
  91. #$attr{$name}{useEIB} = 1;
  92. #Log3 ($name, 0, "Using EIB is deprecated. Please migrate to KNX soon. Module 10_EIB is not maintained any longer. If you still want to use the module EIB,
  93. #please set the attribute useEIB to 1 within the tul-device. Please keep in mind, that 10_KNX has a changed syntax regarding the definition, arguments and readings. Please refer to the commandref.
  94. #As well 10_EIB and 10_KNX are compatible to daemon eibd and knxd.") if (AttrVal($name, "useEIB", 0) =~ m/0/);
  95. $hash->{DeviceName} = $dev;
  96. $hash->{DeviceAddress} = $devaddr;
  97. $hash->{Clients} = $clients;
  98. $hash->{MatchList} = \%matchList;
  99. $hash->{AckLineDef}= $linedef;
  100. my $ret = TUL_OpenDev($hash, 0);
  101. return $ret;
  102. }
  103. #####################################
  104. sub
  105. TUL_Undef($$)
  106. {
  107. my ($hash, $arg) = @_;
  108. my $name = $hash->{NAME};
  109. foreach my $d (sort keys %defs)
  110. {
  111. if(defined($defs{$d}) && defined($defs{$d}{IODev}) && $defs{$d}{IODev} == $hash)
  112. {
  113. my $lev = ($reread_active ? 4 : 2);
  114. Log(GetLogLevel($name,$lev), "deleting port for $d");
  115. delete $defs{$d}{IODev};
  116. }
  117. }
  118. TUL_CloseDev($hash);
  119. return undef;
  120. }
  121. #####################################
  122. sub TUL_Shutdown($)
  123. {
  124. my ($hash) = @_;
  125. TUL_CloseDev($hash);
  126. return undef;
  127. }
  128. #####################################
  129. sub
  130. TUL_SetState($$$$)
  131. {
  132. my ($hash, $tim, $vt, $val) = @_;
  133. return undef;
  134. }
  135. sub
  136. TUL_Clear($)
  137. {
  138. my $hash = shift;
  139. #Clear the pipe
  140. #TUL has no pipe....
  141. }
  142. #####################################
  143. sub
  144. TUL_DoInit($)
  145. {
  146. my $hash = shift;
  147. my $name = $hash->{NAME};
  148. my $err;
  149. TUL_Clear($hash);
  150. # send any initializing request if needed
  151. # TODO move to device init
  152. return 1 unless openGroupSocket($hash);
  153. # reset buffer
  154. purgeReceiverBuf($hash);
  155. $hash->{STATE} = "Initialized" if(!$hash->{STATE});
  156. # Reset the counter
  157. delete($hash->{XMIT_TIME});
  158. delete($hash->{NR_CMD_LAST_H});
  159. return undef;
  160. }
  161. #####################################
  162. sub
  163. TUL_Write($$$)
  164. {
  165. my ($hash,$fn,$msg) = @_;
  166. my $name = $hash->{NAME};
  167. return if(!defined($fn));
  168. #Discard message, if not set to backward-compatibility
  169. if (($useEIB =~ m/0/) and ($fn =~ m/\^B/))
  170. {
  171. Log3 ($name, 0, "EIB is no longer supported. Message discarded.");
  172. return;
  173. }
  174. Log3 ($name, 5, "sending $fn$msg");
  175. my $bstring = "$fn$msg";
  176. TUL_SimpleWrite($hash, $bstring);
  177. }
  178. #####################################
  179. # called from the global loop, when the select for hash->{FD} reports data
  180. sub
  181. TUL_Read($)
  182. {
  183. my ($hash) = @_;
  184. #reset the refused flag, so we can check if a telegram was refused
  185. # and therefor we did not get a response
  186. $hash->{REFUSED} = undef;
  187. my $buf = TUL_SimpleRead($hash);
  188. my $name = $hash->{NAME};
  189. # check if refused
  190. if(defined($hash->{REFUSED}))
  191. {
  192. Log3 ($name, 3,"TUL $name refused message: $hash->{REFUSED}");
  193. $hash->{REFUSED} = undef;
  194. return "";
  195. }
  196. ###########
  197. # Lets' try again: Some drivers return len(0) on the first read...
  198. if(defined($buf) && length($buf) == 0)
  199. {
  200. $buf = TUL_SimpleRead($hash);
  201. }
  202. if(!defined($buf) || length($buf) == 0)
  203. {
  204. TUL_Disconnected($hash);
  205. return "";
  206. }
  207. #place KNX-Message
  208. TUL_Parse($hash, $hash, $name, "B".$buf, $hash->{initString}) if ($useEIB =~ m/1/);
  209. #place EIB-Message
  210. TUL_Parse($hash, $hash, $name, "C".$buf, $hash->{initString});
  211. }
  212. sub
  213. TUL_Parse($$$$$)
  214. {
  215. my ($hash, $iohash, $name, $rmsg, $initstr) = @_;
  216. # there is nothing specal to do at the moment.
  217. # just dispatch
  218. my $dmsg = $rmsg;
  219. Log3 ($name, 4, "$name: $dmsg");
  220. $hash->{"${name}_MSGCNT"}++;
  221. $hash->{"${name}_TIME"} = TimeNow();
  222. $hash->{RAWMSG} = $rmsg;
  223. my %addvals = (RAWMSG => $rmsg);
  224. Dispatch($hash, $dmsg, \%addvals);
  225. }
  226. #####################################
  227. sub
  228. TUL_Ready($)
  229. {
  230. my ($hash) = @_;
  231. return TUL_OpenDev($hash, 1) if($hash->{STATE} eq "disconnected");
  232. # This is relevant for windows/USB only
  233. my $po = $hash->{USBDev};
  234. my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status;
  235. return ($InBytes>0);
  236. }
  237. ########################
  238. sub
  239. TUL_SimpleWrite(@)
  240. {
  241. my ($hash, $msg) = @_;
  242. return if(!$hash);
  243. # Msg must have the format B(w,r,p)g1g2g3v....
  244. # w-> write, r-> read, p-> reply
  245. # g1,g2,g3 are the hex parts of the group name
  246. # v is a simple (1 Byte) or complex value (n bytes)
  247. # For eibd we need a more elaborate structure
  248. # Old
  249. #if($msg =~ /^[BC](.)(.{4})(.*)$/)
  250. # New: its2bit
  251. #if($msg =~ /^[BC](.)(.{5})(.*)$/)
  252. #extended adressing
  253. if ((($useEIB =~ m/1/) and ($msg =~ /^[BC](.)(.{4})(.*)$/)) or (($useEIB =~ m/0/) and ($msg =~ /^[BC](.)(.{5})(.*)$/)))
  254. {
  255. my $eibmsg;
  256. if($1 eq "w")
  257. {
  258. $eibmsg->{'type'} = 'write';
  259. }
  260. elsif ($1 eq "r")
  261. {
  262. $eibmsg->{'type'} = 'read';
  263. }
  264. elsif ($1 eq "p")
  265. {
  266. $eibmsg->{'type'} = 'reply';
  267. }
  268. $eibmsg->{'dst'} = $2;
  269. my $hexvalues = $3;
  270. #The array has to have a given length. During Hex-conversion Trailing
  271. #0 are recognizes for warnings.
  272. #Therefore we backup the length, trim, and reappend the 0
  273. #
  274. #save length and trim right side
  275. my $strLen = length ($hexvalues) / 2;
  276. $hexvalues =~ s/\s+$//;
  277. #convert hex-string to array with dezimal values
  278. my @data = map hex($_), $hexvalues =~ /(..)/g;
  279. #re-append 0x00
  280. for (my $i=0; $strLen - scalar @data; $i++)
  281. {
  282. push (@data, 0);
  283. }
  284. # check: first byte is only allowed to contain data in the lower 6bits
  285. # to make sure all is fine, we mask the first byte
  286. $data[0] = $data[0] & 0x3f if(defined($data[0]));
  287. $eibmsg->{'data'} = \@data;
  288. sendGroup($hash, $eibmsg);
  289. }
  290. else
  291. {
  292. Log3 ($hash->{NAME}, 1,"Could not parse message $msg");
  293. return undef;
  294. }
  295. select(undef, undef, undef, 0.001);
  296. }
  297. ########################
  298. sub
  299. TUL_SimpleRead($)
  300. {
  301. my ($hash) = @_;
  302. my $name = $hash->{NAME};
  303. my $msg = getGroup($hash);
  304. if(!defined($msg))
  305. {
  306. Log3 ($name, 4,"No data received.") ;
  307. return undef;
  308. }
  309. my $type = $msg->{'type'};
  310. my $dst = $msg->{'dst'};
  311. my $src = $msg->{'src'};
  312. my @bindata = @{$msg->{'data'}};
  313. my $data = "";
  314. # convert bin data to hex
  315. foreach my $c (@bindata)
  316. {
  317. $data .= sprintf ("%02x", $c);
  318. }
  319. Log3 ($name, 5, "SimpleRead msg.type: $type, msg.src: $msg->{'src'}, msg.dst: $msg->{'dst'}");
  320. Log3 ($name, 5, "SimpleRead data: $data");
  321. # we will build a string like:
  322. # Bs1s2s3(w|r|p)g1g2g3v
  323. # s -> src
  324. my $buf;
  325. #$buf = "C$src";
  326. $buf = $src;
  327. if($type eq "write")
  328. {
  329. $buf .= "w";
  330. }
  331. elsif ($type eq "read")
  332. {
  333. $buf .= "r";
  334. }
  335. else
  336. {
  337. $buf .= "p";
  338. }
  339. $buf .= $dst;
  340. $buf .= $data;
  341. Log(4,"SimpleRead: $buf\n");
  342. return $buf;
  343. }
  344. ########################
  345. sub
  346. TUL_CloseDev($)
  347. {
  348. my ($hash) = @_;
  349. my $name = $hash->{NAME};
  350. my $dev = $hash->{DeviceName};
  351. return if(!$dev);
  352. if($hash->{TCPDev})
  353. {
  354. $hash->{TCPDev}->close();
  355. delete($hash->{TCPDev});
  356. }
  357. elsif($hash->{USBDev})
  358. {
  359. $hash->{USBDev}->close() ;
  360. delete($hash->{USBDev});
  361. }
  362. delete($selectlist{"$name.$dev"});
  363. delete($readyfnlist{"$name.$dev"});
  364. delete($hash->{FD});
  365. }
  366. ########################
  367. sub
  368. TUL_OpenDev($$)
  369. {
  370. my ($hash, $reopen) = @_;
  371. my $dev = $hash->{DeviceName};
  372. my $name = $hash->{NAME};
  373. my $po;
  374. $hash->{PARTIAL} = "";
  375. Log 3, "TUL opening $name device $dev" if(!$reopen);
  376. # eibd:host[:port]
  377. #if($dev =~ m/^(eibd):(.+)$/)
  378. if($dev =~ m/^(eibd|knxd):(.+)$/)
  379. {
  380. my $host = $2;
  381. my $port = 6720;
  382. #host:port
  383. if($host =~ m/^(.+):([0-9]+)$/)
  384. {
  385. $host = $1;
  386. $port = $2;
  387. }
  388. # This part is called every time the timeout (5sec) is expired _OR_
  389. # somebody is communicating over another TCP connection. As the connect
  390. # for non-existent devices has a delay of 3 sec, we are sitting all the
  391. # time in this connect. NEXT_OPEN tries to avoid this problem.
  392. return if($hash->{NEXT_OPEN} && time() < $hash->{NEXT_OPEN});
  393. my $conn = IO::Socket::INET->new(PeerAddr => $host, PeerPort => $port,Proto => 'tcp');
  394. if($conn)
  395. {
  396. delete($hash->{NEXT_OPEN})
  397. }
  398. else
  399. {
  400. Log3 ($name, 3, "Can't connect to $dev: $!") if(!$reopen);
  401. $readyfnlist{"$name.$dev"} = $hash;
  402. $hash->{STATE} = "disconnected";
  403. $hash->{NEXT_OPEN} = time()+60;
  404. return "";
  405. }
  406. $hash->{DevType} = 'EIBD';
  407. $hash->{TCPDev} = $conn;
  408. $hash->{FD} = $conn->fileno();
  409. delete($readyfnlist{"$name.$dev"});
  410. $selectlist{"$name.$dev"} = $hash;
  411. }
  412. # tpuart:ttydev[@baudrate] / USB/Serial device
  413. elsif ($dev =~ m/^(tul|tpuart):(.+)$/)
  414. {
  415. my $dev = $2;
  416. my $baudrate;
  417. ($dev, $baudrate) = split("@", $dev);
  418. $baudrate = 19200 if(!$baudrate); # fix for TUL board
  419. if ($^O=~/Win/)
  420. {
  421. require Win32::SerialPort;
  422. $po = new Win32::SerialPort ($dev);
  423. } else
  424. {
  425. require Device::SerialPort;
  426. $po = new Device::SerialPort ($dev);
  427. }
  428. if(!$po)
  429. {
  430. return undef if($reopen);
  431. Log3 ($name, 3, "Can't open $dev: $!");
  432. $readyfnlist{"$name.$dev"} = $hash;
  433. $hash->{STATE} = "disconnected";
  434. return "";
  435. }
  436. $hash->{DevType} = 'TPUART';
  437. $hash->{USBDev} = $po;
  438. if( $^O =~ /Win/ )
  439. {
  440. $readyfnlist{"$name.$dev"} = $hash;
  441. }
  442. else
  443. {
  444. $hash->{FD} = $po->FILENO;
  445. delete($readyfnlist{"$name.$dev"});
  446. $selectlist{"$name.$dev"} = $hash;
  447. }
  448. # assumed always available
  449. if($baudrate)
  450. {
  451. $po->reset_error();
  452. Log3 ($name, 3, "TUL setting $name baudrate to $baudrate");
  453. $po->baudrate($baudrate);
  454. $po->databits(8);
  455. $po->parity('even');
  456. $po->stopbits(1);
  457. $po->handshake('none');
  458. # This part is for some Linux kernel versions which has strange default
  459. # settings. Device::SerialPort is nice: if the flag is not defined for your
  460. # OS then it will be ignored.
  461. $po->stty_icanon(0);
  462. #$po->stty_parmrk(0); # The debian standard install does not have it
  463. $po->stty_icrnl(0);
  464. $po->stty_echoe(0);
  465. $po->stty_echok(0);
  466. $po->stty_echoctl(0);
  467. # Needed for some strange distros
  468. $po->stty_echo(0);
  469. $po->stty_icanon(0);
  470. $po->stty_isig(0);
  471. $po->stty_opost(0);
  472. $po->stty_icrnl(0);
  473. }
  474. $po->write_settings;
  475. }
  476. # No more devices supported now
  477. else
  478. {
  479. Log3 ($name, 1, "$dev protocol is not supported");
  480. }
  481. if($reopen)
  482. {
  483. Log3 ($name, 1, "TUL $dev reappeared ($name)");
  484. }
  485. else
  486. {
  487. Log3 ($name, 3, "TUL device opened");
  488. }
  489. $hash->{STATE}=""; # Allow InitDev to set the state
  490. my $ret = TUL_DoInit($hash);
  491. if($ret)
  492. {
  493. TUL_CloseDev($hash);
  494. Log (1, "Cannot init $dev, ignoring it");
  495. }
  496. DoTrigger($name, "CONNECTED") if($reopen);
  497. return $ret;
  498. }
  499. ########################
  500. sub
  501. TUL_Disconnected($)
  502. {
  503. my $hash = shift;
  504. my $dev = $hash->{DeviceName};
  505. my $name = $hash->{NAME};
  506. return if(!defined($hash->{FD})); # Already deleted or RFR
  507. Log3 ($name, 1, "$dev disconnected, waiting to reappear");
  508. TUL_CloseDev($hash);
  509. $readyfnlist{"$name.$dev"} = $hash; # Start polling
  510. $hash->{STATE} = "disconnected";
  511. # Without the following sleep the open of the device causes a SIGSEGV,
  512. # and following opens block infinitely. Only a reboot helps.
  513. sleep(5);
  514. DoTrigger($name, "DISCONNECTED");
  515. }
  516. ########################
  517. sub
  518. TUL_Attr(@)
  519. {
  520. my ($cmd,$name,$aName,$aVal) = @_;
  521. Log3 ($name, 5, "changing value, ATTR: $aName, VALUE: $aVal");
  522. if ($aName =~ m/useEIB/)
  523. {
  524. if ($aVal =~ m/1/)
  525. {
  526. $useEIB = '1';
  527. }
  528. else
  529. {
  530. $useEIB = '0';
  531. }
  532. }
  533. return undef;
  534. }
  535. ####################################################################################
  536. ####################################################################################
  537. #
  538. #
  539. # The following section has been inspired by the EIB module from MrHouse project
  540. # written by Peter Sj?din peter@sjodin.net and Mike Pieper eibdmh@pieper-family.de
  541. # Code has been mainly changed to fit to the FHEM framework by Maz Rashid
  542. # (to be honest the code had to be reworked very intensively due the lack of code quality)
  543. #
  544. # Utility functions
  545. sub tul_hex2addr
  546. {
  547. my $str = lc($_[0]);
  548. # Old
  549. #if ($str =~ /([0-9a-f])([0-9a-f])([0-9a-f]{2})/)
  550. # New its2bit
  551. #if ($str =~ /([0-9a-f]{2})([0-9a-f])([0-9a-f]{2})/)
  552. #extended adressing
  553. if ((($useEIB =~ m/1/) and ($str =~ /([0-9a-f])([0-9a-f])([0-9a-f]{2})/)) or (($useEIB =~ m/0/) and ($str =~ /([0-9a-f]{2})([0-9a-f])([0-9a-f]{2})/)))
  554. {
  555. return (hex($1) << 11) | (hex($2) << 8) | hex($3);
  556. }
  557. else
  558. {
  559. Log(3,"Bad EIB address string: \'$str\'\n");
  560. return;
  561. }
  562. }
  563. sub tul_addr2hex
  564. {
  565. my $a = $_[0];
  566. my $b = $_[1]; # 1 if local (group) address, else physical address
  567. my $str ;
  568. if ($b == 1)
  569. {
  570. #logical address used
  571. #old, short-syntax
  572. #$str = sprintf "%01x%01x%02x", ($a >> 11) & 0xf, ($a >> 8) & 0x7, $a & 0xff;
  573. #extended adress-range
  574. #$str = sprintf "%02x%01x%02x", ($a >> 11) & 0x1f, ($a >> 8) & 0x7, $a & 0xff;
  575. #extended adressing
  576. if ($useEIB =~ m/1/)
  577. {
  578. $str = sprintf "%01x%01x%02x", ($a >> 11) & 0xf, ($a >> 8) & 0x7, $a & 0xff;
  579. }
  580. else
  581. {
  582. $str = sprintf "%02x%01x%02x", ($a >> 11) & 0x1f, ($a >> 8) & 0x7, $a & 0xff;
  583. }
  584. }
  585. else
  586. {
  587. #physical address used
  588. # Old
  589. # $str = sprintf "%01x%01x%02x", $a >> 12, ($a >> 8) & 0xf, $a & 0xff;
  590. # New
  591. #$str = sprintf "%02x%01x%02x", $a >> 12, ($a >> 8) & 0xf, $a & 0xff;
  592. #extended adressing
  593. if ($useEIB =~ m/1/)
  594. {
  595. $str = sprintf "%01x%01x%02x", $a >> 12, ($a >> 8) & 0xf, $a & 0xff;
  596. }
  597. else
  598. {
  599. $str = sprintf "%02x%01x%02x", $a >> 12, ($a >> 8) & 0xf, $a & 0xff;
  600. }
  601. }
  602. return $str;
  603. }
  604. sub tul_str2hex
  605. {
  606. my $str = $_[0];
  607. my $hex;
  608. if (($str =~ /(\d+)\/(\d+)\/(\d+)/) or ($str =~ /(\d+)\.(\d+)\.(\d+)/))
  609. {
  610. # logical address
  611. # old
  612. # my $hex = sprintf("%01x%01x%02x",$1,$2,$3);
  613. # New
  614. #my $hex = sprintf("%02x%01x%02x",$1,$2,$3);
  615. #extended adressing
  616. if ($useEIB =~ m/1/)
  617. {
  618. $hex = sprintf("%01x%01x%02x",$1,$2,$3);
  619. }
  620. else
  621. {
  622. $hex = sprintf("%02x%01x%02x",$1,$2,$3);
  623. }
  624. return $hex;
  625. }
  626. }
  627. # For mapping between APCI symbols and values
  628. my @apcicodes = ('read', 'reply', 'write');
  629. my %apcivalues = ('read' => 0, 'reply' => 1, 'write' => 2,);
  630. # decode: unmarshall a string with an EIB message into a hash
  631. # The hash has the follwing fields:
  632. # - type: APCI (symbolic value)
  633. # - src: source address
  634. # - dst: destiniation address
  635. # - data: array of integers; one for each byte of data
  636. sub decode_eibd($)
  637. {
  638. my ($buf) = @_;
  639. my $drl = 0xe1; # dummy value
  640. my %msg;
  641. my @data;
  642. my ($src, $dst,$bytes) = unpack("nnxa*", $buf);
  643. my $apci;
  644. $apci = vec($bytes, 3, 2);
  645. # mask out apci bits, so we can use the whole byte as data:
  646. vec($bytes, 3, 2) = 0;
  647. if ($apci >= 0 && $apci <= $#apcicodes)
  648. {
  649. $msg{'type'} = $apcicodes[$apci];
  650. }
  651. else
  652. {
  653. $msg{'type'} = 'apci ' . $apci;
  654. }
  655. $msg{'src'} = tul_addr2hex($src,0);
  656. $msg{'dst'} = tul_addr2hex($dst,1);
  657. @data = unpack ("C" . length($bytes), $bytes);
  658. my $datalen = @data;
  659. Log (5, "decode_eibd byte len: " . length($bytes) . " array size: $datalen");
  660. # in case of data len > 1, the first byte (the one with apci) seems not to be used
  661. # and only the following byte are of interest.
  662. if($datalen>1)
  663. {
  664. shift @data;
  665. }
  666. $msg{'data'} = \@data;
  667. return \%msg;
  668. }
  669. # encode: marshall a hash into a EIB message string
  670. sub encode_eibd($)
  671. {
  672. my ($mref) = @_;
  673. my @msg;
  674. my $APCI;
  675. my @data;
  676. $APCI = $apcivalues{$mref->{'type'}};
  677. if (!(defined $APCI))
  678. {
  679. Log(3,"Bad EIB message type $mref->{'type'}\n");
  680. return;
  681. }
  682. @data = @{$mref->{'data'}};
  683. @data = (0x0) if(!@data || !defined($data[0])); #make sure data has at least one element
  684. #@data = (0x0) if(!(defined @data) || !(defined $data[0])); #make sure data has at least one element
  685. my $datalen = @data;
  686. Log (5,"encode_eibd dst: $mref->{'dst'} apci: $APCI datalen: $datalen data: @data");
  687. @msg = (
  688. tul_hex2addr( $mref->{'dst'}), # Destination address
  689. 0x0 | ($APCI >> 2), # TPDU type, Sequence no, APCI (msb)
  690. (($APCI & 0x3) << 6) | $data[0],
  691. );
  692. if ($datalen > 1)
  693. {
  694. shift(@data);
  695. push @msg, @data;
  696. }
  697. return @msg;
  698. }
  699. # decode: unmarshall a string with an EIB telegram into a hash
  700. # A typical telegram looks like: bc110a0002e100813a
  701. # checks:
  702. # - 1st byte must have at least the bits $90 set. (otherwise it is false or a repeat)
  703. # - 2nd/3rd byte are the source (1.1.10)
  704. # - 4th/5th byte are the dst group (0/0/2)
  705. # - 6th byte (msb if 1 dst is group, else a phys. address )
  706. # - low nibble is length of data (counting from 0) (->2)
  707. # - 7th byte is ignored
  708. # - 8th byte is the command / short data byte
  709. # - if 8th byte >>6 is 0 -> read
  710. # - is 2 -> write
  711. # - is 1 -> reply
  712. # - if length is 2 -> 8th byte & 0x3F is data
  713. # otherwise data start after 8th byte
  714. # - last byte is the crc (ignored)
  715. # The hash has the follwing fields:
  716. # - type: APCI (symbolic value)
  717. # - src: source address
  718. # - dst: destiniation address
  719. # - data: array of integers; one for each byte of data
  720. sub decode_tpuart($)
  721. {
  722. my ($buf) = @_;
  723. my ($ctrl,$src, $dst, $routingcnt,$cmd, $bytes) = unpack("CnnCxCa*", $buf);
  724. my $drl = $routingcnt >>7;
  725. my $len = ($routingcnt & 0x0F) +1;
  726. #if(($ctrl & 0xB0)!=0xB0)
  727. if(($ctrl & 0x90)!=0x90)
  728. {
  729. Log (3,"Control Byte " . sprintf("0x%02x",$ctrl) . " does not match expected mask 2x1001nnnn");
  730. return undef;
  731. }
  732. Log (5,"msg cmd: " . sprintf("0x%02x",$cmd) ." datalen: $len");
  733. my $apci = ($cmd >> 6) & 0x0F;
  734. if($len == 2)
  735. { # 1 byte data
  736. $bytes = pack("C",$cmd & 0x3F);
  737. }
  738. Log (5,"msg cmd: " . sprintf("0x%02x",$cmd) ." datalen: $len apci: $apci");
  739. my %msg;
  740. my @data;
  741. if ($apci >= 0 && $apci <= $#apcicodes)
  742. {
  743. $msg{'type'} = $apcicodes[$apci];
  744. }
  745. else
  746. {
  747. $msg{'type'} = 'apci ' . $apci;
  748. }
  749. $msg{'src'} = tul_addr2hex($src,0);
  750. $msg{'dst'} = tul_addr2hex($dst,$drl);
  751. @data = unpack ("C" . length($bytes), $bytes);
  752. my $datalen = @data;
  753. Log (5, "decode_tpuart byte len: " . length($bytes) . " array size: $datalen");
  754. $msg{'data'} = \@data;
  755. return \%msg;
  756. }
  757. # encode: marshall a hash into a EIB message string
  758. sub encode_tpuart($)
  759. {
  760. my ($mref) = @_;
  761. my @msg;
  762. my $APCI;
  763. my @data;
  764. $APCI = $apcivalues{$mref->{'type'}};
  765. if (!(defined $APCI))
  766. {
  767. Log (3,"Bad EIB message type $mref->{'type'}\n");
  768. return;
  769. }
  770. @data = @{$mref->{'data'}};
  771. my $datalen = @data;
  772. if($datalen > 14)
  773. {
  774. Log (3,"Bad EIB message length $datalen\n");
  775. return;
  776. }
  777. Log (5,"encode_tpuart dst: $mref->{'dst'} apci: $APCI datalen: $datalen data: @data");
  778. @msg = (
  779. 0xBC, # EIB ctrl byte
  780. tul_hex2addr($mref->{'src'}), # src address
  781. tul_hex2addr( $mref->{'dst'}), # Destination address
  782. 0xE0 | $datalen, # Routing counter + data len
  783. 0x00,
  784. (($APCI & 0x3) << 6) | $data[0],
  785. );
  786. if ($datalen > 1)
  787. {
  788. shift(@data);
  789. push @msg, @data;
  790. }
  791. # convert to byte array
  792. my $arraystr = pack("CnnC*",@msg);
  793. @msg = unpack("C*",$arraystr);
  794. my @tpuartmsg;
  795. # calculate crc
  796. my $crc = 0xFF;
  797. my $i;
  798. for($i=0; $i<@msg;$i++)
  799. {
  800. $crc ^= $msg[$i];
  801. push @tpuartmsg,(0x80 | $i);
  802. push @tpuartmsg, $msg[$i];
  803. }
  804. push @tpuartmsg,(0x40 | $i);
  805. push @tpuartmsg,$crc;
  806. return @tpuartmsg;
  807. }
  808. #
  809. # eibd communication part
  810. #
  811. # Functions four group socket communication
  812. # Open a group socket for group communication
  813. # openGroupSocket SOCK
  814. sub openGroupSocket($)
  815. {
  816. my $hash = shift;
  817. ## only needed if EIBD
  818. if($hash->{DevType} eq 'EIBD')
  819. {
  820. my @msg = (0x0026,0x0000,0x00); # EIB_OPEN_GROUPCON
  821. sendRequest ($hash, pack "nnC" ,@msg);
  822. goto error unless my $answer = getRequest($hash);
  823. my $head = unpack ("n", $answer);
  824. goto error unless $head == 0x0026;
  825. }
  826. return 1;
  827. error:
  828. print "openGroupSocket failed\n";
  829. return undef;
  830. }
  831. # Send group data
  832. # sendGroup Hash DEST DATA
  833. sub sendGroup($$)
  834. {
  835. my ($hash,$msgref) = @_;
  836. my $dst = $msgref->{'dst'};
  837. my $src = $hash->{DeviceAddress};
  838. $msgref->{'src'} = $src;
  839. if($hash->{DevType} eq 'EIBD')
  840. {
  841. my @encmsg = encode_eibd($msgref);
  842. Log (5,"SendGroup: dst: $dst, msg: @encmsg \n");
  843. my @msg = (0x0027); # EIB_GROUP_PACKET
  844. push @msg, @encmsg;
  845. sendRequest($hash, pack("nnCC*", @msg));
  846. }
  847. elsif($hash->{DevType} eq 'TPUART')
  848. {
  849. my @encmsg = encode_tpuart($msgref);
  850. Log (5,"SendGroup: dst: $dst, msg: @encmsg \n");
  851. sendRequest($hash, pack("C*", @encmsg));
  852. my $response = getRequestFixLength($hash,($#encmsg + 1)/2+1);
  853. }
  854. return 1;
  855. }
  856. # will read as much byte as exists at the
  857. # serial buffer.
  858. sub purgeReceiverBuf($)
  859. {
  860. my ($hash) = @_;
  861. if($hash->{DevType} eq 'TPUART')
  862. {
  863. Log (5,"purging receiver buffer ");
  864. my $data = undef;
  865. do
  866. {
  867. my(undef,$data) = $hash->{USBDev}->read(100);
  868. Log (5,"purging packet: ". unpack("H*",$data) . "\n") if(defined($data) and length($data)>0);
  869. } while(defined($data) and length($data)>0)
  870. }
  871. }
  872. sub getRequestFixLength($$)
  873. {
  874. my ($hash, $len) = @_;
  875. if($hash->{DevType} eq 'TPUART')
  876. {
  877. Log (5,"waiting to receive $len bytes ...");
  878. my $buf = "";
  879. while(length($buf)<$len)
  880. {
  881. #select(undef,undef,undef,0.5);
  882. my (undef,$data) = $hash->{USBDev}->read($len-length($buf));
  883. Log (5,"Received fixlen packet: ". unpack("H*",$data) . "\n") if(defined($data) and length($data)>0);
  884. $buf .= $data if(defined($data));
  885. #Log (5,"buf len: " . length($buf) . " expected: $len");
  886. # TODO: if we are longer than 5 seconds here, we should reset
  887. }
  888. # # we got more than needed
  889. if(length($buf)>$len)
  890. {
  891. #check if this is ok
  892. my $remainpart = substr($buf,$len);
  893. $hash->{PARTIAL} .= $remainpart;
  894. $buf = substr($buf,0,$len);
  895. Log (5,"we got too much.. buf(" .unpack("H*",$buf).") remainingpart(" .unpack("H*",$remainpart).")");
  896. }
  897. Log (5,"getRequest len: $len packet: ". unpack("H*",$buf) . "\n");
  898. return $buf;
  899. }
  900. return undef;
  901. }
  902. # Receive group data
  903. # getGroup hash
  904. sub getGroup($)
  905. {
  906. my $hash = shift;
  907. if($hash->{DevType} eq 'EIBD')
  908. {
  909. goto error unless my $buf = getRequest($hash);
  910. my ($head, $data) = unpack ("na*", $buf);
  911. goto error unless $head == 0x0027;
  912. return decode_eibd($data);
  913. }
  914. elsif($hash->{DevType} eq 'TPUART')
  915. {
  916. my $ackdst = $hash->{AckLineDef};
  917. my $buf = $hash->{PARTIAL};
  918. my $reqlen = 8;
  919. my $telegram;
  920. do
  921. {
  922. my $data = getRequestFixLength($hash,$reqlen-length($buf)) if($reqlen>length($buf));
  923. if(length($buf)==0 && (!defined($data)||length($data)==0))
  924. {
  925. Log (5,"read fix length delivered no data.");
  926. return undef;
  927. }
  928. $buf .= $data if(defined($data));
  929. # check that control byte is correct
  930. my $ctrl = unpack("C",$buf) if(length($buf)>0);
  931. if(defined($ctrl) && ($ctrl&0x40) )
  932. {
  933. $buf = substr($buf,1);
  934. $hash->{PARTIAL} = $buf;
  935. Log (5,"TPUART RSP " . sprintf("0x%02x",$ctrl) ." ignored.");
  936. return undef;
  937. }
  938. if(length($buf)>5)
  939. {
  940. my $routingcnt = unpack("xxxxxC", $buf);
  941. $reqlen = ($routingcnt & 0x0F)+8;
  942. Log (5,"receiving telegram with len: $reqlen");
  943. }
  944. if($reqlen <= length($buf))
  945. {
  946. $telegram = substr($buf,0,$reqlen-1);
  947. $buf = substr($buf,$reqlen);
  948. }
  949. }
  950. while(!defined($telegram));
  951. Log (5, "Telegram: (".length($telegram)."): " . unpack("H*",$telegram));
  952. Log (5, "Buf: (".length($buf)."): " . unpack("H*",$buf));
  953. $hash->{PARTIAL} = $buf;
  954. my $msg = decode_tpuart($telegram);
  955. #check if we refused a telegram (i.e. repeats)
  956. $hash->{REFUSED} = unpack("H*",$telegram) if(!defined($msg));
  957. # We are always too late for Ack
  958. # if(defined($msg) && (substr($msg->{'dst'},0,2) eq $ackdst))
  959. # {
  960. # # ACK
  961. # sendRequest($hash,pack('C',0x11));
  962. # Log (5,"Ack!");
  963. # }
  964. return $msg;
  965. }
  966. Log (2,"DevType $hash->{DevType} not supported for getGroup\n");
  967. return undef;
  968. error:
  969. print "seems like eibd not connected\n";
  970. return undef;
  971. }
  972. # Gets a request from eibd
  973. # DATA = getRequest SOCK
  974. sub getRequest($)
  975. {
  976. my $hash = shift;
  977. my ($data);
  978. if($hash->{TCPDev} && $hash->{DevType} eq 'EIBD')
  979. {
  980. goto error unless sysread($hash->{TCPDev}, $data, 2);
  981. my $size = unpack ("n", $data);
  982. goto error unless sysread($hash->{TCPDev}, $data, $size);
  983. Log (5,"Received packet: ". unpack("H*",$data) . "\n");
  984. return $data;
  985. }
  986. elsif($hash->{USBDev}) {
  987. my $data = $hash->{USBDev}->input();
  988. Log (5,"Received packet: ". unpack("H*",$data) . "\n") if(defined($data) and length($data)>0);
  989. return $data;
  990. }
  991. Log (1,"TUL $hash->{NAME}: can not select a source for reading data.");
  992. return undef;
  993. error:
  994. printf "eibd communication failed\n";
  995. return undef;
  996. }
  997. # Sends a request to eibd
  998. # sendRequest Hash,DATA
  999. sub sendRequest($$)
  1000. {
  1001. my ($hash,$str) = @_;
  1002. Log (5,"sendRequest: ". unpack("H*",$str). "\n");
  1003. if($hash->{TCPDev})
  1004. {
  1005. my $size = length($str);
  1006. my @head = (($size >> 8) & 0xff, $size & 0xff);
  1007. return undef unless syswrite($hash->{TCPDev},pack("CC", @head));
  1008. return undef unless syswrite($hash->{TCPDev}, $str);
  1009. }
  1010. elsif($hash->{USBDev})
  1011. {
  1012. $hash->{USBDev}->write($str);
  1013. }
  1014. else
  1015. {
  1016. Log (2,"TUL $hash->{NAME}: No known physical protocoll defined.");
  1017. return undef;
  1018. }
  1019. return 1;
  1020. }
  1021. 1;
  1022. =pod
  1023. =begin html
  1024. <a name="TUL"></a>
  1025. <h3>TUL</h3>
  1026. <ul>
  1027. <table>
  1028. <tr><td>
  1029. The TUL module is the representation of a EIB / KNX connector in FHEM.
  1030. <a href="#KNX">KNX</a> instances represent the EIB / KNX devices and will need a TUL as IODev to communicate with the EIB / KNX network.<br>
  1031. The TUL module is designed to connect to EIB network either using eibd, knxd or the <a href="http://busware.de/tiki-index.php?page=TUL" target="_blank">TUL usb stick</a> created by busware.de
  1032. Note: this module may require the Device::SerialPort or Win32::SerialPort module if you attach the device via USB and the OS sets strange default parameters for serial devices.
  1033. </td><td>
  1034. <img src="IMG_0483.jpg" width="100%" height="100%"/>
  1035. </td></tr>
  1036. </table>
  1037. <a name="TULdefine"></a>
  1038. <b>Define</b>
  1039. <ul>
  1040. <code>define &lt;name&gt; TUL &lt;device&gt; &lt;physical address&gt;</code> <br>
  1041. <br>
  1042. TUL usb stick / TPUART serial devices:<br><ul>
  1043. &lt;device&gt; specifies the serial port to communicate with the TUL. The name of the serial-device depends on your distribution, under linux the cdc_acm kernel module is responsible, and usually a
  1044. /dev/ttyACM0 device will be created. If your distribution does not have a cdc_acm module, you can force usbserial to handle the TUL by the following command:<ul>modprobe usbserial vendor=0x03eb
  1045. product=0x204b</ul>In this case the device is most probably /dev/ttyUSB0.<br><br>
  1046. You can also specify a baudrate if the device name contains the @ character, e.g.: /dev/ttyACM0@19200<br><br>
  1047. Note: For TUL usb stick the baudrate 19200 is needed and this is the default when no baudrate is given.
  1048. <br><br>
  1049. Example:<br>
  1050. <code>define tul TUL tul:/dev/ttyACM0 1.1.249</code>
  1051. </ul>
  1052. EIBD:<br><ul>
  1053. &lt;device&gt; specifies the host:port of the eibd device. E.g. eibd:192.168.0.244:2323. When using the standard port, the port can be omitted.
  1054. <br><br>
  1055. Example:<br>
  1056. <code>define tul TUL eibd:localhost 1.1.249</code>
  1057. <code>define tul TUL knxd:192.168.178.1 1.1.248</code>
  1058. </ul>
  1059. <br>
  1060. If the device is called none, then no device will be opened, so you can experiment without hardware attached.<br>
  1061. The physical address is used as the source address of telegrams sent to EIB network.
  1062. </ul>
  1063. <br>
  1064. <a name="TULattr"></a>
  1065. <b>Attributes</b>
  1066. <ul>
  1067. <li><a href="#do_not_notify">do_not_notify</a></li><br>
  1068. <li><a href="#attrdummy">dummy</a></li><br>
  1069. <li><a href="#showtime">showtime</a></li><br>
  1070. <li><a href="#verbose">verbose</a></li><br>
  1071. <li><a href="#useEIB">useEIB</a></li><br>
  1072. <ul>
  1073. The device operates the module 10_EIB, if this flag is set to 1. This is used for backward compatibility only. Otherwise, only the client 10_KNX is used.
  1074. </ul>
  1075. </ul>
  1076. <br>
  1077. </ul>
  1078. =end html
  1079. =device
  1080. =item summary Connects FHEM to KNX-Bus (Base-device)
  1081. =item summary_DE Verbindet FHEM mit dem KNX-Bus (Basisger&umlat)
  1082. =begin html_DE
  1083. <a name="TUL"></a>
  1084. <h3>TUL</h3>
  1085. <ul>
  1086. <table>
  1087. <tr><td>
  1088. Das Modul TUL stellt die Verbindung von FHEM zum EIB / KNX dar.
  1089. <a href="#KNX">KNX</a> Instanzen stellen die Vrbindung zu den KNX-Gruppen dar und ben&Ouml;tigen ein TUL-Device als IO-Schnittstelle.<br>
  1090. Das Modul TUL kommuniziert mit dem KNX entweder &Uuml;ber den eibd, den knxd oder den TUL <a href="http://busware.de/tiki-index.php?page=TUL" target="_blank">TUL usb stick</a> hergestellt von busware.de
  1091. Anmerkung: das Modul ben&Ouml;tigt die Device::SerialPort oder Win32::SerialPort wenn der Stick &Uuml;ber USB angeschlossen wird, und das OS unrealistische Parameter f&Uuml;r das Device einstellt.
  1092. </td><td>
  1093. <img src="IMG_0483.jpg" width="100%" height="100%"/>
  1094. </td></tr>
  1095. </table>
  1096. <a name="TULdefine"></a>
  1097. <b>Define</b>
  1098. <ul>
  1099. <code>define &lt;name&gt; TUL &lt;device&gt; &lt;physical address&gt;</code> <br>
  1100. <br>
  1101. TUL usb stick / TPUART serial devices:<br><ul>
  1102. &lt;device&gt; enth&auml;lt die serielle Schnittstelle der TUL. Der name der Schnittstelle h&auml;ngt von Eurer Distribution ab. Unter linux wird f&Uuml;r gew&Ouml;hnlich /dev/ttyACM0 verwandt.
  1103. Wenn Eure Distribution das modul cdc_acm nicht enth&auml;lt, k&Ouml;nnt Ihr das Laden des handles der TUL mit dem folgenden Befehl erzwingen:<ul>modprobe usbserial vendor=0x03eb
  1104. product=0x204b</ul>Dann ist die Schnittstelle meist /dev/ttyUSB0.<br><br>
  1105. Ihr k&Ouml;nnt dem Ger&auml;t eine Baudrate vorgeben. Dazu dem Ger&auml;tenamen das Zeichen @ hinzuf&Uuml;gen, z.B.: /dev/ttyACM0@19200<br><br>
  1106. Anmerkung: F&Uuml;r den TUL-USB-Stick wird die Baudrate 19200 ben&Ouml;tigt. Dies entspricht der Defaulteinstellung.
  1107. <br><br>
  1108. Beispiel:<br>
  1109. <code>define tul TUL tul:/dev/ttyACM0 1.1.249</code>
  1110. </ul>
  1111. EIBD:<br><ul>
  1112. &lt;device&gt; entspricht dem host:port des eibd-servers. z.B. eibd:192.168.0.244:2323. Wenn der Standardport genutzt wird, muss dieser nicht angegeben werden.
  1113. <br><br>
  1114. Beispiel:<br>
  1115. <code>define tul TUL eibd:localhost 1.1.249</code>
  1116. <code>define tul TUL knxd:192.168.178.2 1.1.248</code>
  1117. </ul>
  1118. <br>
  1119. Wenn das Ger&auml;t none konfiguriert wird, wird kein device ge&Ouml;ffnet. So k&Ouml;nnt Ihr ohne angeschlossene Hardware experimentieren. <br>
  1120. Die physikalische Adresse wird als Absender f&Uuml;r KNX-Telegramme genutzt.
  1121. </ul>
  1122. <br>
  1123. <a name="TULattr"></a>
  1124. <b>Attribute</b>
  1125. <ul>
  1126. <li><a href="#do_not_notify">do_not_notify</a></li><br>
  1127. <li><a href="#attrdummy">dummy</a></li><br>
  1128. <li><a href="#showtime">showtime</a></li><br>
  1129. <li><a href="#verbose">verbose</a></li><br>
  1130. <li><a href="#useEIB">useEIB</a></li><br>
  1131. <ul>
  1132. Das Ger&auml;t kann das Modul 10_EIB bedienen, wenn das Flag auf 1 gesetzt ist. Dies ist nur f&Uuml;r R&Uuml;ckw&auml;rtskompatibili&auml;t genutzt. Andernfalls wird nur das Modul 10_KNX bedient.
  1133. </ul>
  1134. </ul>
  1135. <br>
  1136. </ul>
  1137. =end html_DE
  1138. =cut