20_N4HBUS.pm 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #############################################################################
  2. #
  3. # 20_N4HBUS.pm
  4. #
  5. # net4home Busconnector Device
  6. #
  7. # (c) 2014-2018 Oliver Koerber <koerber@net4home.de>
  8. #
  9. # $Id: 20_N4HBUS.pm 15729 2017-12-30 20:38:14Z oliverk $
  10. #
  11. ##############################################################################
  12. package main;
  13. use strict;
  14. use warnings;
  15. use POSIX;
  16. use Data::Dumper;
  17. my $n4hbus_Version = "1.0.2.0 - 30.12.2017";
  18. sub N4HBUS_Read($@);
  19. sub N4HBUS_Write($$$$);
  20. sub N4HBUS_Ready($);
  21. sub N4HBUS_getDevList($$);
  22. sub N4HBUS_decompSection($$$);
  23. sub N4HBUS_CompressSection($$);
  24. sub N4HBUS_Initialize($)
  25. {
  26. my ($hash) = @_;
  27. require "$attr{global}{modpath}/FHEM/DevIo.pm";
  28. # Provider
  29. $hash->{ReadFn} = "N4HBUS_Read";
  30. $hash->{WriteFn} = "N4HBUS_Write";
  31. $hash->{ReadyFn} = "N4HBUS_Ready";
  32. # Normal devices
  33. $hash->{UndefFn} = "N4HBUS_Undef";
  34. $hash->{DefFn} = "N4HBUS_Define";
  35. $hash->{AttrList} = "dummy:1,0 ".
  36. "OBJADR ".
  37. "MI ";
  38. }
  39. #################################################################################
  40. sub N4HBUS_Define($$) {
  41. #################################################################################
  42. my ($hash, $def) = @_;
  43. my @a = split("[ \t]+", $def);
  44. if(@a != 3) {
  45. my $msg = "wrong syntax: define <name> N4HBUS hostname:port";
  46. Log3 $hash, 2, $msg;
  47. return $msg;
  48. }
  49. DevIo_CloseDev($hash);
  50. my $name = $a[0];
  51. my $dev = $a[2];
  52. $hash->{VERSION} = $n4hbus_Version;
  53. $hash->{DeviceName} = $dev;
  54. $hash->{Clients} = ":N4HMODULE:";
  55. my %matchList = ( "1:N4HMODULE" => ".*" );
  56. $hash->{MatchList} = \%matchList;
  57. Log3 $hash, 3, "N4HBUS_Define -> $name at $dev";
  58. if($dev eq "none") {
  59. Log3 $hash, 1, "N4HBUS device is none, commands will be echoed only";
  60. $attr{$name}{dummy} = 1;
  61. return undef;
  62. }
  63. my $ret = DevIo_OpenDev($hash, 0, "N4HBUS_DoInit");
  64. return $ret;
  65. }
  66. #################################################################################
  67. sub N4HBUS_DoInit($) {
  68. #################################################################################
  69. my $hash = shift;
  70. my $name = $hash->{NAME};
  71. delete $hash->{HANDLE};
  72. # set OBJ and MI if not defined as attributes
  73. if (!defined($hash->{OBJADR}) ) {
  74. $attr{$name}{OBJADR} = 32700;
  75. }
  76. if (!defined($hash->{MI}) ) {
  77. $attr{$name}{MI} = 65281;
  78. }
  79. my $sendmsg = "190000000002ac0f400a000002bc02404600000487000000c000000200";
  80. DevIo_SimpleWrite($hash, $sendmsg, 1);
  81. return undef;
  82. }
  83. #################################################################################
  84. sub N4HBUS_Undef($@) {
  85. #################################################################################
  86. my ( $hash, $arg ) = @_;
  87. my $name = $hash->{NAME};
  88. Log3 $hash, 2, "close port for $name";
  89. DevIo_CloseDev($hash);
  90. return undef;
  91. }
  92. ##################################################################################
  93. sub decode_d2b (@) {
  94. ##################################################################################
  95. my $w = sprintf("%04x\n", @_);
  96. my $ret = substr($w,2,2).substr($w,0,2);
  97. return $ret;
  98. }
  99. #################################################################################
  100. sub N4HBUS_CompressSection($$) {
  101. #################################################################################
  102. my ($hash, $pUnCompressed) = @_;
  103. my ($cs, $x) = 0;
  104. my $pCompressed = "";
  105. my $sizeRaw = length($pUnCompressed)/2;
  106. for(my $i=0;$i < (length($pUnCompressed)/2); $i++) {
  107. $cs = $cs + hex(substr($pUnCompressed,$i*2,2));
  108. }
  109. my $len = length($pUnCompressed)/2;
  110. my $hi = $len >> 8;
  111. my $lo = $len & 0b0000000011111111;
  112. $pCompressed = sprintf ("%02X%02X", $hi,$lo);
  113. my $p = 0;
  114. while ($len>0){
  115. $pCompressed = $pCompressed.(substr($pUnCompressed,$p*2,2));
  116. $len--;
  117. $p++;
  118. }
  119. $pCompressed = $pCompressed."C0";
  120. $pCompressed = $pCompressed.sprintf ("%02X", ($cs>>24) );
  121. $pCompressed = $pCompressed.sprintf ("%02X", ($cs>>16) );
  122. $pCompressed = $pCompressed.sprintf ("%02X", ($cs>>8) );
  123. $pCompressed = $pCompressed.sprintf ("%02X", ( ($cs>>0) & 0xff ) );
  124. $pCompressed = sprintf ("%02X", (length($pCompressed)/2))."000000".$pCompressed;
  125. return $pCompressed;
  126. }
  127. #################################################################################
  128. sub N4HBUS_decompSection($$$) {
  129. #################################################################################
  130. my ($hash, $p2, $fs) = @_;
  131. my $ret = 0;
  132. my $inBlock;
  133. my $gPoutPos = 0;
  134. my $zaehler = 0;
  135. my $err = 0;
  136. my $ende = 0;
  137. my $gPout = "";
  138. my $bb = 0;
  139. my $bc = 0;
  140. my $csCalc = 0;
  141. my $csRx;
  142. my $maxoutlen = 372;
  143. my @ar2k;
  144. my $decompressor_err = -4;
  145. my $decompressor_errAdr = 0;
  146. while (($zaehler<$fs) && ($gPoutPos < $maxoutlen) && ($ende != 1) && ($err != 1)) {
  147. $bb = substr($p2,$zaehler*2,2);
  148. my $bbout = hex($bb) & 192;
  149. if ( (hex($bb) & 192) == 192) {
  150. # Ende ist gefunden
  151. $ende = 1;
  152. } elsif ((hex($bb) & 192) == 0) {
  153. $bc = substr($p2,(($zaehler+1)*2),2);
  154. $inBlock = (hex(substr($p2,$zaehler*2,2))*256) + hex($bc);
  155. $zaehler = $zaehler+2;
  156. while ($inBlock > 0) {
  157. $inBlock--;
  158. $gPout = $gPout.substr($p2,$zaehler*2,2);
  159. $zaehler++;
  160. }
  161. } elsif ((hex($bb) & 192) == 64) {
  162. $bc = substr($p2,(($zaehler+1)*2),2);
  163. $inBlock = ((hex(substr($p2,$zaehler*2,2))*256) + hex($bc)) & 16383;
  164. $bb = substr($p2,($zaehler+2)*2,2);
  165. $zaehler = $zaehler+3;
  166. while ($inBlock > 0) {
  167. $inBlock--;
  168. $gPout = $gPout.$bb;
  169. }
  170. } elsif ($bb & 0xC0 == 0x80) {
  171. $err = 1;
  172. $decompressor_err = -2;
  173. $zaehler++;
  174. }
  175. $decompressor_errAdr = $zaehler;
  176. }
  177. if (($err != 1) and ($ende == 1)) {
  178. $ret = $gPout;
  179. }
  180. return $ret;
  181. }
  182. ##################################################################################
  183. sub N4HBUS_bin2text ($) {
  184. ##################################################################################
  185. # Umwandlung der empfangenen oder zu sendenden Daten in lesbares Format
  186. my ( $data ) = @_;
  187. my $ret = "";
  188. my $sub;
  189. if (length($data)>60) {
  190. # Kenne ich noch nicht
  191. $ret = "(".substr($data,0,12).")\t";
  192. # ptype
  193. $sub = hex(substr($data,14,2).substr($data,12,2));
  194. $ret = $ret."ptype=$sub\t";
  195. # payloadlen
  196. $sub = hex(substr($data,18,2).substr($data,16,2));
  197. $ret = $ret."payloadlen=$sub\t";
  198. # MMS oder BIN
  199. $sub = hex(substr($data,22,2).substr($data,20,2));
  200. $ret = $ret."IP=$sub\t";
  201. # Kenne ich noch nicht
  202. $sub = substr($data,24, 6);
  203. $ret = $ret."($sub)\t";
  204. # type8
  205. $sub = hex(substr($data,30,2));
  206. $ret = $ret."type8=$sub\t";
  207. # ipsrc
  208. $sub = (substr($data,34,2).substr($data,32,2));
  209. $ret = $ret."MI=$sub\t";
  210. # ipdst
  211. $ret = $ret."ipdst=".hex(substr($data,38,2).substr($data,36,2))."\t";
  212. # objsrc
  213. $ret = $ret."objsrc=".hex(substr($data,42,2).substr($data,40,2))."\t";
  214. # datalen
  215. my $datalen = hex((substr($data,44,2)));
  216. $ret = $ret."datalen=".$datalen."\t";
  217. # ddata
  218. $ret = $ret."ddata=".substr($data,46, ($datalen*2))."\t";
  219. my $pos = $datalen*2+46;
  220. my $csRX = hex(substr($data,$pos,2));
  221. my $csCalc = hex(substr($data,$pos+2,2));
  222. my $len = hex(substr($data,$pos+4,2));
  223. my $posb = hex(substr($data,$pos+6,2));
  224. $ret = $ret."($csRX/$csCalc/$len/$posb)"
  225. }
  226. return $ret;
  227. }
  228. ##################################################################################
  229. sub N4HBUS_Write($$$$) {
  230. ##################################################################################
  231. my ($hash,$ipdst,$ddata,$objsource) = @_;
  232. my $name = $hash->{NAME};
  233. return if(!$hash || AttrVal($hash->{NAME}, "dummy", 0) != 0);
  234. my $sendmsg = "";
  235. my $sendbus = "";
  236. my $msg = "";
  237. my $objsrc = AttrVal($name, "OBJADR", 32700);
  238. my $ipsrc = AttrVal($name, "MI", 65281);
  239. # A10F 0000 4E00 0000 00 - 00 5902 0D62 2D65 03 32 00 64 03D416070102201500003120736563742000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004A4A030000
  240. # payload type
  241. $sendbus = "A10F0000";
  242. # payload len0
  243. $sendbus = $sendbus."4E000000";
  244. #??
  245. $sendbus = $sendbus."00";
  246. # typ8
  247. $sendbus = $sendbus."00";
  248. $sendbus = $sendbus.decode_d2b($ipsrc);
  249. $sendbus = $sendbus.decode_d2b($ipdst);
  250. if ($objsource !=0 ) {
  251. $objsrc = $objsource;
  252. }
  253. $sendbus = $sendbus.decode_d2b($objsrc);
  254. # ddata
  255. while (length($ddata)<128) {
  256. $ddata = $ddata."00";
  257. }
  258. $sendbus = $sendbus.$ddata;
  259. # csRx, csCalc, len, posb
  260. $sendbus = $sendbus."00000000";
  261. $sendmsg = N4HBUS_CompressSection($hash, $sendbus);
  262. Log3 $hash, 5, "N4HBUS (+++): $sendmsg";
  263. if(defined($hash)) {
  264. DevIo_SimpleWrite($hash, $sendmsg, 1);
  265. }
  266. }
  267. ##################################################################################
  268. sub N4HBUS_Read($@) {
  269. #################################################################################
  270. my ($hash, $local, $regexp) = @_;
  271. my $buf = DevIo_SimpleRead($hash);
  272. return "" if(!defined($buf));
  273. my $name = $hash->{NAME};
  274. my $recdata = unpack('H*', $buf);
  275. my $data;
  276. my $len = 0;
  277. $len = substr($recdata,6,2);
  278. $len = $len.substr($recdata,4,2);
  279. $len = $len.substr($recdata,2,2);
  280. $len = $len.substr($recdata,0,2);
  281. $len =~ s/^0+//;
  282. my $test = "";
  283. $recdata = substr($recdata,8,hex($len)*2);
  284. while (length($recdata) >= ( hex($len) *2)) {
  285. $data = substr($recdata,0, hex($len)*2);
  286. Log3 $hash, 5, "N4HBUS (DECOMP): Länge (".hex($len)." bytes)-$data";
  287. # Log3 $hash, 1, "(DECOMP1): Länge (".hex($len)." bytes)-$data";
  288. # 0005 a10f 0000 04 40 05 0000 1c 7302 ff7f a86a 05 65 09 05 01 c2 4d617263656c20476f6572747a6b6175403000c000000b24
  289. # 0005 a10f 0000 04 40 06 0000 1b 01 bc7f 1127 04 41 00 01 04 624d617263656c20476f6572747a6b6175403000c000000904
  290. # 1b 01 ffff 1127 03 ff ff ff 64b44d617263656c20476f6572747a6b6175403000c000000d33
  291. # 0005 a10f 0000 04 40 05 0000 1f 2600 ffff 2c0a 03 ff ff ff 017f2127100320160100271003201601006f00a19c400aff402300c000001333
  292. my $idx;
  293. $idx = index($data,"a10f");
  294. if ($idx>=0) {
  295. $data = substr($data,$idx); # Cut off beginning - Der Anfang interessiert erst mal nicht...
  296. my $msg = substr($data,18,length($data));
  297. my $type8 = hex(substr($msg,0,2));
  298. # Es ist ein "normales" Status-Paket
  299. if ($type8>=0) {
  300. $hash->{"${name}_MSGCNT"}++;
  301. $hash->{"${name}_TIME"} = TimeNow();
  302. $hash->{RAWMSG} = $msg;
  303. my %addvals = (RAWMSG => $data);
  304. Dispatch($hash, $msg, \%addvals) if($init_done);
  305. }
  306. } # a10f - Statuspaket
  307. $recdata = substr($recdata,( hex($len) *2));
  308. } # while
  309. return undef;
  310. }
  311. #################################################################################
  312. sub N4HBUS_Ready($) {
  313. #################################################################################
  314. my ($hash) = @_;
  315. Log3 $hash, 1, "N4HBUS_Ready";
  316. return DevIo_OpenDev($hash, 1, "N4HBUS_DoInit");
  317. }
  318. # function decompSection(p2:pbyte; offset, fs:dword; p2out:pbyte; MaxOutLen:dword; useCS:boolean):dword;
  319. #################################################################################
  320. 1;
  321. =pod
  322. =item device
  323. =item summary Connector to net4home bus via IP
  324. =item summary_DE Konnektor zum net4home Bus über IP
  325. =begin html
  326. <a name="N4HBUS"></a>
  327. <h3>N4HBUS</h3>
  328. This module connects fhem to the net4home Bus. You need to define ojects with <a href="#N4MODULE">N4MODULE</a> to set or read
  329. data of th net4home bus.
  330. <br /><br />
  331. Further technical information can be found at the <a href="http://www.net4home.de">net4home.de</a> Homepage
  332. <br /><br />
  333. <a name="N4HBUS_Define"></a>
  334. <b>Define</b>
  335. <ul>
  336. <code>define &lt;name&gt; N4HBUS &lt;device&gt;</code>
  337. <br /> <br />
  338. &lt;device&gt; is a combination of &lt;host&gt;:&lt;port&gt;, where &lt;host&gt; is the IP address of the net4home Busconnector and &lt;port&gt; (default:3478).
  339. <br /> <br />
  340. Example:
  341. <ul>
  342. <code>define net4home N4HBUS 192.168.1.69:3478</code>
  343. </ul>
  344. <br />
  345. The device can also be connected to the busconnector on the same machine. <br />
  346. Default Port for communication is 3478. In case you need to change this please change also the Port in the conf of Busconnector service.
  347. </ul>
  348. <br />
  349. <a name="N4HBUS_Readings"></a>
  350. <b>Readings</b>
  351. <ul>
  352. <li>state - current state of the Bus connection</li>
  353. </ul><br />
  354. <a name="N4HBUS_Attr"></a>
  355. <b>Attributes</b>
  356. <ul>
  357. <li>MI - a unique MI in the net4home environment (default:65281)</li>
  358. <li>OBJADR - a unique OBJADR in the net4home environment (default:32700)</li>
  359. </ul>
  360. =end html
  361. =begin html_DE
  362. <a name="N4HBUS"></a>
  363. <h3>N4HBUS</h3>
  364. Dieses Modul verbindet fhem &uuml;ber IP mit dem net4home Bus. Zus&auml;tzlich m&uuml;ssen Objekte &uuml;ber den Typ
  365. <a href="#N4MODULE">N4MODULE</a> definiert werden, um Daten an den net4home-Bus zu senden oder zu lesen.
  366. <br /><br />
  367. Weitere technische Informationen gibt es auf der Homepage unter <a href="http://www.net4home.de">net4home.de</a>
  368. <br /><br />
  369. <a name="N4HBUS_Define"></a>
  370. <b>Define</b>
  371. <ul>
  372. <code>define &lt;name&gt; N4HBUS &lt;device&gt;</code>
  373. <br /> <br />
  374. &lt;device&gt; ist eine Kombination aus IP Adresse des net4home Busconnectors und dem Port (default:3478).
  375. <br /> <br />
  376. Beispiel:
  377. <ul>
  378. <code>define net4home N4HBUS 192.168.1.69:3478</code>
  379. </ul>
  380. <br />
  381. Das Device kann sich auch mit dem Busconnector auf dem selben System verbinden.
  382. Der Default-Port für die Kommunikation ist 3478. Sollte es n&ouml;tig sein den Port zu ver&auml;ndern, so muss dies ebenfalls
  383. in der Konfiguration des Services durchgef&uuml;hrt werden.<br />
  384. </ul>
  385. <br />
  386. <a name="N4HBUS_Readings"></a>
  387. <b>Readings</b>
  388. <ul>
  389. <li>state - aktueller Status der Verbindung zum net4home Busconnector</li>
  390. </ul><br />
  391. <a name="N4HBUS_Attr"></a>
  392. <b>Attributes</b>
  393. <ul>
  394. <li>MI - die eindeutige MI in der net4home Umgebung (default:65281)</li>
  395. <li>OBJADR - die eindeutige OBJADR in der net4home Umgebung (default:32700)</li>
  396. </ul>
  397. =end html_DE
  398. =cut