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

343 lines
8.5 KiB
Java
Raw Blame History

package org.hwo.servicelink;
import java.io.IOException;
import java.io.ObjectInputStream.GetField;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import org.hwo.ChkSum;
import org.hwo.Smoother;
import org.hwo.bitfields.BitField;
import org.hwo.interactiveobjects.InteractiveObject;
import org.hwo.io.SerialPort;
import org.hwo.io.NewSerialPort.NewSerialPort;
/* ServiceLink
*
* Kommunikation via USB mit RegBus f<>higem System
*
* <20>bertragungssicherheit wird durch USB sichergestellt
*
* <20>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;
public class ServiceTelegram
{
private byte request;
private byte achse;
private byte knoten;
private 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);
if (register > 32767)
bb.putShort((short)(register));
else
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();
if (ch != SL_MAGIC)
System.err.println(String.format("PRE-JUNK: 0x%02x",ch));
}
getSerialPort().getInputStream().read(rxbuffer,0,5);
request = bb.get();
achse = bb.get();
knoten = bb.get();
register = bb.getShort();
if (register < 0)
register = (register & 0x7FFF) | 0x8000;
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();
//System.err.println(String.format("recv(): %d.%d:%d = 0x%08x",achse,knoten,register,bb.getInt(5)));
} catch (IOException e) {
getSerialPort().close();
System.err.println(e.toString());
throw new ServiceLinkException(e);
}
}
public byte getRequest() {
return request;
}
public void setRequest(byte request) {
this.request = request;
}
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;
}
public int getRegister() {
return register;
}
public void setRegister(int register) {
this.register = register;
}
}
private NewSerialPort serialPort;
int retries;
private ServiceRegisterCache
serviceRegisterCache;
Smoother requestTime;
private AsynchronServiceLinkProvider
asynchronServiceLinkProvider;
public ServiceLink(NewSerialPort serialPort)
{
this.retries = 3;
this.serialPort = serialPort;
this.serialPort.setTimeOut(250);
this.serviceRegisterCache = new ServiceRegisterCache(this);
this.asynchronServiceLinkProvider = new AsynchronServiceLinkProvider(serviceRegisterCache);
this.requestTime = new Smoother();
this.requestTime.setTn(16);
}
public int getAverageRequestTime()
{
return requestTime.getWert();
}
public ServiceRegisterCache getServiceRegisterCache()
{
return this.serviceRegisterCache;
}
public AsynchronServiceLinkProvider getAsynchronServiceLinkProvider() {
return asynchronServiceLinkProvider;
}
public synchronized void open() throws ServiceLinkException
{
if (serialPort != null)
serialPort.open();
throwNotOpen();
}
public synchronized void close()
{
if (serialPort != null)
serialPort.close();
}
@Override
protected void finalize() throws Throwable {
if (serialPort.isOpen())
serialPort.close();
}
public Integer readInt(int achse,int knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
return readInt((byte)achse, (byte)knoten, register);
}
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(int achse,int knoten,int register,int value) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
{
writeInt((byte)achse, (byte)knoten, register, value);
}
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
{
long rstart,rend;
ServiceTelegram telegram = new ServiceTelegram();
telegram.setRequest(request);
telegram.setAchse(achse);
telegram.setKnoten(knoten);
telegram.setRegister(register);
if (value.length == 4)
telegram.value = value;
telegram.send();
rstart = System.currentTimeMillis();
for (int n = 0; n<3; n++)
{
telegram.recv();
if (
(telegram.getAchse() == achse) &&
(telegram.getKnoten() == knoten) &&
(telegram.getRegister() == register)
)
break;
};
rend = System.currentTimeMillis();
requestTime.cycle((int)(rend - rstart));
if ((telegram.getRequest() & REQ_ACK)==0)
throw new ServiceLinkRequestFailedException(telegram);
return telegram;
}
public synchronized NewSerialPort getSerialPort() {
return serialPort;
}
public synchronized void setSerialPort(NewSerialPort serialPort) {
if (isOpen())
this.serialPort.close();
this.serialPort = serialPort;
}
private synchronized void throwNotOpen() throws ServiceLinkException
{
if (!isOpen())
throw new ServiceLinkException("Port not Opened!");
}
public synchronized boolean isOpen()
{
return this.serialPort.isOpen();
}
}