WIP161208

master
Harald Wolff 2016-12-08 10:26:46 +01:00
parent fd83cf147e
commit ae09543e3d
5 changed files with 215 additions and 122 deletions

View File

@ -51,6 +51,8 @@ public class ServiceLink implements NewSerialPortListener {
Smoother requestTime;
int requestTimeOut;
boolean useV2 = true;
LinkedList<ServiceLinkTelegram> txQueue;
Hashtable<ServiceLinkAddress, List<ServiceLinkTelegram>>
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);
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}