10_EIB.pm 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512
  1. ##############################################
  2. # $Id: 10_EIB.pm 16389 2018-03-11 20:50:59Z andi291 $
  3. # MH various changes/fixes from forum e.g dpt9, 0 is not necessarily off, ...
  4. # MH 20140313 changed Log to Log3, verbose instead of loglevel
  5. # MH 20140313 testing setstate....
  6. # MH 20141202 changing to readingsupdate
  7. # MH 20150518 . based on SVN 10_EIB.pm 8584 2015-05-15 18:46:52Z andi291
  8. # ABU 20150617 added dpt1, removed special handling of dpt5, added default-values for messages without dpt, changed retVal of EIB_ParseByDatapointType
  9. # MH 20150622 added getGx/setGx Readings and Attr EIBreadingX
  10. # ABU 20150617 cleanup unused lines, finalized dpt-handling, cleanup logging, added debug-par
  11. # ABU 20150729 removed special handling DPT7 in write, fixed DPT7 encoding
  12. # ABU 20150812 renamed return-value for autocreate; added attribute for reading containing sender; fixed HTML-Doku
  13. # ABU 20150917 cleaned up, implemented DPT16 for sending, implemented DPT6, added EIBanswerOnRead, changed time/date-handling, fixed DPT14-sending, removed Root-Causes for several warnings
  14. # ABU 20150919 fixed set string containing letter g
  15. # ABU 20150920 removed ne-warning, added attribute eventMarker, fixed behaviour if no model defined
  16. # ABU 20150922 fixed DPT14, restructured DPT9, fixed datum and time
  17. # ABU 20150923 improved failure-tolerance for none / wrong model
  18. # ABU 20150924 fixed date/time again
  19. # ABU 20150926 removed eventMarker, removed no get for dummies
  20. # ABU 20151207 added dpt3, fixed doku-section myDimmer
  21. # ABU 20151213 added dpt13
  22. # ABU 20151221 added multiple group support for get according thread 45954
  23. # ABU 20160111 added feature EIBreadingRegex, EIBwritingRegex, Fixed some doku
  24. # ABU 20160116 fixed motd-error due to debug-mode
  25. # ABU 20160122 fixed doku, changed return value for EIB_Set from undef to "", reintegrated multiple group sending
  26. # ABU 20160123 fixed issue for sending with additional groups
  27. # ABU 20180311 added summary in description
  28. package main;
  29. use strict;
  30. use warnings;
  31. my $debug=0;
  32. # Open Tasks
  33. # - precision for model percent to 0,1
  34. # - allow defined groups that are only used for sending of data (no status shown)
  35. my %eib_c2b = (
  36. "off" => "00",
  37. "on" => "01",
  38. "on-for-timer" => "01",
  39. "on-till" => "01",
  40. "raw" => "",
  41. "value" => "",#value must be last.. because of slider functionality in Set
  42. "string" => "" #value must be last.. because of slider functionality in Set
  43. );
  44. my %codes = (
  45. "00" => "off",
  46. "01" => "on",
  47. "" => "value",
  48. );
  49. my %readonly = (
  50. "dummy" => 1,
  51. );
  52. my $eib_simple ="off on value on-for-timer on-till";
  53. my %models = (
  54. );
  55. my %eib_dpttypes = (
  56. #Binary value
  57. "dpt1" => {"CODE"=>"dpt1", "UNIT"=>"", "factor"=>1},
  58. #Step value (four-bit)
  59. "dpt3" => {"CODE"=>"dpt3", "UNIT"=>"", "factor"=>1},
  60. # 1-Octet unsigned value
  61. "dpt5" => {"CODE"=>"dpt5", "UNIT"=>"", "factor"=>1},
  62. "percent" => {"CODE"=>"dpt5", "UNIT"=>"%", "factor"=>100/255, "slider"=>"0,1,100"},
  63. "dpt5.003" => {"CODE"=>"dpt5", "UNIT"=>"°", "factor"=>360/255},
  64. "angle" => {"CODE"=>"dpt5", "UNIT"=>"°", "factor"=>360/255}, # alias for dpt5.003
  65. "dpt5.004" => {"CODE"=>"dpt5", "UNIT"=>"%", "factor"=>1},
  66. "percent255" => {"CODE"=>"dpt5", "UNIT"=>"%", "factor"=>1 , "slider"=>"0,1,255"}, #alias for dpt5.004
  67. "dpt5.Slider" => {"CODE"=>"dpt5", "UNIT"=>"", "factor"=>100/255, "slider"=>"0,1,100"}, ##MH same as percent w.o. unit
  68. # 1-Octet signed value
  69. "dpt6" => {"CODE"=>"dpt6", "UNIT"=>"", "factor"=>1},
  70. "dpt6.001" => {"CODE"=>"dpt6", "UNIT"=>"%", "factor"=>1},
  71. "dpt6.010" => {"CODE"=>"dpt6", "UNIT"=>"", "factor"=>1},
  72. # 2-Octet unsigned Value (current, length, brightness)
  73. "dpt7" => {"CODE"=>"dpt7", "UNIT"=>""},
  74. "length-mm" => {"CODE"=>"dpt7", "UNIT"=>"mm"},
  75. "current-mA" => {"CODE"=>"dpt7", "UNIT"=>"mA"},
  76. "brightness" => {"CODE"=>"dpt7", "UNIT"=>"lux"},
  77. "timeperiod-ms" => {"CODE"=>"dpt7", "UNIT"=>"ms"},
  78. "timeperiod-min" => {"CODE"=>"dpt7", "UNIT"=>"min"},
  79. "timeperiod-h" => {"CODE"=>"dpt7", "UNIT"=>"h"},
  80. # 2-Octet Float Value (Temp / Light)
  81. "dpt9" => {"CODE"=>"dpt9", "UNIT"=>""},
  82. "tempsensor" => {"CODE"=>"dpt9", "UNIT"=>"°C"},
  83. "lightsensor" => {"CODE"=>"dpt9", "UNIT"=>"Lux"},
  84. "speedsensor" => {"CODE"=>"dpt9", "UNIT"=>"m/s"},
  85. "speedsensor-km/h" => {"CODE"=>"dpt9", "UNIT"=>"km/h"},
  86. "pressuresensor" => {"CODE"=>"dpt9", "UNIT"=>"Pa"},
  87. "rainsensor" => {"CODE"=>"dpt9", "UNIT"=>"l/m²"},
  88. "time1sensor" => {"CODE"=>"dpt9", "UNIT"=>"s"},
  89. "time2sensor" => {"CODE"=>"dpt9", "UNIT"=>"ms"},
  90. "humiditysensor" => {"CODE"=>"dpt9", "UNIT"=>"%"},
  91. "airqualitysensor" => {"CODE"=>"dpt9", "UNIT"=>"ppm"},
  92. "voltage-mV" => {"CODE"=>"dpt9", "UNIT"=>"mV"},
  93. "current-mA2" => {"CODE"=>"dpt9", "UNIT"=>"mA"},
  94. "power" => {"CODE"=>"dpt9", "UNIT"=>"kW"},
  95. "powerdensity" => {"CODE"=>"dpt9", "UNIT"=>"W/m²"},
  96. # Time of Day
  97. "dpt10" => {"CODE"=>"dpt10", "UNIT"=>""},
  98. "dpt10_no_seconds" => {"CODE"=>"dpt10_ns", "UNIT"=>""},
  99. "time" => {"CODE"=>"time", "UNIT"=>""},
  100. # Date
  101. "dpt11" => {"CODE"=>"dpt11", "UNIT"=>""},
  102. "date" => {"CODE"=>"date", "UNIT"=>""},
  103. # 4-Octet unsigned value (handled as dpt7)
  104. "dpt12" => {"CODE"=>"dpt12", "UNIT"=>""},
  105. # 4-Octet Signed Value
  106. "dpt13" => {"CODE"=>"dpt13", "UNIT"=>"", "factor"=>1},
  107. "dpt13.010" => {"CODE"=>"dpt13", "UNIT"=>"W/h", "factor"=>1},
  108. "dpt13.013" => {"CODE"=>"dpt13", "UNIT"=>"kW/h", "factor"=>1},
  109. # 4-Octet single precision float
  110. "dpt14" => {"CODE"=>"dpt14", "UNIT"=>""},
  111. # 14-Octet String
  112. "dpt16" => {"CODE"=>"dpt16", "UNIT"=>""},
  113. );
  114. sub
  115. EIB_Initialize($) {
  116. my ($hash) = @_;
  117. $hash->{Match} = "^B.*";
  118. $hash->{GetFn} = "EIB_Get";
  119. $hash->{SetFn} = "EIB_Set";
  120. $hash->{StateFn} = "EIB_SetState";
  121. $hash->{DefFn} = "EIB_Define";
  122. $hash->{UndefFn} = "EIB_Undef";
  123. $hash->{ParseFn} = "EIB_Parse";
  124. $hash->{AttrFn} = "EIB_Attr";
  125. $hash->{AttrList} = "IODev do_not_notify:1,0 ignore:0,1 dummy:1,0 showtime:1,0 " .
  126. "EIBreadingX:1,0 " .
  127. "EIBreadingSender:1,0 " .
  128. "EIBanswerReading:1,0 " .
  129. "EIBreadingRegex " .
  130. "EIBwritingRegex " .
  131. "$readingFnAttributes " .
  132. "model:".join(",", keys %eib_dpttypes);
  133. }
  134. #############################
  135. sub
  136. EIB_Define($$) {
  137. my ($hash, $def) = @_;
  138. my @a = split("[ \t][ \t]*", $def);
  139. my $u = "wrong syntax: define <name> EIB <group name> [<read group names>*]";
  140. return $u if(int(@a) < 3);
  141. return "Define $a[0]: wrong group name format: specify as 0-15/0-15/0-255 or as hex" if( ($a[2] !~ m/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{1,3}$/i) && (lc($a[2]) !~ m/^[0-9a-f]{4}$/i));
  142. my $groupname = eib_name2hex(lc($a[2]));
  143. $hash->{GROUP} = lc($groupname);
  144. my $code = "$groupname";
  145. my $ncode = 1;
  146. my $name = $a[0];
  147. $hash->{CODE}{$ncode++} = $code;
  148. # add read group names
  149. if(int(@a)>3) {
  150. for (my $count = 3; $count < int(@a); $count++) {
  151. $hash->{CODE}{$ncode++} = eib_name2hex(lc($a[$count]));;
  152. }
  153. }
  154. $modules{EIB}{defptr}{$code}{$name} = $hash;
  155. AssignIoPort($hash);
  156. }
  157. #############################
  158. sub
  159. EIB_Undef($$) {
  160. my ($hash, $name) = @_;
  161. foreach my $c (keys %{ $hash->{CODE} } )
  162. {
  163. $c = $hash->{CODE}{$c};
  164. # As after a rename the $name may be different from the $defptr{$c}{$n}
  165. # we look for the hash.
  166. foreach my $dname (keys %{ $modules{EIB}{defptr}{$c} })
  167. {
  168. delete($modules{EIB}{defptr}{$c}{$dname}) if($modules{EIB}{defptr}{$c}{$dname} == $hash);
  169. }
  170. }
  171. return undef;
  172. }
  173. #####################################
  174. sub
  175. EIB_Attr(@)
  176. {
  177. my ($cmd,$name,$aName,$aVal) = @_;
  178. #debug
  179. print "Name: $name, Attribut: $aName, Wert: $aVal\n" if ($debug eq 1);
  180. # $cmd can be "del" or "set"
  181. # $name is device name
  182. # aName and aVal are Attribute name and value
  183. if ($cmd eq "set")
  184. {
  185. }
  186. elsif ($cmd eq "del")
  187. {
  188. }
  189. return undef;
  190. }
  191. #####################################
  192. sub
  193. EIB_SetState($$$$) {
  194. my ($hash, $tim, $vt, $val) = @_;
  195. Log3 $hash, 5,"EIB setState for $hash->{NAME} tim: $tim vt: $vt $val";
  196. $val = $1 if($val =~ m/^(.*) \d+$/);
  197. return undef if(!defined($eib_c2b{$val}));
  198. }
  199. ###################################
  200. sub
  201. EIB_Get($@) {
  202. #my ($hash, @a) = @_;
  203. ##return "No get for dummies" if(IsDummy($hash->{NAME}));
  204. #return "" if($a[1] && $a[1] eq "?"); # Temporary hack for FHEMWEB
  205. ##send read-request to the bus
  206. #IOWrite($hash, "B", "r" . $hash->{GROUP});
  207. #return "Current value for $hash->{NAME} ($hash->{GROUP}) requested.";
  208. my ($hash, @a, $str) = @_;
  209. my $na = int(@a);
  210. my $value = $a[1];
  211. return "" if($a[1] && $a[1] eq "?"); # Temporary hack for FHEMWEB
  212. my $groupnr = 1;
  213. # the command can be send to any of the defined groups indexed starting by 1
  214. # optional last argument starting with g indicates the group
  215. # execute only for non-strings. Otherwise a "g" is interpreted to execute this group-send-mechanism...
  216. if (defined($value) and ($value ne "string"))
  217. {
  218. $groupnr = $1 if($na=2 && $a[1]=~ m/g([0-9]*)/);
  219. #return, if unknown group
  220. return "groupnr $groupnr not known." if(!$hash->{CODE}{$groupnr});
  221. }
  222. my $groupcode = $hash->{CODE}{$groupnr};
  223. #send read-request to the bus
  224. IOWrite($hash, "B", "r" . $groupcode);
  225. return "Current value for $hash->{NAME} ($groupcode) requested.";
  226. }
  227. ###################################
  228. sub
  229. EIB_Set($@) {
  230. my ($hash, @a, $str) = @_;
  231. #my $ret = undef;
  232. my $ret = "";
  233. my $na = int(@a);
  234. #return, if no set value specified
  235. return "no set value specified" if($na < 2);# || $na > 4);
  236. #return, if this is a readonly-device
  237. return "Readonly value $a[1]" if(defined($readonly{$a[1]}));
  238. #return, if this is a dummy device
  239. return "No $a[1] for dummies" if(IsDummy($hash->{NAME}));
  240. my $name = $a[0];
  241. my $value = $a[1];
  242. my $arg1 = undef;
  243. my $arg2 = undef;
  244. $arg1 = $a[2] if($na>2);
  245. $arg2 = $a[3] if($na>3);
  246. my $model = $attr{$name}{"model"};
  247. my $sliderdef = !defined($model)?undef:$eib_dpttypes{"$model"}{"slider"};
  248. my $c = $eib_c2b{$value};
  249. if(!defined($c))
  250. {
  251. my $resp = "Unknown argument $value, choose one of " . join(" ", sort keys %eib_c2b);
  252. $resp = $resp . ":slider,$sliderdef" if(defined $sliderdef);
  253. return $resp;
  254. }
  255. my $groupnr = 1;
  256. my $extGroupNr = undef;
  257. # the command can be send to any of the defined groups indexed starting by 1
  258. # optional last argument starting with g indicates the group
  259. $extGroupNr = $1 if($na>2 && $a[$na-1]=~ m/g([0-9]*)/);
  260. if (defined ($extGroupNr))
  261. {
  262. $groupnr = $extGroupNr;
  263. print ("Found supplied group-no.: $extGroupNr\n") if ($debug eq 1);
  264. }
  265. return "groupnr $groupnr not known." if(!$hash->{CODE}{$groupnr});
  266. my $v = join(" ", @a);
  267. Log3 $name, 5, "EIB set $v";
  268. (undef, $v) = split(" ", $v, 2); # Not interested in the name...
  269. if($value eq "raw" && defined($arg1))
  270. {
  271. # complex value command.
  272. # the additional argument is transfered alone.
  273. $c = $arg1;
  274. }
  275. elsif ($value eq "value" && defined($arg1))
  276. {
  277. # value to be translated according to datapoint type
  278. $c = EIB_EncodeByDatapointType($hash,$name,$arg1,$groupnr); #MH add group in call
  279. # set the value to the back translated value
  280. $v = EIB_ParseByDatapointType($hash,$name,$c,$groupnr); # MH probably stupid - but required!!!!
  281. }
  282. elsif ($value eq "string" && ($na>2))
  283. {
  284. my $str = "";
  285. #append all following args...
  286. my $argLen = $na;
  287. #...except the last argument is a group-no
  288. $argLen -= 1 if (defined $extGroupNr);
  289. #join string
  290. for (my $i=2;$i<$argLen;$i++)
  291. {
  292. $str.= $a[$i]." ";
  293. }
  294. #trim whitespaces at the end
  295. $str =~ s/^\s+|\s+$//g;
  296. return "String too long, max. 14 chars allowed" if(length($str) > 14);
  297. Log3 $name, 5, "set string $str";
  298. # value to be translated according to datapoint type
  299. $c = EIB_EncodeByDatapointType($hash,$name,$str,$groupnr);
  300. # set the value to the back translated value
  301. $v = EIB_ParseByDatapointType($hash,$name,$c,$groupnr);
  302. }
  303. my $groupcode = $hash->{CODE}{$groupnr};
  304. $model = $attr{$name}{"model"}; ##MH
  305. $model = "" unless defined($model); ##MH avoid uninit msg
  306. my $code = $eib_dpttypes{"$model"}{"CODE"};
  307. #send new value
  308. IOWrite($hash, "B", "w" . $groupcode . $c);
  309. ###########################################
  310. # Delete any timer for on-for_timer
  311. if($modules{EIB}{ldata}{$name})
  312. {
  313. CommandDelete(undef, $name . "_timer");
  314. delete $modules{EIB}{ldata}{$name};
  315. }
  316. ###########################################
  317. # Add a timer if any for-timer command has been chosen
  318. if($value =~ m/for-timer/ && defined($arg1))
  319. {
  320. my $dur = $arg1;
  321. my $to = sprintf("%02d:%02d:%02d", $dur/3600, ($dur%3600)/60, $dur%60);
  322. $modules{EIB}{ldata}{$name} = $to;
  323. Log3 $name, 4, "Follow: +$to set $name off g$groupnr";
  324. CommandDefine(undef, $name . "_timer at +$to set $name off g$groupnr");
  325. }
  326. ###########################################
  327. # Delete any timer for on-till
  328. if($modules{EIB}{till}{$name})
  329. {
  330. CommandDelete(undef, $name . "_till");
  331. delete $modules{EIB}{till}{$name};
  332. }
  333. ###########################################
  334. # Add a timer if on-till command has been chosen
  335. if($value =~ m/on-till/ && defined($arg1))
  336. {
  337. my ($err, $hr, $min, $sec, $fn) = GetTimeSpec($arg1);
  338. if($err)
  339. {
  340. Log3 $name, 2, "Error trying to parse timespec for $a[0] $a[1] $a[2] : $err";
  341. }
  342. else
  343. {
  344. my @lt = localtime;
  345. my $hms_till = sprintf("%02d:%02d:%02d", $hr, $min, $sec);
  346. my $hms_now = sprintf("%02d:%02d:%02d", $lt[2], $lt[1], $lt[0]);
  347. if($hms_now ge $hms_till)
  348. {
  349. Log3 $name, 4, "on-till: won't switch as now ($hms_now) is later than $hms_till";
  350. }
  351. else
  352. {
  353. $modules{EIB}{till}{$name} = $hms_till;
  354. Log3 $name, 4, "Follow: $hms_till set $name off g$groupnr";
  355. CommandDefine(undef, $name . "_till at $hms_till set $name off g$groupnr");
  356. }
  357. }
  358. }
  359. ##########################
  360. # Look for all devices with the same code, and set state, timestamp
  361. $code = "$hash->{GROUP}"; ##MH reuse variable
  362. my $tn = TimeNow();
  363. my $defptr = $modules{EIB}{defptr}{$code};
  364. foreach my $n (keys %{ $defptr })
  365. {
  366. my $regAttr = $attr{$n}{"EIBwritingRegex"};
  367. if ($regAttr)
  368. {
  369. #substitute contents of state, if desired
  370. #
  371. #get array of given attributes
  372. my @reg = split("[ ]", $regAttr);
  373. #format reading as input for regex
  374. my $tempVal = "setG$groupnr:$v";
  375. #loop over all regex
  376. for (my $i = 0; $i < int(@reg); $i++)
  377. {
  378. #get search / replaye parts
  379. my @regInner = split("\/", $reg[$i]);
  380. $tempVal =~ s/$regInner[0]/$regInner[1]/g;
  381. #log it
  382. Log (5, "modified set with regex s/$regInner[0]/$regInner[1]/g to value $tempVal");
  383. print ("modified set with regex s/$regInner[0]/$regInner[1]/g to value $tempVal\n") if ($debug eq 1);
  384. }
  385. #process result
  386. readingsSingleUpdate($defptr->{$n},"state",$tempVal,1);
  387. } else
  388. {
  389. #process regular reading
  390. readingsSingleUpdate($defptr->{$n},"state",$v,1);
  391. }
  392. #debug
  393. print "setg = $defptr->{$n}{NAME} , $groupnr , attr = AttrVal($defptr->{$n}{NAME},'EIBreadingX',0)n" if ($debug eq 1);
  394. #process extended reading - mark as set
  395. readingsSingleUpdate($defptr->{$n},"setG" . $groupnr,$v,1) if (AttrVal($defptr->{$n}{NAME},'EIBreadingX',0) == 1);
  396. }
  397. return $ret;
  398. }
  399. ###################################
  400. sub
  401. EIB_Parse($$) {
  402. my ($hash, $msg) = @_;
  403. # Msg format:
  404. # B(w/r/p)<group><value> i.e. Bw00000101
  405. # we will also take reply telegrams into account,
  406. # as they will be sent if the status is asked from bus
  407. #split message into parts
  408. $msg =~ m/^B(.{4})(.{1})(.{4})(.*)$/;
  409. my $src = $1;
  410. my $cmd = $2;
  411. my $dev = $3;
  412. my $val = $4;
  413. my $v = $codes{$val};
  414. $v = "$val" if(!defined($v));
  415. my $rawv = $v;
  416. my @list;
  417. my $found = 0;
  418. # check if the code is within the read groups
  419. # we will inform all definitions subsribed to this code
  420. foreach my $mod (keys %{$modules{EIB}{defptr}})
  421. {
  422. my $def = $modules{EIB}{defptr}{"$mod"};
  423. if($def)
  424. {
  425. foreach my $n (keys %{ $def })
  426. {
  427. my $lh = $def->{$n};
  428. foreach my $gnr (keys %{ $lh->{CODE} })
  429. {
  430. my $c = $lh->{CODE}{$gnr};
  431. if($c eq $dev)
  432. {
  433. $n = $lh->{NAME}; # It may be renamed
  434. next if(IsIgnored($n)); # Little strange.
  435. push(@list, $n);
  436. $found = 1;
  437. # handle write and reply messages
  438. if($cmd =~ /[w|p]/)
  439. {
  440. # parse/translate by datapoint type
  441. $v = EIB_ParseByDatapointType($lh,$n,$rawv,$gnr); # MH added optional groupnr
  442. $lh->{RAWSTATE} = $rawv;
  443. $lh->{LASTGROUP} = $dev;
  444. my $regAttr = $attr{$n}{"EIBreadingRegex"};
  445. if ($regAttr)
  446. {
  447. #substitute contents of state, if desired
  448. #
  449. #get array of given attributes
  450. my @reg = split("[ ]", $regAttr);
  451. #format reading as input for regex
  452. my $tempVal = "getG$gnr:$v";
  453. #loop over all regex
  454. for (my $i = 0; $i < int(@reg); $i++)
  455. {
  456. #get search / replaye parts
  457. my @regInner = split("\/", $reg[$i]);
  458. $tempVal =~ s/$regInner[0]/$regInner[1]/g;
  459. #log it
  460. Log (5, "modified set with regex s/$regInner[0]/$regInner[1]/g to value $tempVal");
  461. print ("modified set with regex s/$regInner[0]/$regInner[1]/g to value $tempVal\n") if ($debug eq 1);
  462. }
  463. #process result
  464. readingsSingleUpdate($lh,"state",$tempVal,1);
  465. }
  466. else
  467. {
  468. #process regular reading
  469. readingsSingleUpdate($lh,"state",$v,1);
  470. }
  471. #debug
  472. print "getg = $n , group= $gnr , EIBreadingX = AttrVal($def->{$n}{NAME},'EIBreadingX',0)\n" if ($debug eq 1);
  473. #process extended reading - mark as "get"
  474. readingsSingleUpdate($lh,'getG' . $gnr,$v,1) if (AttrVal($def->{$n}{NAME},'EIBreadingX',0) == 1);
  475. #process output of sender
  476. if (AttrVal($def->{$n}{NAME},'EIBreadingSender',0) == 1)
  477. {
  478. my $srcName = eib_hex2name($src);
  479. #debug
  480. print "sender = $srcName, group= $gnr, EIBreadingSender = AttrVal($def->{$n}{NAME},'EIBreadingSender',0)\n" if ($debug eq 1);
  481. readingsSingleUpdate($lh,'sender',$srcName,1);
  482. }
  483. Log3 $n, 5, "EIB parse write message $n $v";
  484. }
  485. # handle read messages, if Attribute is set
  486. elsif (($cmd =~ /[r]/) && (AttrVal($def->{$n}{NAME},'EIBanswerReading',0) == 1))
  487. {
  488. #debug
  489. print "group= $c, EIBanswerReading = AttrVal($def->{$n}{NAME},'EIBanswerReading',0)\n" if ($debug eq 1);
  490. #convert value from state
  491. my $tmp = EIB_EncodeByDatapointType($hash, $n, $lh->{STATE}, $gnr);
  492. #write answer
  493. TUL_Write($hash, "B", "p" . $c . $tmp);
  494. Log3 $n, 5, "EIB parse read message $n $v";
  495. }
  496. }
  497. }
  498. }
  499. }
  500. }
  501. return @list if $found>0;
  502. if($found==0)
  503. {
  504. my $dev_name = eib_hex2name($dev);
  505. Log3 $dev, 3, "EIB Unknown device $dev ($dev_name), Value $val, please define it";
  506. return "UNDEFINED EIB_$dev EIB $dev_name";
  507. }
  508. }
  509. ###################################
  510. sub
  511. EIB_EncodeByDatapointType($$$$) {
  512. my ($hash, $name, $value, $gnr) = @_;
  513. my @model_array = split(" ",$attr{$name}{"model"}) if (defined($attr{$name}{"model"}));
  514. my $model = $model_array[0];
  515. my $transval = undef;
  516. #no model defined
  517. if (!defined($model))
  518. {
  519. $model = "dpt1";
  520. Log3 $hash, 3,"EIB encode: no model defined for $name. Replaced with DPT1.";
  521. }
  522. #no gnr defined
  523. if (defined($gnr))
  524. {
  525. $model = $model_array[$gnr-1] if (defined($model_array[$gnr-1]));
  526. }
  527. else
  528. {
  529. Log3 $hash, 2,"EIB encode no gnr defined";
  530. return undef;
  531. }
  532. my $code = $eib_dpttypes{"$model"}{"CODE"};
  533. #invalid model defined
  534. if (!defined($code))
  535. {
  536. Log3 $hash, 1,"EIB encode: invalid model defined for $name. Breaking up...";
  537. return undef;
  538. }
  539. if (!defined($value))
  540. {
  541. Log3 $hash, 2,"EIB encode no value defined";
  542. return undef;
  543. }
  544. Log3 $hash, 5,"EIB_EncodeByDatapointType: $name, Value= $value, model= $model";
  545. my $dpt = $eib_dpttypes{"$model"};
  546. my $unit = $eib_dpttypes{"$model"}{"UNIT"};
  547. my $adjustment = $eib_dpttypes{"$model"}{"ADJUSTMENT"};
  548. if (defined ($adjustment) && defined ($unit))
  549. {
  550. Log3 $hash, 4,"EIB encode $value for $name model: $model dpt: $code unit: $unit";
  551. }
  552. #start with model-selection. Go through DPT's
  553. if ($code eq "dpt1")
  554. {
  555. my $fullval = "";
  556. #replace on/off
  557. $fullval = "00" if ($value eq "off");
  558. $fullval = "01" if ($value eq "on");
  559. #return value, if encode was successful
  560. if ($fullval ne "")
  561. {
  562. $transval = $fullval;
  563. }
  564. #if not return hex-data
  565. else
  566. {
  567. $transval = sprintf("%x", $value);
  568. }
  569. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  570. }
  571. elsif ($code eq "dpt3")
  572. {
  573. #4-bit steps
  574. my $rawval = $value;
  575. my $sign = undef;
  576. my $fullval = undef;
  577. #determine dim-direction, assuming positive direction by default
  578. if ($value =~ /^-/)
  579. {
  580. $value = -$value;
  581. $sign = 0;
  582. }
  583. else
  584. {
  585. $sign = 1;
  586. }
  587. #determine value
  588. if ($value >= 75)
  589. {
  590. #adjust 100%
  591. $fullval = 01;
  592. }
  593. elsif ($value >= 50)
  594. {
  595. #adjust 50%
  596. $fullval = 02;
  597. }
  598. elsif ($value >= 25)
  599. {
  600. #adjust 25%
  601. $fullval = 03;
  602. }
  603. elsif ($value >= 12)
  604. {
  605. #adjust 12%
  606. $fullval = 04;
  607. }
  608. elsif ($value >= 6)
  609. {
  610. #adjust 6%
  611. $fullval = 05;
  612. }
  613. elsif ($value >= 3)
  614. {
  615. #adjust 3%
  616. $fullval = 06;
  617. }
  618. elsif ($value >= 1)
  619. {
  620. #adjust 1%
  621. $fullval = 07;
  622. }
  623. elsif ($value >= 0)
  624. {
  625. #adjust 0%
  626. $fullval = 00;
  627. }
  628. else
  629. {
  630. #do nothing
  631. $fullval = undef;
  632. }
  633. #place signe
  634. if (defined ($fullval) && ($sign eq 1))
  635. {
  636. $fullval = $fullval | 8;
  637. }
  638. #make it hex
  639. $transval = sprintf("0%.1x",$fullval);
  640. Log3 $hash, 5,"EIB $code encode $rawval = sign $sign value $value to $fullval. Translated to hex $transval.";
  641. }
  642. elsif ($code eq "dpt5")
  643. {
  644. #1-byte unsigned
  645. my $dpt5factor = $eib_dpttypes{"$model"}{"factor"};
  646. my $fullval = sprintf("00%.2x",($value/$dpt5factor));
  647. $transval = $fullval;
  648. Log3 $hash, 5,"EIB $code encode $value = $fullval factor = $dpt5factor translated: $transval";
  649. }
  650. elsif ($code eq "dpt6")
  651. {
  652. #1-byte signed
  653. my $dpt6factor = $eib_dpttypes{"$model"}{"factor"};
  654. my $fullval = int($value/$dpt6factor);
  655. $fullval += 256 if ($fullval < 0);
  656. $fullval = 0 if ($fullval < 0);
  657. $fullval = 0xFF if ($fullval > 0xFF);
  658. $transval = sprintf("00%.2x",$fullval);
  659. Log3 $hash, 5,"EIB $code encode $value = $fullval factor = $dpt6factor translated: $transval";
  660. }
  661. elsif ($code eq "dpt7")
  662. {
  663. #2-byte unsigned
  664. my $fullval = "";
  665. if($adjustment eq "255")
  666. {
  667. $fullval = sprintf("00%.4x",($value/2.55));
  668. }
  669. else
  670. {
  671. $fullval = sprintf("00%.4x",$value);
  672. }
  673. $transval = $fullval;
  674. Log3 $hash, 5,"EIB $code encode $value = $fullval translated: $transval";
  675. }
  676. elsif($code eq "dpt9")
  677. {
  678. #2-byte float
  679. my $fullval;
  680. my $sign = ($value <0 ? 0x8000 : 0);
  681. my $exp = 0;
  682. my $mant = 0;
  683. $mant = int($value * 100.0);
  684. while (abs($mant) > 2047) {
  685. $mant /= 2;
  686. $exp++;
  687. }
  688. $fullval = $sign | ($exp << 11) | ($mant & 0x07ff);
  689. $transval = sprintf("00%.4x",$fullval);
  690. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  691. }
  692. elsif ($code eq "dpt10")
  693. {
  694. # Time
  695. my $fullval = 0;
  696. my ($hh, $mm, $ss) = split /:/, $value;
  697. $fullval = $ss + ($mm<<8) + (($hh)<<16);
  698. $transval = sprintf("00%.6x",$fullval);
  699. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  700. }
  701. elsif ($code eq "dpt10_ns")
  702. {
  703. # Time, seconds = zero
  704. my $fullval = 0;
  705. my ($hh, $mm, $ss) = split /:/, $value;
  706. $ss = 0;
  707. $fullval = $ss + ($mm<<8) + (($hh)<<16);
  708. $transval = sprintf("00%.6x",$fullval);
  709. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  710. }
  711. elsif ($code eq "time")
  712. {
  713. # current Time
  714. my ($secs,$mins,$hours,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  715. $year+=1900;
  716. $mon++;
  717. my $fullval = 0;
  718. # calculate offset for weekday
  719. $wday = 7 if ($wday eq "0");
  720. my $hoffset = 32*$wday;
  721. $fullval = $secs + ($mins<<8) + (($hoffset + $hours)<<16);
  722. $value = sprintf("%02d:%02d:%02d",$hours,$mins,$secs); # value for log
  723. $transval = sprintf("00%.6x",$fullval);
  724. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  725. }
  726. elsif ($code eq "dpt11")
  727. {
  728. # Date
  729. my $fullval = 0;
  730. my ($dd, $mm, $yyyy) = split /\./, $value;
  731. $fullval = ($yyyy - 2000) + ($mm<<8) + ($dd<<16);
  732. $transval = sprintf("00%.6x",$fullval);
  733. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  734. }
  735. elsif ($code eq "date")
  736. {
  737. # current Date
  738. my ($secs,$mins,$hours,$day,$month,$year,$wday,$yday,$isdst) = localtime(time);
  739. $year+=1900;
  740. $month++;
  741. my $fullval = 0;
  742. #encode current date
  743. $fullval = ($year-2000) + ($month<<8) + ($day<<16);
  744. $transval = sprintf("00%.6x",$fullval);
  745. Log3 $hash, 5,"EIB $code encode $value = $fullval day: $day month: $month year: $year translated: $transval";
  746. }
  747. elsif ($code eq "dpt12")
  748. {
  749. #4-byte unsigned
  750. my $fullval = sprintf("00%.8x",$value);
  751. $transval = $fullval;
  752. Log3 $hash, 5,"EIB $code encode $value" . '=' . " $fullval translated: $transval";
  753. }
  754. elsif ($code eq "dpt13")
  755. {
  756. #4-byte signed
  757. my $dpt13factor = $eib_dpttypes{"$model"}{"factor"};
  758. my $fullval = int($value/$dpt13factor);
  759. $fullval += 4294967296 if ($fullval < 0);
  760. $fullval = 0 if ($fullval < 0);
  761. $fullval = 0xFFFFFFFF if ($fullval > 0xFFFFFFFF);
  762. $transval = sprintf("00%.8x",$fullval);
  763. Log3 $hash, 5,"EIB $code encode $value = $fullval factor = $dpt13factor translated: $transval";
  764. }
  765. elsif($code eq "dpt14")
  766. {
  767. #4-byte float
  768. my $fullval;
  769. $fullval = unpack("L", pack("f", $value));
  770. $transval = sprintf("00%.8x", $fullval);
  771. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  772. }
  773. elsif ($code eq "dpt16")
  774. {
  775. #text
  776. my $dat = $value;
  777. #convert to hex-string
  778. $dat =~ s/(.)/sprintf("%x",ord($1))/eg;
  779. #format for 14-byte-length
  780. $dat = sprintf("%-028s",$dat);
  781. #append leading zeros
  782. $dat = "00" . $dat;
  783. $transval = $dat;
  784. Log3 $hash, 5,"EIB $code encode $value translated: $transval";
  785. }
  786. elsif ($code eq "dptxx")
  787. {
  788. }
  789. # set state to translated value
  790. if(defined($transval))
  791. {
  792. Log3 $hash, 4,"EIB $name translated $value to $transval";
  793. $value = "$transval";
  794. }
  795. return $value;
  796. }
  797. sub
  798. EIB_ParseByDatapointType($$$$)
  799. {
  800. my ($hash, $name, $value, $gnr) = @_; #MH
  801. my @model_array = split(" ",$attr{$name}{"model"}) if (defined($attr{$name}{"model"}));
  802. my $model = $model_array[0];
  803. # nothing to do if no model is given
  804. #return $value if(!defined($model));
  805. if (defined($gnr))
  806. {
  807. $model = $model_array[$gnr-1] if defined ($model_array[$gnr-1]);
  808. }
  809. #debug
  810. print "EIB_ParseByDatapointType: $name, val= $value, Group= $gnr, Model= $model \n" if ($debug eq 1);
  811. #no model defined
  812. if (!defined($model))
  813. {
  814. $model = "dpt1";
  815. Log3 $hash, 3,"EIB encode: no model defined for $name. Replaced with DPT1.";
  816. }
  817. my $code = $eib_dpttypes{"$model"}{"CODE"};
  818. #invalid model defined
  819. if (!defined($code))
  820. {
  821. Log3 $hash, 1,"EIB encode: invalid model defined for $name. Breaking up....";
  822. return undef;
  823. }
  824. my $dpt = $eib_dpttypes{"$model"};
  825. my $unit = $eib_dpttypes{"$model"}{"UNIT"};
  826. my $transval = undef;
  827. Log3 $hash, 5,"EIB parse $value for $name model: $model dpt: $code unit: $unit";
  828. #debug
  829. print "EIB_ParseByDatapointType: $name, val= $value, Group= $gnr, Model= $model, code= $code, unit= $unit \n" if ($debug eq 1);
  830. #moved to the front... - execute if DPT is NOT 1
  831. if ($code ne "dpt1")
  832. {
  833. $value = 0 if ($value eq "off");
  834. $value = 1 if ($value eq "on");
  835. }
  836. #correct value in realtion to potential non-compatible states
  837. if ($code eq "dpt1")
  838. {
  839. #1-bit
  840. $value = "off" if ($value eq 0);
  841. $value = "on" if ($value eq 1);
  842. $transval = $value;
  843. }
  844. elsif ($code eq "dpt3")
  845. {
  846. #4-bit steps
  847. my $rawval = $value;
  848. my $sign = undef;
  849. my $fullval = undef;
  850. #make it decimal
  851. $value = hex ($value);
  852. #determine dim-direction
  853. if ($value & 8)
  854. {
  855. $sign = "+";
  856. }
  857. else
  858. {
  859. $sign = "-";
  860. }
  861. #mask it...
  862. $value = $value & 7;
  863. #determine value
  864. if ($value == 7)
  865. {
  866. #adjust 1%
  867. $fullval = 1;
  868. }
  869. elsif ($value == 6)
  870. {
  871. #adjust 3%
  872. $fullval = 3;
  873. }
  874. elsif ($value == 5)
  875. {
  876. #adjust 6%
  877. $fullval = 6;
  878. }
  879. elsif ($value == 4)
  880. {
  881. #adjust 12%
  882. $fullval = 12;
  883. }
  884. elsif ($value == 3)
  885. {
  886. #adjust 25%
  887. $fullval = 25;
  888. }
  889. elsif ($value == 2)
  890. {
  891. #adjust 50%
  892. $fullval = 50;
  893. }
  894. elsif ($value == 1)
  895. {
  896. #adjust 100%
  897. $fullval = 100;
  898. }
  899. elsif ($value == 0)
  900. {
  901. #adjust 0%
  902. $fullval = 0;
  903. }
  904. else
  905. {
  906. #do nothing
  907. $fullval = undef;
  908. }
  909. if (defined ($sign) && defined ($fullval))
  910. {
  911. $transval = "$sign$fullval";
  912. }
  913. Log3 $hash, 5,"EIB $code decode $rawval = sign $sign value $value to $fullval";
  914. }
  915. elsif ($code eq "dpt5")
  916. {
  917. #1-byte unsigned
  918. my $dpt5factor = $eib_dpttypes{"$model"}{"factor"};
  919. my $fullval = hex($value);
  920. $transval = $fullval;
  921. $transval = sprintf("%.0f",$transval * $dpt5factor) if($dpt5factor != 0);
  922. }
  923. elsif ($code eq "dpt6")
  924. {
  925. my $dpt6factor = $eib_dpttypes{"$model"}{"factor"};
  926. my $fullval = hex($value);
  927. $transval = $fullval;
  928. $transval -= 256 if $transval >= 0x80;
  929. $transval = sprintf("%.0f",$transval * $dpt6factor) if($dpt6factor != 0);
  930. }
  931. elsif ($code eq "dpt7")
  932. {
  933. #2-byte unsigned
  934. my $fullval = hex($value);
  935. $transval = $fullval;
  936. }
  937. elsif($code eq "dpt9")
  938. {
  939. #2-bate float
  940. my $fullval = hex($value);
  941. my $sign = 1;
  942. $sign = -1 if(($fullval & 0x8000)>0);
  943. my $exp = ($fullval & 0x7800)>>11;
  944. my $mant = ($fullval & 0x07FF);
  945. $mant = -(~($mant-1)&0x07FF) if($sign==-1);
  946. $transval = (1<<$exp)*0.01*$mant;
  947. }
  948. elsif ($code eq "dpt10")
  949. {
  950. # Time
  951. my $fullval = hex($value);
  952. my $hours = ($fullval & 0x1F0000)>>16;
  953. my $mins = ($fullval & 0x3F00)>>8;
  954. my $secs = ($fullval & 0x3F);
  955. $transval = sprintf("%02d:%02d:%02d",$hours,$mins,$secs);
  956. }
  957. elsif ($code eq "dpt10_ns")
  958. {
  959. # Time without seconds
  960. my $fullval = hex($value);
  961. my $hours = ($fullval & 0x1F0000)>>16;
  962. my $mins = ($fullval & 0x3F00)>>8;
  963. my $secs = ($fullval & 0x3F);
  964. $transval = sprintf("%02d:%02d",$hours,$mins);
  965. }
  966. elsif ($code eq "time")
  967. {
  968. # Time
  969. my $fullval = hex($value);
  970. my $hours = ($fullval & 0x1F0000)>>16;
  971. my $mins = ($fullval & 0x3F00)>>8;
  972. my $secs = ($fullval & 0x3F);
  973. $transval = sprintf("%02d:%02d:%02d",$hours,$mins,$secs);
  974. }
  975. elsif ($code eq "dpt11")
  976. {
  977. # Date
  978. my $fullval = hex($value);
  979. my $day = ($fullval & 0x1F0000)>>16;
  980. my $month = ($fullval & 0x0F00)>>8;
  981. my $year = ($fullval & 0x7F);
  982. #translate year (21st cent if <90 / else 20th century)
  983. $year += 1900 if($year>=90);
  984. $year += 2000 if($year<90);
  985. $transval = sprintf("%02d.%02d.%04d",$day,$month,$year);
  986. }
  987. elsif ($code eq "date")
  988. {
  989. # Date
  990. my $fullval = hex($value);
  991. my $day = ($fullval & 0x1F0000)>>16;
  992. my $month = ($fullval & 0x0F00)>>8;
  993. my $year = ($fullval & 0x7F);
  994. #translate year (21st cent if <90 / else 20th century)
  995. $year += 1900 if($year>=90);
  996. $year += 2000 if($year<90);
  997. $transval = sprintf("%02d.%02d.%04d",$day,$month,$year);
  998. }
  999. elsif ($code eq "dpt12")
  1000. {
  1001. #4-bate unsigned
  1002. my $fullval = hex($value);
  1003. $transval = $fullval;
  1004. }
  1005. elsif ($code eq "dpt13")
  1006. {
  1007. my $dpt13factor = $eib_dpttypes{"$model"}{"factor"};
  1008. my $fullval = hex($value);
  1009. $transval = $fullval;
  1010. $transval -= 4294967296 if $transval >= 0x80000000;
  1011. $transval = sprintf("%.0f",$transval * $dpt13factor) if($dpt13factor != 0);
  1012. }
  1013. elsif ($code eq "dpt14")
  1014. {
  1015. # 4-byte float
  1016. my $fullval;
  1017. $fullval = unpack "f", pack "L", hex $value;
  1018. $transval = sprintf ("%f","$fullval");
  1019. }
  1020. elsif ($code eq "dpt16")
  1021. {
  1022. #text
  1023. $transval = "";
  1024. for (my $i=0;$i<14;$i++)
  1025. {
  1026. my $c = hex(substr($value,$i*2,2));
  1027. if ($c eq 0)
  1028. {
  1029. $i = 14;
  1030. }
  1031. else
  1032. {
  1033. $transval .= sprintf("%c", $c);
  1034. }
  1035. }
  1036. }
  1037. elsif ($code eq "dptxx")
  1038. {
  1039. }
  1040. # set state to translated value
  1041. if(defined($transval))
  1042. {
  1043. Log3 $hash, 4, "EIB_ParseByDatapointType: $name, origval= $value, transval= $transval, Group= $gnr, Model= $model, code= $code, unit= $unit";
  1044. print "EIB_ParseByDatapointType: $name, origval= $value, transval= $transval, Group= $gnr, Model= $model, code= $code, unit= $unit \n" if ($debug eq 1);
  1045. $value = "$transval $unit";
  1046. $value =~ s/^\s+|\s+$//g;
  1047. }
  1048. else
  1049. {
  1050. Log3 $hash, 4, "EIB_ParseByDatapointType: $name, origval= $value could not be translated, Group= $gnr, Model= $model, code= $code, unit= $unit"; #MH
  1051. }
  1052. return $value;
  1053. }
  1054. #############################
  1055. sub
  1056. eib_hex2name($)
  1057. {
  1058. my $v = shift;
  1059. my $p1 = hex(substr($v,0,1));
  1060. my $p2 = hex(substr($v,1,1));
  1061. my $p3 = hex(substr($v,2,2));
  1062. my $r = sprintf("%d/%d/%d", $p1,$p2,$p3);
  1063. return $r;
  1064. }
  1065. #############################
  1066. sub
  1067. eib_name2hex($)
  1068. {
  1069. my $v = shift;
  1070. my $r = $v;
  1071. # Log(5, "name2hex: $v");
  1072. if($v =~ /^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{1,3})$/) {
  1073. $r = sprintf("%01x%01x%02x",$1,$2,$3);
  1074. }
  1075. elsif($v =~ /^([0-9]{1,2})\.([0-9]{1,2})\.([0-9]{1,3})$/) {
  1076. $r = sprintf("%01x%01x%02x",$1,$2,$3);
  1077. }
  1078. return $r;
  1079. }
  1080. 1;
  1081. =pod
  1082. =item summary Communicates to EIB via TUL (deprecated, use KNX)
  1083. =item summary_DE Kommuniziert mit EIB über TUL (veraltet, nutze KNX)
  1084. =begin html
  1085. <a name="EIB"></a>
  1086. <h3>EIB / KNX</h3>
  1087. <div>
  1088. <p>EIB/KNX is a standard for building automation / home automation.
  1089. It is mainly based on a twisted pair wiring, but also other mediums (ip, wireless) are specified.</p>
  1090. <p>While the module <a href="#TUL">TUL</a> represents the connection to the EIB network,
  1091. the EIB modules represent individual EIB devices. This module provides a basic set of operations (on, off, on-till, etc.)
  1092. to switch on/off EIB devices. Sophisticated setups can be achieved by combining a number of
  1093. EIB module instances or by sending raw hex values to the network (set &lt;devname&gt; raw &lt;hexval&gt;).</p>
  1094. <p>EIB/KNX defines a series of Datapoint Type as standard data types used
  1095. to allow general interpretation of values of devices manufactured by different companies.
  1096. These datatypes are used to interpret the status of a device, so the state in FHEM will then
  1097. show the correct value.</p>
  1098. <p><a name="EIBdefine"></a> <b>Define</b></p>
  1099. <div>
  1100. <code>define &lt;name&gt; EIB &lt;main group&gt; [&lt;additional group&gt; ..]</code>
  1101. <p>Define an EIB device, connected via a <a href="#TUL">TUL</a>. The
  1102. &lt;group&gt; parameters are either a group name notation (0-15/0-15/0-255) or the hex representation of the value (0-f0-f0-ff).
  1103. The &lt;main group&gt; is used for sending of commands to the EIB network.</p>
  1104. <p>The state of the instance will be updated when a new state is received from the network for any of the given groups.
  1105. This is useful for example for toggle switches where a on command is send to one group and the real state (on or off) is
  1106. responded back on a second group.</p>
  1107. <p>For actors and sensors the <a href="#autocreate">autocreate</a> module may help.</p>
  1108. <p>Example:</p>
  1109. <pre>
  1110. define lamp1 EIB 0/10/12
  1111. define lamp1 EIB 0/10/12 0/0/5
  1112. define lamp1 EIB 0A0C
  1113. </pre>
  1114. </div>
  1115. <p><a name="EIBset"></a> <b>Set</b></p>
  1116. <div>
  1117. <code>set &lt;name&gt; &lt;value&gt; [&lt;time&gt; g&lt;groupnr&gt;]</code>
  1118. <p>where value one of:</p>
  1119. <li><b>on</b> switch on device</li>
  1120. <li><b>off</b> switch off device</li>
  1121. <li><b>on-for-timer</b> &lt;secs&gt; switch on the device for the given time. After the specified seconds a switch off command is sent.</li>
  1122. <li><b>on-till</b> &lt;time spec&gt; switches the device on. The device will be switched off at the given time.</li>
  1123. <li><b>raw</b> &lt;hexvalue&gt; sends the given value as raw data to the device.</li>
  1124. <li><b>value</b> &lt;decimal value&gt; transforms the value according to the chosen model and send the result to the device.</li>
  1125. <p>Example:</p>
  1126. <pre>
  1127. set lamp1 on
  1128. set lamp1 off
  1129. set lamp1 on-for-timer 10
  1130. set lamp1 on-till 13:15:00
  1131. set lamp1 raw 234578
  1132. set lamp1 value 23.44
  1133. </pre>
  1134. <p>When as last argument a g&lt;groupnr&gt; is present, the command will be sent
  1135. to the EIB group indexed by the groupnr (starting by 1, in the order as given in Define).</p>
  1136. <pre>
  1137. define lamp1 EIB 0/10/01 0/10/02
  1138. set lamp1 on g2 (will send "on" to 0/10/02)
  1139. </pre>
  1140. <p>A dimmer can be used with a slider as shown in following example:</p>
  1141. <pre>
  1142. define dim1 EIB 0/0/5
  1143. attr dim1 model percent
  1144. attr dim1 webCmd value
  1145. </pre>
  1146. <p>The current date and time can be sent to the bus by the following settings:</p>
  1147. <pre>
  1148. define timedev EIB 0/0/7
  1149. attr timedev model time
  1150. attr timedev eventMap /value now:now/
  1151. attr timedev webCmd now
  1152. define datedev EIB 0/0/8
  1153. attr datedev model date
  1154. attr datedev eventMap /value now:now/
  1155. attr datedev webCmd now
  1156. # send every midnight the new date
  1157. define dateset at *00:00:00 set datedev value now
  1158. # send every hour the current time
  1159. define timeset at +*01:00:00 set timedev value now
  1160. </pre>
  1161. </div>
  1162. <p><a name="EIBget"></a> <b>Get</b></p>
  1163. <div>
  1164. <p>If you execute get for a EIB/KNX-Element there will be requested a state from the device. The device has to be able to respond to a read - this is not given for all devices.<br>
  1165. The answer from the bus-device is not shown in the toolbox, but is treated like a regular telegram.</p>
  1166. </div>
  1167. <p><a name="EIBattr"></a> <b>Attributes</b></p>
  1168. <div>
  1169. <a href="#IODev">IODev</a><br>
  1170. <a href="#alias">alias</a><br>
  1171. <a href="#comment">comment</a><br>
  1172. <a href="#devStateIcon">devStateIcon</a><br>
  1173. <a href="#devStateStyle">devStateStyle</a><br>
  1174. <a href="#do_not_notify">do_not_notify</a><br>
  1175. <a href="#dummy">dummy</a><br>
  1176. <a href="#readingFnAttributes">readingFnAttributes</a><br>
  1177. <a href="#event-aggregator">event-aggregator</a><br>
  1178. <a href="#event-min-interval">event-min-interval</a><br>
  1179. <a href="#event-on-change-reading">event-on-change-reading</a><br>
  1180. <a href="#event-on-update-reading">event-on-update-reading</a><br>
  1181. <a href="#eventMap">eventMap</a><br>
  1182. <a href="#group">group</a><br>
  1183. <a href="#icon">icon</a><br>
  1184. <a href="#ignore">ignore</a><br>
  1185. <a href="#room">room</a><br>
  1186. <a href="#showtime">showtime</a><br>
  1187. <a href="#sortby">sortby</a><br>
  1188. <a href="#stateFormat">stateFormat</a><br>
  1189. <a href="#userReadings">userReadings</a><br>
  1190. <a href="#userattr">userattr</a><br>
  1191. <a href="#verbose">verbose</a><br>
  1192. <a href="#webCmd">webCmd</a><br>
  1193. <a href="#widgetOverride">widgetOverride</a><br>
  1194. <br>
  1195. <p><a name="EIBreadingX"></a> <b>EIBreadingX</b></p>
  1196. <div>
  1197. Enable additional readings for this EIB-device. With this Attribute set, a reading setG&lt;x&gt; will be updated when a set command is issued from FHEM, a reading getG&lt;x&gt; will be updated as soon a Value is received from EIB-Bus (&lt;x&gt; stands for the groupnr. - see define statement). The logic for the state reading remains unchanged. This is especially useful when the define statement contains more than one group parameter.
  1198. <p>If set to 1, the following additional readings will be available:</p>
  1199. <pre>
  1200. setGx will be updated on a SET command issued by FHEM. &lt;x&gt; stands for the groupnr. - see define statement
  1201. getGx will be updated on reception of a message from EIB-bus.
  1202. </pre>
  1203. <p>Example:</p>
  1204. <pre>
  1205. define myDimmer EIB 0/1/1 0/1/2
  1206. attr myDimmer EIBreadingX 1
  1207. attr myDimmer model dpt1 dpt5 # GA 0/1/1 will be interpreted as on/off, GA 0/1/2 will be handled as dpt5
  1208. attr myDimmer stateFormat getG2 % # copies actual dim-level (as received from dimmer) into STATE
  1209. </pre>
  1210. <p>If the EIBreadingX is set, you can specify multiple blank separated models to cope with multiple groups in the define statement. The setting cannot be done thru the pulldown-menu, you have to specify them with <code>attr &lt;device&gt; model &lt;dpt1&gt; &lt;dpt2&gt; &lt;dpt3&gt;</code></p>
  1211. </div>
  1212. <p><a name="EIBreadingSender"></a> <b>EIBreadingSender</b></p>
  1213. <div>
  1214. Enable an additional reading for this EIB-device. With this Attribute set, a reading sender will be updated any time a new telegram arrives.
  1215. <p>If set to 1, the following additional reading will be available: <pre>sender</pre></p>
  1216. <pre>
  1217. sender will be updated any time a new telegram arrives at this group-adress
  1218. </pre>
  1219. <p>Example:</p>
  1220. <pre>
  1221. define myDimmer EIB 0/1/1
  1222. attr myDimmer EIBreadingSender 1
  1223. </pre>
  1224. </div>
  1225. <p><a name="EIBanswerReading"></a> <b>EIBanswerReading</b></p>
  1226. <div>
  1227. If enabled, FHEM answers on read requests. The content of state is send to the bus as answer.
  1228. <p>If set to 1, read-requests are answered</p>
  1229. <p>Example:</p>
  1230. <pre>
  1231. define myValue EIB 0/1/1
  1232. attr myValue EIBanswerReading 1
  1233. </pre>
  1234. </div>
  1235. <p><a name="EIBreadingRegex"></a> <b>EIBreadingRegex</b></p>
  1236. <div>
  1237. You can pass n pairs of regex-pattern and string to replace, seperated by a slash. Internally the "new" state is always in the format getG[n]:[state]. The substitution is done every time, a new object is received. You can use this function for converting, adding units, having more fun with icons, ...
  1238. This function has only an impact on the content of state - no other functions are disturbed.
  1239. <p>Example:</p>
  1240. <pre>
  1241. define myLamp EIB 0/1/1 0/1/2 0/1/2
  1242. attr myLamp EIBreadingRegex getG[1]:/steuern: getG[2]:/status: getG[3]:/sperre:
  1243. attr myLamp EIBreadingRegex devStateIcon status.on:general_an status.off:general_aus sperre.on:lock
  1244. </pre>
  1245. </div>
  1246. <p><a name="EIBwritingRegex"></a> <b>EIBwritingRegex</b></p>
  1247. You can pass n pairs of regex-pattern and string to replace, seperated by a slash. Internally the "new" state is always in the format setG1:[state]. The substitution is done every time, after an object is send. You can use this function for converting, adding units, having more fun with icons, ...
  1248. This function has only an impact on the content of state - no other functions are disturbed.
  1249. <p>Example:</p>
  1250. <pre>
  1251. define myLockObject EIB 0/1/1
  1252. attr myLamp EIBwritingRegex setG1:on/LOCKED setG1:/UNLOCKED
  1253. </pre>
  1254. </div>
  1255. <p><a name="model"></a> <b>model</b></p>
  1256. <div>
  1257. <p>This attribute is mandatory!</p>
  1258. Set the model according to the datapoint types defined by the (<a href="http://www.sti.uniurb.it/romanell/110504-Lez10a-KNX-Datapoint%20Types%20v1.5.00%20AS.pdf" target="_blank">EIB / KNX specifications</a>). The device state in FHEM is interpreted and shown according to the specification.<br>
  1259. <br>
  1260. <U>dpt1</U> - 1 bit<br>
  1261. Will be interpreted as on/off, 1=on 0=off and vice versa<br>
  1262. <br>
  1263. <U>dpt3</U> - Discrete Dim-Message<br>
  1264. Usage: set value to +/-0..100. -54 means dim down by 50%<br>
  1265. <br>
  1266. <U>dpt5</U> - 1 byte unsigned<br>
  1267. dpt5.003 - angle in degrees<br>
  1268. angle - same as dpt5.003<br>
  1269. dpt5.004 - percent<br>
  1270. percent - same as above<br>
  1271. percent255 - scaled percentage: 255=100%<br>
  1272. <br>
  1273. <U>dpt6</U> - 1 byte signed <br>
  1274. dpt6.001 - percent<br>
  1275. dpt6.010<br>
  1276. <br>
  1277. <U>dpt7</U> - 2 byte unsigned<br>
  1278. length - mm<br>
  1279. current - mA<br>
  1280. brightness<br>
  1281. timeperiod - ms<br>
  1282. timeperiod - min<br>
  1283. timeperiod - h<br>
  1284. <br>
  1285. <U>dpt9</U> - 2 byte float<br>
  1286. tempsensor<br>
  1287. lightsensor<br>
  1288. speedsensor<br>
  1289. speedsensor-km/h<br>
  1290. pressuresensor<br>
  1291. rainsensor<br>
  1292. time1sensor<br>
  1293. time2sensor<br>
  1294. humiditysensor<br>
  1295. airqualitysensor<br>
  1296. voltage-mV<br>
  1297. current-mA2<br>
  1298. current-mA2<br>
  1299. power<br>
  1300. powerdensity<br>
  1301. <br>
  1302. <U>dpt10</U> - time hh:mm:ss<br>
  1303. dpt10_ns - same as DPT10, seconds always 0<br>
  1304. time - receiving has no effect, sending any value contains actual system time. For examle use set timedev value now<br>
  1305. <br>
  1306. <U>dpt11</U> - date dd.mm.yyyy<br>
  1307. date - receiving has no effect, sending any value contains actual system date. For examle use set timedev value now<br>
  1308. <br>
  1309. <U>dpt12</U> - 4 byte unsigned<br>
  1310. <br>
  1311. <U>dpt13</U> - 4 byte signed<br>
  1312. <br>
  1313. <U>dpt14</U> - 4 byte float<br>
  1314. <br>
  1315. <U>dpt16</U> - text, use with "string": set textdev string Hallo Welt<br>
  1316. </div>
  1317. </div>
  1318. =end html
  1319. =cut