11_FHT.pm 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
  1. # $Id: 11_FHT.pm 16293 2018-02-28 21:33:57Z rudolfkoenig $
  2. ##############################################################################
  3. #
  4. # 11_FHT.pm
  5. # Copyright by
  6. # e-mail:
  7. #
  8. # This file is part of FHEM.
  9. #
  10. # Fhem is free software: you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation, either version 2 of the License, or
  13. # (at your option) any later version.
  14. #
  15. # Foobar is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with FHEM. If not, see <http://www.gnu.org/licenses/>.
  22. #
  23. ##############################################################################
  24. package main;
  25. use strict;
  26. use warnings;
  27. sub doSoftBuffer($);
  28. sub softBufferTimer($);
  29. sub getFhtMin($);
  30. sub getFhtBuffer($);
  31. my %codes = (
  32. "00" => "actuator",
  33. "01" => "actuator1",
  34. "02" => "actuator2",
  35. "03" => "actuator3",
  36. "04" => "actuator4",
  37. "05" => "actuator5",
  38. "06" => "actuator6",
  39. "07" => "actuator7",
  40. "08" => "actuator8",
  41. "14" => "mon-from1",
  42. "15" => "mon-to1",
  43. "16" => "mon-from2",
  44. "17" => "mon-to2",
  45. "18" => "tue-from1",
  46. "19" => "tue-to1",
  47. "1a" => "tue-from2",
  48. "1b" => "tue-to2",
  49. "1c" => "wed-from1",
  50. "1d" => "wed-to1",
  51. "1e" => "wed-from2",
  52. "1f" => "wed-to2",
  53. "20" => "thu-from1",
  54. "21" => "thu-to1",
  55. "22" => "thu-from2",
  56. "23" => "thu-to2",
  57. "24" => "fri-from1",
  58. "25" => "fri-to1",
  59. "26" => "fri-from2",
  60. "27" => "fri-to2",
  61. "28" => "sat-from1",
  62. "29" => "sat-to1",
  63. "2a" => "sat-from2",
  64. "2b" => "sat-to2",
  65. "2c" => "sun-from1",
  66. "2d" => "sun-to1",
  67. "2e" => "sun-from2",
  68. "2f" => "sun-to2",
  69. "3e" => "mode",
  70. "3f" => "holiday1", # Not verified
  71. "40" => "holiday2", # Not verified
  72. "41" => "desired-temp",
  73. "XX" => "measured-temp", # sum of next. two, never really sent
  74. "42" => "measured-low",
  75. "43" => "measured-high",
  76. "44" => "warnings",
  77. "45" => "manu-temp", # No clue what it does.
  78. "4b" => "ack",
  79. "53" => "can-xmit",
  80. "54" => "can-rcv",
  81. "60" => "year",
  82. "61" => "month",
  83. "62" => "day",
  84. "63" => "hour",
  85. "64" => "minute",
  86. "65" => "report1",
  87. "66" => "report2",
  88. "69" => "ack2",
  89. "7d" => "start-xmit",
  90. "7e" => "end-xmit",
  91. "82" => "day-temp",
  92. "84" => "night-temp",
  93. "85" => "lowtemp-offset", # Alarm-Temp.-Differenz
  94. "8a" => "windowopen-temp",
  95. );
  96. my %cantset = (
  97. "actuator" => 1,
  98. "actuator1" => 1,
  99. "actuator2" => 1,
  100. "actuator3" => 1,
  101. "actuator4" => 1,
  102. "actuator5" => 1,
  103. "actuator6" => 1,
  104. "actuator7" => 1,
  105. "actuator8" => 1,
  106. "ack" => 1,
  107. "ack2" => 1,
  108. "battery" => 1,
  109. "can-xmit" => 1,
  110. "can-rcv" => 1,
  111. "start-xmit" => 1,
  112. "end-xmit" => 1,
  113. "lowtemp" => 1,
  114. "measured-temp" => 1,
  115. "measured-high" => 1,
  116. "measured-low" => 1,
  117. "warnings" => 1,
  118. "window" => 1,
  119. "windowsensor" => 1,
  120. );
  121. # additional warnings
  122. my %warnings = (
  123. "battery" => 1,
  124. "lowtemp" => 1,
  125. "window" => 1,
  126. "windowsensor" => 1,
  127. );
  128. my %priority = (
  129. "desired-temp"=> 1,
  130. "mode" => 2,
  131. "report1" => 3,
  132. "report2" => 3,
  133. "holiday1" => 4,
  134. "holiday2" => 5,
  135. "day-temp" => 6,
  136. "night-temp" => 7,
  137. );
  138. my %c2m = (0 => "auto", 1 => "manual", 2 => "holiday", 3 => "holiday_short");
  139. my %m2c; # Reverse c2m
  140. my %c2b; # command->button hash (reverse of codes)
  141. my %c2bset; # command->button hash (settable values)
  142. my $defmin = 0; # min fhtbuf free bytes before sending commands
  143. my $retryafter = 240; # in seconds, only when fhtsoftbuffer is active
  144. my $cmdcount = 0;
  145. #####################################
  146. sub
  147. FHT_Initialize($)
  148. {
  149. my ($hash) = @_;
  150. foreach my $k (keys %codes) {
  151. my $v = $codes{$k};
  152. $c2b{$v} = $k;
  153. $c2bset{$v} = $k if(!$cantset{$v});
  154. }
  155. foreach my $k (keys %c2m) {
  156. $m2c{$c2m{$k}} = $k;
  157. }
  158. # { Dispatch($defs{CUL}, "810b04028309830151024130001d", undef) }
  159. # 810c0426 0909a001 1111 1600
  160. # 810c04b3 0909a001 1111 44006900
  161. # 810b0402 83098301 1111 41301d
  162. # 81090421 c409c401 1111 00
  163. # 810c0d20 0909a001 3232 7e006724 (NYI)
  164. $hash->{Match} = "^81..(04|09|0d)..(0909a001|83098301|c409c401)..";
  165. $hash->{SetFn} = "FHT_Set";
  166. $hash->{DefFn} = "FHT_Define";
  167. $hash->{UndefFn} = "FHT_Undef";
  168. $hash->{ParseFn} = "FHT_Parse";
  169. $hash->{StateFn} = "FHT_State";
  170. $hash->{AttrList} = "IODev do_not_notify:1,0 model:fht80b dummy:1,0 " .
  171. "showtime:1,0 retrycount " .
  172. "minfhtbuffer lazy tmpcorr ignore:1,0 ".
  173. $readingFnAttributes;
  174. $hash->{AutoCreate}=
  175. { "FHT.*" => { GPLOT => "fht:Temp/Act,", FILTER => "%NAME" } };
  176. }
  177. sub
  178. FHT_Set($@)
  179. {
  180. my ($hash, @a) = @_;
  181. my $ret = "";
  182. return "\"set $a[0]\" needs at least two parameters" if(@a < 2);
  183. my $name = shift(@a);
  184. # Replace refreshvalues with report1 and report2, and time with hour/minute
  185. for(my $i = 0; $i < @a; $i++) {
  186. splice(@a,$i,1,("report1","255","report2","255"))
  187. if($a[$i] eq "refreshvalues");
  188. if($a[$i] eq "time") {
  189. my @t = localtime;
  190. splice(@a,$i,1,("hour",$t[2],"minute",$t[1]));
  191. }
  192. if($a[$i] eq "date") {
  193. my @t = localtime;
  194. splice(@a,$i,1,("year",$t[5]-100,"month",$t[4]+1,"day",$t[3]));
  195. }
  196. }
  197. my $ncmd = 0;
  198. my $arg = "020183" . $hash->{CODE};
  199. my ($cmd, $allcmd, $val) = ("", "", "");
  200. my $lazy= defined($attr{$name}) &&
  201. defined($attr{$name}{"lazy"}) &&
  202. ($attr{$name}{"lazy"}>0);
  203. my $readings= $hash->{READINGS};
  204. while(@a) {
  205. $cmd = shift(@a);
  206. if(!defined($c2b{$cmd})) {
  207. my $cmdList = join(" ",sort keys %c2bset);
  208. my @list = map { ($_.".0", $_+0.5) } (6..30);
  209. pop @list;
  210. my $tmpList="on,off,".join(",",@list);
  211. $cmdList =~ s/-temp/-temp:$tmpList/g; # FHEMWEB sugar
  212. $cmdList =~ s/(-from.|-to.)/$1:time/g;
  213. return "Unknown argument $cmd, choose one of $cmdList";
  214. }
  215. return "Readonly parameter $cmd"
  216. if(defined($cantset{$cmd}));
  217. return "\"set $name $cmd\" needs a parameter"
  218. if(@a < 1);
  219. $val = shift(@a);
  220. $arg .= $c2b{$cmd};
  221. if ($cmd =~ m/-temp/) {
  222. if(!($val eq "on" || $val eq "off" ||
  223. ($val =~ m/^\d*\.?\d+$/ && $val >= 5.5 && $val <= 30.5))) {
  224. my @list = map { ($_.".0", $_+0.5) } (6..30);
  225. pop @list;
  226. return "Invalid temperature $val, choose one of on off "
  227. . join(" ",@list);
  228. }
  229. $val = 30.5 if($val eq "on");
  230. $val = 5.5 if($val eq "off");
  231. my $a = int($val*2);
  232. $arg .= sprintf("%02x", $a);
  233. $val = sprintf("%.1f", $a/2);
  234. } elsif($cmd =~ m/-from/ || $cmd =~ m/-to/) {
  235. return "Invalid timeformat, use HH:MM"
  236. if($val !~ m/^([0-2]\d):([0-5]\d)/);
  237. my $a = ($1*6) + ($2/10);
  238. $arg .= sprintf("%02x", $a);
  239. my $nt = sprintf("%02d:%02d", $1, int($2/10)*10);
  240. $ret .= "Rounded $cmd to $nt" if($nt ne $val);
  241. $val = $nt;
  242. } elsif($cmd eq "mode") {
  243. return "Invalid mode, choose one of " . join(" ", sort keys %m2c)
  244. if(!defined($m2c{$val}));
  245. $arg .= sprintf("%02x", $m2c{$val});
  246. } elsif ($cmd eq "lowtemp-offset") {
  247. return "Invalid lowtemperature-offset, must between 1 and 5"
  248. if($val !~ m/^[1-5]$/);
  249. $arg .= sprintf("%02x", $val);
  250. $val = "$val.0";
  251. } else { # Holiday1, Holiday2
  252. return "Invalid argument, must be between 1 and 255"
  253. if($val !~ m/^\d+$/ || $val < 0 || $val > 255);
  254. $arg .= sprintf("%02x", $val) if(defined($val));
  255. }
  256. if($lazy &&
  257. $cmd ne "report1" && $cmd ne "report2" && $cmd ne "refreshvalues" &&
  258. defined($readings->{$cmd}) && $readings->{$cmd}{VAL} eq $val) {
  259. $ret .= "Lazy mode ignores $cmd";
  260. Log3 $name, 2, "Lazy mode ignores $cmd $val";
  261. } else {
  262. $ncmd++;
  263. $allcmd .=" " if($allcmd);
  264. $allcmd .= $cmd;
  265. $allcmd .= " $val" if(defined($val));
  266. }
  267. }
  268. return "Too many commands specified, an FHT only supports up to 8"
  269. if($ncmd > 8);
  270. return $ret if(!$ncmd);
  271. my $ioname = "";
  272. $ioname = $hash->{IODev}->{NAME} if($hash->{IODev});
  273. if($attr{$ioname} && $attr{$ioname}{fhtsoftbuffer}) {
  274. my $io = $hash->{IODev};
  275. my %h = (HASH => $hash, CMD => $allcmd, ARG => $arg);
  276. my $prio = $priority{$cmd};
  277. $prio = "9" if(!$prio);
  278. my $key = $prio . ":" . gettimeofday() . ":" . $cmdcount++;
  279. $io->{SOFTBUFFER}{$key} = \%h;
  280. doSoftBuffer($io);
  281. } else {
  282. IOWrite($hash, "04", $arg);
  283. Log3 $name, 2, "FHT set $name $allcmd";
  284. }
  285. return $ret;
  286. }
  287. #####################################
  288. sub
  289. FHT_Define($$)
  290. {
  291. my ($hash, $def) = @_;
  292. my @a = split("[ \t][ \t]*", $def);
  293. return "wrong syntax: define <name> FHT CODE" if(int(@a) != 3);
  294. $a[2] = lc($a[2]);
  295. return "Define $a[0]: wrong CODE format: specify a 4 digit hex value"
  296. if($a[2] !~ m/^[a-f0-9][a-f0-9][a-f0-9][a-f0-9]$/i);
  297. $hash->{CODE} = $a[2];
  298. AssignIoPort($hash);
  299. # Check if the CULs id collides with our id.
  300. if($hash->{IODev} && $hash->{IODev}{TYPE} eq "CUL") {
  301. $hash->{IODev}{FHTID} =~ m/^(..)(..)$/;
  302. my ($i1, $i2) = (hex($1), hex($2));
  303. $a[2] =~ m/^(..)(..)$/;
  304. my ($l1, $l2) = (hex($1), hex($2));
  305. if($l2 == $i2 && $l1 >= $i1 && $l1 <= $i1+7) {
  306. my $err = "$a[0]: CODE collides with the FHTID of the corresponding CUL";
  307. Log3 $a[0], 1, $err;
  308. return $err;
  309. }
  310. }
  311. $modules{FHT}{defptr}{$a[2]} = $hash;
  312. #Log3 $a[0], 2, "Asking the FHT device $a[0]/$a[2] to send its data";
  313. #FHT_Set($hash, ($a[0], "report1", "255", "report2", "255"));
  314. return undef;
  315. }
  316. #####################################
  317. sub
  318. FHT_Undef($$)
  319. {
  320. my ($hash, $name) = @_;
  321. delete($modules{FHT}{defptr}{$hash->{CODE}}) if($hash && $hash->{CODE});
  322. return undef;
  323. }
  324. #####################################
  325. sub
  326. FHT_Parse($$)
  327. {
  328. my ($hash, $msg) = @_;
  329. $msg = lc($msg);
  330. my $dev = substr($msg, 16, 4);
  331. my $cde = substr($msg, 20, 2);
  332. my $val = (length($msg) > 26 ? substr($msg, 26, 2) : undef);
  333. my $confirm = 0;
  334. if(!defined($modules{FHT}{defptr}{$dev})) {
  335. # it might be our own FHT8v, then be silent
  336. foreach my $d (%defs) {
  337. my $dp = $defs{$d};
  338. next if(!$dp->{TYPE} || $dp->{TYPE} ne "FHT8V");
  339. return "" if($dp->{addr} eq $dev);
  340. }
  341. Log3 $hash, 3, "FHT Unknown device $dev, please define it";
  342. return "UNDEFINED FHT_$dev FHT $dev";
  343. }
  344. my $def = $modules{FHT}{defptr}{$dev};
  345. my $name = $def->{NAME};
  346. return "" if(IsIgnored($name));
  347. my $io = $def->{IODev};
  348. # Short message
  349. if(length($msg) < 26) {
  350. Log3 $name, 4, "FHT Short message. Device $name, Message: $msg";
  351. return "";
  352. }
  353. if($io->{TYPE} eq "CUL") {
  354. $confirm = 1;
  355. } elsif(!$val || $cde eq "65" || $cde eq "66") {
  356. # This is a confirmation message. We reformat it so that
  357. # it looks like a real message, and let the rest parse it
  358. Log3 $name, 4, "FHT $name confirmation: $cde";
  359. $val = substr($msg, 22, 2);
  360. $confirm = 1;
  361. }
  362. $val = hex($val);
  363. my $cmd = $codes{$cde};
  364. if(!$cmd) {
  365. Log3 $name, 4, "FHT $name (Unknown: $cde => $val)";
  366. readingsSingleUpdate($def, "unknown_$cde", $val, 1);
  367. return $name;
  368. }
  369. #
  370. # special treatment for measured-temp which is actually sent in two bytes
  371. #
  372. # the measured temperature comes in two bytes: measured-low and measured-high
  373. # measured-temp= (measured-high * 256 + measured-low) / 10.
  374. # measured-low and measured-high will only be stored as internals
  375. if($cmd eq "measured-low") {
  376. $def->{".measuredLow"}= $val;
  377. return "";
  378. } elsif($cmd eq "measured-high") {
  379. $def->{".measuredHigh"}= $val;
  380. if(defined($def->{".measuredLow"})) {
  381. $val = sprintf("%.1f", ($val*256.0 + $def->{".measuredLow"})/10.0+
  382. AttrVal($name, "tmpcorr", 0.0));
  383. $cmd = "measured-temp";
  384. } else {
  385. return "";
  386. }
  387. }
  388. #
  389. # from here readings are effectively updated
  390. #
  391. readingsBeginUpdate($def);
  392. # The first four are confirmation messages, so they must be converted to
  393. # the same format as the input (for the softbuffer)
  394. if($cmd =~ m/-from/ || $cmd =~ m/-to/) {
  395. $val = sprintf("%02d:%02d", $val/6, ($val%6)*10);
  396. } elsif($cmd eq "mode") {
  397. $val = $c2m{$val} if(defined($c2m{$val}));
  398. } elsif($cmd =~ m/.*-temp/ && $cmd ne "measured-temp") {
  399. $val = sprintf("%.1f", $val / 2);
  400. if($cmd eq "desired-temp") {
  401. $val = ($val > 30 ? "on" : ($val < 6 ? "off" : $val));
  402. }
  403. } elsif($cmd eq "lowtemp-offset") {
  404. $val = sprintf("%d.0", $val)
  405. } elsif($cmd =~ m/^actuator/) {
  406. my $sval = lc(substr($msg,24,2));
  407. my $fv = sprintf("%d%%", int(100*$val/255+0.5));
  408. if($sval =~ m/[ab]0/) { $val = $fv; } # sync in the summer
  409. elsif($sval =~ m/.0/) { $val = "syncnow"; }
  410. elsif($sval =~ m/.1/) { $val = "99%" } # FHT set to 30.5, FHT80B=="ON"
  411. elsif($sval =~ m/.2/) { $val = "0%" } # FHT set to 5.5
  412. elsif($sval =~ m/.6/) { $val = "$fv" }
  413. elsif($sval =~ m/.8/) { $val = "offset: " . ($val>128?(128-$val):$val) }
  414. elsif($sval =~ m/[23]a/) { $val = "lime-protection" }
  415. elsif($sval =~ m/[ab]a/) { $val = $fv } # lime protection bug
  416. elsif($sval =~ m/.c/) { $val = sprintf("synctime: %d", int($val/2)-1); }
  417. elsif($sval =~ m/.e/) { $val = "test" }
  418. elsif($sval =~ m/.f/) { $val = "pair" }
  419. else { $val = "unknown_$sval: $fv" }
  420. } elsif($cmd eq "warnings") {
  421. my $nVal;
  422. # initialize values for additional warnings
  423. my $valBattery;
  424. my $valLowTemp;
  425. my $valWindow;
  426. my $valSensor;
  427. my $nBattery;
  428. my $nLowTemp;
  429. my $nWindow;
  430. my $nSensor;
  431. # parse warnings
  432. if($val & 1) {
  433. $nVal = "Battery low";
  434. $nBattery = "low";
  435. }
  436. if($val & 2) {
  437. $nVal .= "; " if($nVal); $nVal .= "Temperature too low";
  438. $nLowTemp = "warn";
  439. }
  440. if($val &32) {
  441. $nVal .= ", " if($nVal); $nVal .= "Window open";
  442. $nWindow = "open";
  443. }
  444. if($val &16) {
  445. $nVal .= ", " if($nVal); $nVal .= "Fault on window sensor";
  446. $nSensor = "fault";
  447. }
  448. # set default values or new values if they were changed
  449. $valBattery = $nBattery? $nBattery : "ok";
  450. $valLowTemp = $nLowTemp? $nLowTemp : "ok";
  451. $valWindow = $nWindow? $nWindow : "closed";
  452. $valSensor = $nSensor? $nSensor : "ok";
  453. $val = $nVal? $nVal : "none";
  454. # set additional warnings and trigger notify
  455. readingsBulkUpdate($def, "battery", $valBattery);
  456. Log3 $name, 4, "FHT $name battery: $valBattery";
  457. readingsBulkUpdate($def, "lowtemp", $valLowTemp);
  458. Log3 $name, 4, "FHT $name lowtemp: $valLowTemp";
  459. readingsBulkUpdate($def, "window", $valWindow);
  460. Log3 $name, 4, "FHT $name window: $valWindow";
  461. readingsBulkUpdate($def, "windowsensor", $valSensor);
  462. Log3 $name, 4, "FHT $name windowsensor: $valSensor";
  463. }
  464. $cmd = "FHZ_$cmd" if(substr($msg,24,1) eq "7");
  465. readingsBulkUpdate($def, $cmd, $val);
  466. if($cmd eq "measured-temp") {
  467. readingsBulkUpdate($def, "state", "measured-temp: $val", 0);
  468. readingsBulkUpdate($def, "temperature", $val); # For dewpoint
  469. }
  470. Log3 $name, 4, "FHT $name $cmd: $val";
  471. #
  472. # now we are done with updating readings
  473. #
  474. readingsEndUpdate($def, 1);
  475. ################################
  476. # Softbuffer: delete confirmed commands
  477. if($confirm) {
  478. my $found;
  479. foreach my $key (sort keys %{$io->{SOFTBUFFER}}) {
  480. my $h = $io->{SOFTBUFFER}{$key};
  481. my $hcmd = $h->{CMD};
  482. my $hname = $h->{HASH}->{NAME};
  483. Log3 $name, 4, "FHT softbuffer check: $hname / $hcmd";
  484. if($hname eq $name && $hcmd =~ m/^$cmd $val/) {
  485. $found = $key;
  486. Log3 $name, 4, "FHT softbuffer found";
  487. last;
  488. }
  489. }
  490. delete($io->{SOFTBUFFER}{$found}) if($found);
  491. }
  492. return $name;
  493. }
  494. #####################################
  495. # Check the softwarebuffer and send/resend commands
  496. sub
  497. doSoftBuffer($)
  498. {
  499. my ($io) = @_;
  500. my $now = gettimeofday();
  501. my $count = 0;
  502. my $fhzbuflen = -999;
  503. foreach my $key (keys %{ $io->{SOFTBUFFER} }) {
  504. $count++;
  505. my $h = $io->{SOFTBUFFER}{$key};
  506. my $name = $h->{HASH}->{NAME};
  507. if($h->{NSENT}) {
  508. next if($now-$h->{SENDTIME} < $retryafter);
  509. my $retry = AttrVal($name, "retrycount", 1);
  510. if($h->{NSENT} > $retry) {
  511. Log3 $name, 2, "$name set $h->{CMD}: ".
  512. "no confirmation after $h->{NSENT} tries, giving up";
  513. delete($io->{SOFTBUFFER}{$key});
  514. next;
  515. }
  516. }
  517. # Check if it is still in the CUL buffer.
  518. if($io->{TYPE} eq "CUL") {
  519. my $cul = CallFn($io->{NAME}, "GetFn", $io, (" ", "raw", "T02"));
  520. my $arg = uc($h->{ARG});
  521. $arg =~ s/^020183//;
  522. $arg =~ s/(....)/,$1/g;
  523. $arg =~ s/,(....),/$1:/;
  524. $arg = uc($arg);
  525. if($cul =~ m/$arg/) {
  526. Log3 $name, 3, "fhtsoftbuffer: $name set $h->{CMD} ".
  527. "is still in the culfw buffer, wont send it again";
  528. $h->{SENDTIME} = $now;
  529. $h->{NSENT}++;
  530. next;
  531. }
  532. }
  533. $fhzbuflen = getFhtBuffer($io) if($fhzbuflen == -999);
  534. my $arglen = length($h->{ARG})/2 - 2; # Length in bytes
  535. next if($fhzbuflen < $arglen || $fhzbuflen < getFhtMin($io));
  536. IOWrite($h->{HASH}, "04", $h->{ARG});
  537. Log3 $name, 2, "FHT set $name $h->{CMD}";
  538. $fhzbuflen -= $arglen;
  539. $h->{SENDTIME} = $now;
  540. $h->{NSENT}++;
  541. }
  542. if($count && !$io->{SOFTBUFFERTIMER}) {
  543. $io->{SOFTBUFFERTIMER} = 1;
  544. InternalTimer(gettimeofday()+30, "softBufferTimer", $io, 0);
  545. }
  546. }
  547. #####################################
  548. # Wrapper for the InternalTimer
  549. sub
  550. softBufferTimer($)
  551. {
  552. my ($io) = @_;
  553. delete($io->{SOFTBUFFERTIMER});
  554. doSoftBuffer($io);
  555. }
  556. #####################################
  557. sub
  558. getFhtMin($)
  559. {
  560. my ($io) = @_;
  561. my $ioname = $io->{NAME};
  562. return $attr{$ioname}{minfhtbuffer}
  563. if($attr{$ioname} && $attr{$ioname}{minfhtbuffer});
  564. return $defmin;
  565. }
  566. #####################################
  567. # get the FHZ hardwarebuffer without logentry as decimal value
  568. sub
  569. getFhtBuffer($)
  570. {
  571. my ($io) = @_;
  572. my $count = 0;
  573. return getFhtMin($io) if(IsDummy($io->{NAME}));
  574. for(;;) {
  575. return 0 if(!defined($io->{FD})); # Avoid crash if the CUL/FHZ is absent
  576. my $msg = CallFn($io->{NAME}, "GetFn", $io, (" ", "fhtbuf"));
  577. Log3 $io, 5, "getFhtBuffer: $count $msg";
  578. return hex($1) if($msg && $msg =~ m/=> ([0-9A-F]+)$/i);
  579. return 0 if($count++ >= 5);
  580. }
  581. }
  582. #####################################
  583. # Remap the old FHZ: readingnames to FHZ_
  584. sub
  585. FHT_State($$$$)
  586. {
  587. my ($hash, $tim, $rname, $rval) = @_;
  588. return undef if($rname !~ m/^FHZ:/);
  589. my $newname = $rname;
  590. $newname =~ s/:/_/g;
  591. setReadingsVal($hash, $newname, $rval, $tim);
  592. return "FHT: renamed reading $rname to $newname for $hash->{NAME}";
  593. }
  594. 1;
  595. =pod
  596. =item summary devices communicating via the ELV FHT protocol (FHT80b)
  597. =item summary_DE Anbindung von ELV FHT Ger&auml;ten (FHT80b)
  598. =begin html
  599. <a name="FHT"></a>
  600. <h3>FHT</h3>
  601. <ul>
  602. Fhem can receive FHT radio (868.35 MHz) messages either through an <a
  603. href="#FHZ">FHZ</a> or an <a href="#CUL">CUL</a> device, so this must be
  604. defined first.<br><br>
  605. <a name="FHTdefine"></a>
  606. <b>Define</b>
  607. <ul>
  608. <code>define &lt;name&gt; FHT &lt;fhtaddress&gt;</code>
  609. <br><br>
  610. <code>&lt;fhtaddress&gt;</code> is a four digit hex number,
  611. corresponding to the address of the FHT80b device.
  612. <br>
  613. Examples:
  614. <ul>
  615. <code>define wz FHT 3232</code><br>
  616. </ul>
  617. <br>
  618. See the FHT section in <a href="#set">set</a> for more.
  619. </ul>
  620. <br>
  621. <a name="FHTset"></a>
  622. <b>Set </b>
  623. <ul>
  624. <code>set &lt;name&gt; &lt;valuetype&gt; &lt;value&gt;</code>
  625. <br><br>
  626. where <code>value</code> is one of:<br>
  627. <ul><code>
  628. desired-temp<br>
  629. day-temp night-temp<br>
  630. report1 report2<br>
  631. refreshvalues<br>
  632. mode<br>
  633. holiday1 holiday2 # see mode holiday_short or holiday<br>
  634. manu-temp # No clue what it does.<br>
  635. year month day hour minute<br>
  636. time date<br>
  637. lowtemp-offset # Alarm-Temp.-Differenz<br>
  638. windowopen-temp<br>
  639. mon-from1 mon-to1 mon-from2 mon-to2<br>
  640. tue-from1 tue-to1 tue-from2 tue-to2<br>
  641. wed-from1 wed-to1 wed-from2 wed-to2<br>
  642. thu-from1 thu-to1 thu-from2 thu-to2<br>
  643. fri-from1 fri-to1 fri-from2 fri-to2<br>
  644. sat-from1 sat-to1 sat-from2 sat-to2<br>
  645. sun-from1 sun-to1 sun-from2 sun-to2<br>
  646. </code></ul>
  647. Examples:
  648. <ul>
  649. <code>set wz desired-temp 22.5</code><br>
  650. <code>set fl desired-temp 20.5 day-temp 19.0 night-temp 16.0</code><br>
  651. </ul>
  652. <br>
  653. Notes:
  654. <ul>
  655. <li>Following events are reported (more or less regularly) by each FHT
  656. device: <code>measured-temp actuator actuator1...actuator8
  657. warnings</code><br>
  658. You can use these strings for <a href="#notify">notify</a> or
  659. <a href="#FileLog">FileLog</a> definitions.
  660. <ul>
  661. <li>warnings can contain following strings:
  662. none, Battery low,Temperature too low, Window open,
  663. Fault on window sensor
  664. </li>
  665. <li>actuator (without a suffix) stands for all actuators.</li>
  666. <li>actuator or actuator1..8 can take following values:
  667. <ul>
  668. <li>&lt;value&gt;%<br>
  669. This is the normal case, the actuator is instructed to
  670. open to this value.
  671. </li>
  672. <li>offset &lt;value&gt;%<br>
  673. The actuator is running with this offset.
  674. </li>
  675. <li>lime-protection<br>
  676. The actuator was instructed to execute the lime-protection
  677. procedure.
  678. </li>
  679. <li>synctime<br>
  680. If you select Sond/Sync on the FHT80B, you'll see a count
  681. down.
  682. </li>
  683. <li>test<br>
  684. The actuator was instructed by the FHT80b to emit a beep.
  685. </li>
  686. <li>pair<br>
  687. The the FHT80b sent a "you-belong-to-me" to this actuator.
  688. </li>
  689. </ul></li>
  690. </ul></li>
  691. <br>
  692. <li>The FHT is very economical (or lazy), it accepts one message from the
  693. FHZ1x00 every 115+x seconds, where x depends on the fhtaddress. Don't
  694. be surprised if your command is only accepted 10 minutes later by the
  695. device. FHT commands are buffered in the FHZ1x00/CUL till they are
  696. sent to the FHT, see the related <code>fhtbuf</code> entry in the
  697. <code><a href="#get">get</a></code> section.<br> You can send up to 8
  698. commands in one message at once to the FHT if you specify them all as
  699. arguments to the same set command, see the example above.
  700. </li>
  701. <br>
  702. <li>time sets hour and minute to local time</li><br>
  703. <li>date sets year, month and date to local time</li><br>
  704. <li>refreshvalues is an alias for report1 255 report2 255</li><br>
  705. <li>All <code>*-temp</code> values need a temperature
  706. as argument, which will be rounded to 0.5 Celsius.<br>
  707. Temperature values must between 5.5 and 30.5 Celsius. Value 5.5 sets
  708. the actuator to OFF, value 30.5 set the actuator to ON</li><br>
  709. <li><code>mode</code> is one of <code>auto, manual, holiday or
  710. holiday_short.</code><br>
  711. If the mode is either holiday or holiday_short, then the mode
  712. switches back to auto at the specified day and time independent of
  713. the current mode of the device and the desired temperature will be
  714. set to the night or day temperature according to the defined weekly
  715. schedule stored within the device.
  716. In case of mode holiday
  717. <ul>
  718. <li>holiday1 sets the end-day of the holiday (at 00:00)</li>
  719. <li>holiday2 sets the end-month of the holiday</li>
  720. </ul>
  721. For holiday_short (party mode)
  722. <ul>
  723. <li>holiday1 sets the absolute hour to switch back from this mode (in
  724. 10-minute steps, max 144)</li>
  725. <li>holiday2 sets the day of month to switch back from this mode (can only be today or tomorrow, since holiday1 accepts only 24 hours).</li>
  726. </ul>
  727. Example:
  728. <ul>
  729. <li>current date is 29 Jan, time is 18:05</li>
  730. <li>you want to switch to party mode until tomorrow 1:00</li>
  731. <li>set holiday1 to 6 (6 x 10min = 1hour) and holiday2 to 30</li>
  732. </ul>
  733. The temperature for the holiday period is set by the
  734. desired-temperature parameter.<br>
  735. Note that you cannot set holiday mode for days earlier than the day
  736. after tomorrow, for this you must use holiday_short.<br>
  737. The parameters holiday1 and holiday2 must be set in one command
  738. together with mode.<br>
  739. Example:
  740. <ul>
  741. set FHT1 mode holiday holiday1 24 holiday2 12 desired-temp 14
  742. </ul>
  743. Please note: If the event time specified by the holiday parameters
  744. has already past, then the device will immediately switch back to
  745. auto mode including the selection of the corresponding day or night
  746. temperature. This is valid at least for FHT80b model 2 and 3, Lifetec
  747. MD12050. For those devices setting holiday_short with a holiday1
  748. value of 0 and without the parameter holiday2 e.g.
  749. <ul>
  750. set FHT1 mode holiday_short holiday1 0
  751. </ul>
  752. will immediately switch back the device to mode auto including the
  753. adjustment of the desired- temp parameter.
  754. Some elderly FHT models, however, only switch the mode to auto, if
  755. the event is within the past, but don't adjust the desired
  756. temperature. In this case specifying appropriate values for the
  757. parameters holiday1 and holiday2 thus defining an event in the very
  758. near future (e.g. 10 minutes) could be the solution to force a switch
  759. back to the correct automatic mode.
  760. </li>
  761. <br>
  762. <li>The <code>*-from1/*-from2/*-to1/*-to2</code> valuetypes need a time
  763. spec as argument in the HH:MM format. They define the periods, where
  764. the day-temp is valid. The minute (MM) will be rounded to 10, and
  765. 24:00 means off.</li><br>
  766. <li>To synchronize the FHT time and to "wake" muted FHTs it is adviseable
  767. to schedule following command:<br>
  768. <code>define fht_sync at +*3:30 set TYPE=FHT time</code>
  769. </li>
  770. <br>
  771. <li><code>report1</code> with parameter 255 requests all settings for
  772. monday till sunday to be sent. The argument is a bitfield, to request
  773. unique values add up the following:
  774. <ul>
  775. <li> 1: monday</li>
  776. <li> 2: tuesday</li>
  777. <li> 4: thursday</li>
  778. <li> 8: wednesday</li>
  779. <li>16: friday</li>
  780. <li>32: saturday</li>
  781. <li>64: sunday</li>
  782. </ul>
  783. measured-temp and actuator is sent along if it is considered
  784. appropriate
  785. by the FHT.
  786. <br><br>
  787. <b>Note:</b> This command generates a lot of RF traffic, which can
  788. lead to further problems, especially if the reception is not clear.
  789. </li><br>
  790. <li><code>report2</code> with parameter 255 requests the following
  791. settings to be reported: day-temp night-temp windowopen-temp
  792. lowtemp-offset desired-temp measured-temp mode warnings.
  793. The argument is (more or less) a bitfield, to request unique values
  794. add up the following:
  795. <ul>
  796. <li> 1: warnings</li>
  797. <li> 2: mode</li>
  798. <li> 4: day-temp, night-temp, windowopen-temp</li>
  799. <li> 8: desired-temp</li>
  800. <li>64: lowtemp-offset</li>
  801. </ul>
  802. measured-temp and actuator is sent along if it is considered
  803. appropriate by the FHT.</li>
  804. <br>
  805. <li><code>lowtemp-offset</code> needs a temperature as argument, valid
  806. values must be between 1.0 and 5.0 Celsius.<br> It will trigger a
  807. warning if <code>desired-temp - measured-temp &gt;
  808. lowtemp-offset</code> in a room for at least 1.5 hours after the last
  809. desired-temp change.</li>
  810. <br>
  811. <li>FHEM optionally has an internal software buffer for FHT devices.
  812. This buffer should prevent transmission errors. If there is no
  813. confirmation for a given period, FHEM resends the command. You can
  814. see the queued commands with <a href="#list">list</a>
  815. &lt;fht-device&gt;.
  816. See the <a href="#fhtsoftbuffer">fhtsoftbuffer</a>,
  817. <a href="#retrycount">retrycount</a> and
  818. <a href="#minfhtbuffer">minfhtbuffer</a> attributes for details.
  819. </li>
  820. <br>
  821. <li>If a buffer is still in the softbuffer, it will be sent in the
  822. following order:<br> <code>desired-temp,mode,report1,report2,
  823. holiday1,holiday2,day-temp,night-temp, [all other commands]</code>
  824. </li>
  825. <br>
  826. </ul>
  827. </ul>
  828. <br>
  829. <b>Get</b> <ul>N/A</ul><br>
  830. <a name="FHTattr"></a>
  831. <b>Attributes</b>
  832. <ul>
  833. <li><a href="#attrdummy">dummy</a><br>
  834. <b>Note:</b>It makes sense to define an FHT device even for an FHT8b,
  835. else you will receive "unknown FHT device, please define one" message
  836. for each FHT8b as the CUL is reporting the 8b valve messages. But you
  837. should set the dummy attribute for these devices, else the internal FHT
  838. buffer of the CUL will be filled with data for the 8b's which is never
  839. consumed. If the buffer is full, you'll get "EOB" messages from the CUL,
  840. and you cannot transmit any data to the 80b's</li><br>
  841. <a name="retrycount"></a>
  842. <li>retrycount<br>
  843. If the <a href="#fhtsoftbuffer">fhtsoftbuffer</a> attribute is set, then
  844. resend commands <code>retrycount</code> times if after 240 seconds
  845. no confirmation message is received from the corresponding FHT
  846. device.<br>
  847. Default is 1.</li><br>
  848. <a name="minfhtbuffer"></a>
  849. <li>minfhtbuffer<br>
  850. FHEM won't send commands to the FHZ if its fhtbuffer is below
  851. this value, default is 0. If this value is low, then the ordering of
  852. fht commands (see the note in the FHT section of <a href="#set">set</a>)
  853. has little effect, as only commands in the softbuffer can be
  854. prioritized. The maximum value should be 7 below the hardware maximum
  855. (see fhtbuf).
  856. </li><br>
  857. <a name="lazy"></a>
  858. <li>lazy<br>
  859. If the lazy attribute is set, FHEM won't send commands to the FHT if
  860. the current reading and the value to be set are already identical. This
  861. may help avoiding conflicts with the max-1%-time-on-air rule in large
  862. installations. Not set per default.
  863. </li><br>
  864. <a name="tmpcorr"></a>
  865. <li>tmpcorr<br>
  866. Correct the temperature reported by the FHT by the value specified.
  867. Note: only the measured-temp value reported by FHEM (used for logging)
  868. will be modified.
  869. </li><br>
  870. <li><a href="#ignore">ignore</a></li>
  871. <li><a href="#do_not_notify">do_not_notify</a></li>
  872. <li><a href="#model">model</a> (fht80b)</li>
  873. <li><a href="#showtime">showtime</a></li>
  874. <li><a href="#IODev">IODev</a></li>
  875. <li><a href="#eventMap">eventMap</a></li>
  876. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  877. </ul>
  878. <br>
  879. <a name="FHTevents"></a>
  880. <b>Generated events:</b>
  881. <ul>
  882. <li>actuator</li>
  883. <li>actuator1 actuator2 actuator3 actuator4<br>
  884. actuator5 actuator6 actuator7 actuator8<br>
  885. (sent if you configured an offset for the associated valve)</li>
  886. <li>mon-from1 mon-to1 mon-from2 mon-to2</li>
  887. <li>tue-from1 tue-to1 tue-from2 tue-to2</li>
  888. <li>wed-from1 wed-to1 wed-from2 wed-to2</li>
  889. <li>thu-from1 thu-to1 thu-from2 thu-to2</li>
  890. <li>fri-from1 fri-to1 fri-from2 fri-to2</li>
  891. <li>sat-from1 sat-to1 sat-from2 sat-to2</li>
  892. <li>sun-from1 sun-to1 sun-from2 sun-to2</li>
  893. <li>mode</li>
  894. <li>holiday1 holiday2</li>
  895. <li>desired-temp</li>
  896. <li>measured-temp measured-low measured-high</li>
  897. <li>warnings</li>
  898. <li>manu-temp</li>
  899. <li>year month day hour minute</li>
  900. <li>day-temp night-temp lowtemp-offset windowopen-temp</li>
  901. <li>ack can-xmit can-rcv ack2 start-xmit end-xmit
  902. (only if the CUL is configured to transmit FHT protocol data)</li>
  903. </ul>
  904. <br>
  905. </ul>
  906. =end html
  907. =begin html_DE
  908. <a name="FHT"></a>
  909. <h3>FHT</h3>
  910. <ul>
  911. Fhem kann FHT Funktelegramme (868.35 MHz) entweder mit einem <a
  912. href="#FHZ">FHZ</a> oder einem <a href="#CUL">CUL</a> empfangen, daher muss
  913. dieses zuerst definiert sein.
  914. <br><br>
  915. <a name="FHTdefine"></a>
  916. <b>Define</b>
  917. <ul>
  918. define &lt;name&gt; FHT &lt;fhtaddress&gt;
  919. <br><br>
  920. &lt;fhtaddress&gt; ist eine vierstellige HEX Zahl entsprechend der
  921. Adresse des FHT80b Ger&auml;tes.
  922. <br>
  923. Beispiel:
  924. <ul>
  925. define wz FHT 3232<br>
  926. </ul>
  927. <br>
  928. Mehr dazu im FHT Abschnitt <a href="#set">set</a>.
  929. </ul>
  930. <br>
  931. <a name="FHTset"></a>
  932. <b>Set </b>
  933. <ul>
  934. set &lt;name&gt; &lt;valuetype&gt; &lt;value&gt;
  935. <br><br>
  936. Wobei value eines von folgenden ist:<br>
  937. <ul>
  938. desired-temp<br>
  939. day-temp night-temp<br>
  940. report1 report2<br>
  941. refreshvalues<br>
  942. mode<br>
  943. holiday1 holiday2 # siehe mode holiday_short oder holiday<br>
  944. manu-temp # Keine Ahnung was das bewirkt<br>
  945. year month day hour minute<br>
  946. time date<br>
  947. lowtemp-offset # Alarm-Temp.-Differenz<br>
  948. windowopen-temp<br>
  949. mon-from1 mon-to1 mon-from2 mon-to2<br>
  950. tue-from1 tue-to1 tue-from2 tue-to2<br>
  951. wed-from1 wed-to1 wed-from2 wed-to2<br>
  952. thu-from1 thu-to1 thu-from2 thu-to2<br>
  953. fri-from1 fri-to1 fri-from2 fri-to2<br>
  954. sat-from1 sat-to1 sat-from2 sat-to2<br>
  955. sun-from1 sun-to1 sun-from2 sun-to2<br>
  956. </ul>
  957. Beispiele:
  958. <ul>
  959. set wz desired-temp 22.5<br>
  960. set fl desired-temp 20.5 day-temp 19.0 night-temp 16.0<br>
  961. </ul>
  962. <br>
  963. Hinweise:
  964. <ul>
  965. <li>Folgende Events werden (mehr oder weniger regelm&auml;&szlig;ig) von
  966. jedem FHT Device gemeldet:
  967. <ul>
  968. measured-temp actuator actuator1...actuator8 warnings<br>
  969. </ul>
  970. Diese Strings k&ouml;nnen f&uuml;r <a href="#notify">notify</a> oder
  971. <a href="#FileLog">FileLog</a> Definitionen verwendet werden.
  972. <ul>
  973. <li>Warnings k&ouml;nnen folgende Strings enthalten:
  974. none, Battery low,Temperature too low, Window open,
  975. Fault on window sensor
  976. </li>
  977. <li>actuator (ohne Suffix) steht f&uuml;r alle Aktoren.</li>
  978. <li>actuator or actuator1..8 kann folgende Werte verarbeiten:
  979. <ul>
  980. <li>&lt;value&gt;%<br>
  981. Das ist der Normalfall. Der Aktor wird angewiesen auf diesen
  982. Wert zu &ouml;ffnen.
  983. </li>
  984. <li>offset &lt;value&gt;%<br>
  985. Der Aktor l&auml;uft mit diesem Offset.
  986. </li>
  987. <li>lime-protection<br>
  988. Der Aktor wird angewiesen die lime-protection (Kalkschutz)
  989. Prozedur auszuf&uuml;hren.
  990. </li>
  991. <li>synctime<br>
  992. Wenn Sond/Sync beim FHT80B gew&auml;hlt wird, wird ein
  993. Countdown gesetzt.
  994. </li>
  995. <li>test<br>
  996. Der Aktor wird vom FHT80b angewiesen zu piepsen (beep).
  997. </li>
  998. <li>pair<br>
  999. Das FHT80b sendet ein "you-belong-to-me"
  1000. (Du-geh&ouml;rst-zu-mir) an diesen Aktor.
  1001. </li>
  1002. </ul></li>
  1003. </ul></li>
  1004. <br>
  1005. <li>Das FHT ist sehr sparsam (oder faul). Es akzeptiert eine Nachricht
  1006. vom FHZ1x00 alle 115+x Sekunden, wobei x von der fhtaddress
  1007. abh&auml;ngt. Nicht &uuml;berrascht sein wenn ein Befehl erst 10
  1008. Minuten sp&auml;ter vom Ger&auml;t angenommen wird. Die FHT Befehle
  1009. werden im FHZ1x00/CUL gepuffert bis sie zum FHT geschickt werden.
  1010. Siehe den zugeh&ouml;rigen fhtbuf Eintrag im der <a
  1011. href="#get">get</a> Abschnitt. Es k&ouml;nnen bis zu 8 Befehle in
  1012. einer Nachricht an ein FHT geschickt werden wenn diese alle als
  1013. Argumente im gleichen set Befehl zusammengefasst werden. Siehe
  1014. nachfolgendes Beispiel. </li><br>
  1015. <li>time setzt Stunde und Minute auf lokale Zeit</li><br>
  1016. <li>date setzt Jahr, Monat und Tag auf lokale Zeit</li><br>
  1017. <li>refreshvalues ist ein Alias f&uuml;r report1 255 report2 255</li><br>
  1018. <li>Alle *-temp Werte brauchen eine Temperatur als Argument welche auf
  1019. 0.5&deg;C gerundet wird.<br> Temperatur Werte m&uuml;ssen zwischen
  1020. 5.5&deg;C und 30.5&deg;C sein. Der Wert 5.5 setzt den Aktor auf OFF,
  1021. der Wert 30.5 setzt den Aktor auf ON</li><br>
  1022. <li>mode kann auto, manual, holiday or
  1023. holiday_short sein.<br>
  1024. Wenn der mode holiday ist, schaltet dieser zur&uuml;ck auf entweder
  1025. auto oder manual um 00:00 des Tages der wie folgt spezifiziert wird:
  1026. <ul>
  1027. <li>holiday1 setzt Endtag des Urlaubs</li>
  1028. <li>holiday2 setzt den Endmonat des Urlaubs</li>
  1029. </ul>
  1030. F&uuml;r holiday_short (Party Modus)
  1031. <ul>
  1032. <li> holiday1 setzt die absolute Stunde zu der von diesem Modus
  1033. zur&uuml;ck geschalten wird (in 10-Minuten Schritten, max.
  1034. 144)</li>
  1035. <li> holiday2 setzt den Tag des Monats an dem von diesem Modus
  1036. zur&uuml;ck geschalten wird (kann nur heute oder morgen sein, da
  1037. holiday1 nur 24h akzeptiert.)</li>
  1038. Beispiel:
  1039. <ul>
  1040. <li>Aktuelles Datum ist der 29. Januar, Uhrzeit ist 18:05</li>
  1041. <li>Es soll bis morgen 1:00Uhr in den Party Modus geschalten
  1042. sein</li>
  1043. <li>set holiday1 to 6 (6 x 10min = Std) and holiday2 to
  1044. 30</li>
  1045. </ul>
  1046. </ul>
  1047. Die Temperatur f&uuml;r den Urlaubszeitraum wird durch den
  1048. desired-temperature Parameter setzt. <br> Bitte beachten, dass der
  1049. Holiday Mode nicht fr&uuml;her als auf &Uuml;bermorgen eingestellt
  1050. werden kann. Alternativ muss hier holiday_short genutzt werden.<br>
  1051. Weiterhin bitte beachten das diese Kommandos nur in einem
  1052. "Sammelkommando" erfolgen k&ouml;nnen. Beispiel:
  1053. <br>
  1054. set FHT1 mode holiday holiday1 24 holiday2 12 desired-temp 14
  1055. </li><br>
  1056. <li>Die *-from1/*-from2/*-to1/*-to2 Wertetypen brauchen eine
  1057. Zeitspezifikation als Argument im Format HH:MM. Diese definieren den
  1058. Zeitraum in dem die day-temp g&uuml;ltig ist. Minuten (MM) werden
  1059. auf 10er gerundet, 24:00 bedeutet OFF. </li><br>
  1060. <li>Um die FHZ Zeit zu synchronisieren und um "stumme" Ger&auml;te
  1061. zu wecken, wird folgendes Kommando empfohlen:<br> define fht_sync at
  1062. +*3:30 set TYPE=FHT time </li><br>
  1063. <li>report1 mit dem Parameter 255 fordert das Senden aller Einstellungen
  1064. von Montag bis Sonntag an. Das Argument ist ein Bitfeld um einzelne
  1065. Werte wie folgt anzufordern:
  1066. <ul>
  1067. <li> 1: monday</li>
  1068. <li> 2: tuesday</li>
  1069. <li> 4: thursday</li>
  1070. <li> 8: wednesday</li>
  1071. <li>16: friday</li>
  1072. <li>32: saturday</li>
  1073. <li>64: sunday</li>
  1074. </ul>
  1075. measured-temp und actuator werden mitgesendet wenn vom FHT als
  1076. notwendig erachtet.
  1077. <br><br>
  1078. <b>Hinweis:</b> Dieser Befehl erzeugt sehr viel Funkverkehr was zu
  1079. weiteren Problemen f&uuml;hren kann, besonders wenn Empfang nicht gut
  1080. ist. </li><br>
  1081. <li>report2 mit dem Parameter 255 fordert die Ausgabe der nachfolgenden
  1082. Einstellungen an:<br> day-temp night-temp windowopen-temp
  1083. lowtemp-offset desired-temp measured-temp mode warnings.<br> Das
  1084. Argument ist ein Bitfeld, um einzelne Werte abzufragen folgendes
  1085. anh&auml;ngen:
  1086. <ul>
  1087. <li> 1: warnings</li>
  1088. <li> 2: mode</li>
  1089. <li> 4: day-temp, night-temp, windowopen-temp</li>
  1090. <li> 8: desired-temp</li>
  1091. <li>64: lowtemp-offset</li>
  1092. </ul>
  1093. measured-temp und actuator werden mitgesendet wenn vom FHT als
  1094. notwendig erachtet. <br></li>
  1095. <li>lowtemp-offset braucht eine Temperatur als Argument. G&uuml;ltige
  1096. Werte m&uuml;ssen zwischen 1.0 und 5.0&deg;C liegen.<br> Wird eine
  1097. Warnung erzeugen wenn die desired-temp - measured-temp &gt;
  1098. lowtemp-offset, jedoch fr&uuml;hestens 1,5Stunden nach der letzten
  1099. &Auml;nderung der desired-temp. </li><br>
  1100. <li>FHEM hat optional einen internen Softwarepuffer f&uuml;r FHT
  1101. Devices. Dieser Puffer soll vor &Uuml;bertragungsfehlern
  1102. sch&uuml;tzen. Wenn nach einem bestimmten Zeitraum keine
  1103. Best&auml;tigung erhalten wurde wird FHEM den Befehl erneut senden.
  1104. Die Befehle in der Warteschlagen k&ouml;nnen mit <a
  1105. href="#list">list</a> &lt;fht-device&gt; angezeigt werden. Siehe die
  1106. Attribute <a href="#fhtsoftbuffer">fhtsoftbuffer</a>, <a
  1107. href="#retrycount">retrycount</a> und <a
  1108. href="#minfhtbuffer">minfhtbuffer</a> f&uuml;r weitere Details.
  1109. </li><br>
  1110. <li>Befehle im Softwarepuffer werden in folgender Reihenfolge
  1111. gesendet:<br>
  1112. desired-temp,mode,report1,report2,holiday1,holiday2,day-temp,night-temp,
  1113. [all other commands] </li><br>
  1114. </ul>
  1115. </ul>
  1116. <br>
  1117. <b>Get</b> <ul>N/A</ul><br>
  1118. <a name="FHTattr"></a>
  1119. <b>Attribute</b>
  1120. <ul>
  1121. <li><a href="#attrdummy">dummy</a><br>
  1122. <b>Hinweis:</b> Es macht Sinn ein FHT Device auch f&uuml;r ein FHT8b zu
  1123. definieren da sonst der Fehler "unknown FHT device, please define one"
  1124. f&uuml;r jedes FHT8b generiert wird, denn das CUL meldet die 8b
  1125. Nachrichten. Das dummy Attribut sollte bei diesen Devices gesetzt werden
  1126. da sonst der interne FHT Buffer des CUL mit 8b-Daten gef&uuml;llt wird
  1127. die niemals gebraucht werden. Wenn der Puffer dann voll ist werden "EOB"
  1128. Nachrichten vom CUL erzeugt, und Senden zu den 8b ist nicht mehr
  1129. m&ouml;glich.</li><br>
  1130. <a name="retrycount"></a>
  1131. <li>retrycount<br>
  1132. Wenn das <a href="#fhtsoftbuffer">fhtsoftbuffer</a> Attribut gesetzt ist,
  1133. dann werden die Befehle entsprechend dem retrycount n-mal erneut
  1134. versendet wenn nach 240 Sekunden keine Best&auml;tigungsmeldung vom
  1135. entsprechenden FHZ Device empfangen wurde.<br> Der Default-Wert ist
  1136. 1.</li><br>
  1137. <a name="minfhtbuffer"></a>
  1138. <li>minfhtbuffer<br>
  1139. FHEM sendet keine Befehle mehr zum FHZ wenn der fhtbuffer-Wert diesen
  1140. Wert unterschritten hat. Default-Wert ist 0. Wenn dieser Wert zu niedrig
  1141. ist hat die Reihenfolge von fht-Befehlen weniger Einfluss da nur Befehle
  1142. im Softbuffer priorisiert werden k&ouml;nnen. (Siehe Hinweise in der FHT
  1143. Sektion <a href="#set">set</a>) Der Maximalwert sollte 7 unter dem
  1144. Hardware Maximum sein, siehe fhtbuf. </li><br>
  1145. <a name="lazy"></a>
  1146. <li>lazy<br>
  1147. Wenn das Attribut lazy (faul) gesetzt wurde sendet FHEM keine Befehle
  1148. wenn die aktuell gelesenen Werte und der zu setzende Wert identisch sind.
  1149. Das spart Funkzeit und hilft Konflikte mit der Regelung die besagt, dass
  1150. maximal 1% der Zeit als Funkzeit verwendet werden darf, zu vermeiden.
  1151. Nicht standardm&auml;&szlig;ig aktiviert. </li><br>
  1152. <a name="tmpcorr"></a>
  1153. <li>tmpcorr<br>
  1154. Korrigiert die Werte die vom FHZ gemeldet werden um den angegebenen Wert.
  1155. Hinweis: nur die measured-temp Werte die von FHEM gemeldet (f&uuml;r
  1156. Logging genutzt) werden angepasst. </li><br>
  1157. <li><a href="#ignore">ignore</a></li>
  1158. <li><a href="#do_not_notify">do_not_notify</a></li>
  1159. <li><a href="#model">model</a> (fht80b)</li>
  1160. <li><a href="#showtime">showtime</a></li>
  1161. <li><a href="#IODev">IODev</a></li>
  1162. <li><a href="#eventMap">eventMap</a></li>
  1163. <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
  1164. </ul>
  1165. <br>
  1166. <a name="FHTevents"></a>
  1167. <b>Erzeugte Events:</b>
  1168. <ul>
  1169. <li>actuator</li>
  1170. <li>actuator1 actuator2 actuator3 actuator4<br>
  1171. actuator5 actuator6 actuator7 actuator8<br>
  1172. (wird gesendet wenn ein Offset zum entsprechenden Ventil konfiguriert wurde)</li>
  1173. <li>mon-from1 mon-to1 mon-from2 mon-to2</li>
  1174. <li>tue-from1 tue-to1 tue-from2 tue-to2</li>
  1175. <li>wed-from1 wed-to1 wed-from2 wed-to2</li>
  1176. <li>thu-from1 thu-to1 thu-from2 thu-to2</li>
  1177. <li>fri-from1 fri-to1 fri-from2 fri-to2</li>
  1178. <li>sat-from1 sat-to1 sat-from2 sat-to2</li>
  1179. <li>sun-from1 sun-to1 sun-from2 sun-to2</li>
  1180. <li>mode</li>
  1181. <li>holiday1 holiday2</li>
  1182. <li>desired-temp</li>
  1183. <li>measured-temp measured-low measured-high</li>
  1184. <li>warnings</li>
  1185. <li>manu-temp</li>
  1186. <li>year month day hour minute</li>
  1187. <li>day-temp night-temp lowtemp-offset windowopen-temp</li>
  1188. <li>ack can-xmit can-rcv ack2 start-xmit end-xmit (Nur wenn das CUL
  1189. f&uuml;r die &Uuml;bertragung von FHT Protokoll Daten konfiguriert
  1190. ist)</li>
  1191. </ul>
  1192. <br>
  1193. </ul>
  1194. =end html_DE
  1195. =cut