00_TUL.pm 35 KB

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