From c3195d8a7a4b92835b5892caba25e1b0ca2cf3bc Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sat, 19 Jan 2008 19:02:30 +0000 Subject: [PATCH] mutliple buffer finished git-svn-id: https://svn.fhem.de/fhem/trunk@147 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 3 +- fhem/FHEM/00_FHZ.pm | 2 +- fhem/FHEM/11_FHT.pm | 163 +++++++++++++-------------- fhem/HISTORY | 12 ++ fhem/docs/commandref.html | 225 ++++++++++++++++++++++++-------------- fhem/fhem.pl | 8 +- 6 files changed, 238 insertions(+), 175 deletions(-) diff --git a/fhem/CHANGED b/fhem/CHANGED index d728c1ea9..7d32ae79c 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -378,7 +378,8 @@ - bugfix: 99_SUNRISE_EL.pm: may schedule double events - bugfix: 62_EMEM.pl, contrib/em1010.pl: correct readings for energy_kWh and energy_kWh_w (Boris, 06.01.08) - - feature: gloabl attr allowfrom, as wished by Holger (8.1.2008) + - feature: global attr allowfrom, as wished by Holger (8.1.2008) + - feature: FHT: multiple commands, softbuffer changes, cmd rename, doc - TODO emem -2.5kW / getDevData for emwz -1 diff --git a/fhem/FHEM/00_FHZ.pm b/fhem/FHEM/00_FHZ.pm index e6258258d..245524023 100755 --- a/fhem/FHEM/00_FHZ.pm +++ b/fhem/FHEM/00_FHZ.pm @@ -142,7 +142,7 @@ FHZ_Get($@) my $v = join(" ", @a); my $name = $hash->{NAME}; - Log GetLogLevel($name,2), "FHZ get $name $v"; + Log GetLogLevel($name,2), "FHZ get $v"; FHZ_Write($hash, $fn, $arg) if(!IsDummy("FHZ")); diff --git a/fhem/FHEM/11_FHT.pm b/fhem/FHEM/11_FHT.pm index 733b72ad3..723db80ed 100755 --- a/fhem/FHEM/11_FHT.pm +++ b/fhem/FHEM/11_FHT.pm @@ -6,11 +6,15 @@ use warnings; sub doSoftBuffer($); sub softBufferTimer($); -sub sendCommand($$$$); +sub getFhtMin($); +sub getFhtBuffer($); my %codes = ( "0000.6" => "actuator", + "00002a" => "lime-protection", "00002c" => "synctime", # Not verified + "0000aa" => "code_0000aa", + "0000ba" => "code_0000ba", "0100.6" => "actuator1", # Not verified (1-8) "0200.6" => "actuator2", "0300.6" => "actuator3", @@ -19,6 +23,7 @@ my %codes = ( "0600.6" => "actuator6", "0700.6" => "actuator7", "0800.6" => "actuator8", + "140069" => "mon-from1", "150069" => "mon-to1", "160069" => "mon-from2", @@ -47,33 +52,34 @@ my %codes = ( "2d0069" => "sun-to1", "2e0069" => "sun-from2", "2f0069" => "sun-to2", + "3e0069" => "mode", "3f0069" => "holiday1", # Not verified "400069" => "holiday2", # Not verified "410069" => "desired-temp", - "XX0069" => "measured-temp", # sum of next. two, never "really" sent + "XX0069" => "measured-temp", # sum of next. two, never really sent "420069" => "measured-low", "430069" => "measured-high", + "430079" => "code_430079", "440069" => "warnings", - "450069" => "manu-temp", # Manuelle Temperatur keine ahnung was das bewirkt + "440079" => "code_440079", + "450069" => "manu-temp", # No clue what it does. + + "..0067" => "repeat1", # repeat the last data (?) + "..0077" => "repeat2", + "600069" => "year", "610069" => "month", "620069" => "day", "630069" => "hour", "640069" => "minute", - "650069" => "init", + "650069" => "refresh", + "660069" => "init", # ? + "820069" => "day-temp", "840069" => "night-temp", - "850069" => "lowtemp-offset", # Alarm-Temp.-Differenz + "850069" => "lowtemp-offset", # Alarm-Temp.-Differenz "8a0069" => "windowopen-temp", - "00002a" => "lime-protection", - "0000aa" => "code_0000aa", - "0000ba" => "code_0000ba", - "430079" => "code_430079", - "440079" => "code_440079", - "4b0067" => "code_4b0067", - "4b0077" => "code_4b0077", - "7e0067" => "code_7e0067", ); my %cantset = ( @@ -91,26 +97,23 @@ my %cantset = ( "measured-high" => 1, "measured-low" => 1, "warnings" => 1, - "init" => 1, "lime-protection"=>1, + "repeat1" => 1, + "repeat2" => 1, "code_0000aa" => 1, "code_0000ba" => 1, "code_430079" => 1, "code_440079" => 1, - "code_4b0067" => 1, - "code_4b0077" => 1, - "code_7e0067" => 1, ); my %nosetarg = ( - "refreshvalues" => 1, ); my %priority = ( "desired-temp"=> 1, "mode" => 2, - "refreshvalues"=> 3, + "refresh" => 3, "holiday1" => 4, "holiday2" => 5, "day-temp" => 6, @@ -123,7 +126,7 @@ my %c2b; # command->button hash (reverse of codes) my %c2bset; # Setteable values my %defptr; -my $minFhzHardwareBuffer = 10; # min fhtbuf free bytes before sending commands +my $defmin = 0; # min fhtbuf free bytes before sending commands my $retryafter = 240; # in seconds, only when fhtsoftbuffer is active my $cmdcount = 0; @@ -141,7 +144,6 @@ FHT_Initialize($) foreach my $k (keys %c2m) { $m2c{$c2m{$k}} = $k; } - $c2bset{refreshvalues} = "65ff66ff"; # 810c0426 0909a001 1111 1600 # 810c04b3 0909a001 1111 44006900 @@ -155,7 +157,7 @@ FHT_Initialize($) $hash->{UndefFn} = "FHT_Undef"; $hash->{ParseFn} = "FHT_Parse"; $hash->{AttrList} = "do_not_notify:0,1 model;fht80b dummy:0,1 " . - "showtime:0,1 loglevel:0,1,2,3,4,5,6 retrycount"; + "showtime:0,1 loglevel:0,1,2,3,4,5,6 retrycount minfhtbuffer"; } @@ -167,35 +169,39 @@ FHT_Set($@) return "\"set $a[0]\" needs at least two parameters" if(@a < 2); - my $name = shift(@a); + my $name = shift(@a); + # Backward compatibility, replace refreshvalues with refresh and init. + for(my $i = 0; $i < @a; $i++) { + splice(@a,$i,1,("refresh","255","init","255")) + if($a[$i] eq "refreshvalues"); + } my $ncmd = 0; my $arg = "020183" . $hash->{CODE}; - my ($cmd, $val) = ("", ""); + my ($cmd, $allcmd, $val) = ("", "", ""); while(@a) { - my $lcmd = shift(@a); + $cmd = shift(@a); - $cmd .=" " if($cmd); - $cmd .= $lcmd; + $allcmd .=" " if($allcmd); + $allcmd .= $cmd; - return "Unknown argument $lcmd, choose one of " . + return "Unknown argument $cmd, choose one of " . join(" ", sort {$c2bset{$a} cmp $c2bset{$b} } keys %c2bset) - if(!defined($c2bset{$lcmd})); + if(!defined($c2bset{$cmd})); return "\"set $name\" needs a parameters" - if(@a < 1 && !$nosetarg{$lcmd}); + if(@a < 1 && !$nosetarg{$cmd}); $ncmd++; - if(!$nosetarg{$lcmd}) { - $val = shift(@a); - $cmd .= " $val"; - } else { + if($nosetarg{$cmd}) { $val = undef; + } else { + $val = shift(@a); } - $arg .= $c2bset{$lcmd}; + $arg .= $c2bset{$cmd}; - if ($lcmd =~ m/-temp/) { + if ($cmd =~ m/-temp/) { return "Invalid temperature, use NN.N" if($val !~ m/^\d*\.?\d+$/); return "Invalid temperature, must between 5.5 and 30.5" @@ -205,7 +211,7 @@ FHT_Set($@) $ret = sprintf("Rounded temperature to %.1f", $a/2) if($a/2 != $val); $val = sprintf("%.1f", $a/2); - } elsif($lcmd =~ m/-from/ || $lcmd =~ m/-to/) { + } elsif($cmd =~ m/-from/ || $cmd =~ m/-to/) { return "Invalid timeformat, use HH:MM" if($val !~ m/^([0-2]\d):([0-5]\d)/); @@ -216,13 +222,13 @@ FHT_Set($@) $ret = "Rounded time to $nt" if($nt ne $val); $val = $nt; - } elsif($lcmd eq "mode") { + } elsif($cmd eq "mode") { return "Invalid mode, use one of " . join(" ", sort keys %m2c) if(!defined($m2c{$val})); $arg .= sprintf("%02x", $m2c{$val}); - } elsif ($lcmd eq "lowtemp-offset") { + } elsif ($cmd eq "lowtemp-offset") { return "Invalid lowtemperature-offset, must between 1 and 5" if($val !~ m/^[1-5]$/); @@ -234,19 +240,17 @@ FHT_Set($@) $arg .= sprintf("%02x", $val) if(defined($val)); } + $allcmd .= " $val" if($val); } - $val = "" if (!defined($val) || $ncmd > 1); - + return "Too many commands specified, an FHT only supports up to 8" + if($ncmd > 8); my $ioname = ""; $ioname = $hash->{IODev}->{NAME} if($hash->{IODev}); if($attr{$ioname} && $attr{$ioname}{fhtsoftbuffer}) { - if($ncmd > 1) { - return "Cannot accept multiple FHT commands with fhtsoftbuffer enabled"; - } my $io = $hash->{IODev}; - my %h = (HASH => $hash, CMD => $cmd, VAL => $val, ARG => $arg); + my %h = (HASH => $hash, CMD => $allcmd, ARG => $arg); my $prio = $priority{$cmd}; $prio = "9" if(!$prio); @@ -257,7 +261,8 @@ FHT_Set($@) } else { - sendCommand($hash, $cmd, $val, $arg); + IOWrite($hash, "04", $arg) if(!IsDummy($name)); + Log GetLogLevel($name,2), "FHT set $name $allcmd"; } @@ -297,7 +302,7 @@ FHT_Define($$) AssignIoPort($hash); Log GetLogLevel($a[0],2),"Asking the FHT device $a[0]/$a[2] to send its data"; - FHT_Set($hash, ($a[0], "refreshvalues")); + FHT_Set($hash, ($a[0], "init", "255", "refresh", "255")); return undef; } @@ -430,17 +435,18 @@ FHT_Parse($$) Log 4, "FHT $name $type: $val"; ################################ - # Softbuffer: deleted confirmed commands + # Softbuffer: delete confirmed commands if($confirm) { my $found; my $io = $def->{IODev}; foreach my $key (sort keys %{$io->{SOFTBUFFER}}) { my $h = $io->{SOFTBUFFER}{$key}; my $hcmd = $h->{CMD}; - $hcmd = "init" if($hcmd eq "refreshvalues"); - Log 5, "FHT check $h->{HASH}->{NAME} eq $name && $hcmd eq $type"; - if($h->{HASH}->{NAME} eq $name && $hcmd eq $type) { + my $hname = $h->{HASH}->{NAME}; + Log 4, "FHT softbuffer check: $hname / $hcmd"; + if($hname eq $name && $hcmd =~ m/^$type $val/) { $found = $key; + Log 4, "FHT softbuffer found"; last; } } @@ -471,17 +477,21 @@ doSoftBuffer($) next if($now-$h->{SENDTIME} < $retryafter); my $retry = $attr{$name}{retrycount}; if($h->{NSENT} > $retry) { - Log GetLogLevel($name,2), "$name set $h->{CMD} $h->{VAL}: ". + Log GetLogLevel($name,2), "$name set $h->{CMD}: ". "no confirmation after $h->{NSENT} tries, giving up"; delete($io->{SOFTBUFFER}{$key}); next; } } - $fhzbuflen = getFhzBuffer($io) if($fhzbuflen == -999); - next if($fhzbuflen < $minFhzHardwareBuffer); - sendCommand($h->{HASH}, $h->{CMD}, $h->{VAL}, $h->{ARG}); - $fhzbuflen -= ($h->{CMD} eq "refreshvalues" ? 7 : 5); + $fhzbuflen = getFhtBuffer($io) if($fhzbuflen == -999); + my $arglen = length($h->{ARG})/2 - 2; # Length in bytes + + next if($fhzbuflen < $arglen || $fhzbuflen < getFhtMin($io)); + IOWrite($h->{HASH}, "04", $h->{ARG}) if(!IsDummy($name)); + Log GetLogLevel($name,2), "FHT set $name $h->{CMD}"; + + $fhzbuflen -= $arglen; $h->{SENDTIME} = $now; $h->{NSENT}++; @@ -503,50 +513,35 @@ softBufferTimer($) doSoftBuffer($io); } +##################################### +sub +getFhtMin($) +{ + my ($io) = @_; + my $ioname = $io->{NAME}; + return $attr{$ioname}{minfhtbuffer} + if($attr{$ioname} && $attr{$ioname}{minfhtbuffer}); + return $defmin; +} ##################################### # get the FHZ hardwarebuffer without logentry as decimal value sub -getFhzBuffer($) +getFhtBuffer($) { my ($io) = @_; my $count = 0; - return $minFhzHardwareBuffer if(IsDummy($io->{NAME})); + return getFhtMin($io) if(IsDummy($io->{NAME})); for(;;) { FHZ_Write($io, "04", "c90185"); my $msg = FHZ_ReadAnswer($io, "fhtbuf"); - Log 5, "getFhzBuffer: $count $msg"; + Log 5, "getFhtBuffer: $count $msg"; return hex(substr($msg, 16, 2)) if($msg && $msg =~ m/^[0-9A-F]+$/i); return 0 if($count++ > 5); } } -##################################### -# Send FHZ command -sub -sendCommand($$$$) -{ - my ($hash, $cmd, $val, $arg) = @_; - my $name = $hash->{NAME}; - - if($cmd eq "refreshvalues") { - - # This is special. Without the sleep the next FHT won't send its data - if(!IsDummy($name)) { - my $havefhz = ($hash->{IODev} && defined($hash->{IODev}->{FD})); - IOWrite($hash, "04", $arg); - sleep(1) if($havefhz); - } - - } else { - - IOWrite($hash, "04", $arg) if(!IsDummy($name)); - - } - Log GetLogLevel($name,2), "FHT set $name $cmd $val"; -} - 1; diff --git a/fhem/HISTORY b/fhem/HISTORY index e2cb3acc0..b4b9164c2 100644 --- a/fhem/HISTORY +++ b/fhem/HISTORY @@ -197,3 +197,15 @@ - feature: attr global allowfrom If set, only connects from these addresses are allowed. This is to "simulate" a little bit of security. + +- Rudi Sat Jan 19 18:04:12 MET 2008 + - FHT: multiple commands + Up to 8 commands in one set, these are transmitted at once to the FHT + - softbuffer changes + minfhtbuffer attribute, as otherwise nearly everything will be sent to + the FHT buffer, so ordering won't take effect. + - cmd rename + repeat1,repeat2. refreshvalues changed to refresh and init. refreshvalues + won't be advertized but still replaced to "refresh 255 init 255" + - extensive documentation update for the FHT + diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index 56bf7f811..86c6c2f83 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -448,22 +448,34 @@ split in multiple lines

time.
-
  • fhtsoftbuffer
    - Can be applied to FHZ devices.
    - As the FHZ command buffer for FHT devices is limited, and commands - are only sent to the FHT devices every 150 seconds, the hardware - buffer may overflow and FHT commands get lost. Setting this attribute - to 1 implements an "unlimited" software buffer
    +
  • fhtsoftbuffer
    + Can be applied to FHZ devices.
    + As the FHZ command buffer for FHT devices is limited (see fhtbuf), + and commands are only sent to the FHT device every 120 seconds, + the hardware buffer may overflow and FHT commands get lost. + Setting this attribute implements an "unlimited" software buffer
    Default is disabled (i.e. not set or set to 0).

  • -
  • retrycount
    - Can be applied to FHT devices.
    +
  • retrycount
    + Can be applied to FHT devices.
    If the fhtsoftbuffer attribute is set, then resend commands retrycount times if after 240 seconds no confirmation message is rececived from the corresponding FHT device.
    Default is 3.

  • + + +
  • minfhtbuffer
    + Can be applied to FHT devices.
    + FHEM wont send commands to the FHZ if its fhtbuffer is below + this value, default is 0. If this value is low, then the ordering of + fht commands (see the note in the FHT section of set) + has little effect, as only commands in the softbuffer can be + prioritized. The maximum value should be 7 below the hardware maximum + (see fhtbuf). + +

  • @@ -472,11 +484,11 @@ split in multiple lines

    attr global verbose 3
    attr lamp room kitchen
    attr lamp dummy
    - attr lamp loglevel 6
    + attr lamp loglevel 6

    - attr FHZ fhtsoftbuffer 0 # disable the fhtsoftbuffer for FHT devices
    - attr FHZ softrepeat 300 # resend failed commands to FHT devices after 300 seconds
    - attr FHZ softmaxretry 4 # stop resending failed commands to FHT devices after 4 retries. + attr FHZ fhtsoftbuffer 0 # disable the fhtsoftbuffer
    + attr FHZ retrycount 4 # resend commands to FHT devices at most 4 times. +
    Notes:
    @@ -617,7 +629,7 @@ split in multiple lines

    define wz FHT 3232

    - See the section set for more. + See the FHT section in set for more.
    @@ -1229,11 +1241,17 @@ split in multiple lines

  • The answer for a command is also displayed by list FHZ
  • - The FHZ1000PC has a message buffer for the FHT, as it - only can send messages to it every 2 (or so) minutes. If the buffer - is full, then newly issued ones will be dropped. fhtbuf - returns the free memory in this buffer (in hex), my maximum is 2c (42 - bytes).
  • + The FHZ1x00PC has a message buffer for the FHT (see the FHT entry in + the set section). If the buffer is full, then newly + issued commands will be dropped, if the attribute fhtsoftbuffer is not set. + fhtbuf returns the free memory in this buffer (in hex), + an empty buffer in the FHZ1000 is 2c (42 bytes), in the FHZ1300 is 4a + (74 bytes). A message occupies 3 + 2x(number of FHT commands) bytes, + this is the second reason why sending multiple FHT commands with one + set is a good idea. The first reason is, that + these FHT commands are sent at once to the FHT. + @@ -1395,8 +1413,8 @@ split in multiple lines

    2006-11-02 04:13:27 wed-from1 06:00 2006-11-02 04:13:28 wed-to1 23:00 2006-11-02 04:13:36 windowopen-temp 12.0 (Celsius) -Send buffer:
    2007-10-19 00:31:24 desired-temp 22.5 - 2007-10-19 00:33:20 mode auto
    +Send buffer:
    2007-10-19 00:31:24 desired-temp 22.5 + 2007-10-19 00:33:20 mode auto
    @@ -1617,56 +1635,73 @@ Send buffer:
    2007-10-19 00:31:24 desired-temp 22.5

    where value is one of:
    -    mon-from1
    -    mon-to1
    -    mon-from2
    -    mon-to2
    -    tue-from1
    -    tue-to1
    -    tue-from2
    -    tue-to2
    -    wed-from1
    -    wed-to1
    -    wed-from2
    -    wed-to2
    -    thu-from1
    -    thu-to1
    -    thu-from2
    -    thu-to2
    -    fri-from1
    -    fri-to1
    -    fri-from2
    -    fri-to2
    -    sat-from1
    -    sat-to1
    -    sat-from2
    -    sat-to2
    -    sun-from1
    -    sun-to1
    -    sun-from2
    -    sun-to2
    -    mode
    -    holiday1
    -    holiday2
    -    desired-temp
    -    day-temp
    -    night-temp
    -    year
    -    month
    -    day
    -    hour
    -    minute
    -    refreshvalues
    -    lowtemp-offset
    +      desired-temp
    +      day-temp night-temp
    +      refresh
    +      init
    +      mode  
    +      holiday1 holiday2      # Not verified
    +      manu-temp              # No clue what it does.
    +      year month day hour minute
    +      lowtemp-offset         # Alarm-Temp.-Differenz
    +      windowopen-temp
    +      mon-from1 mon-to1 mon-from2 mon-to2
    +      tue-from1 tue-to1 tue-from2 tue-to2
    +      wed-from1 wed-to1 wed-from2 wed-to2
    +      thu-from1 thu-to1 thu-from2 thu-to2
    +      fri-from1 fri-to1 fri-from2 fri-to2
    +      sat-from1 sat-to1 sat-from2 sat-to2
    +      sun-from1 sun-to1 sun-from2 sun-to2
     
    + + Examples: + +
    + Notes: diff --git a/fhem/fhem.pl b/fhem/fhem.pl index a3619252a..a31638021 100755 --- a/fhem/fhem.pl +++ b/fhem/fhem.pl @@ -138,7 +138,7 @@ my %intAt; # Internal at timer hash. my $intAtCnt=0; my $reread_active = 0; my $AttrList = "room comment"; -my $cvsid = '$Id: fhem.pl,v 1.37 2008-01-08 20:15:58 rudolfkoenig Exp $'; +my $cvsid = '$Id: fhem.pl,v 1.38 2008-01-19 19:02:30 rudolfkoenig Exp $'; $init_done = 0; @@ -1388,11 +1388,11 @@ CommandAttr($$) { my ($cl, $param) = @_; my $ret = undef; + my @a; + @a = split(" ", $param, 3) if($param); - my @a = split(" ", $param, 3); return "Usage: attr []\n" . - "$namedef" if(@a < 2); - + "$namedef" if(@a && @a < 2); my @rets; foreach my $sdev (devspec2array($a[0])) {