java-org.hwo/src/org/hwo/io/servicelink/ServiceLink.java

492 lines
11 KiB
Java

package org.hwo.io.servicelink;
import java.io.IOException;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import org.hwo.BitField;
import org.hwo.ChkSum;
import org.hwo.interactiveobjects.InteractiveObject;
import org.hwo.io.SerialPort;
import org.hwo.models.TableMapper.TableColumn;
/* ServiceLink
*
* Kommunikation via USB mit RegBus fŠhigem System
*
* †bertragungssicherheit wird durch USB sichergestellt
*
* †bertragen werden Telegramme mit folgendem Aufbau:
*
* Offset Type Inhalt
* 0 Byte RequestTyp ( 0 = NoOP, 1 = Wert lesen, 2 = Wert schreiben, 3 = Ereignis senden )
* 1 Byte Achse
* 2 Byte Knoten
* 3 Short Register Nummer
* 5 Int32/Float Wert (nur bei schreiben oder lesen antwort)
*
*/
public class ServiceLink {
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;
static int SL_MAGIC = 0x66;
class ServiceTelegram
{
byte request;
byte achse;
byte knoten;
int register;
byte[] value;
public ServiceTelegram()
{
request = 0;
achse = 0;
knoten = 0;
register = 0;
value = new byte[4];
ByteBuffer.wrap(value).asIntBuffer().put(0);
}
public void send()
{
byte[] txbuffer = new byte[12];
ByteBuffer bb = ByteBuffer.wrap(txbuffer).order(ByteOrder.LITTLE_ENDIAN);
bb.put( (byte)SL_MAGIC );
bb.put(request);
bb.put(achse);
bb.put(knoten);
bb.putShort((short)register);
if ((request & REQ_WRITE) == REQ_WRITE)
bb.put(value);
short chk = ChkSum.chksum(txbuffer, 1, bb.position()-1);
bb.putShort(chk);
try
{
getSerialPort().getOutputStream().write(txbuffer,0,bb.position());
} catch (IOException ex)
{
getSerialPort().close();
System.err.println(ex.toString());
}
}
public void recv() throws ServiceLinkException
{
byte[] rxbuffer = new byte[12];
ByteBuffer bb = ByteBuffer.wrap(rxbuffer).order(ByteOrder.LITTLE_ENDIAN);
try {
int ch = getSerialPort().getInputStream().read();
while ((ch != SL_MAGIC) && (ch >= 0))
ch = getSerialPort().getInputStream().read();
getSerialPort().getInputStream().read(rxbuffer,0,5);
request = bb.get();
achse = bb.get();
knoten = bb.get();
register = bb.getShort();
if ((request & (REQ_READ | REQ_ACK)) == (REQ_READ | REQ_ACK))
{
getSerialPort().getInputStream().read(rxbuffer,bb.position(),4);
bb.get(value);
};
getSerialPort().getInputStream().read(rxbuffer,bb.position(),2);
short chksum = bb.getShort();
if (chksum != ChkSum.chksum(rxbuffer, 0, bb.position() - 2))
throw new ServiceLinkException();
} catch (IOException e) {
getSerialPort().close();
System.err.println(e.toString());
throw new ServiceLinkException(e);
}
}
}
public class ServiceNode
{
@InteractiveObject(editor=RegisterEditor.class)
public class ServiceNodeRegister
{
@TableColumn(label="Register",readonly=true,width=60)
Integer register;
@TableColumn(label="Bezeichnung",readonly=true,width=150)
String label;
private Float floatValue;
private Integer intValue;
boolean floatType;
private BitField bitField;
public ServiceNodeRegister(int register,boolean floatType)
{
this.label = String.format("%d", register);
this.register = register;
this.floatType = floatType;
}
public ServiceNodeRegister(int register,String label,boolean floatType)
{
this.label = label;
this.register = register;
this.floatType = floatType;
}
public boolean isBitField()
{
return (bitField != null);
}
public boolean isFloat()
{
return floatType;
}
public boolean isInteger()
{
return (!isBitField() && !isFloat());
}
@TableColumn(label="Wert",width=500)
public String value()
{
if (bitField != null)
return bitField.toText(intValue);
if (intValue != null)
return String.format("%d", intValue);
if (floatValue != null)
return String.format("%f", floatValue);
return "N/A";
}
public void setValue(String value)
{
if (floatType)
floatValue = new Float(value);
else
intValue = new Integer(value);
}
public void read()
{
try {
if (floatType)
floatValue = ServiceNode.this.readFloat(register);
else
intValue = ServiceNode.this.readInt(register);
} catch (Exception e) {
floatValue = null;
intValue = 0;
e.printStackTrace();
};
}
public void write()
{
try
{
if (floatType)
ServiceNode.this.writeFloat(register, floatValue);
else
ServiceNode.this.writeInt(register, intValue);
} catch (Exception e)
{
e.printStackTrace();
}
}
public BitField getBitField() {
return bitField;
}
public void setBitField(BitField bitField) {
this.bitField = bitField;
}
public Integer getIntValue() {
return intValue;
}
public void setIntValue(Integer intValue) {
this.intValue = intValue;
}
public Float getFloatValue() {
return floatValue;
}
public void setFloatValue(Float floatValue) {
this.floatValue = floatValue;
}
}
private byte achse;
private byte knoten;
List<ServiceNodeRegister> registers;
public ServiceNode(byte achse,byte knoten)
{
this.achse = achse;
this.knoten = knoten;
this.registers = new ArrayList<ServiceLink.ServiceNode.ServiceNodeRegister>();
}
public ServiceNodeRegister createRegister(int register,String label,boolean floatType)
{
return new ServiceNodeRegister(register, label, floatType);
}
public List<ServiceNodeRegister> getRegisters()
{
return registers;
}
public void read()
{
for (ServiceNodeRegister r:registers)
r.read();
}
public ServiceLink getServiceLink()
{
return ServiceLink.this;
}
public int readInt(int register) throws IOException, ServiceLinkException
{
for (int n=0;n<retries;n++)
{
try
{
return ServiceLink.this.readInt(achse, knoten, register);
} catch (ServiceLinkException e)
{
if (n == (retries -1))
throw e;
}
}
throw new ServiceLinkException();
}
public float readFloat(int register) throws IOException, ServiceLinkException
{
for (int n=0;n<retries;n++)
{
try
{
return ServiceLink.this.readFloat(achse, knoten, register);
} catch (ServiceLinkException e)
{
if (n == (retries -1))
throw e;
}
}
throw new ServiceLinkException();
}
public void writeInt(int register,int value) throws IOException, ServiceLinkException
{
for (int n=0;n<retries;n++)
{
try
{
ServiceLink.this.writeInt(achse, knoten, register, value);
return;
} catch (ServiceLinkException e)
{
if (n == (retries -1))
throw e;
}
}
throw new ServiceLinkException();
}
public void writeFloat(int register,float value) throws IOException, ServiceLinkException
{
for (int n=0;n<retries;n++)
{
try
{
ServiceLink.this.writeFloat(achse, knoten, register,value);
return;
} catch (ServiceLinkException e)
{
if (n == (retries -1))
throw e;
}
}
throw new ServiceLinkException();
}
public byte getAchse() {
return achse;
}
public void setAchse(byte achse) {
this.achse = achse;
}
public byte getKnoten() {
return knoten;
}
public void setKnoten(byte knoten) {
this.knoten = knoten;
}
}
private SerialPort serialPort;
int retries;
public ServiceLink(SerialPort serialPort)
{
this.retries = 3;
this.serialPort = serialPort;
this.serialPort.setTimeout(500);
try
{
System.err.println(String.format("BRKVAL : 0x%04x",readInt((byte)0,(byte)0,(short)0x200)));
System.err.println(String.format("SPLIMIT: 0x%04x",readInt((byte)0,(byte)0,(short)0x201)));
} catch (Exception e)
{
e.printStackTrace();
}
}
public void open() throws ServiceLinkException
{
if (serialPort != null)
serialPort.open();
throwNotOpen();
}
public void close()
{
if (serialPort != null)
serialPort.close();
}
@Override
protected void finalize() throws Throwable {
if (serialPort.isOpen())
serialPort.close();
}
public ServiceNode getServiceNode(byte achse,byte knoten)
{
return new ServiceNode(achse, knoten);
}
public Integer readInt(byte achse,byte knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
throwNotOpen();
return ByteBuffer.wrap( request((byte)(REQ_READ | REQ_INT), achse, knoten, register).value ).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get();
}
public Float readFloat(byte achse,byte knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
throwNotOpen();
return ByteBuffer.wrap( request((byte)(REQ_READ | REQ_FLOAT), achse, knoten, register).value ).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer().get();
}
public void writeInt(byte achse,byte knoten,int register,int value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
throwNotOpen();
byte[] v = new byte[4];
ByteBuffer bb = ByteBuffer.wrap(v).order(ByteOrder.LITTLE_ENDIAN);
bb.putInt(value);
ServiceTelegram telegram = request((byte)(REQ_WRITE | REQ_INT), achse, knoten, register, v);
}
public void writeFloat(byte achse,byte knoten,int register,float value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
throwNotOpen();
byte[] v = new byte[4];
ByteBuffer bb = ByteBuffer.wrap(v).order(ByteOrder.LITTLE_ENDIAN);
bb.putFloat(value);
ServiceTelegram telegram = request((byte)(REQ_WRITE | REQ_FLOAT), achse, knoten, register, v);
}
private synchronized ServiceTelegram request(byte request,byte achse,byte knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
return request(request,achse,knoten,register,new byte[0]);
}
private synchronized ServiceTelegram request(byte request,byte achse,byte knoten,int register,byte[] value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
ServiceTelegram telegram = new ServiceTelegram();
telegram.request = request;
telegram.achse = achse;
telegram.knoten = knoten;
telegram.register = register;
if (value.length == 4)
telegram.value = value;
telegram.send();
telegram.recv();
if ((telegram.request & REQ_ACK)==0)
throw new ServiceLinkRequestFailedException();
return telegram;
}
public SerialPort getSerialPort() {
return serialPort;
}
public void setSerialPort(SerialPort serialPort) {
if (isOpen())
this.serialPort.close();
this.serialPort = serialPort;
}
private void throwNotOpen() throws ServiceLinkException
{
if (!isOpen())
throw new ServiceLinkException("Port not Opened!");
}
public boolean isOpen()
{
return this.serialPort.isOpen();
}
}