WMBUS: support for CI-field 78h

git-svn-id: https://svn.fhem.de/fhem/trunk@7412 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
kaihs
2015-01-02 19:09:41 +00:00
parent 3bdcbd7f47
commit f148cc7476

View File

@@ -38,6 +38,7 @@ use constant {
# CI field
CI_RESP_4 => 0x7a, # Response from device, 4 Bytes
CI_RESP_12 => 0x72, # Response from device, 12 Bytes
CI_RESP_0 => 0x78, # Response from device, 0 Byte header, variable length
# DIF types (Data Information Field), see page 32
DIF_NONE => 0x00,
@@ -108,7 +109,7 @@ sub valueCalcDate($$) {
my $month = (($value & 0b111100000000) >> 8);
my $year = ((($value & 0b1111000000000000) >> 9) | (($value & 0b11100000) >> 5)) + 2000;
if ($day > 31 || $month > 12 || $year > 2099) {
return "invalid";
return sprintf("invalid: %x", $value);
} else {
return sprintf("%04d-%02d-%02d", $year, $month, $day);
}
@@ -145,7 +146,7 @@ sub valueCalcDateTime($$) {
my $hour = ($value >> 8) & 0b11111;
my $su = ($value & 0b1000000000000000);
if ($min > 59 || $hour > 23) {
$dateTime = 'invalid';
$dateTime = sprintf('invalid: %x', $value);
} else {
$dateTime .= sprintf(' %02d:%02d %s', $hour, $min, $su ? 'DST' : '');
}
@@ -356,7 +357,7 @@ my %VIFInfo = (
unit => '',
calcFunc => \&valueCalcDateTime,
},
VIF_HCA => { # dimensionless
VIF_HCA => { # Unit for Heat Cost Allocator, dimensonless
typeMask => 0b01111111,
expMask => 0b00000000,
type => 0b01101110,
@@ -1017,6 +1018,9 @@ sub decodeApplicationLayer($) {
$self->{meter_devtypestring} = $validDeviceTypes{$self->{meter_dev}} || 'unknown';
$self->{meter_manufacturer} = uc($self->manId2ascii($self->{meter_man}));
$offset += 12;
} elsif ($self->{cifield} == CI_RESP_0) {
# no header
$self->{cw} = 0;
} else {
# unsupported
$self->{errormsg} = 'Unsupported CI Field ' . sprintf("%x", $self->{cifield});
@@ -1024,48 +1028,47 @@ sub decodeApplicationLayer($) {
return 0;
}
$self->{statusstring} = join(", ", $self->state2string($self->{status}));
$self->decodeConfigword();
my $payload;
$self->{encryptionMode} = $encryptionModes{$self->{cw_parts}{mode}};
if ($self->{cw_parts}{mode} == 0) {
# no encryption
$self->{isEncrypted} = 0;
$self->{decrypted} = 1;
$payload = substr($applicationlayer, $offset);
} elsif ($self->{cw_parts}{mode} == 5) {
# data is encrypted with AES 128, dynamic init vector
# decrypt data before further processing
$self->{isEncrypted} = 1;
$self->{decrypted} = 0;
if ($self->{aeskey}) {
$payload = $self->decrypt(substr($applicationlayer,$offset));
if (unpack('n', $payload) == 0x2f2f) {
$self->{decrypted} = 1;
} else {
# Decryption verification failed
$self->{errormsg} = 'Decryption failed, wrong key?';
$self->{errorcode} = ERR_DECRYPTION_FAILED;
#printf("%x\n", unpack('n', $payload));
return 0;
}
} else {
$self->{errormsg} = 'encrypted message and no aeskey provided';
$self->{errorcode} = ERR_NO_AESKEY;
return 0;
}
$self->decodeConfigword();
my $payload;
$self->{encryptionMode} = $encryptionModes{$self->{cw_parts}{mode}};
if ($self->{cw_parts}{mode} == 0) {
# no encryption
$self->{isEncrypted} = 0;
$self->{decrypted} = 1;
$payload = substr($applicationlayer, $offset);
} elsif ($self->{cw_parts}{mode} == 5) {
# data is encrypted with AES 128, dynamic init vector
# decrypt data before further processing
$self->{isEncrypted} = 1;
$self->{decrypted} = 0;
} else {
# error, encryption mode not implemented
$self->{errormsg} = sprintf('Encryption %x mode not implemented', $self->{cw_parts}{mode});
$self->{errorcode} = ERR_UNKNOWN_ENCRYPTION;
$self->{decrypted} = 0;
return 0;
}
if ($self->{aeskey}) {
$payload = $self->decrypt(substr($applicationlayer,$offset));
if (unpack('n', $payload) == 0x2f2f) {
$self->{decrypted} = 1;
} else {
# Decryption verification failed
$self->{errormsg} = 'Decryption failed, wrong key?';
$self->{errorcode} = ERR_DECRYPTION_FAILED;
#printf("%x\n", unpack('n', $payload));
return 0;
}
} else {
$self->{errormsg} = 'encrypted message and no aeskey provided';
$self->{errorcode} = ERR_NO_AESKEY;
return 0;
}
} else {
# error, encryption mode not implemented
$self->{errormsg} = sprintf('Encryption %x mode not implemented', $self->{cw_parts}{mode});
$self->{errorcode} = ERR_UNKNOWN_ENCRYPTION;
$self->{decrypted} = 0;
return 0;
}
return $self->decodePayload($payload);
}