2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-15 22:26:04 +00:00

98_WKRCD4.pm: fixed some bugs, cleaned logging

git-svn-id: https://svn.fhem.de/fhem/trunk@9128 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
ststrobel 2015-08-24 18:51:46 +00:00
parent cf2d29b24e
commit ad610f8397

View File

@ -7,12 +7,37 @@
# http://www.ip-symcon.de/forum/threads/2092-ComPort-und-Waterkotte-abfragen (Protokollbeschreibung)
# http://www.haustechnikdialog.de/Forum/t/6144/Waterkotte-5017-3-an-den-Computer-anschliessen?page=4 (Beispiel Befehls-Strings)
#
# This file is part of fhem.
#
# Fhem is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# Fhem is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# Changelog:
#
# 2013-11-1 initial version
# 2013-12-25 bug fixes, GPL comment added, loglevel reading removed
# 2014-4-7 performance tuning, read handling with binary string instead of hex string
# 2014-5-22 decode mode - heating, cooling, warm water on / off
# 2015-7-23 added utf8 encoding of state string, Added name to Log3 calls
#
package main;
use strict;
use warnings;
use Time::HiRes qw(gettimeofday);
use Encode qw(decode encode);
#
# list of Readings / values that can explicitely be requested
@ -29,7 +54,7 @@ my %WKRCD4_sets = (
# Definition of the values that can be read / written
# with the relative address, number of bytes and
# fmat to be used in sprintfd when formatting the value
# fmat to be used in sprintf when formatting the value
# unp to be used in pack / unpack commands
# min / max for setting values
#
@ -93,7 +118,10 @@ my %frameReadings = (
'Status-Kuehlung' => { addr => 0x00DA, bytes => 0x0003, unp => 'B24' },
'Mode-Heizung' => { addr => 0x00DF, bytes => 0x0001, unp => 'B8' },
'Mode-Kuehlung' => { addr => 0x00E0, bytes => 0x0001, unp => 'B8' },
'Mode-Warmwasser' => { addr => 0x00E1, bytes => 0x0001, unp => 'B8' }
'Mode-Warmwasser' => { addr => 0x00E1, bytes => 0x0001, unp => 'B8' },
'Heizung' => { addr => 0x00DF, bytes => 0x0001, unp => 'b' },
'Kuehlung' => { addr => 0x00E0, bytes => 0x0001, unp => 'b' },
'Warmwasser' => { addr => 0x00E1, bytes => 0x0001, unp => 'b' }
);
#
@ -113,7 +141,7 @@ sub WKRCD4_Initialize($)
$hash->{SetFn} = "WKRCD4_Set";
$hash->{GetFn} = "WKRCD4_Get";
$hash->{AttrList} =
"do_not_notify:1,0 loglevel:0,1,2,3,4,5,6 " . $readingFnAttributes;
"do_not_notify:1,0 " . $readingFnAttributes;
}
#
@ -126,7 +154,7 @@ sub WKRCD4_Define($$)
my ( $hash, $def ) = @_;
my @a = split( "[ \t][ \t]*", $def );
return "wrong syntax: define <name> WKRCD4 [devicename|none] interval"
return "wrong syntax: define <name> WKRCD4 [devicename\@speed|none] [interval]"
if ( @a < 3 );
DevIo_CloseDev($hash);
@ -135,7 +163,7 @@ sub WKRCD4_Define($$)
my $interval = 60;
if ( $dev eq "none" ) {
Log3 undef, 1, "WKRCD4 device is none, commands will be echoed only";
Log3 undef, 1, "$name: device is none, commands will be echoed only";
return undef;
}
@ -205,7 +233,7 @@ sub WPCMD($$$$;@)
} elsif ($cmd eq "write") {
@frame = (0x01, 0x13, Encode10($addr>>8, $addr%256), Encode10(@value));
} else {
Log3 $name, 3, "undefined cmd ($cmd) in WPCMD";
Log3 $name, 3, "$name: undefined cmd ($cmd) in WPCMD";
return 0;
}
my $crc = CRC16(@frame);
@ -230,7 +258,7 @@ sub WKRCD4_Get($@)
}
# get Hash pointer for the attribute requested from the global hash
my $properties = $frameReadings{$WKRCD4_sets{$attr}};
my $properties = $frameReadings{$WKRCD4_gets{$attr}};
if(!$properties) {
return "No Entry in frameReadings found for $attr";
}
@ -238,7 +266,7 @@ sub WKRCD4_Get($@)
# get details about the attribute requested from its hash
my $addr = $properties->{addr};
my $bytes = $properties->{bytes};
Log3 $name, 4, sprintf ("Read %02x bytes starting from %02x for $attr", $bytes, $addr);
Log3 $name, 4, sprintf ("$name: Get will read %02x bytes starting from %02x for $attr", $bytes, $addr);
# create command for WP
my $cmd = pack('C*', WPCMD($hash, 'read', $addr, $bytes));
@ -249,7 +277,7 @@ sub WKRCD4_Get($@)
$hash->{LastRequest} = gettimeofday();
$hash->{SerialRequests}++;
Log3 $name, 4, "Get -> Call DevIo_SimpleWrite: " . unpack ('H*', $cmd);
Log3 $name, 4, "$name: Get -> Call DevIo_SimpleWrite: " . unpack ('H*', $cmd);
DevIo_SimpleWrite( $hash, $cmd , 0 );
return sprintf ("Read %02x bytes starting from %02x", $bytes, $addr);
@ -292,7 +320,7 @@ sub WKRCD4_Set($@)
my $vp = pack($unp, $arg);
my @value = unpack ('C*', $vp);
Log3 $name, 4, sprintf ("Write $attr: %02x bytes starting from %02x with %s (%s) packed with $unp", $bytes, $addr, unpack ('H*', $vp), unpack ($unp, $vp));
Log3 $name, 4, sprintf ("$name: Set will write $attr: %02x bytes starting from %02x with %s (%s) packed with $unp", $bytes, $addr, unpack ('H*', $vp), unpack ($unp, $vp));
my $cmd = pack('C*', WPCMD($hash, 'write', $addr, $bytes, @value));
# set internal variables to track what is happending
@ -319,28 +347,34 @@ sub WKRCD4_Read($)
my $buf = DevIo_SimpleRead($hash);
return "" if ( !defined($buf) );
# convert to hex string to make parsing with regex easier
$hash->{buffer} .= unpack ('H*', $buf);
Log3 $name, 5, "Current buffer content: " . $hash->{buffer};
$hash->{buffer} .= $buf;
Log3 $name, 5, "$name: read buffer content: " . unpack ('H*', $hash->{buffer});
# did we already get a full frame?
if ($hash->{buffer} =~ "ff1002(.{4})(.*)1003(.{4})ff(.*)")
if ( $hash->{buffer} !~ /\xff\x10\x02(.{2})(.*)\x10\x03(.{2})\xff(.*)/s )
{
my $msg = $1;
my $frame = $msg . $2;
my $crc = $3;
Log3 $name, 5, "$name: read NoMatch: " . unpack ('H*', $hash->{buffer});
return "";
}
my $msg = unpack ('H*', $1);
my @aframe = unpack ('C*', $1 . $2);
my $crc = unpack ('S>', $3);
my $rest = $4;
Log3 $name, 4, "Match msg: " .$msg . " " . $frame . " CRC " . $crc . " Rest " . $4;
$hash->{buffer} = $4;
# convert frame contents to byte array
my @aframe = unpack ('C*', pack ('H*', $frame));
$hash->{buffer} = $rest;
Log3 $name, 4, "$name: read match msg: $msg CRC $crc";
Log3 $name, 5, "$name: read frame is " . unpack ('H*', pack ('C*', @aframe)) . ", Rest " . unpack ('H*', $rest);
# calculate CRC and compare with CRC from read
my $crc2 = sprintf("%04x",CRC16(@aframe));
if ($crc eq $crc2)
{
Log3 $name, 4, "CRC Ok.";
my $crc2 = CRC16(@aframe);
if ($crc != $crc2) {
Log3 $name, 3, "$name: read Bad CRC from WP: $crc, berechnet: $crc2";
Log3 $name, 4, "$name: read Frame was " . unpack ('H*', pack ('C*', @aframe));
$hash->{SerialBadReads} ++;
@aframe = ();
return "";
};
Log3 $name, 4, "$name: read CRC Ok.";
$hash->{SerialGoodReads}++;
# reply to read request ?
@ -352,23 +386,15 @@ sub WKRCD4_Read($)
if (($aframe[$offset]==16)&&($aframe[$offset+1]==16)) { $offset++; }
$data[$i] = $aframe[$offset];
}
Log3 $name, 4, "Parse with relative request start " . $hash->{LastRequestAdr} . " Len " . $hash->{LastRequestLen};
Log3 $name, 4, "$name: read -> Parse with relative request start " . $hash->{LastRequestAdr} . " Len " . $hash->{LastRequestLen};
# extract values from data
parseReadings($hash, @data);
} elsif ($msg eq "0011") {
# reply to write
} else {
Log3 $name, 3, "Unknown Msg type " . $msg . " in " . $hash->{buffer};
Log3 $name, 3, "$name: read got unknown Msg type " . $msg . " in " . $hash->{buffer};
}
} else
{
Log3 $name, 3, "Bad CRC from WP: " . $crc . " berechnet: " . $crc2 . " Frame ". $frame;
$hash->{SerialBadReads} ++;
};
@aframe = ();
} else {
Log3 $name, 5, "NoMatch: " . $hash->{buffer};
};
return "";
}
@ -405,7 +431,7 @@ sub WKRCD4_Wakeup($)
my $cmd = "41540D100201150008000410037EA010020115003000041003FDC3100201150034000410037D90";
DevIo_SimpleWrite( $hash, $cmd , 1 );
Log3 $name, 5, "sent wakeup string: " . $cmd . " done.";
Log3 $name, 5, "$name: sent wakeup string: " . $cmd . " done.";
return undef;
}
@ -428,7 +454,7 @@ sub WKRCD4_GetUpdate($)
$hash->{LastRequest} = gettimeofday();
DevIo_SimpleWrite( $hash, $cmd , 0 );
Log3 $name, 5, "GetUpdate -> Call DevIo_SimpleWrite: " . unpack ('H*', $cmd);
Log3 $name, 5, "$name: GetUpdate -> Call DevIo_SimpleWrite: " . unpack ('H*', $cmd);
return 1;
}
@ -490,14 +516,24 @@ sub parseReadings
my $value = sprintf ($fmat, unpack ($unpack, pack ($pack, @slice)));
readingsBulkUpdate( $hash, $reading, $value );
Log3 $name, 4, "parse set reading $reading to $value" if (@data <= 20);
Log3 $name, 4, "$name: parse set reading $reading to $value" if (@data <= 20);
}
}
my $Status = "WP idle";
if (ReadingsVal($name, "Heizung", 0)) {
$Status = sprintf ("Heizung %s", ReadingsVal ($name, "Temp-Vorlauf", 0));
} elsif (ReadingsVal($name, "Kuehlung", 0)) {
$Status = sprintf ("Kühlung %s", ReadingsVal ($name, "Temp-Vorlauf", 0));
} elsif (ReadingsVal($name, "Kuehlung", 0)) {
$Status = sprintf ("Warmwasser %s", ReadingsVal ($name, "Temp-WW", 0));
}
$Status = encode ("utf8", $Status);
readingsBulkUpdate( $hash, "Status", $Status);
readingsEndUpdate( $hash, 1 );
}
else
{
Log3 $name, 3, "Data len smaller than requested ($reqLen) : " . unpack ('H*', pack ('C*', @data));
Log3 $name, 3, "$name: parse - data len smaller than requested ($reqLen) : " . unpack ('H*', pack ('C*', @data));
return 0;
}
}