mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
- Softwarebuffer for FHT devices with queuing unsent commands and repeating commands by transmission failure
- FHT low temperatur warning and setting for lowtemp-offset - Change naming for state into warnings git-svn-id: https://svn.fhem.de/fhem/trunk@101 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
72b261d6aa
commit
04a95a803f
@ -348,3 +348,6 @@
|
||||
- feature: webpgm2 output reformatted
|
||||
- feature: webpgm2 can display multiple plots.
|
||||
- feature: FHT lime-protection code discovered by Dirk (7.10)
|
||||
- feature: Softwarebuffer for FHT devices with queuing unsent commands and repeating commands by transmission failure (Dirk 17.10)
|
||||
- feature: FHT low temperatur warning and setting for lowtemp-offset (Dirk 17.10)
|
||||
- change: Change naming for state into warnings (Dirk 17.10)
|
@ -68,7 +68,7 @@ FHZ_Initialize($)
|
||||
$hash->{SetFn} = "FHZ_Set";
|
||||
$hash->{StateFn} = "FHZ_SetState";
|
||||
$hash->{ParseFn} = "FHZ_Parse";
|
||||
$hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 filtertimeout repeater:1,0 showtime:1,0 model:fhz1000,fhz1300 loglevel:0,1,2,3,4,5,6";
|
||||
$hash->{AttrList}= "do_not_notify:1,0 dummy:1,0 filtertimeout repeater:1,0 showtime:1,0 model:fhz1000,fhz1300 loglevel:0,1,2,3,4,5,6 softbuffer softrepeat softmaxretry";
|
||||
}
|
||||
|
||||
#####################################
|
||||
@ -160,6 +160,24 @@ FHZ_Get($@)
|
||||
return "$a[0] $a[1] => $v";
|
||||
}
|
||||
|
||||
#####################################
|
||||
# get the FHZ hardwarebuffer without logentry
|
||||
# and as decimal value
|
||||
sub getFhzBuffer()
|
||||
{
|
||||
my $msg = "Timeout";
|
||||
|
||||
while (index($msg,"Timeout") >= 0) { # try getting FHZ buffer until no Timeout occurs
|
||||
FHZ_Write($defs{FHZ}, "04", "c90185") if(!IsDummy("FHZ"));
|
||||
$msg = FHZ_ReadAnswer($defs{FHZ}, "fhtbuf");
|
||||
}
|
||||
|
||||
my $v = substr($msg, 16, 2);
|
||||
$v = hex $v;
|
||||
|
||||
return "$v";
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
FHZ_SetState($$$$)
|
||||
@ -346,7 +364,8 @@ FHZ_ReadAnswer($$)
|
||||
|
||||
my $buf = $hash->{PortObj}->input();
|
||||
|
||||
Log 5, "FHZ/RAW: " . unpack('H*',$buf);
|
||||
# Log 5, "FHZ/RAW: " . unpack('H*',$buf);
|
||||
Log 4, "FHZ/RAW: " . unpack('H*',$buf);
|
||||
$mfhzdata .= $buf;
|
||||
next if(length($mfhzdata) < 2);
|
||||
|
||||
|
@ -50,7 +50,8 @@ my %codes = (
|
||||
"XX0069" => "measured-temp", # sum of next. two, never "really" sent
|
||||
"420069" => "measured-low",
|
||||
"430069" => "measured-high",
|
||||
"440069" => "state",
|
||||
"440069" => "warnings",
|
||||
"450069" => "manu-temp", # Manuelle Temperatur keine ahnung was das bewirkt
|
||||
"600069" => "year",
|
||||
"610069" => "month",
|
||||
"620069" => "day",
|
||||
@ -59,10 +60,9 @@ my %codes = (
|
||||
"650069" => "init",
|
||||
"820069" => "day-temp",
|
||||
"840069" => "night-temp",
|
||||
"850069" => "unknown_85",
|
||||
"850069" => "lowtemp-offset", # Alarm-Temp.-Differenz
|
||||
"8a0069" => "windowopen-temp",
|
||||
"00002a" => "lime-protection",
|
||||
|
||||
"0000aa" => "code_0000aa",
|
||||
"0000ba" => "code_0000ba",
|
||||
"430079" => "code_430079",
|
||||
@ -86,7 +86,7 @@ my %cantset = (
|
||||
"measured-temp" => 1,
|
||||
"measured-high" => 1,
|
||||
"measured-low" => 1,
|
||||
"state" => 1,
|
||||
"warnings" => 1,
|
||||
"init" => 1,
|
||||
"lime-protection"=>1,
|
||||
|
||||
@ -104,12 +104,25 @@ my %nosetarg = (
|
||||
"refreshvalues" => 1,
|
||||
);
|
||||
|
||||
my %priority = (
|
||||
"desired-temp" => 1,
|
||||
"mode" => 2,
|
||||
"refreshvalues" => 3,
|
||||
"holiday1" => 4,
|
||||
"holiday2" => 5,
|
||||
"day-temp" => 6,
|
||||
"night-temp" => 7,
|
||||
);
|
||||
|
||||
my %c2m = (0 => "auto", 1 => "manual", 2 => "holiday", 3 => "holiday_short");
|
||||
my %m2c; # Reverse c2m
|
||||
my %c2b; # command->button hash (reverse of codes)
|
||||
my %c2bset; # Setteable values
|
||||
my %m2c; # Reverse c2m
|
||||
my %c2b; # command->button hash (reverse of codes)
|
||||
my %c2bset; # Setteable values
|
||||
my %defptr;
|
||||
|
||||
my $timerCheckBufferIsRunning = 0; # set to 1 if the timer is running
|
||||
my $minFhzHardwareBufferSpace = 10; # min. bytes free in hardware buffer before sending commands
|
||||
my $fhzHardwareBufferSpace = 0; # actual hardware buffer space in fhz
|
||||
|
||||
#####################################
|
||||
sub
|
||||
@ -143,29 +156,115 @@ FHT_Initialize($)
|
||||
$hash->{AttrList} = "do_not_notify:0,1 model;fht80b dummy:0,1 showtime:0,1 loglevel:0,1,2,3,4,5,6";
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
sub
|
||||
FHT_Set($@)
|
||||
# Parse the incomming commands and send them via sendCommand to the FHZ
|
||||
# or via toSendbuffer in the Softwarebuffer (queue)
|
||||
#
|
||||
sub FHT_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
my $ret = undef;
|
||||
my ($hash, @a) = @_;
|
||||
my $ret = undef;
|
||||
my $arg = "020183" . $hash->{CODE} . $c2bset{$a[1]};
|
||||
my $val = $a[2];
|
||||
|
||||
return "\"set $a[0]\" needs two parameters" if(@a < 2);
|
||||
return "Unknown argument $a[1], choose one of " .
|
||||
join(" ", sort {$c2bset{$a} cmp $c2bset{$b} } keys %c2bset)
|
||||
if(!defined($c2bset{$a[1]}));
|
||||
return "\"set $a[0]\" needs two parameters"
|
||||
if(@a != 3 && !(@a == 2 && $nosetarg{$a[1]}));
|
||||
|
||||
Log GetLogLevel($a[0],2), "FHT set " . join(" ", @a);
|
||||
|
||||
my $arg = "020183" . $hash->{CODE} . $c2bset{$a[1]};
|
||||
if(@a != 3 && !(@a == 2 && $nosetarg{$a[1]}));
|
||||
|
||||
if($a[1] eq "refreshvalues") {
|
||||
|
||||
} elsif ($a[1] =~ m/-temp/) {
|
||||
return "Invalid temperature, use NN.N" if($val !~ m/^\d*\.?\d+$/);
|
||||
|
||||
# additional check for temperature
|
||||
return "Invalid temperature, must between 5.5 and 30.5" if($val < 5.5 || $val > 30.5);
|
||||
|
||||
my $a = int($val*2);
|
||||
$arg .= sprintf("%02x", $a);
|
||||
$ret = sprintf("Rounded temperature to %.1f", $a/2) if($a/2 != $val);
|
||||
$val = sprintf("%.1f", $a/2) if($a/2 != $val);
|
||||
$val = sprintf("%.1f", $val);
|
||||
|
||||
} elsif($a[1] =~ m/-from/ || $a[1] =~ m/-to/) {
|
||||
return "Invalid timeformat, use HH:MM" if($val !~ m/^([0-2]\d):([0-5]\d)/);
|
||||
my $a = ($1*6) + ($2/10);
|
||||
$arg .= sprintf("%02x", $a);
|
||||
|
||||
my $nt = sprintf("%02d:%02d", $1, ($2/10)*10);
|
||||
$val = $nt if($nt ne $val);
|
||||
$ret = "Rounded time to $nt" if($nt ne $val);
|
||||
|
||||
} elsif($a[1] eq "mode") {
|
||||
return "Invalid mode, use one of " . join(" ", sort keys %m2c)
|
||||
if(!defined($m2c{$val}));
|
||||
$arg .= sprintf("%02x", $m2c{$val});
|
||||
|
||||
} elsif ($a[1] eq "lowtemp-offset") {
|
||||
return "Invalid lowtemperature-offset, use N" if($val !~ m/^\d*\.?\d+$/);
|
||||
|
||||
# additional check for temperature
|
||||
return "Invalid lowtemperature-offset, must between 1 and 5" if($val < 1 || $val > 5);
|
||||
|
||||
my $a = int($val);
|
||||
$arg .= sprintf("%02x", $a);
|
||||
$ret = sprintf("Rounded temperature to %d.0", $a) if($a != $val);
|
||||
$val = "$a.0";
|
||||
|
||||
} else { # Holiday1, Holiday2
|
||||
$arg .= sprintf("%02x", $val);
|
||||
}
|
||||
|
||||
my $dev = $hash->{CODE};
|
||||
my $def = $defptr{$dev};
|
||||
my $name = $def->{NAME};
|
||||
my $type = $a[1];
|
||||
my $sbCount = keys(%{$def->{SENDBUFFER}}); # Count of sendbuffer
|
||||
|
||||
# get firsttime hardware buffer of FHZ if $fhzHardwareBufferSpace not set
|
||||
$fhzHardwareBufferSpace = getFhzBuffer () if ($fhzHardwareBufferSpace == 0);
|
||||
|
||||
# set default values for config value attr FHZ softbuffer
|
||||
$attr{FHZ}{softbuffer} = 1 if (!defined($attr{FHZ}{softbuffer}));
|
||||
|
||||
$val = "" if (!defined($val));
|
||||
|
||||
if ( ($sbCount == 0 && $fhzHardwareBufferSpace >= $minFhzHardwareBufferSpace) || $attr{FHZ}{softbuffer} == 0) {
|
||||
sendCommand ($hash, $arg, $name, $type, $val); # send command direct to FHZ
|
||||
} else {
|
||||
|
||||
Log GetLogLevel($name,2), "FHT set $name $type $val (Enqueue to buffer)" if ($fhzHardwareBufferSpace >= $minFhzHardwareBufferSpace);
|
||||
|
||||
Log GetLogLevel($name,2), "Can't send command set $name $type $val. " .
|
||||
"No space left in FHZ hardware buffer." if($fhzHardwareBufferSpace < $minFhzHardwareBufferSpace);
|
||||
|
||||
}
|
||||
|
||||
# only if softbuffer not disabled via config
|
||||
if ($attr{FHZ}{softbuffer} == 1) {
|
||||
toSendbuffer ($hash, $type, $val, $arg, "", 0); # send command also to buffer
|
||||
|
||||
if ($timerCheckBufferIsRunning == 0 && $init_done) {
|
||||
$timerCheckBufferIsRunning = 1; # set $timerCheckBufferIsRunning to 1 to remeber a timer is running
|
||||
InternalTimer(gettimeofday()+70, "timerCheckBuffer", $hash); # start internal Timer to periodical check the buffer
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
# Send command to FHZ
|
||||
#
|
||||
sub sendCommand ($$$$$)
|
||||
{
|
||||
|
||||
my ($hash, $arg, $name, $type, $val) = @_;
|
||||
|
||||
if($type eq "refreshvalues") {
|
||||
# This is special. Without the sleep the next FHT won't send its data
|
||||
if(!IsDummy($a[0])) {
|
||||
if(!IsDummy($name)) {
|
||||
my $havefhz;
|
||||
$havefhz = 1 if($hash->{IODev} && defined($hash->{IODev}->{FD}));
|
||||
|
||||
@ -174,36 +273,40 @@ FHT_Set($@)
|
||||
IOWrite($hash, "04", "c90185"); # Check the fht buffer
|
||||
sleep(1) if($havefhz);
|
||||
}
|
||||
return $ret;
|
||||
|
||||
} elsif($a[1] =~ m/-temp/) {
|
||||
return "Invalid temperature, use NN.N" if($a[2] !~ m/^\d*\.?\d+$/);
|
||||
my $a = int($a[2]*2);
|
||||
$arg .= sprintf("%02x", $a);
|
||||
$ret = "Rounded temperature to " . $a/2 if($a/2 != $a[2]);
|
||||
|
||||
} elsif($a[1] =~ m/-from/ || $a[1] =~ m/-to/) {
|
||||
return "Invalid timeformat, use HH:MM" if($a[2] !~ m/^([0-2]\d):([0-5]\d)/);
|
||||
my $a = ($1*6) + ($2/10);
|
||||
$arg .= sprintf("%02x", $a);
|
||||
|
||||
my $nt = sprintf("%02d:%02d", $1, ($2/10)*10);
|
||||
$ret = "Rounded time to $nt" if($nt ne $a[2]);
|
||||
|
||||
} elsif($a[1] eq "mode") {
|
||||
return "Invalid mode, use one of " . join(" ", sort keys %m2c)
|
||||
if(!defined($m2c{$a[2]}));
|
||||
$arg .= sprintf("%02x", $m2c{$a[2]});
|
||||
|
||||
} else { # Holiday1, Holiday2
|
||||
$arg .= sprintf("%02x", $a[2]);
|
||||
|
||||
} else {
|
||||
IOWrite($hash, "04", $arg) if(!IsDummy($name));
|
||||
}
|
||||
|
||||
IOWrite($hash, "04", $arg) if(!IsDummy($a[0]));
|
||||
return $ret;
|
||||
Log GetLogLevel($name,2), "FHT set $name $type $val";
|
||||
|
||||
# decrease $fhzHardwareBufferSpace for each command sending to the FHZ
|
||||
$fhzHardwareBufferSpace = $fhzHardwareBufferSpace -5 if(!IsDummy($name));
|
||||
}
|
||||
|
||||
|
||||
sub resendCommand ($)
|
||||
{
|
||||
|
||||
my ($buffer) = @_;
|
||||
my $hash = $buffer->{HASH};
|
||||
my $dev = $hash->{CODE};
|
||||
my $def = $defptr{$dev};
|
||||
my $nRetry = $buffer->{RETRY} + 1;
|
||||
|
||||
if ($fhzHardwareBufferSpace > $minFhzHardwareBufferSpace) {
|
||||
Log GetLogLevel($def->{NAME},2), "Resending command to FHT set " . $def->{NAME} . " " . $buffer->{TYPE} . " " . $buffer->{VAL} .
|
||||
" (Retry $nRetry / ". $attr{FHZ}{softmaxretry} . ")";
|
||||
|
||||
sendCommand ($buffer->{HASH}, $buffer->{ARG}, $buffer->{NAME}, $buffer->{TYPE}, $buffer->{VAL});
|
||||
toSendbuffer ($buffer->{HASH}, $buffer->{TYPE}, $buffer->{VAL}, $buffer->{ARG}, $buffer->{KEY}, $nRetry); # send command also to buffer
|
||||
|
||||
} else {
|
||||
Log GetLogLevel($def->{NAME},2), "Can't send command \"set " . $def->{NAME} . " " . $buffer->{TYPE} . " " . $buffer->{VAL} .
|
||||
"\". No space in FHZ hardware buffer left. Resending next time if free bufferspace available.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#####################################
|
||||
sub
|
||||
FHT_SetState($$$$)
|
||||
@ -249,27 +352,27 @@ FHT_Undef($$)
|
||||
}
|
||||
|
||||
#####################################
|
||||
sub
|
||||
sub
|
||||
FHT_Parse($$)
|
||||
{
|
||||
my ($hash,$msg) = @_;
|
||||
my ($hash, $msg) = @_;
|
||||
|
||||
my $dev = substr($msg, 16, 4);
|
||||
my $cde = substr($msg, 20, 6);
|
||||
my $val = substr($msg, 26, 2) if(length($msg) > 26);
|
||||
my $confirm = 0;
|
||||
|
||||
$fhzHardwareBufferSpace = getFhzBuffer () if ($fhzHardwareBufferSpace == 0);
|
||||
|
||||
if(!defined($defptr{$dev})) {
|
||||
Log 3, "FHT Unknown device $dev, please define it";
|
||||
return "UNDEFINED FHT $dev";
|
||||
}
|
||||
|
||||
|
||||
my $def = $defptr{$dev};
|
||||
|
||||
# Unknown, but don't want report it. Should come with c409c401
|
||||
if($cde eq "00") {
|
||||
return "";
|
||||
}
|
||||
return "" if($cde eq "00");
|
||||
|
||||
if(length($cde) < 6) {
|
||||
my $name = $def->{NAME};
|
||||
@ -284,7 +387,18 @@ FHT_Parse($$)
|
||||
# it looks like a real message, and let the rest parse it
|
||||
Log 4, "FHT $def->{NAME} confirmation: $cde)";
|
||||
$val = substr($cde, 2, 2);
|
||||
|
||||
# get the free hardware buffer space in the FHZ after each confirmation message
|
||||
$fhzHardwareBufferSpace = hex substr($cde, 4, 2);
|
||||
|
||||
# increase $fhzHardwareBufferSpace at 5 because the confirmed command is deleted in the FHZ after confirmation
|
||||
$fhzHardwareBufferSpace = $fhzHardwareBufferSpace + 5;
|
||||
Log 4, "FHZ new FHT Buffer: $fhzHardwareBufferSpace";
|
||||
|
||||
$cde = substr($cde, 0, 2) . "0069";
|
||||
|
||||
# set help var to remember this is a confirmation
|
||||
$confirm = 1;
|
||||
}
|
||||
|
||||
my $type;
|
||||
@ -303,7 +417,6 @@ FHT_Parse($$)
|
||||
return $def->{NAME};
|
||||
}
|
||||
|
||||
|
||||
my $tn = TimeNow();
|
||||
|
||||
###########################
|
||||
@ -348,13 +461,26 @@ FHT_Parse($$)
|
||||
} elsif($type =~ m/.*-temp/) {
|
||||
$val = sprintf("%.1f (Celsius)", $val / 2)
|
||||
|
||||
} elsif($type eq "state") {
|
||||
} elsif($type eq "warnings") {
|
||||
|
||||
my $nval;
|
||||
$nval = "Bat: " . (($val & 1) ? "empty" : "ok");
|
||||
$nval .= ", Window: " . (($val & 32) ? "open" : "closed");
|
||||
$nval .= ", Fault: " . (($val & 16) ? "yes" : "no");
|
||||
$val = $nval;
|
||||
my @nVal;
|
||||
$nVal[0] = "Battery low" if ($val & 1);
|
||||
$nVal[1] = "Window open" if ($val & 32);
|
||||
$nVal[2] = "Fault on window sensor" if ($val & 16);
|
||||
$nVal[3] = "Temperature to low" if ($val & 2);
|
||||
|
||||
if ($val > 0) {
|
||||
$val = "";
|
||||
foreach (@nVal) {
|
||||
$val .= "$_; " if (defined($_));
|
||||
}
|
||||
$val = substr($val, 0, length($val)-2);
|
||||
} else {
|
||||
$val = "none";
|
||||
}
|
||||
|
||||
} elsif($type eq "lowtemp-offset") {
|
||||
$val = sprintf("%d.0 (Celsius)", $val)
|
||||
|
||||
} elsif($type =~ m/echo_/) { # Ignore these messages
|
||||
return "";
|
||||
@ -365,9 +491,192 @@ FHT_Parse($$)
|
||||
$def->{READINGS}{$type}{VAL} = $val;
|
||||
|
||||
Log 4, "FHT $def->{NAME} ($type: $val)";
|
||||
|
||||
###########################################################################
|
||||
# here starts the processing the confirmation to control the softwarebuffer
|
||||
#
|
||||
|
||||
$attr{FHZ}{softbuffer} = 1 if (!defined($attr{FHZ}{softbuffer})); # set default values for config value attr FHZ softbuffer
|
||||
|
||||
my $sbCount = keys(%{$def->{SENDBUFFER}}); # count the existing sendbuffer
|
||||
my $nsCount = keys(%{$def->{NOTSEND}}); # count the existing failbuffer
|
||||
|
||||
if ($confirm && ($sbCount > 0 || $nsCount > 0) && $attr{FHZ}{softbuffer} == 1) {
|
||||
$type = "refreshvalues" if ($type eq "init");
|
||||
|
||||
my ($sbPr, $sbTs);
|
||||
my $sbType = "";
|
||||
my $sbVal;
|
||||
my $dKey;
|
||||
|
||||
my ($val2) = split (/\s/, $val);
|
||||
|
||||
# if the confirmation message for a command recive to late
|
||||
# (the command moved to the notsend list yet)
|
||||
# found the specific command ond delete them from the notsend list
|
||||
foreach my $c (sort keys %{$def->{NOTSEND}}) { # go through the notsend list
|
||||
($sbPr, $sbTs, $sbType) = split (/:/, $c);
|
||||
$sbVal = $def->{NOTSEND}->{$c}{VAL};
|
||||
$dKey = $c;
|
||||
|
||||
$sbVal = $val2 if ($type eq "refreshvalues"); # refreshvalues have no value
|
||||
if ($sbType eq $type && $sbVal eq $val2) {
|
||||
|
||||
Log GetLogLevel($def->{NAME},2), "FHT $def->{NAME} late - confirmation ".
|
||||
"($sbType: $sbVal) (delete from NOTSEND)";
|
||||
|
||||
delete($def->{NOTSEND}{$dKey}); # delete command from notsend list
|
||||
last; # we can leave the loop because the command was deleted from the list
|
||||
}
|
||||
}
|
||||
|
||||
# get the next entry from the buffer queue
|
||||
foreach my $c (sort keys %{$def->{SENDBUFFER}}) {
|
||||
($sbPr, $sbTs, $sbType) = split (/:/, $c);
|
||||
$sbVal = $def->{SENDBUFFER}->{$c}{VAL};
|
||||
$dKey = $c;
|
||||
last; # exit foreach because we need the first entry only
|
||||
}
|
||||
|
||||
$sbVal = $val2 if ($type eq "refreshvalues"); # refreshvalues have no value
|
||||
|
||||
# if the actual confirmation message part of the first command in the queue
|
||||
if ($sbType eq $type && $sbVal eq $val2) {
|
||||
delete($def->{SENDBUFFER}{$dKey}); # this buffer entry can deleted
|
||||
|
||||
foreach my $c (sort keys %{$def->{SENDBUFFER}}) { # get the next buffer entry
|
||||
my $nType = $def->{SENDBUFFER}->{$c}{TYPE};
|
||||
my $nArg = $def->{SENDBUFFER}->{$c}{ARG};
|
||||
my $nName = $def->{SENDBUFFER}->{$c}{NAME};
|
||||
my $nHash = $def->{SENDBUFFER}->{$c}{HASH};
|
||||
my $nVal = $def->{SENDBUFFER}->{$c}{VAL};
|
||||
my $nKey = $def->{SENDBUFFER}->{$c}{KEY};
|
||||
|
||||
sendCommand ($nHash, $nArg, $nName, $nType, $nVal); # nächsten Buffereintrag senden
|
||||
toSendbuffer ($nHash, $nType, $nVal, $nArg, $nKey, 0); # send command also to buffer
|
||||
|
||||
last; # exit foreach because we need the next entry only
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#
|
||||
# end processing confirmation to control the softwarebuffer
|
||||
###########################################################################
|
||||
|
||||
$def->{CHANGED}[0] = "$type: $val";
|
||||
$def->{STATE} = "$type: $val" if($type eq "measured-temp");
|
||||
return $def->{NAME};
|
||||
}
|
||||
|
||||
# check are commands in softwarebuffer
|
||||
# ans send the next command to the FHZ
|
||||
sub timerCheckBuffer ($)
|
||||
{
|
||||
|
||||
Log 4, "Timer (Checking for unsend FHT commands)";
|
||||
|
||||
my ($hash) = @_;
|
||||
my $bufCount = 0; # help counter
|
||||
my $now = gettimeofday();
|
||||
my $ts = time;
|
||||
|
||||
# set default values for config value attr FHZ softbuffer
|
||||
$attr{FHZ}{softrepeat} = 240 if (!defined($attr{FHZ}{softrepeat}));
|
||||
$attr{FHZ}{softmaxretry} = 3 if (!defined($attr{FHZ}{softmaxretry}));
|
||||
|
||||
# loop to process all FHT devices
|
||||
foreach my $d (keys %defptr) {
|
||||
my $def = $defptr{$d}; # the actual FHT device
|
||||
|
||||
# process all buffer entries
|
||||
foreach my $c (sort keys %{$def->{SENDBUFFER}}) {
|
||||
my ($rPr, undef, $rType) = split (/:/, $c); # priority and type
|
||||
my $rVal = $def->{SENDBUFFER}{$c}{VAL}; # value
|
||||
my $rTs = $def->{SENDBUFFER}{$c}{SENDTIME}; # the time of the sending moment to the FHT
|
||||
my $rRetry = $def->{SENDBUFFER}{$c}{RETRY}; # retry counter
|
||||
$rRetry ++ if ($fhzHardwareBufferSpace > $minFhzHardwareBufferSpace); # increase retrycounter if enough hardwarebuffer available
|
||||
my $rKey = $c; # the bufferkey
|
||||
|
||||
$rVal = "" if (!defined($rVal)); # set value to "" if value not defined (e.g. "refreshvalues" have no value)
|
||||
$bufCount ++; # increase $bufCount
|
||||
|
||||
my $buffer = $def->{SENDBUFFER}{$c}; # actual buffer entry
|
||||
|
||||
# if the forst command in buffer to old, resend them again to the FHZ
|
||||
if ($ts-$rTs > $attr{FHZ}{softrepeat}) {
|
||||
if ($rRetry <= $attr{FHZ}{softmaxretry}) { # resend the command only if the max resend amount not reached
|
||||
resendCommand ($buffer); # resend the actual command
|
||||
} else {
|
||||
# command resend fail after "softmaxretry" attempt to send
|
||||
Log GetLogLevel($def->{NAME},2), $def->{NAME} . " $rType $rVal no confirmation after $rRetry retry";
|
||||
$def->{NOTSEND}{$rKey} = $def->{SENDBUFFER}{$rKey}; # put the buffer entry to the notsend list
|
||||
$def->{NOTSEND}{$rKey}{RETRY} = $rRetry;
|
||||
delete($def->{SENDBUFFER}{$rKey}); # delete command from buffer queue
|
||||
}
|
||||
}
|
||||
last # exit foreach because we need only the first buffer value
|
||||
}
|
||||
}
|
||||
|
||||
if ($bufCount > 0) {
|
||||
Log 4, "Refresh FHT resend timer";
|
||||
InternalTimer(gettimeofday()+70, "timerCheckBuffer", $hash); # restart the internal Timer if any buffer contains commands
|
||||
} else {
|
||||
$timerCheckBufferIsRunning = 0; # remember timer is not running anymore
|
||||
}
|
||||
}
|
||||
|
||||
# set given command tothe internal software buffer
|
||||
# each command queued until the previous command become a confirmation
|
||||
#
|
||||
sub toSendbuffer ($$$$)
|
||||
{
|
||||
|
||||
my ($hash, $type, $val, $arg, $nBufferKey, $retry) = @_;
|
||||
|
||||
if (!$init_done || $attr{FHZ}{softbuffer} == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
my $dev = $hash->{CODE};
|
||||
my $def = $defptr{$dev};
|
||||
|
||||
my $tn = TimeNow(); # Readable time
|
||||
my $ts = time; # Unix timestamp
|
||||
my $pr = 9; # Default priority for command
|
||||
my $sendTime = 0; # Timestamp for last sending command
|
||||
my $sbCount = keys(%{$def->{SENDBUFFER}}); # Count of sendbuffer
|
||||
|
||||
$pr = $priority{$type} if (defined($priority{$type})); # get priority for specific command type
|
||||
$val = "" if (!defined($val));
|
||||
|
||||
if ($sbCount == 0) {
|
||||
$pr = 0; # First command in buffer have always priority 0 (highest)
|
||||
$sendTime = $ts;
|
||||
}
|
||||
|
||||
my $bufferKey = "$pr:$ts:$type"; #Default bufferkey
|
||||
|
||||
# if bufferkey existing. delete the entry and save the entry with a new buffer
|
||||
if ($nBufferKey ne "") {
|
||||
$sendTime = $ts;
|
||||
$bufferKey = $nBufferKey;
|
||||
($pr, $ts, $type) = split (/:/, $bufferKey);
|
||||
delete($def->{SENDBUFFER}{$bufferKey}); # delete "old" bufferentry
|
||||
|
||||
$bufferKey = "0:$ts:$type"; # new bufferkey für new bufferentry
|
||||
}
|
||||
|
||||
$def->{SENDBUFFER}{$bufferKey}{TIME} = $tn;
|
||||
$def->{SENDBUFFER}{$bufferKey}{VAL} = $val;
|
||||
$def->{SENDBUFFER}{$bufferKey}{NAME} = $def->{NAME};
|
||||
$def->{SENDBUFFER}{$bufferKey}{TYPE} = $type;
|
||||
$def->{SENDBUFFER}{$bufferKey}{ARG} = $arg;
|
||||
$def->{SENDBUFFER}{$bufferKey}{SENDTIME} = $sendTime;
|
||||
$def->{SENDBUFFER}{$bufferKey}{RETRY} = $retry;
|
||||
$def->{SENDBUFFER}{$bufferKey}{KEY} = $bufferKey;
|
||||
$def->{SENDBUFFER}{$bufferKey}{HASH} = $hash;
|
||||
}
|
||||
|
||||
1;
|
||||
|
10
fhem/HISTORY
10
fhem/HISTORY
@ -147,3 +147,13 @@
|
||||
- weblinks added. Used by webpgm2 to display more than one plot at once
|
||||
- webpgm2 output reformatted. Using CSS to divide the screen area in 3
|
||||
parts: command line, room-list and rest
|
||||
|
||||
- Dirk Wed Oct 7 12:45:09 MEST 2007
|
||||
- FHT lime-protection code discovered
|
||||
|
||||
- Dirk Wed Oct 18 23:28:00 MEST 2007
|
||||
- Softwarebuffer for FHT devices with queuing unsent commands and
|
||||
repeating commands by transmission failure
|
||||
- FHT low temperatur warning and setting for lowtemp-offset
|
||||
- Change naming for state into warnings
|
||||
Tagged as dirkh_20071019_0
|
File diff suppressed because it is too large
Load Diff
@ -1,255 +1,261 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>Home of FHEM</title>
|
||||
</head>
|
||||
|
||||
<body style="background-color: white">
|
||||
|
||||
|
||||
<h1>FHEM</h1>
|
||||
GPL'd server to access devices like FHZ1000/FHZ1300,EM1010PC,WS300,SCIVT.
|
||||
Formerly known as fhz1000.pl
|
||||
|
||||
<h2>News (as of =DATE=, Version =VERS=)</h2>
|
||||
<ul>
|
||||
<li> doc: linux.html (private udev-rules, not 50-..., ATTRS)
|
||||
<li> bugfix: setting devices with "-" in their name did not work
|
||||
<li> doc: fhem.pl and commandref.html (notifyon -> notify, correction
|
||||
of examples)
|
||||
<li> feature: modify command added
|
||||
<li> feature: The "-" in the name is not allowed any more
|
||||
<li> bugfix: disabled notify causes "uninitialized value" (STefan, 1.5)
|
||||
<li> bugfix: deleted FS20 items are still logging (zombie) (Gerhard, 16.5)
|
||||
<li> bugfix: added FS20S8, removed stty_parmrk (Martin, 24.5)
|
||||
<li> feature: added archivedir/archivecmd to the FileLog
|
||||
<li> feature: added EM1010PC/EM1000WZ/EM1000EM support
|
||||
<li> bugfix: undefined messages for unknown HMS devs (Peter, 8.6)
|
||||
<li> bugfix: em1010 and %oldvalue bugs (Peter, 9.6)
|
||||
<li> bugfix: SCIVT solar controller (peterp, 1.7)
|
||||
<li> bugfix: WS300 loglevel change (from 2 to 5 or device specific loglevel)
|
||||
<li> feature: First steps for a Fritz!Box port. See the fritzbox.html
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Description</h2>
|
||||
<ul>
|
||||
This program makes the FHZ1000/FHZ1300/WS300 USB devices sold by ELV, Conrad and
|
||||
others useable with Linux. In fact, there is nothing Linux special in it, you
|
||||
should be able to use it on other platforms as long as you can access the
|
||||
hardware as a serial device.<br>
|
||||
The program runs as a server, you can control it via telnet, command line
|
||||
program or TCP/IP directly, like the supplied web frontends do.<br> <br>
|
||||
|
||||
Currently implemented features:<br>
|
||||
<ul>
|
||||
<li>Via the FHZ module (with access to one or more FHZ1000/FHZ1300 device):
|
||||
<ul>
|
||||
<li>reading and sending FS20 events (on/off/dimming, timer commands)<br>
|
||||
<li>support of FS20 address features function group, local and global master
|
||||
<li>reading and changing FHT80b parameters (temp, actuator, etc).<br>
|
||||
The FHT8b seems to work too. <b>Note:</b> the FHT8 wont work.</li>
|
||||
<li>reading HMS data (HMS100-T,-TF,-WD,-MG,-TFK and RM100-2)</li>
|
||||
<li>reading KS300 data</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>reading WS300 data, and up to 9 attached devices</li>
|
||||
<li>reading EM1000WZ/EM1000EM data via an attached EM1010PC</li>
|
||||
<li>reading an attached SCIVT device</li>
|
||||
<li>logging events to files (or database), with regexp filters</li>
|
||||
<li>notifying external programs or internal modules when receiving certain
|
||||
events</li>
|
||||
<li>timed commands (e.g. switching a lamp on from sunset till midnight)</li>
|
||||
<li>modular architecture</li>
|
||||
<li>a lot of web frontends, choose your favorite</li>
|
||||
<br>
|
||||
</ul>
|
||||
See <a href="commandref.html">commandref.html</a> for a detailed command
|
||||
description and <a href="faq.html">faq.html</a> for the F.A.Q.
|
||||
</ul>
|
||||
|
||||
<h2>Links:</h2>
|
||||
<ul>
|
||||
Homepage: <a href="http://www.koeniglich.de/fhem/fhem.html">
|
||||
http://www.koeniglich.de/fhem/fhem.html</a><br>
|
||||
Download: <a href="http://www.koeniglich.de/fhem/fhem-=VERS=.tar.gz">
|
||||
http://www.koeniglich.de/fhem/fhem-=VERS=.tar.gz</a><br>
|
||||
FAQ: <a href="http://www.koeniglich.de/fhem/faq.html">
|
||||
http://www.koeniglich.de/fhem/faq.html</a><br>
|
||||
Google-Group: <a href="http://groups.google.com/group/FHZ1000-users-on-unix">
|
||||
http://groups.google.com/group/FHZ1000-users-on-unix</a><br>
|
||||
Martins Web frontend (webpgm3): <a href="http://www.martin-haas.de/fhz">
|
||||
http://www.martin-haas.de/fhz</a><br>
|
||||
CVS@berlios: <a href="http://developer.berlios.de/projects/fhem">
|
||||
http://developer.berlios.de/projects/fhem</a><br>
|
||||
LinViex (home automation frontend):
|
||||
<a href="http://sourceforge.net/projects/linviex">
|
||||
|
||||
http://sourceforge.net/projects/linviex</a><br><br>
|
||||
Device/OS Specific installation guides:<br>
|
||||
<ul>
|
||||
Linux driver installation:
|
||||
<a href="http://www.koeniglich.de/fhem/linux.html">
|
||||
http://www.koeniglich.de/fhem/linux.html</a><br>
|
||||
Instructions for Nas/Routers (NSLU2):
|
||||
<a href="http://www.martin-haas.de/fhz/nslu2fhz">
|
||||
http://www.martin-haas.de/fhz/nslu2fhz</a><br>
|
||||
Instructions for the Fritz!Box:
|
||||
<a href="fritzbox.html">
|
||||
http://www.koeniglich.de/fhem/fritzbox.html</a><br>
|
||||
Instructions for the Allnet all6250:
|
||||
<a href="http://wiki.dungeon.de/all6250_opennas_mit_fhem">
|
||||
http://wiki.dungeon.de/all6250_opennas_mit_fhem</a><br>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
<h2>Related projects:</h2>
|
||||
<ul>
|
||||
<a href="http://fhz4linux.info/">http://fhz4linux.info/</a><br>
|
||||
</ul>
|
||||
|
||||
<h2>Installation</h2>
|
||||
<ul>
|
||||
|
||||
<h3>Linux driver</h3>
|
||||
See <a href="http://www.koeniglich.de/fhem/linux.html">
|
||||
http://www.koeniglich.de/fhem/linux.html</a><br>
|
||||
For kernels older then 2.6.x apply the patch from the doc directory to your
|
||||
kernel, recompile it and reboot or load/reload the ftdi_sio module.
|
||||
</ul>
|
||||
|
||||
<h3>Perl modules</h3>
|
||||
<ul>
|
||||
You need perl with the Device::SerialPort (<a
|
||||
href="http://search.cpan.org/dist/Device-SerialPort/">
|
||||
http://search.cpan.org/dist/Device-SerialPort/</a>)
|
||||
module. All other needed modules were present in my installation.
|
||||
If this module reports <code>Can't call method "opened" on an undefined
|
||||
value...</code> when starting the server, then you either may ignore
|
||||
this message, or replace the mentioned line with:<pre>
|
||||
$self->{HANDLE}->close if (defined($self->{HANDLE}) &&
|
||||
$self->{HANDLE}->opened);</pre>
|
||||
</ul>
|
||||
|
||||
<h3>Server installation</h3>
|
||||
<ul>
|
||||
<li>Copy the file <code>fhem.pl</code> into your path (e.g.
|
||||
<code>/usr/local/bin</code>), and the FHEM directory e.g. to
|
||||
<code>/usr/local/lib</code>. </li>
|
||||
<li>Make sure that you can access the serial USB
|
||||
device (e.g. <code>/dev/tts/USB0</code>).</li>
|
||||
<li>Create a configuration file (see the examples directory and
|
||||
docs/commandref.html), and change at least the modpath
|
||||
(<code>/usr/local/lib</code>) and define FHZ FHZ (<code>/dev/tts/USB0</code>)
|
||||
parameters.</li>
|
||||
<li>Delete the savefile if you are upgrading from an older version.</li>
|
||||
<li>Start the server with <code>fhem.pl <configfile></code></li>
|
||||
</ul>
|
||||
|
||||
<h3>General Notes for Webfrontends:</h3>
|
||||
<ul>
|
||||
<li>You don't have to install all of them, one is probably more than
|
||||
enough :-)</li>
|
||||
<li>The web server and the fhem server must be on the same host</li>
|
||||
<li><b>Important:</b> Make sure you add some protection (.htaccess, etc)
|
||||
else everybody will be able to set your devices</li>
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 2 (webfrontend/pgm2, the simple one)</h3>
|
||||
<ul>
|
||||
This frontend is CGI/CSS based. It has support for rooms, and FHT/KS300 logs.<br>
|
||||
Screenshots: <a href="pgm2-1.gif">overview</a>, <a href="pgm2-2.gif">details
|
||||
</a> and KS300 temperature <a href="pgm2-3.gif">logs</a><br><br>
|
||||
|
||||
<ul>
|
||||
<li>Copy the file fhemweb.pl and *.gplot to your cgi-bin directory
|
||||
(/home/httpd/cgi-bin), the icons (*.gif) to your httpd icons
|
||||
(/home/httpd/icons), and commandref.html to the html directory
|
||||
(/home/httpd/html).<br>
|
||||
Note: The program looks for icons in the following order:
|
||||
<device-name>.<state>, <device-name>,
|
||||
<device-type>.<state>, <device-type><br>
|
||||
</li>
|
||||
<li>Edit <code>fhemweb.pl</code>, and check the "Config" section.</li>
|
||||
<li>If you want to have access to plotted logs, then make sure that
|
||||
gnuplot is installed and set the logtype for the FileLog device
|
||||
(see commandref.html and example/04_log).
|
||||
</li>
|
||||
<li>Call <your-site>/cgi-bin/fhemweb.pl
|
||||
</ul>
|
||||
For special features like assigning devices to rooms see the README file.
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 3 (webfrontend/pgm3, the professional one)</h3>
|
||||
<ul>
|
||||
This frontend is PHP based and was contributed by Martin Haas.
|
||||
Look at the webfrontends/pgm3/docs for more documentation or at
|
||||
<a href="pgm3-0.5.1.png">this screenshot</a>. A lot more details can be
|
||||
found on Martins page: <a href="http://www.martin-haas.de/fhz">
|
||||
http://www.martin-haas.de/fhz</a>
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
<li>Install PHP and enable it by commenting in the "LoadModule
|
||||
phpX_module ..." directive in httpd.conf (perhaps it is already
|
||||
done by your distro). Restart/reload httpd.</li>
|
||||
|
||||
<li>Create a directory (e.g.: /home/httpd/html/pgm3) and copy all the
|
||||
files from the webfrontend/pgm3 to this directory.<br>Make sure that this
|
||||
directory is writeable by the webserver!</li>
|
||||
|
||||
<li>Edit index.php (/home/httpd/html/pgm3/index.php), and check the
|
||||
required settings section</li>
|
||||
|
||||
<li>If you want to have access to the FHT temperature logs, then:
|
||||
<ul>
|
||||
<li>Make sure gnuplot is installed</li>
|
||||
<li>check the showgnuplot section in index.php</li>
|
||||
<li>For each FHT device copy the file docs/gnuplot/gnuplot.wz to
|
||||
gnuplot.fhtdevicename (to the /home/httpd/html/pgm3 directory) and
|
||||
replace fht.log in this file with the absolute name of the current
|
||||
logfile.</li>
|
||||
</ul>
|
||||
<li>Call <your-site>/pgm3/index.php</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 4 (webfrontend/pgm4, the template)</h3>
|
||||
<ul>
|
||||
This frontend is PHP based and was contributed by Stefan Mayer. It won't work
|
||||
for you without modification, it is meant as a template or as an example. See
|
||||
the <a href="pgm4.gif">screenshot</a>. To install:
|
||||
<ul>
|
||||
<li>Copy the directory webfrontend/pgm4 to your html directory.</li>
|
||||
<li>Install/enable PHP (see the description for frontend3)</li>
|
||||
<li>Call the program with http://webserver/pgm4/fs20.php</li>
|
||||
</ul>
|
||||
Now you can go on, and modify it to suit your needs :-)
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>License:</h2>
|
||||
<ul>
|
||||
Copyright:<br>
|
||||
<ul>
|
||||
<li>Rudolf Koenig (r dot koenig at koeniglich dot de)</li>
|
||||
<li>Raoul Matthiessen (webfrontends/pgm1)</li>
|
||||
<li>Martin Haas (webfrontends/pgm3)</li>
|
||||
</ul>
|
||||
License: GPL (v2)
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Misc:</h2>
|
||||
<ul>
|
||||
Thanks for Tosti for inspiration and numerous other people for help. <br>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>Home of FHEM</title>
|
||||
</head>
|
||||
|
||||
<body style="background-color: white">
|
||||
|
||||
|
||||
<h1>FHEM</h1>
|
||||
GPL'd server to access devices like FHZ1000/FHZ1300,EM1010PC,WS300,SCIVT.
|
||||
Formerly known as fhz1000.pl
|
||||
|
||||
<h2>News (as of =DATE=, Version =VERS=)</h2>
|
||||
<ul>
|
||||
<li> doc: linux.html (private udev-rules, not 50-..., ATTRS)
|
||||
<li> bugfix: setting devices with "-" in their name did not work
|
||||
<li> doc: fhem.pl and commandref.html (notifyon -> notify, correction
|
||||
of examples)
|
||||
<li> feature: modify command added
|
||||
<li> feature: The "-" in the name is not allowed any more
|
||||
<li> bugfix: disabled notify causes "uninitialized value" (STefan, 1.5)
|
||||
<li> bugfix: deleted FS20 items are still logging (zombie) (Gerhard, 16.5)
|
||||
<li> bugfix: added FS20S8, removed stty_parmrk (Martin, 24.5)
|
||||
<li> feature: added archivedir/archivecmd to the FileLog
|
||||
<li> feature: added EM1010PC/EM1000WZ/EM1000EM support
|
||||
<li> bugfix: undefined messages for unknown HMS devs (Peter, 8.6)
|
||||
<li> bugfix: em1010 and %oldvalue bugs (Peter, 9.6)
|
||||
<li> bugfix: SCIVT solar controller (peterp, 1.7)
|
||||
<li> bugfix: WS300 loglevel change (from 2 to 5 or device specific loglevel)
|
||||
<li> feature: First steps for a Fritz!Box port. See the fritzbox.html
|
||||
<li>feature: FHT lime-protection code discovered by Dirk (7.10)
|
||||
<li>feature: Softwarebuffer for FHT devices with queuing unsent commands and repeating commands by transmission failure (Dirk 17.10)
|
||||
<li> feature: FHT low temperatur warning and setting for lowtemp-offset (Dirk 17.10)
|
||||
<li>change: Change naming for state into warnings (Dirk 17.10)
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Description</h2>
|
||||
<ul>
|
||||
This program makes the FHZ1000/FHZ1300/WS300 USB devices sold by ELV, Conrad and
|
||||
others useable with Linux. In fact, there is nothing Linux special in it, you
|
||||
should be able to use it on other platforms as long as you can access the
|
||||
hardware as a serial device.<br>
|
||||
The program runs as a server, you can control it via telnet, command line
|
||||
program or TCP/IP directly, like the supplied web frontends do.<br> <br>
|
||||
|
||||
Currently implemented features:<br>
|
||||
<ul>
|
||||
<li>Via the FHZ module (with access to one or more FHZ1000/FHZ1300 device):
|
||||
<ul>
|
||||
<li>reading and sending FS20 events (on/off/dimming, timer commands)<br>
|
||||
<li>support of FS20 address features function group, local and global master
|
||||
<li>reading and changing FHT80b parameters (temp, actuator, etc).<br>
|
||||
The FHT8b seems to work too. <b>Note:</b> the FHT8 wont work.<br />
|
||||
For FHT8b devices, FHEM have an internal software buffer for sending commands step by step. This buffer should prevent lost commands. In case of transmission failures FHEM tries to resend commands. <br />
|
||||
</li>
|
||||
<li>reading HMS data (HMS100-T,-TF,-WD,-MG,-TFK and RM100-2)</li>
|
||||
<li>reading KS300 data</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>reading WS300 data, and up to 9 attached devices</li>
|
||||
<li>reading EM1000WZ/EM1000EM data via an attached EM1010PC</li>
|
||||
<li>reading an attached SCIVT device</li>
|
||||
<li>logging events to files (or database), with regexp filters</li>
|
||||
<li>notifying external programs or internal modules when receiving certain
|
||||
events</li>
|
||||
<li>timed commands (e.g. switching a lamp on from sunset till midnight)</li>
|
||||
<li>modular architecture</li>
|
||||
<li>a lot of web frontends, choose your favorite</li>
|
||||
<br>
|
||||
</ul>
|
||||
See <a href="commandref.html">commandref.html</a> for a detailed command
|
||||
description and <a href="faq.html">faq.html</a> for the F.A.Q.
|
||||
</ul>
|
||||
|
||||
<h2>Links:</h2>
|
||||
<ul>
|
||||
Homepage: <a href="http://www.koeniglich.de/fhem/fhem.html">
|
||||
http://www.koeniglich.de/fhem/fhem.html</a><br>
|
||||
Download: <a href="http://www.koeniglich.de/fhem/fhem-=VERS=.tar.gz">
|
||||
http://www.koeniglich.de/fhem/fhem-=VERS=.tar.gz</a><br>
|
||||
FAQ: <a href="http://www.koeniglich.de/fhem/faq.html">
|
||||
http://www.koeniglich.de/fhem/faq.html</a><br>
|
||||
Google-Group: <a href="http://groups.google.com/group/FHZ1000-users-on-unix">
|
||||
http://groups.google.com/group/FHZ1000-users-on-unix</a><br>
|
||||
Martins Web frontend (webpgm3): <a href="http://www.martin-haas.de/fhz">
|
||||
http://www.martin-haas.de/fhz</a><br>
|
||||
CVS@berlios: <a href="http://developer.berlios.de/projects/fhem">
|
||||
http://developer.berlios.de/projects/fhem</a><br>
|
||||
LinViex (home automation frontend):
|
||||
<a href="http://sourceforge.net/projects/linviex">
|
||||
|
||||
http://sourceforge.net/projects/linviex</a><br><br>
|
||||
Device/OS Specific installation guides:<br>
|
||||
<ul>
|
||||
Linux driver installation:
|
||||
<a href="http://www.koeniglich.de/fhem/linux.html">
|
||||
http://www.koeniglich.de/fhem/linux.html</a><br>
|
||||
Instructions for Nas/Routers (NSLU2):
|
||||
<a href="http://www.martin-haas.de/fhz/nslu2fhz">
|
||||
http://www.martin-haas.de/fhz/nslu2fhz</a><br>
|
||||
Instructions for the Fritz!Box:
|
||||
<a href="fritzbox.html">
|
||||
http://www.koeniglich.de/fhem/fritzbox.html</a><br>
|
||||
Instructions for the Allnet all6250:
|
||||
<a href="http://wiki.dungeon.de/all6250_opennas_mit_fhem">
|
||||
http://wiki.dungeon.de/all6250_opennas_mit_fhem</a><br>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
<h2>Related projects:</h2>
|
||||
<ul>
|
||||
<a href="http://fhz4linux.info/">http://fhz4linux.info/</a><br>
|
||||
</ul>
|
||||
|
||||
<h2>Installation</h2>
|
||||
<ul>
|
||||
|
||||
<h3>Linux driver</h3>
|
||||
See <a href="http://www.koeniglich.de/fhem/linux.html">
|
||||
http://www.koeniglich.de/fhem/linux.html</a><br>
|
||||
For kernels older then 2.6.x apply the patch from the doc directory to your
|
||||
kernel, recompile it and reboot or load/reload the ftdi_sio module.
|
||||
</ul>
|
||||
|
||||
<h3>Perl modules</h3>
|
||||
<ul>
|
||||
You need perl with the Device::SerialPort (<a
|
||||
href="http://search.cpan.org/dist/Device-SerialPort/">
|
||||
http://search.cpan.org/dist/Device-SerialPort/</a>)
|
||||
module. All other needed modules were present in my installation.
|
||||
If this module reports <code>Can't call method "opened" on an undefined
|
||||
value...</code> when starting the server, then you either may ignore
|
||||
this message, or replace the mentioned line with:<pre>
|
||||
$self->{HANDLE}->close if (defined($self->{HANDLE}) &&
|
||||
$self->{HANDLE}->opened);</pre>
|
||||
</ul>
|
||||
|
||||
<h3>Server installation</h3>
|
||||
<ul>
|
||||
<li>Copy the file <code>fhem.pl</code> into your path (e.g.
|
||||
<code>/usr/local/bin</code>), and the FHEM directory e.g. to
|
||||
<code>/usr/local/lib</code>. </li>
|
||||
<li>Make sure that you can access the serial USB
|
||||
device (e.g. <code>/dev/tts/USB0</code>).</li>
|
||||
<li>Create a configuration file (see the examples directory and
|
||||
docs/commandref.html), and change at least the modpath
|
||||
(<code>/usr/local/lib</code>) and define FHZ FHZ (<code>/dev/tts/USB0</code>)
|
||||
parameters.</li>
|
||||
<li>Delete the savefile if you are upgrading from an older version.</li>
|
||||
<li>Start the server with <code>fhem.pl <configfile></code></li>
|
||||
</ul>
|
||||
|
||||
<h3>General Notes for Webfrontends:</h3>
|
||||
<ul>
|
||||
<li>You don't have to install all of them, one is probably more than
|
||||
enough :-)</li>
|
||||
<li>The web server and the fhem server must be on the same host</li>
|
||||
<li><b>Important:</b> Make sure you add some protection (.htaccess, etc)
|
||||
else everybody will be able to set your devices</li>
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 2 (webfrontend/pgm2, the simple one)</h3>
|
||||
<ul>
|
||||
This frontend is CGI/CSS based. It has support for rooms, and FHT/KS300 logs.<br>
|
||||
Screenshots: <a href="pgm2-1.gif">overview</a>, <a href="pgm2-2.gif">details
|
||||
</a> and KS300 temperature <a href="pgm2-3.gif">logs</a><br><br>
|
||||
|
||||
<ul>
|
||||
<li>Copy the file fhemweb.pl and *.gplot to your cgi-bin directory
|
||||
(/home/httpd/cgi-bin), the icons (*.gif) to your httpd icons
|
||||
(/home/httpd/icons), and commandref.html to the html directory
|
||||
(/home/httpd/html).<br>
|
||||
Note: The program looks for icons in the following order:
|
||||
<device-name>.<state>, <device-name>,
|
||||
<device-type>.<state>, <device-type><br>
|
||||
</li>
|
||||
<li>Edit <code>fhemweb.pl</code>, and check the "Config" section.</li>
|
||||
<li>If you want to have access to plotted logs, then make sure that
|
||||
gnuplot is installed and set the logtype for the FileLog device
|
||||
(see commandref.html and example/04_log).
|
||||
</li>
|
||||
<li>Call <your-site>/cgi-bin/fhemweb.pl
|
||||
</ul>
|
||||
For special features like assigning devices to rooms see the README file.
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 3 (webfrontend/pgm3, the professional one)</h3>
|
||||
<ul>
|
||||
This frontend is PHP based and was contributed by Martin Haas.
|
||||
Look at the webfrontends/pgm3/docs for more documentation or at
|
||||
<a href="pgm3-0.5.1.png">this screenshot</a>. A lot more details can be
|
||||
found on Martins page: <a href="http://www.martin-haas.de/fhz">
|
||||
http://www.martin-haas.de/fhz</a>
|
||||
<br><br>
|
||||
|
||||
<ul>
|
||||
<li>Install PHP and enable it by commenting in the "LoadModule
|
||||
phpX_module ..." directive in httpd.conf (perhaps it is already
|
||||
done by your distro). Restart/reload httpd.</li>
|
||||
|
||||
<li>Create a directory (e.g.: /home/httpd/html/pgm3) and copy all the
|
||||
files from the webfrontend/pgm3 to this directory.<br>Make sure that this
|
||||
directory is writeable by the webserver!</li>
|
||||
|
||||
<li>Edit index.php (/home/httpd/html/pgm3/index.php), and check the
|
||||
required settings section</li>
|
||||
|
||||
<li>If you want to have access to the FHT temperature logs, then:
|
||||
<ul>
|
||||
<li>Make sure gnuplot is installed</li>
|
||||
<li>check the showgnuplot section in index.php</li>
|
||||
<li>For each FHT device copy the file docs/gnuplot/gnuplot.wz to
|
||||
gnuplot.fhtdevicename (to the /home/httpd/html/pgm3 directory) and
|
||||
replace fht.log in this file with the absolute name of the current
|
||||
logfile.</li>
|
||||
</ul>
|
||||
<li>Call <your-site>/pgm3/index.php</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h3>Web frontend 4 (webfrontend/pgm4, the template)</h3>
|
||||
<ul>
|
||||
This frontend is PHP based and was contributed by Stefan Mayer. It won't work
|
||||
for you without modification, it is meant as a template or as an example. See
|
||||
the <a href="pgm4.gif">screenshot</a>. To install:
|
||||
<ul>
|
||||
<li>Copy the directory webfrontend/pgm4 to your html directory.</li>
|
||||
<li>Install/enable PHP (see the description for frontend3)</li>
|
||||
<li>Call the program with http://webserver/pgm4/fs20.php</li>
|
||||
</ul>
|
||||
Now you can go on, and modify it to suit your needs :-)
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>License:</h2>
|
||||
<ul>
|
||||
Copyright:<br>
|
||||
<ul>
|
||||
<li>Rudolf Koenig (r dot koenig at koeniglich dot de)</li>
|
||||
<li>Raoul Matthiessen (webfrontends/pgm1)</li>
|
||||
<li>Martin Haas (webfrontends/pgm3)</li>
|
||||
</ul>
|
||||
License: GPL (v2)
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Misc:</h2>
|
||||
<ul>
|
||||
Thanks for Tosti for inspiration and numerous other people for help. <br>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
52
fhem/fhem.pl
52
fhem/fhem.pl
@ -134,7 +134,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.26 2007-09-24 07:09:17 rudolfkoenig Exp $';
|
||||
my $cvsid = '$Id: fhem.pl,v 1.27 2007-10-19 09:29:00 dirkh Exp $';
|
||||
|
||||
$init_done = 0;
|
||||
|
||||
@ -1044,10 +1044,58 @@ CommandList($$)
|
||||
if($r) {
|
||||
$str .= "Readings:\n";
|
||||
foreach my $c (sort keys %{$r}) {
|
||||
$str .= sprintf(" %-19s %-15s %s\n",$r->{$c}{TIME},$c,$r->{$c}{VAL});
|
||||
my $val = "";
|
||||
if (defined($r->{$c}{VAL})) {
|
||||
$val = $r->{$c}{VAL};
|
||||
}
|
||||
$str .= sprintf(" %-19s %-15s %s\n",$r->{$c}{TIME},$c,$val);
|
||||
}
|
||||
}
|
||||
|
||||
$attr{FHZ}{softbuffer} = 1 if (!defined($attr{FHZ}{softbuffer}));
|
||||
|
||||
if ($attr{FHZ}{softbuffer} == 1) {
|
||||
my %lists = (
|
||||
"SENDBUFFER" => "Send buffer",
|
||||
"NOTSEND" => "Send fail list",
|
||||
);
|
||||
|
||||
foreach my $list (keys %lists) {
|
||||
my $l = $d->{$list};
|
||||
if(keys (%{$l}) > 0) {
|
||||
$str .= $lists{$list} .":\n";
|
||||
foreach my $c (sort keys %{$l}) {
|
||||
my (undef, undef, $vC) = split (/:/, $c);
|
||||
# $str .= sprintf(" %-19s %-15s %-10s %s\n",$l->{$c}{TIME},$c,$l->{$c}{VAL},$l->{$c}{SENDTIME});
|
||||
$str .= sprintf(" %-19s %-15s %s\n",$l->{$c}{TIME},$vC,$l->{$c}{VAL});
|
||||
}
|
||||
}
|
||||
|
||||
if ($defs{$param}->{NAME} eq "FHZ") {
|
||||
$str .= $lists{$list} .":\n";
|
||||
|
||||
foreach my $d (sort keys %defs) {
|
||||
my $p = $defs{$d};
|
||||
my $t = $p->{TYPE};
|
||||
|
||||
if ($t eq "FHT") {
|
||||
|
||||
$l = $p->{$list};
|
||||
if(keys (%{$l}) > 0) {
|
||||
foreach my $c (sort keys %{$l}) {
|
||||
my (undef, undef, $vC) = split (/:/, $c);
|
||||
my $val = "";
|
||||
if (defined($l->{$c}{VAL})) {
|
||||
$val = $l->{$c}{VAL};
|
||||
}
|
||||
$str .= sprintf(" %-19s %-15s %-15s %s\n",$l->{$c}{TIME},$p->{NAME},$vC,$val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
|
Loading…
Reference in New Issue
Block a user