This is an automated email from the ASF dual-hosted git repository. cdutz pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/master by this push: new 3a59b41 - Further updates to the DeltaV POC code .... 3a59b41 is described below commit 3a59b41ac28327b2d6f9dd193c10287a084d3bfc Author: Christofer Dutz <christofer.d...@c-ware.de> AuthorDate: Wed Oct 10 12:13:28 2018 +0200 - Further updates to the DeltaV POC code .... --- .../java/org/apache/plc4x/java/deltav/PoC.java | 452 +++++++++++++++------ 1 file changed, 328 insertions(+), 124 deletions(-) diff --git a/plc4j/protocols/delta-v/src/test/java/org/apache/plc4x/java/deltav/PoC.java b/plc4j/protocols/delta-v/src/test/java/org/apache/plc4x/java/deltav/PoC.java index 4c7dd31..723089b 100644 --- a/plc4j/protocols/delta-v/src/test/java/org/apache/plc4x/java/deltav/PoC.java +++ b/plc4j/protocols/delta-v/src/test/java/org/apache/plc4x/java/deltav/PoC.java @@ -1,22 +1,3 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. - */ - package org.apache.plc4x.java.deltav; import io.netty.buffer.ByteBuf; @@ -27,7 +8,9 @@ import org.pcap4j.packet.UdpPacket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.File; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; @@ -43,27 +26,37 @@ public class PoC { private PcapHandle receiveHandle; - private PoC() throws Exception { - PcapNetworkInterface nif = null; - for (PcapNetworkInterface dev : Pcaps.findAllDevs()) { - if("en7".equals(dev.getName())) { - nif = dev; - break; + private PoC(String inputPath) throws Exception { + if(inputPath == null) { + PcapNetworkInterface nif = null; + for (PcapNetworkInterface dev : Pcaps.findAllDevs()) { + if ("en7".equals(dev.getName())) { + nif = dev; + break; + } } - } - if(nif == null) { - throw new RuntimeException("Couldn't find network device"); - } + if(nif == null) { + throw new RuntimeException("Couldn't find network device"); + } + + // Setup receiving of packets and redirecting them to the corresponding listeners. + // Filter packets to contain only the ip protocol number of the current protocol. + receiveHandle = nif.openLive(SNAPLEN, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, READ_TIMEOUT); + } else { + File input = new File(inputPath); + if(!input.exists() || !input.isFile()) { + throw new RuntimeException("Couldn't open the pcap file as it doesn't seem to exist."); + } - // Setup receiving of packets and redirecting them to the corresponding listeners. - // Filter packets to contain only the ip protocol number of the current protocol. - receiveHandle = nif.openLive(SNAPLEN, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, READ_TIMEOUT); + receiveHandle = Pcaps.openOffline(input.getAbsolutePath(), PcapHandle.TimestampPrecision.NANO); + } // Set the filter. String filterString = "udp port 18507"; receiveHandle.setFilter(filterString, BpfProgram.BpfCompileMode.OPTIMIZE); + Map<String, String> names = new HashMap<>(); Map<String, Object> values = new HashMap<>(); byte[] timeBytes = ByteBuffer.allocate(8).putLong(System.currentTimeMillis()).array(); @@ -102,8 +95,8 @@ public class PoC { // // 02 01 00 00 00 00 00 65 01 de 00 18 00 00 00 00 // 00 00 00 00 - System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet from " + senderId); - outputPacket(buf); +// System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet from " + senderId); +// outputPacket(buf); break; } case 0x0202: { @@ -168,8 +161,8 @@ public class PoC { // 00 04 36 17 5f 00 53 00 70 00 00 03 e8 00 00 04 // 37 17 60 00 54 00 71 00 00 03 e8 00 00 04 32 17 // 5b 00 4f 00 6c 00 00 03 e8 00 00 00 00 00 00 - System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet from " + senderId); - outputPacket(buf); +// System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet from " + senderId); +// outputPacket(buf); break; } case 0x0302: { @@ -271,56 +264,49 @@ public class PoC { //outputPacket(buf); break; } + case 0x1B02: + System.out.println("Hurz"); case 0x0403: { System.out.println("----------------------------------------------------------------------------------------"); // System.out.println(Hex.encodeHexString(udpPacket.getPayload().getRawData()).replaceAll("(.{2})", "$1 ").replaceAll("(.{48})", "$1\n")); // System.out.println("----------------------"); // Skip the rest of the header. - buf.skipBytes(39); + if(payloadType == 0x1B02) { + buf.skipBytes(123); + } else { + buf.skipBytes(31); + } + byte[] blockId = new byte[4]; + buf.readBytes(blockId); + buf.skipBytes(4); + int endOfLastBlock = buf.readerIndex(); int lastBlockSize = 0; - short currentContext = 0; for (byte code = buf.readByte(); buf.readableBytes() > 2; code = buf.readByte()) { - short blockId = buf.readShort(); - byte type = buf.readByte(); - // First check the code of the next block ... switch (code) { case (byte) 0x01: { - switch (type) { - case (byte) 0x01: { - // - It seems that the ids of a variable seem to occur multiple times - // - Also does it seem that this type of block sets some sort of context for following blocks - // - After setting up a machine with a new OS, the type of every of these is 0x00 - - // Found blocks: - // 01 00 23 01 1a 04 32 1c fd (size 7) - currentContext = blockId; - buf.skipBytes(5); - outputDetectedBlock("-- Switch Context --", buf, endOfLastBlock); - break; - } - case (byte) 0x00: { - // Is seems this simply signals the end of a packet. - currentContext = blockId; - buf.skipBytes(5); - outputDetectedBlock("-- Switch Context --", buf, endOfLastBlock); - break; - } - default: { - dumpAndExit(buf, endOfLastBlock, lastBlockSize, "Unexpected 0x01 type code: " + Hex.encodeHexString(new byte[]{type})); - } + if(payloadType == 0x1B02) { + buf.skipBytes(4); } + buf.readBytes(blockId); + buf.skipBytes(4); + outputDetectedBlock("-- Switch Context (" + Hex.encodeHexString(blockId) + ")", buf, endOfLastBlock); break; } case (byte) 0x02: { + short fieldId = buf.readShort(); + byte type = buf.readByte(); + String id = Hex.encodeHexString(blockId) + "-" + fieldId; + String name = names.getOrDefault(id, id); + if(!names.containsKey(id)) { + System.out.println("Missing variable"); + } // Now inspect the block content ... switch (type) { case (byte) 0x01: { // Possibly boolean value? - String id = "BOOL-" + currentContext + "-" + blockId; byte booleanByteValue = buf.readByte(); - outputDetectedBlock("BOOL value", buf, endOfLastBlock); boolean booleanValue = false; switch (booleanByteValue) { case (byte) 0x00: @@ -332,6 +318,7 @@ public class PoC { default: System.out.println("Unknown second byte for boolean value 0x" + Hex.encodeHexString(new byte[]{booleanByteValue})); } + outputDetectedBlock(name + " (BOOL)", booleanValue, null, buf, endOfLastBlock); if (!values.containsKey(id)) { valueLogger.info(String.format("Variable with id: %s set to: %b", id, booleanValue)); values.put(id, booleanValue); @@ -344,40 +331,38 @@ public class PoC { } case (byte) 0x03: { buf.skipBytes(5); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } case (byte) 0x05: { // NOTE: - // - Each packet seems to have one of these - // - For each following packet the content is identical + // - Name of the variable "A/GFE_ALARM", "BA" + // // Found Block: - // 02 00 0c 05: 00 02 00 13 63 00 00 69 9c 1a - // 02 00 0c 05: 00 01 00 47 00 64 04 2a 17 53 - buf.skipBytes(10); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + // 02 00 0c 05: 00 + // 02 00 0c 05: 00 + // 02 00 0c 05: 00 + buf.skipBytes(1); + outputDetectedBlock(name + " (Unknown (BA))", buf, endOfLastBlock); break; } case (byte) 0x06: { // Possibly Parse 16 bit int? - String id = "(U)INT-" + currentContext + "-" + blockId; short shortValue = buf.readShort(); - outputDetectedBlock("(U)INT value", buf, endOfLastBlock); + outputDetectedBlock(name + " ((U)INT)", shortValue, null, buf, endOfLastBlock); break; } case (byte) 0x07: { // Possibly Parse 32 bit int? - String id = "(U)DINT-" + currentContext + "-" + blockId; int intValue = buf.readInt(); - outputDetectedBlock("(U)DINT value", buf, endOfLastBlock); + outputDetectedBlock(name + " ((U)DINT)", intValue, null, buf, endOfLastBlock); break; } case (byte) 0x08: { // Parse float - String id = "REAL-" + currentContext + "-" + blockId; float floatValue = buf.readFloat(); - outputDetectedBlock("REAL value", buf, endOfLastBlock); floatValue = Math.round(floatValue * 100.0f) / 100.0f; + outputDetectedBlock(name + " (REAL)", floatValue, null, buf, endOfLastBlock); if (!values.containsKey(id)) { valueLogger.info(String.format("Variable with id: %s set to: %f", id, floatValue)); values.put(id, floatValue); @@ -390,12 +375,11 @@ public class PoC { } case (byte) 0x21: { // From having a look at the byte values these could be 32bit floating point values with some sort of parameters - String id = "REAL(P)-" + currentContext + "-" + blockId; byte param = buf.readByte(); decodeParam(param); float floatValue = buf.readFloat(); - outputDetectedBlock("REAL(P) value", buf, endOfLastBlock); floatValue = Math.round(floatValue * 100.0f) / 100.0f; + outputDetectedBlock(name + " (REAL(P))", floatValue, param, buf, endOfLastBlock); if (!values.containsKey(id)) { valueLogger.info(String.format("Variable with id: %s set to: %f with params %s", id, floatValue, Hex.encodeHexString(new byte[]{param}))); values.put(id, floatValue); @@ -408,11 +392,9 @@ public class PoC { } case (byte) 0x22: { // Parse boolean (From what I learnt, this could be a flagged boolean, where the first byte is some sort of param) - String id = "BOOL(P)-" + currentContext + "-" + blockId; byte param = buf.readByte(); decodeParam(param); byte booleanByteValue = buf.readByte(); - outputDetectedBlock("BOOL(P) value", buf, endOfLastBlock); boolean booleanValue = false; switch (booleanByteValue) { case (byte) 0x00: @@ -424,6 +406,7 @@ public class PoC { default: System.out.println("Unknown second byte for boolean value 0x" + Hex.encodeHexString(new byte[]{booleanByteValue})); } + outputDetectedBlock(name + " (BOOL(P))", booleanValue, param, buf, endOfLastBlock); if (!values.containsKey(id)) { valueLogger.info(String.format("Variable with id: %s set to: %b with params %s", id, booleanValue, Hex.encodeHexString(new byte[]{param}))); values.put(id, booleanValue); @@ -435,27 +418,42 @@ public class PoC { break; } case (byte) 0x24: { - // No idea what this type is. // NOTE: - // - It seems that the last byte seems to mirror the id of the block (Maybe the field id is just one byte and not a short) - // - It seems that these blocks are contained in every packet. - byte[] tmp = new byte[13]; // Has to be 13 in case of 0x0201 but some times 12 - buf.readBytes(tmp); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + // - Name of the variable "SKAL1", "SKAL2", "SKAL3". + // - Might be scaling variables providing information on how to scale a value + // - Potentially needed to display a bar graph for a value. + // - Quite a lot of these are used. + // - I would assume it's 3 32 bit unsigned integers and a trailing flag-byte + // - The flag byte seems to contain the values: 0, 1, 2 and 3 (So it's either two boolean flags or 4 types) + // + // Found Packets: + // 00 0e 43 48 00 00 c2 20 00 00 03 e9 01 + // + // 00 0e 42 c8 00 00 00 00 00 00 04 40 00 + // + // 00 0e 41 20 00 00 00 00 00 00 05 45 01 + // + // 00 0e 3f 80 00 00 bf 80 00 00 82 df 03 + long val1 = buf.readUnsignedInt(); + long val2 = buf.readUnsignedInt(); + long val3 = buf.readUnsignedInt(); + byte flag = buf.readByte(); + outputDetectedBlock(name + " (Trend Scaling) - " + val1 + ", " + val2 + ", " + val3 + ", " + flag, buf, endOfLastBlock); break; } case (byte) 0x25: { buf.skipBytes(6); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } case (byte) 0x47: { - // No idea what this type is. // NOTE: + // - Name of the variable "A/ALA_T9002_Y/SCHRITTTEXT_ALT", "A/ALA_T9002_Y/SCHRITTTEXT" + // - Seems to be a text-value + // - The longer UTF-16 Text seems to start at byte 4 and ends at 0x0000 + // - The shorter Text seems to come after some bytes after the longer text and again end with 0x0000 // - Seems to be sent as soon as a user confirms an alarm. // - Seems the length is variable - // - Seems content is terminated by a "0x0000" value - // - All content seems to be encoded as short values with the first byte set to "0x00". // // Found Blocks: // 00 4b 00 22 00 49 00 6e 00 69 00 74 00 69 00 61 @@ -465,29 +463,42 @@ public class PoC { // 00 72 00 74 00 65 00 6e 00 00 02 00 67 47 00 1d // 00 0b 00 57 00 41 00 52 00 54 00 45 00 4e 00 20 // 00 2e 00 2e 00 2e 00 20 00 00 + // Decoded: + // K"Initialisierung ..... bitte wartene) 0x48: { - // No idea what this type is. // NOTE: + // - Name of the variable "C/GW_AW_MIN", "C/GW_AW_MAX", "C/GW_SW_MIN", "C/GW_SW_MAX", "C/GW_GW_MIN", "C/GW_GW_MAX" // - Seems to be sent as soon as an alarm is fired, changed or removed from the controller. // - There seem to be only two types of values: 0x8000 and 0x8001 + // - Might be something similar to "BOOL(P)" + // + // Found packets: + // 02 00 10 48: 80 00 byte[] tmp = new byte[2]; buf.readBytes(tmp); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } case (byte) 0x49: { + // NOTE: // - Judging from the 0x80 first byte I would assume this is again one of these parametrized values // - Would suggest this is a 32 bit integer value. // Found blocks: // 80 00 00 06 0d - String id = "(U)DINT(P)-" + currentContext + "-" + blockId; byte param = buf.readByte(); decodeParam(param); int intValue = buf.readInt(); @@ -499,29 +510,26 @@ public class PoC { valueLogger.info(String.format("Variable with id: %s changed from: %d to: %d with params %s", id, oldValue, intValue, Hex.encodeHexString(new byte[]{param}))); values.put(id, intValue); } - outputDetectedBlock("(U)DINT(P) value", buf, endOfLastBlock); + outputDetectedBlock(name + " ((U)DINT(P))", intValue, param, buf, endOfLastBlock); break; } case (byte) 0x5B: { // No idea what this type is. buf.readShort(); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); } case (byte) 0x63: { - // No idea what this type is. // NOTE: - // - It seems that this block is contained in every packet exactly once - // Found blocks: - // 02 00 06 63: 64 00 19 b9 88 + // - Name of the variable "IST_FW_KURZ" byte[] tmp = new byte[5]; buf.readBytes(tmp); // System.out.println(String.format("Got 0x63 type for id %s with content: %s", blockId, Hex.encodeHexString(tmp))); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } case (byte) 0x75: { - // No idea what this type is. // NOTE: + // - Name of the variable "MIN_ALM", "MAX_ALM", "MIN_SCHALT", "MAX_SCHALT" // - Exactly 3 blocks of this type with extremely similar content is being sent every 60 seconds for the ids: 17, 16 and 34 // 001600280d0100000000280015f360000000000100 // 001600280d0100000000280015f360000000000100 @@ -529,21 +537,13 @@ public class PoC { byte[] tmp = new byte[size]; buf.readBytes(tmp); // System.out.println(String.format("Got 0x75 type for id %s with content: %s", blockId, Hex.encodeHexString(tmp))); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } case (byte) 0x76: { - // No idea what this type is. - // These strange blocks containing a repeating pattern of 0x00 and 0xFF // NOTE: - // - These blocks seem to be transferred whenever a boolean value is changed. - // - There seem to be two variants: - // - Variant 1 (shorter) is transferred as soon as a boolean value is set - // - Variant 2 (longer) is transferred as soon as a boolean values is unset - // - Variant always looks the same no matter what combination of boolean values is set - // - The blocks always refer to ids 0, 1 and 2 - // - The additional part of Variant 2 always starts with: - // "000700420049004e005f0041004c004d000000180018000300002ae7" + // - After knowing the name of the variables, it turns out that these are all "Alarm" variables. + // - Possibly a data-structure is returned which contains all information about a modules alarms // The last 4 bytes (maybe more) seem to be an always increasing value // (Maybe some sort of timestamp) short length = (short) (buf.readShort() - 3); @@ -551,13 +551,14 @@ public class PoC { buf.readBytes(tmp); String hexBlock = Hex.encodeHexString(tmp).replaceAll("(.{32})", "$1\n"); // System.out.println(String.format("Got 0x76 type for id %s with content: \n%s", blockId, hexBlock)); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown (Alarms))", buf, endOfLastBlock); break; } case (byte) 0xF6: { + // TODO: Potentially obsolete ... // Only seen in 0x0102 blocks buf.skipBytes(4); - outputDetectedBlock("Unknown", buf, endOfLastBlock); + outputDetectedBlock(name + " (Unknown)", buf, endOfLastBlock); break; } default: { @@ -574,10 +575,14 @@ public class PoC { break; } case (byte) 0x03: { + short fieldId = buf.readShort(); + byte type = buf.readByte(); + // Note: // - Might be error responses ... // Found blocks: // 03 00 23 00 00 00 4a (size 6) + // 03 00 00 00 00 00 1f switch (type) { case (byte) 0x00: { buf.skipBytes(3); @@ -641,7 +646,7 @@ public class PoC { // 41 00 57 00 56 00 42 00 31 00 4d 00 43 00 54 00 // 30 00 33 00 00 02 // Contained a text at the end: PS02AWVB1MCT10 and PS02AWVB1MCT03 - System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet"); +// System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet"); // outputPacket(buf); break; } @@ -670,6 +675,8 @@ public class PoC { // 01 01 break; } + // Seem to be read subscriptions. + // Each 0x1B01 is confirmed by a 0x1B02 containing values, but after a 0x1B01 also we start getting 0x0403 packets with content. case 0x1B01: { // NOTE: // - Seems to be sent as soon as the OS start up and a screen is opened. @@ -689,6 +696,7 @@ public class PoC { // 00 00 00 05 00 49 00 44 00 49 00 53 00 50 00 00 // ff ff 01 // + // // Another short one: // 1b 01 00 00 00 00 00 07 03 8c 01 c6 00 04 00 30 // 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -702,6 +710,7 @@ public class PoC { // 00 01 00 0e 00 43 00 2f 00 53 00 57 00 5f 00 4d 00 41 00 58 00 5f 00 53 00 43 00 41 00 4c 00 45 00 00 // ff ff 01 // + // // When opening a new screen: // 1b 01 00 00 00 00 00 07 03 6d 01 97 00 04 05 04 // 00 08 00 00 00 08 01 78 00 08 02 90 00 08 03 fa @@ -775,13 +784,112 @@ public class PoC { // 00 09 00 0a 00 44 00 59 00 4e 00 5f 00 42 00 45 00 53 00 43 00 48 00 31 00 00 // 00 0a 00 08 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 31 00 00 // ff ff 04 + // + // + // Another big packet: + // 1b 01 00 00 00 00 00 07 03 6e 01 98 00 04 05 10 + // 00 08 00 00 00 08 00 5a 00 08 01 e0 00 08 04 d8 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 + // + // 04 93 17 bc 00 35 01 3c 00 00 03 e8 + // 00 06 00 0e 00 41 00 2f 00 42 00 41 00 5f 00 47 00 46 00 45 00 53 00 5f 00 41 00 55 00 54 00 4f 00 00 + // 00 07 00 0b 00 41 00 2f 00 47 00 46 00 45 00 5f 00 41 00 4c 00 41 00 52 00 4d 00 00 + // 00 08 00 04 00 41 00 2f 00 41 00 33 00 00 + // ff ff + // 04 94 17 bd 00 36 01 3d 00 00 03 e8 + // 00 00 00 06 00 42 00 45 00 53 00 43 00 48 00 32 00 00 + // 00 01 00 05 00 53 00 4b 00 41 00 4c 00 31 00 00 + // 00 02 00 06 00 41 00 4c 00 41 00 52 00 4d 00 53 00 00 + // 00 03 00 0e 00 41 00 2f 00 42 00 41 00 5f 00 47 00 46 00 45 00 53 00 5f 00 41 00 55 00 54 00 4f 00 00 + // 00 04 00 09 00 47 00 46 00 5f 00 53 00 54 00 41 00 54 00 55 00 53 00 00 + // 00 05 00 05 00 53 00 4b 00 41 00 4c 00 32 00 00 + // 00 06 00 0a 00 44 00 59 00 4e 00 5f 00 42 00 45 00 53 00 43 00 48 00 31 00 00 + // 00 07 00 0b 00 41 00 2f 00 47 00 46 00 45 00 5f 00 41 00 4c 00 41 00 52 00 4d 00 00 + // 00 08 00 0a 00 44 00 59 00 4e 00 5f 00 42 00 45 00 53 00 43 00 48 00 32 00 00 + // 00 09 00 08 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 32 00 00 + // 00 0a 00 04 00 41 00 2f 00 41 00 31 00 00 + // 00 0b 00 06 00 42 00 45 00 53 00 43 00 48 00 31 00 00 + // 00 0c 00 07 00 47 00 46 00 5f 00 4e 00 41 00 4d 00 45 00 00 + // 00 0d 00 04 00 41 00 2f 00 42 00 41 00 00 + // 00 0e 00 0d 00 41 00 2f 00 49 00 53 00 54 00 5f 00 46 00 57 00 5f 00 4b 00 55 00 52 00 5a 00 00 + // 00 0f 00 0b 00 41 00 4b 00 54 00 5f 00 53 00 43 00 48 00 52 00 49 00 54 00 54 00 00 + // 00 10 00 08 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 31 00 00 + // ff ff + // 04 95 17 be 00 37 01 3e 00 00 03 e8 + // 00 00 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 46 00 41 00 52 00 42 00 45 00 31 00 00 + // 00 01 00 19 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 45 00 4e 00 41 00 42 00 4c 00 45 00 44 00 32 00 00 + // 00 02 00 09 00 47 00 46 00 45 00 5f 00 41 00 4c 00 41 00 52 00 4d 00 00 + // 00 03 00 13 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 42 00 45 00 53 00 43 00 48 00 31 00 00 + // 00 04 00 09 00 47 00 46 00 5f 00 53 00 54 00 41 00 54 00 55 00 53 00 00 + // 00 05 00 13 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 42 00 45 00 53 00 43 00 48 00 32 00 00 + // 00 06 00 0b 00 49 00 53 00 54 00 5f 00 46 00 57 00 5f 00 4b 00 55 00 52 00 5a 00 00 + // 00 07 00 06 00 41 00 4c 00 41 00 52 00 4d 00 53 00 00 + // 00 08 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 44 00 59 00 4e 00 5f 00 42 00 45 00 53 00 43 00 48 00 32 00 00 + // 00 09 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 46 00 41 00 52 00 42 00 45 00 32 00 00 + // 00 0a 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 53 00 43 00 41 00 4c 00 45 00 31 00 00 + // 00 0b 00 0c 00 42 00 41 00 5f 00 47 00 46 00 45 00 53 00 5f 00 41 00 55 00 54 00 4f 00 00 + // 00 0c 00 02 00 42 00 41 00 00 + // 00 0d 00 11 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 32 00 00 + // 00 0e 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 53 00 43 00 41 00 4c 00 45 00 32 00 00 + // 00 0f 00 19 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 5f 00 45 00 4e 00 41 00 42 00 4c 00 45 00 44 00 31 00 00 + // 00 10 00 07 00 44 00 59 00 4e 00 5f 00 42 00 45 00 5a 00 00 + // 00 11 00 17 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 44 00 59 00 4e 00 5f 00 42 00 45 00 53 00 43 00 48 00 31 00 00 + // 00 12 00 11 00 44 00 59 00 4e 00 5f 00 49 00 53 00 54 00 57 00 45 00 52 00 54 00 45 00 2f 00 4f 00 55 00 54 00 31 00 00 + // ff ff + // 04 9a 17 c3 00 3c 01 43 00 00 03 e8 + // 00 00 00 06 00 41 00 4c 00 41 00 52 00 4d 00 53 00 00 + // 00 01 00 09 00 47 00 46 00 5f 00 53 00 54 00 41 00 54 00 55 00 53 00 00 + // ff ff + // 04 + + + + // Skip the header part. + buf.skipBytes(118); + for (byte code = buf.readByte(); buf.readableBytes() > 2; code = buf.readByte()) { + switch (code) { + case (byte) 0x04: { + // Skip the 0x04 block and continue reading the variables. + buf.skipBytes(3); + byte[] blockId = new byte[4]; + buf.readBytes(blockId); + buf.skipBytes(4); + // The first block is part of the id of an address. + for (short fieldId = buf.readShort(); fieldId != (short) 0xFFFF; fieldId = buf.readShort()) { + // This is followed by a short value providing the length of the following + // string. + short length = buf.readShort(); + // Then comes the string, each character encoded as two bytes. + byte[] bytes = new byte[length * 2]; + buf.readBytes(bytes); + buf.skipBytes(2); + String address = new String(bytes, StandardCharsets.UTF_16); + + // Save the name for later. + names.put(Hex.encodeHexString(blockId) + "-" + fieldId, address); + } + break; + } + default: { + System.out.println("Error"); + } + } + } + break; } - case 0x1B02: { + /*case 0x1B02: { // NOTE: // - Seems to be sent as soon as the OS start up and a screen is opened. // - Sent from the Controller to the OS // - Seems to be a response to a previous 0x1B01 message // - Size of the response seems to be in direct correlation with the size of the corresponding 0x1B01 message + // - Also contains content for each subscription in a 0x1B01 message + // - The reason might be that in order to be notified about value changes, the client needs to be informed about the initial value. // // Found packets: // 1b 02 00 00 00 00 00 07 03 8a 01 c4 00 04 00 00 @@ -793,9 +901,10 @@ public class PoC { // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // 00 00 00 00 00 00 00 00 // 01 00 00 00 00 00 35 01 2c 04 cf 1a 0b - // 03 00 00 00 00 00 1f <!-- Error response with return code (0x0000001F) + // 03 00 00 00 00 00 1f <!-- Error response with return code? (0x0000001F) // 01 // + // // Another short one: // 1b 02 00 00 00 00 00 07 03 8c 01 c6 00 04 00 00 // 00 06 00 01 00 00 00 00 00 00 00 00 00 00 00 00 @@ -809,6 +918,7 @@ public class PoC { // 02 00 01 24 00 0e 43 48 00 00 c2 20 00 00 03 e9 01 // 01 // + // // When opening a new screen: // 1b 02 00 00 00 00 00 07 03 6d 01 97 00 04 00 00 // 00 06 00 01 00 06 01 51 00 06 02 3c 00 06 03 59 @@ -883,7 +993,91 @@ public class PoC { // 02 00 0a 08 00 00 00 00 // // 01 - } + // + // + // Another big one: + // 1b 02 00 00 00 01 00 07 03 6e 01 98 00 04 00 00 + // 00 06 00 01 00 06 00 1d 00 06 01 52 00 06 02 83 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + // 00 00 00 00 00 00 00 00 + // + // 04 00 00 00 00 00 35 01 3c 04 93 17 bc + // 02 00 06 01 00 + // 02 00 07 05 01 + // 02 00 08 05 01 + // + // 01 00 00 00 00 00 36 01 3d 04 94 17 bd + // 02 00 00 47 00 09 00 01 00 50 00 00 + // 02 00 01 24 00 0e 45 35 40 00 00 00 00 00 82 dc 00 + // 02 00 02 76 00 58 05 01 01 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 + // 02 00 03 01 01 + // 02 00 04 63 00 00 19 c4 2f + // 02 00 05 24 00 0e 43 c8 00 00 c2 c8 00 00 82 dd 01 + // 02 00 06 47 00 07 00 00 00 00 + // 02 00 07 05 01 + // 02 00 08 47 00 11 00 05 00 44 00 52 00 55 00 43 00 4b 00 00 + // 02 00 09 21 88 c2 20 00 00 + // 02 00 0a 05 01 + // 02 00 0b 47 00 09 00 01 00 53 00 00 + // 02 00 0c 47 00 19 00 09 00 50 00 54 00 30 00 39 00 41 00 44 00 47 00 4f 00 31 00 00 + // 02 00 0d 05 00 + // 02 00 0e 47 00 17 00 08 00 4b 00 65 00 69 00 6e 00 65 00 20 00 46 00 57 00 00 + // 02 00 0f 47 00 0d 00 03 00 41 00 75 00 73 00 00 + // 02 00 10 21 80 00 00 00 00 + // + // 01 00 00 00 00 00 37 01 3e 04 95 17 be + // 02 00 00 05 00 + // 02 00 01 01 01 + // 02 00 02 05 00 + // 02 00 03 47 00 09 00 01 00 54 00 00 + // 02 00 04 63 00 00 19 c4 2f + // 02 00 05 47 00 09 00 01 00 54 00 00 + // 02 00 06 63 64 00 19 b9 88 + // 02 00 07 76 00 6a 05 01 01 00 00 00 08 00 53 00 54 00 4f 00 45 00 52 00 55 00 4e 00 47 00 00 00 39 00 39 00 0f 00 00 2a f1 c6 c4 7a 4f ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 + // 02 00 08 47 00 0b 00 02 00 52 00 4c 00 00 + // 02 00 09 05 00 + // 02 00 0a 24 00 0e 43 48 00 00 c2 20 00 00 03 e9 01 + // 02 00 0b 01 00 + // 02 00 0c 05 00 + // 02 00 0d 08 41 a0 8e 39 + // 02 00 0e 24 00 0e 43 48 00 00 c2 20 00 00 03 e9 01 + // 02 00 0f 01 01 + // 02 00 10 47 00 19 00 09 00 50 00 54 00 30 00 39 00 41 00 4c 00 42 00 43 00 31 00 00 + // 02 00 11 47 00 0b 00 02 00 56 00 4c 00 00 + // 02 00 12 08 41 a0 8e 39 + // + // 01 00 00 00 00 00 3c 01 43 04 9a 17 c3 + // 02 00 00 76 00 58 05 01 01 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 ff ff 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 + // 02 00 01 63 00 00 19 c4 2f + // + // 01 + + // Skip the header part. + buf.skipBytes(118); + for (byte code = buf.readByte(); buf.readableBytes() > 2; code = buf.readByte()) { + switch (code) { + case (byte) 0x01: + case (byte) 0x04: { + // Skip the 0x04 block and continue reading the variables. + buf.skipBytes(4); + int blockId = buf.readInt(); + buf.skipBytes(4); + + + + return; + } + default: { + + } + } + } + break; + }*/ default: { System.out.println("Got 0x" + Hex.encodeHexString(new byte[]{(byte)(payloadType >> 8), (byte)(payloadType & 0xFF)}) + " packet"); outputPacket(buf); @@ -906,11 +1100,17 @@ public class PoC { } protected void outputDetectedBlock(String name, ByteBuf byteBuf, int endOfLastBlock) { + outputDetectedBlock(name, null, null, byteBuf, endOfLastBlock); + } + + protected void outputDetectedBlock(String name, Object value, Byte param, ByteBuf byteBuf, int endOfLastBlock) { int blockSize = byteBuf.readerIndex() - endOfLastBlock; byte[] blockContent = new byte[blockSize]; byteBuf.getBytes(endOfLastBlock, blockContent); + String valueString = (value != null) ? value.toString() : ""; + String paramString = (param != null) ? Hex.encodeHexString(new byte[] {param}) : ""; String content = " " + Hex.encodeHexString(blockContent).replaceAll("(.{2})", "$1 "); -// System.out.println(String.format("Block: %20s %s", name, content)); + System.out.println(String.format("Block: %30s %10s %2s %s", name, valueString, paramString, content)); } protected void outputPacket(ByteBuf byteBuf) { @@ -962,7 +1162,11 @@ public class PoC { } public static void main(String[] args) throws Exception { - new PoC(); + if(args.length == 0) { + new PoC(null); + } else { + new PoC(args[0]); + } } }