diff --git a/README.md b/README.md index d8f11dc..3d116bd 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,8 @@ Example output: `MyTapWater 12345678 6.388 m3 6.377 m3 8°C 23°C DRY(dry 22-31 days) 2018-03-05 12:02.50` -(Temperature is only sent every 8 message. Until such a full message has been received, the temperature is reported as 127°C.) +(Temperature is only sent every 8 message. Until such a full message has been received, the temperature is reported as -°C +in the human readable output, and as 127°C in the robot outputs and json.) Example robot json output: @@ -90,6 +91,11 @@ If the meter does not use encryption of its meter data, then enter an empty key `wmbusmeters --robot --meterfiles auto MyTapWater multical21 12345678 ""` +If you have a Multical21 meter and you have received a KEM file and its password, +from your water municipality, then you can use the XMLExtract.java utility to get +the meter key from the KEM file. You need to unzip the the KEM file first though, +if it is zipped. + You can run wmbusmeters with --logtelegrams to get log output that can be placed in a simulation.txt file. You can then run wmbusmeter and instead of auto (or an usb device) provide the simulationt.xt file as argument. See test.sh for more info. diff --git a/XMLExtract.java b/XMLExtract.java new file mode 100644 index 0000000..46063cd --- /dev/null +++ b/XMLExtract.java @@ -0,0 +1,41 @@ +// +// A utility to extract the contents of an +// XML containing an XML-Encrypted CipherValue. +// +// Compile with javac XMLExtract.java (requires jdk8 or above). +// +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Base64; +import java.util.stream.Collectors; + +public class XMLExtract +{ + static Cipher getCipherDecrypt(String password) throws Exception { + byte[] key = Arrays.copyOf(password.toUpperCase().getBytes("UTF-8"), 16); + Cipher c = Cipher.getInstance("AES/CBC/NoPadding"); + SecretKeySpec sks = new SecretKeySpec(key, "AES"); + IvParameterSpec ips = new IvParameterSpec(key); + c.init(Cipher.DECRYPT_MODE, sks, ips); + return c; + } + + public static void main(String args[]) throws Exception + { + if (args.length < 2) { + System.out.println("java -cp . XMLExtract [password] [encrypted_xml_file] "); + return; + } + Cipher c = getCipherDecrypt(args[0]); + String xml = Files.lines(Paths.get(args[1])).collect(Collectors.joining("")); + String hex = xml.substring(xml.indexOf("")+13, xml.indexOf("")); + byte[] raw = Base64.getDecoder().decode(hex); + String plain = new String(c.doFinal(raw)); + System.out.println(plain); + } +}