From ae09543e3d8b8b7e9dd5eb8c1a069fce44f81ca1 Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Thu, 8 Dec 2016 10:26:46 +0100 Subject: [PATCH] WIP161208 --- src/org/hwo/servicelink/ServiceLink.java | 23 +++- .../hwo/servicelink/ServiceLinkTelegram.java | 117 +---------------- .../servicelink/ServiceLinkV1Telegram.java | 122 ++++++++++++++++++ .../servicelink/ServiceLinkV2Telegram.java | 67 ++++++++++ .../ServiceLinkRequestFailedException.java | 8 +- 5 files changed, 215 insertions(+), 122 deletions(-) create mode 100644 src/org/hwo/servicelink/ServiceLinkV1Telegram.java create mode 100644 src/org/hwo/servicelink/ServiceLinkV2Telegram.java diff --git a/src/org/hwo/servicelink/ServiceLink.java b/src/org/hwo/servicelink/ServiceLink.java index 3eb5361..a62f182 100644 --- a/src/org/hwo/servicelink/ServiceLink.java +++ b/src/org/hwo/servicelink/ServiceLink.java @@ -51,6 +51,8 @@ public class ServiceLink implements NewSerialPortListener { Smoother requestTime; int requestTimeOut; + boolean useV2 = true; + LinkedList txQueue; Hashtable> pendingRequests; @@ -251,24 +253,32 @@ public class ServiceLink implements NewSerialPortListener { public Integer readInt(int achse,int knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException { - ServiceLinkTelegram request = ServiceLinkTelegram.create(REQ_INT | REQ_READ, achse, knoten, register, null); + ServiceLinkTelegram request = useV2 ? + new ServiceLinkV2Telegram(REQ_INT | REQ_READ, achse, knoten, register, null) : + new ServiceLinkV1Telegram(REQ_INT | REQ_READ, achse, knoten, register, null); queueRequest(request); return (Integer)request.getValue(); } public Float readFloat(int achse,int knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException { - ServiceLinkTelegram request = ServiceLinkTelegram.create(REQ_FLOAT | REQ_READ, achse, knoten, register, null); + ServiceLinkTelegram request = useV2 ? + new ServiceLinkV2Telegram(REQ_FLOAT | REQ_READ, achse, knoten, register, null) : + new ServiceLinkV1Telegram(REQ_FLOAT | REQ_READ, achse, knoten, register, null); queueRequest(request); return (Float)request.getValue(); } public void writeInt(int achse,int knoten,int register,int value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException { - ServiceLinkTelegram request = ServiceLinkTelegram.create(REQ_INT | REQ_WRITE, achse, knoten, register, value); + ServiceLinkTelegram request = useV2 ? + new ServiceLinkV2Telegram(REQ_INT | REQ_WRITE, achse, knoten, register, null) : + new ServiceLinkV1Telegram(REQ_INT | REQ_WRITE, achse, knoten, register, null); queueRequest(request); } public void writeFloat(int achse,int knoten,int register,float value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException{ - ServiceLinkTelegram request = ServiceLinkTelegram.create(REQ_FLOAT | REQ_WRITE, achse, knoten, register, value); + ServiceLinkTelegram request = useV2 ? + new ServiceLinkV2Telegram(REQ_FLOAT | REQ_WRITE, achse, knoten, register, null) : + new ServiceLinkV1Telegram(REQ_FLOAT | REQ_WRITE, achse, knoten, register, null); queueRequest(request); } @@ -323,7 +333,10 @@ public class ServiceLink implements NewSerialPortListener { return; } } - rx = ServiceLinkTelegram.read(getSerialPort().getInputStream()); + rx = useV2 ? + new ServiceLinkV2Telegram(getSerialPort().getInputStream()) : + new ServiceLinkV1Telegram(getSerialPort().getInputStream()) ; + if (rx != null){ received(rx); } diff --git a/src/org/hwo/servicelink/ServiceLinkTelegram.java b/src/org/hwo/servicelink/ServiceLinkTelegram.java index da9947d..30e3948 100644 --- a/src/org/hwo/servicelink/ServiceLinkTelegram.java +++ b/src/org/hwo/servicelink/ServiceLinkTelegram.java @@ -1,20 +1,10 @@ package org.hwo.servicelink; -import java.io.IOException; -import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.zip.CRC32; -import org.hwo.ByteArrayHexlifier; -import org.hwo.ChkSum; -import org.hwo.servicelink.exceptions.CRCFailedException; +public abstract class ServiceLinkTelegram { -import static org.hwo.logging.Logging.*; -import static org.hwo.logging.LogLevel.*; - -public class ServiceLinkTelegram { static int REQ_READ = 0x01; static int REQ_WRITE = 0x02; static int REQ_EVENT = 0x04; @@ -26,63 +16,6 @@ public class ServiceLinkTelegram { static int SL_MAGIC = 0x66; - public static ServiceLinkTelegram create(int operation,int achse,int knoten,int register,Object value){ - return new ServiceLinkTelegram(operation,achse,knoten,register,value); - } - - public static byte[] readTelegramBytes(InputStream in){ - int l, - sync, - opcode; - - byte[] rxbuffer; - - try { - int ch = in.read(); - - while ((ch != SL_MAGIC)) { - ch = in.read(); - if (ch != SL_MAGIC){ - if (ch == -1){ - return null; - } - log(DEBUGDETAIL,"readTelegramBytes(): junk byte in the line: %d [ 0x%02x ]",ch,ch); - } - } - sync = (byte)ch; - opcode = (byte)in.read(); - - l = ((opcode & (REQ_READ | REQ_ACK)) == (REQ_READ | REQ_ACK)) ? 10 : 6; - - rxbuffer = new byte[ l + 2 ]; - - rxbuffer[0] = (byte)sync; - rxbuffer[1] = (byte)opcode; - - l = in.read(rxbuffer,2,l); - log(DEBUGDETAIL,"RX BYTES: %2d: %s",rxbuffer.length,ByteArrayHexlifier.byteArrayToString(rxbuffer)); - - return rxbuffer; - } catch (IOException e) { - log(e); - } - return null; - } - - public static ServiceLinkTelegram read(InputStream in){ - byte[] rx = readTelegramBytes(in); - - if (rx != null){ - try { - return new ServiceLinkTelegram(rx); - } catch (Exception e){ - log(e); - } - } - return null; - } - - int opcode; ServiceLinkAddress address; @@ -96,31 +29,8 @@ public class ServiceLinkTelegram { this.opcode = operation; this.address = new ServiceLinkAddress(achse, knoten, register); this.value = value; - } - protected ServiceLinkTelegram(byte[] buffer) throws CRCFailedException { - if ((buffer.length != 12) && (buffer.length != 8) ){ - throw new ArrayIndexOutOfBoundsException(String.format("ServiceLinkTelegram needs to be constructed from 8 or 12 bytes! But got %d bytes.",buffer.length)); - } - ByteBuffer bb = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN); - short chk = ChkSum.chksum(buffer, 1, buffer.length - 3); - - - if (bb.getShort(buffer.length - 2) != chk) { - log(DEBUG,"CRC failed: 0x%04x != 0x%04x",bb.getShort(buffer.length - 2),chk); - throw new CRCFailedException(buffer, "ServiceLinkTelegram bytes with wrong crc"); - } - - this.opcode = bb.get(1); - this.address = new ServiceLinkAddress(bb.get(2),bb.get(3),bb.getShort(4)); - if (buffer.length == 12){ - int v = bb.getInt(6); - if ((opcode & REQ_FLOAT)==REQ_FLOAT){ - this.value = Float.intBitsToFloat(v); - } else if ((opcode & REQ_INT)==REQ_INT){ - this.value = v; - } - } + this.checkPlausible(); } private void checkPlausible(){ @@ -131,7 +41,7 @@ public class ServiceLinkTelegram { } } - private byte[] valueAsByteArray(){ + protected byte[] valueAsByteArray(){ byte[] v = new byte[4]; if (value == null) @@ -144,26 +54,7 @@ public class ServiceLinkTelegram { return v; } - public byte[] toByteArray(){ - byte[] txbuffer = new byte[ ((opcode & REQ_WRITE) == REQ_WRITE) ? 12 : 8 ]; - ByteBuffer bb = ByteBuffer.wrap(txbuffer).order(ByteOrder.LITTLE_ENDIAN); - - bb.put( (byte)SL_MAGIC ); - bb.put( (byte)opcode ); - bb.put( (byte)address.getAx()); - bb.put( (byte)address.getNode()); - bb.putShort((short)(address.getRegister())); - - - if ((opcode & REQ_WRITE) == REQ_WRITE){ - bb.put(valueAsByteArray()); - } - - short chk = ChkSum.chksum(txbuffer, 1, bb.position()-1); - bb.putShort(chk); - - return txbuffer; - } + public abstract byte[] toByteArray(); public ServiceLinkAddress getAddress() { return address; diff --git a/src/org/hwo/servicelink/ServiceLinkV1Telegram.java b/src/org/hwo/servicelink/ServiceLinkV1Telegram.java new file mode 100644 index 0000000..3c94f97 --- /dev/null +++ b/src/org/hwo/servicelink/ServiceLinkV1Telegram.java @@ -0,0 +1,122 @@ +package org.hwo.servicelink; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.zip.CRC32; + +import javax.management.RuntimeErrorException; + +import org.hwo.ByteArrayHexlifier; +import org.hwo.ChkSum; +import org.hwo.servicelink.exceptions.CRCFailedException; + +import static org.hwo.logging.Logging.*; +import static org.hwo.logging.LogLevel.*; + +public class ServiceLinkV1Telegram extends ServiceLinkTelegram { + + public ServiceLinkV1Telegram(int operation,int achse,int knoten,int register,Object value){ + super(operation,achse,knoten,register,value); + } + + public ServiceLinkV1Telegram(InputStream in) { + byte[] bytes = readTelegramBytes(in); + try { + fromBytes(bytes); + } catch (CRCFailedException e){ + log(e); + throw new RuntimeException(e); + } + } + + protected byte[] readTelegramBytes(InputStream in){ + int l, + sync, + opcode; + + byte[] rxbuffer; + + try { + int ch = in.read(); + + while ((ch != SL_MAGIC)) { + ch = in.read(); + if (ch != SL_MAGIC){ + if (ch == -1){ + return null; + } + log(DEBUGDETAIL,"readTelegramBytes(): junk byte in the line: %d [ 0x%02x ]",ch,ch); + } + } + sync = (byte)ch; + opcode = (byte)in.read(); + + l = ((opcode & (REQ_READ | REQ_ACK)) == (REQ_READ | REQ_ACK)) ? 10 : 6; + + rxbuffer = new byte[ l + 2 ]; + + rxbuffer[0] = (byte)sync; + rxbuffer[1] = (byte)opcode; + + l = in.read(rxbuffer,2,l); + log(DEBUGDETAIL,"RX BYTES: %2d: %s",rxbuffer.length,ByteArrayHexlifier.byteArrayToString(rxbuffer)); + + return rxbuffer; + } catch (IOException e) { + log(e); + } + return null; + } + + protected void fromBytes(byte[] buffer) throws CRCFailedException { + if ((buffer.length != 12) && (buffer.length != 8) ){ + throw new ArrayIndexOutOfBoundsException(String.format("ServiceLinkTelegram needs to be constructed from 8 or 12 bytes! But got %d bytes.",buffer.length)); + } + + ByteBuffer bb = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN); + short chk = ChkSum.chksum(buffer, 1, buffer.length - 3); + + + if (bb.getShort(buffer.length - 2) != chk) { + log(DEBUG,"CRC failed: 0x%04x != 0x%04x",bb.getShort(buffer.length - 2),chk); + throw new CRCFailedException(buffer, "ServiceLinkTelegram bytes with wrong crc"); + } + + this.opcode = bb.get(1); + this.address = new ServiceLinkAddress(bb.get(2),bb.get(3),bb.getShort(4)); + if (buffer.length == 12){ + int v = bb.getInt(6); + if ((opcode & REQ_FLOAT)==REQ_FLOAT){ + this.value = Float.intBitsToFloat(v); + } else if ((opcode & REQ_INT)==REQ_INT){ + this.value = v; + } + } + } + + public byte[] toByteArray(){ + byte[] txbuffer = new byte[ ((opcode & REQ_WRITE) == REQ_WRITE) ? 12 : 8 ]; + ByteBuffer bb = ByteBuffer.wrap(txbuffer).order(ByteOrder.LITTLE_ENDIAN); + + bb.put( (byte)SL_MAGIC ); + bb.put( (byte)opcode ); + bb.put( (byte)address.getAx()); + bb.put( (byte)address.getNode()); + bb.putShort((short)(address.getRegister())); + + + if ((opcode & REQ_WRITE) == REQ_WRITE){ + bb.put(valueAsByteArray()); + } + + short chk = ChkSum.chksum(txbuffer, 1, bb.position()-1); + bb.putShort(chk); + + return txbuffer; + } + +} + diff --git a/src/org/hwo/servicelink/ServiceLinkV2Telegram.java b/src/org/hwo/servicelink/ServiceLinkV2Telegram.java new file mode 100644 index 0000000..8010c34 --- /dev/null +++ b/src/org/hwo/servicelink/ServiceLinkV2Telegram.java @@ -0,0 +1,67 @@ +package org.hwo.servicelink; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.zip.CRC32; + +import org.hwo.ByteArrayHexlifier; +import org.hwo.ChkSum; +import org.hwo.servicelink.exceptions.CRCFailedException; + +import static org.hwo.logging.Logging.*; +import static org.hwo.logging.LogLevel.*; + +public class ServiceLinkV2Telegram extends ServiceLinkTelegram { + static int REQ_READ = 0x01; + static int REQ_WRITE = 0x02; + static int REQ_EVENT = 0x04; + static int REQ_FAIL = 0x08; + + static int REQ_INT = 0x10; + static int REQ_FLOAT = 0x20; + static int REQ_ACK = 0x40; + + public ServiceLinkV2Telegram(int operation,int achse,int knoten,int register,Object value){ + super(operation,achse,knoten,register,value); + } + + public ServiceLinkV2Telegram(InputStream in){ + byte[] buffer = new byte[8]; + + try { + in.read(buffer, 0, 8); + } catch (IOException e) { + log(e); + throw new RuntimeException(e); + } + + setAddress(new ServiceLinkAddress((buffer[1]>>4) & 0x0F, buffer[1] & 0x0F, ((int)buffer[2]) | ((int)buffer[3])<<8 )); + + int op = 0; + + op |= ( buffer[0] & 0x01 ) == 0 ? REQ_WRITE : REQ_READ; + op |= ( buffer[0] & 0x02 ) == 0 ? REQ_INT : REQ_FLOAT; + op |= ( buffer[0] & 0x04 ) == 0 ? REQ_ACK : REQ_FAIL; + + setOpcode(op); + + if ((op & (REQ_READ | REQ_ACK))==(REQ_READ | REQ_ACK)){ + // ToDo: set value... + } else { + setValue(null); + } + } + + + @Override + public byte[] toByteArray() { + return null; + } + + + +} + diff --git a/src/org/hwo/servicelink/exceptions/ServiceLinkRequestFailedException.java b/src/org/hwo/servicelink/exceptions/ServiceLinkRequestFailedException.java index db1a266..bc61cea 100644 --- a/src/org/hwo/servicelink/exceptions/ServiceLinkRequestFailedException.java +++ b/src/org/hwo/servicelink/exceptions/ServiceLinkRequestFailedException.java @@ -1,12 +1,12 @@ package org.hwo.servicelink.exceptions; -import org.hwo.servicelink.ServiceLinkTelegram; +import org.hwo.servicelink.ServiceLinkV1Telegram; public class ServiceLinkRequestFailedException extends ServiceLinkException { - private ServiceLinkTelegram serviceTelegram; + private ServiceLinkV1Telegram serviceTelegram; - public ServiceLinkRequestFailedException(ServiceLinkTelegram telegram) + public ServiceLinkRequestFailedException(ServiceLinkV1Telegram telegram) { serviceTelegram = telegram; } @@ -16,7 +16,7 @@ public class ServiceLinkRequestFailedException extends ServiceLinkException { serviceTelegram = null; } - public ServiceLinkTelegram getServiceLinkTelegram() + public ServiceLinkV1Telegram getServiceLinkTelegram() { return this.serviceTelegram; }