mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-07 19:04:20 +00:00
WMBUS: better support for Kamstrup Multical (compact frames)
git-svn-id: https://svn.fhem.de/fhem/trunk@25166 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
5511fac343
commit
a2e08cf43b
@ -1054,6 +1054,27 @@ my %VIFInfo_KAM = (
|
||||
},
|
||||
);
|
||||
|
||||
# according to MBUS Spec:
|
||||
# E00x xxxx
|
||||
# Reserved for object actions (master to slave): see table on page 75
|
||||
# or for error codes (slave to master): see table on page 74
|
||||
|
||||
# but Kamstrup uses it for a value that is called
|
||||
# "target V1, month"
|
||||
# or
|
||||
# "V1 reverse"
|
||||
# both are volumes, with one is sent depends of the value of the configuration register R
|
||||
# the value of the register is not part of the WMBUS data but is set at manufacturing
|
||||
my %VIFInfo_KAM2 = (
|
||||
VIF_TARGET_OR_REVERSE_VOLUME => { # 10(nnn-6) m3/h 0.001l/h to 10000l/h
|
||||
typeMask => 0b00010000,
|
||||
expMask => 0b00000111,
|
||||
type => 0b00010000,
|
||||
bias => -6,
|
||||
unit => 'm³/h',
|
||||
calcFunc => \&valueCalcNumeric,
|
||||
},
|
||||
);
|
||||
|
||||
# see 4.2.3, page 24
|
||||
my %validDeviceTypes = (
|
||||
@ -1380,6 +1401,7 @@ sub decodeValueInformationBlock($$$) {
|
||||
my @VIFExtensions = ();
|
||||
my $analyzeVIF = 1;
|
||||
|
||||
|
||||
$dataBlockRef->{type} = '';
|
||||
# The unit and multiplier is taken from the table for primary VIF
|
||||
$vifInfoRef = \%VIFInfo;
|
||||
@ -1445,13 +1467,19 @@ sub decodeValueInformationBlock($$$) {
|
||||
#print "ESY\n";
|
||||
$vifInfoRef = \%VIFInfo_ESY2;
|
||||
$dataBlockExt->{value} = unpack('C',substr($vib,2,1)) * 100;
|
||||
} elsif ($self->{manufacturer} eq 'KAM') {
|
||||
#print "KAM\n";
|
||||
#$dataBlockExt->{value} = $vif;
|
||||
$vifInfoRef = \%VIFInfo_KAM2;
|
||||
} else {
|
||||
$dataBlockExt->{value} = $vif;
|
||||
$vifInfoRef = \%VIFInfo_other;
|
||||
}
|
||||
|
||||
if (findVIF($vif, $vifInfoRef, $dataBlockExt)) {
|
||||
push @VIFExtensions, $dataBlockExt;
|
||||
# if ($self->{manufacturer} ne 'KAM') {
|
||||
push @VIFExtensions, $dataBlockExt;
|
||||
# }
|
||||
} else {
|
||||
$dataBlockRef->{type} = 'unknown';
|
||||
$dataBlockRef->{errormsg} = "unknown VIFE " . sprintf("%x", $vifExtension) . " at offset " . ($offset-1);
|
||||
@ -1566,6 +1594,9 @@ sub decodePayload($$) {
|
||||
my @dataBlocks = ();
|
||||
my $dataBlock;
|
||||
|
||||
#printf ("payload is %s\n" , unpack("H*", $payload));
|
||||
|
||||
|
||||
|
||||
PAYLOAD: while ($offset < length($payload)) {
|
||||
$dataBlockNo++;
|
||||
@ -1860,6 +1891,8 @@ sub decodeCompactFrame($$)
|
||||
# all in all that would be 4 * 4 (for vif) * 4 * 4 (for dif) * 3 (type of telegram) combinations (768)
|
||||
# for now only search for those that are documented or have been observed in real telegrams
|
||||
for my $vif ("13","14","15","16") {
|
||||
my $vifExt = '9' . substr($vif,1,1);
|
||||
#print $vifExt;
|
||||
#printf("compact frame $vif\n");
|
||||
if ($self->{format_signature} == $self->calcCRC(pack("H*", "02FF20" . "04$vif" . "44$vif"))) {
|
||||
# Info, Volume, Target Volume
|
||||
@ -1868,8 +1901,17 @@ sub decodeCompactFrame($$)
|
||||
. pack("H*", "04$vif") . substr($compact,7,4) # volume
|
||||
. pack("H*", "44$vif") . substr($compact,11,4); # target volume
|
||||
last;
|
||||
} elsif ($self->{format_signature} == $self->calcCRC(pack("H*", "02FF20" . "0413" . "523B" . "04${vifExt}3C"))) {
|
||||
# Info, Volume, Max flow, Target Volume
|
||||
# convert into full frame
|
||||
print "CF found\n";
|
||||
$applicationlayer = pack("H*", "02FF20") . substr($compact, 5, 2) # Info
|
||||
. pack("H*", "04$vif") . substr($compact,7,4) # volume
|
||||
. pack("H*", "523B") . substr($compact,11,2) # max flow
|
||||
. pack("H*", "04${vifExt}3C") . substr($compact,13,4); # target volume
|
||||
last;
|
||||
} elsif ($self->{format_signature} == $self->calcCRC(pack("H*", "02FF20" . "04$vif" . "523B"))) {
|
||||
# Info, Volume, Max flow
|
||||
# Info, Volume, Max flow, Target Volume
|
||||
# convert into full frame
|
||||
$applicationlayer = pack("H*", "02FF20") . substr($compact, 5, 2) # Info
|
||||
. pack("H*", "04$vif") . substr($compact,7,4) # volume
|
||||
@ -2460,16 +2502,19 @@ sub dumpResult($)
|
||||
printf("Type %x %s\n", $self->{afield_type}, $self->{typestring});
|
||||
printf("IsEncrypted %d\n", $self->{isEncrypted});
|
||||
|
||||
printf("Status: %x %s\n", $self->{status}, $self->{statusstring});
|
||||
if ($self->{cw_parts}{mode} == 5) {
|
||||
print "Codeword:\n";
|
||||
print "bidirectional: ". $self->{cw_parts}{bidirectional} . "\n";
|
||||
print "accessability: ". $self->{cw_parts}{accessability} . "\n";
|
||||
print "synchronous: $self->{cw_parts}{synchronous}\n";
|
||||
print "mode: $self->{cw_parts}{mode}\n";
|
||||
print "encrypted_blocks: $self->{cw_parts}{encrypted_blocks}\n";
|
||||
print "content: $self->{cw_parts}{content}\n";
|
||||
print "hops: $self->{cw_parts}{hops}\n";
|
||||
|
||||
if ($self->{errorcode} == ERR_NO_ERROR) {
|
||||
printf("Status: %x %s\n", $self->{status}, $self->{statusstring});
|
||||
if ($self->{cw_parts}{mode} == 5) {
|
||||
print "Codeword:\n";
|
||||
print "bidirectional: ". $self->{cw_parts}{bidirectional} . "\n";
|
||||
print "accessability: ". $self->{cw_parts}{accessability} . "\n";
|
||||
print "synchronous: $self->{cw_parts}{synchronous}\n";
|
||||
print "mode: $self->{cw_parts}{mode}\n";
|
||||
print "encrypted_blocks: $self->{cw_parts}{encrypted_blocks}\n";
|
||||
print "content: $self->{cw_parts}{content}\n";
|
||||
print "hops: $self->{cw_parts}{hops}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user