ServiceLink Änderungen

thobaben_serialize
Harald Wolff 2015-12-16 16:35:09 +01:00
parent 3094b6a5ad
commit 29188d7adb
7 changed files with 19 additions and 640 deletions

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class BitField {
@ -12,7 +13,6 @@ public class BitField {
public BitField()
{
this.fields = new ArrayList<Field>();
initialize();
}
@ -22,20 +22,7 @@ public class BitField {
if (fieldsNode != null)
{
NodeList fields = fieldsNode.getElementsByTagName("Field");
for (int i=0;i<fields.getLength();i++)
{
Element fieldNode = (Element)fields.item(i);
int start = 0,
len = 1;
if (!fieldNode.getAttribute("len").equals(""))
len = Integer.decode(fieldNode.getAttribute("len"));
if (!fieldNode.getAttribute("start").equals(""))
start = Integer.decode(fieldNode.getAttribute("start"));
this.fields.add(new Field(this,start,len,fieldNode.getTextContent()));
}
fieldsFromXML(fieldsNode);
}
}
@ -45,6 +32,23 @@ public class BitField {
this.fields.add(new Field(this, i, 1));
}
public void fieldsFromXML(Node fieldsNode){
NodeList fields = ((Element)fieldsNode).getElementsByTagName("Field");
for (int i=0;i<fields.getLength();i++)
{
Element fieldNode = (Element)fields.item(i);
int start = 0,
len = 1;
if (!fieldNode.getAttribute("len").equals(""))
len = Integer.decode(fieldNode.getAttribute("len"));
if (!fieldNode.getAttribute("start").equals(""))
start = Integer.decode(fieldNode.getAttribute("start"));
this.fields.add(new Field(this,start,len,fieldNode.getTextContent()));
}
}
public synchronized String toText(Integer value)
{
StringBuilder sb = new StringBuilder();

View File

@ -1,87 +0,0 @@
package org.hwo.io.servicelink;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
public class AsynchronServiceLinkProvider {
ServiceRegisterCache cache;
Hashtable<Integer, List<ServiceRegisterListener>> serviceRegisterListeners;
public AsynchronServiceLinkProvider(ServiceRegisterCache cache){
this.cache = cache;
this.serviceRegisterListeners = new Hashtable<Integer, List<ServiceRegisterListener>>();
}
private Integer calcRegisterHash(int ax,int node,int registerno,boolean asFloat){
Integer hash = (ax << 24) | (node << 16) | registerno;
if (asFloat)
hash |= 0x40000000;
return hash;
}
private Integer axFromHash(Integer hash){
return (hash >> 24) & 0x0F;
}
private Integer nodeFromHash(Integer hash){
return (hash >> 16) & 0x0F;
}
private Integer regFromHash(Integer hash){
return (hash) & 0xFFFF;
}
private List<ServiceRegisterListener> getListeners(Integer hash){
if (!serviceRegisterListeners.containsKey(hash))
serviceRegisterListeners.put(hash, new LinkedList<ServiceRegisterListener>());
return serviceRegisterListeners.get(hash);
}
public void addServiceRegisterListener(int ax,int node,int registerno,boolean asFloat,ServiceRegisterListener listener){
getListeners(calcRegisterHash(ax, node, registerno,asFloat)).add(listener);
}
public void removeServiceRegisterListener(int ax,int node,int registerno,boolean asFloat,ServiceRegisterListener listener){
getListeners(calcRegisterHash(ax, node, registerno,asFloat)).remove(listener);
}
public Hashtable<Integer, List<ServiceRegisterListener>> getServiceRegisterListeners() {
return serviceRegisterListeners;
}
public void setServiceRegisterListeners(
Hashtable<Integer, List<ServiceRegisterListener>> serviceRegisterListeners) {
this.serviceRegisterListeners = serviceRegisterListeners;
}
public void update(){
for (Integer hash: serviceRegisterListeners.keySet()){
if (!getListeners(hash).isEmpty()){
//System.err.println(String.format("AsyncUpdate for Hash: 0x%08x", hash));
if ((hash & 0x40000000) != 0){
Float f = this.cache.getCachedFloat( axFromHash(hash),nodeFromHash(hash),regFromHash(hash));
if (f != null){
for (ServiceRegisterListener listener: getListeners(hash)){
listener.ServiceRegisterValueUpdated(axFromHash(hash),nodeFromHash(hash),regFromHash(hash),f);
}
}
} else {
Integer i = this.cache.getCachedInteger( axFromHash(hash),nodeFromHash(hash),regFromHash(hash));
if (i != null){
for (ServiceRegisterListener listener: getListeners(hash)){
listener.ServiceRegisterValueUpdated(axFromHash(hash),nodeFromHash(hash),regFromHash(hash),i);
}
}
}
}
}
}
}

View File

@ -1,342 +0,0 @@
package org.hwo.io.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<EFBFBD>higem System
*
* <EFBFBD>bertragungssicherheit wird durch USB sichergestellt
*
* <EFBFBD>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();
}
}

View File

@ -1,23 +0,0 @@
package org.hwo.io.servicelink;
import java.io.IOException;
public class ServiceLinkException extends Exception {
public ServiceLinkException()
{
}
public ServiceLinkException(String message)
{
super(message);
}
public ServiceLinkException(Throwable e) {
super(e);
}
}

View File

@ -1,30 +0,0 @@
package org.hwo.io.servicelink;
import org.hwo.io.servicelink.ServiceLink.ServiceTelegram;
public class ServiceLinkRequestFailedException extends ServiceLinkException {
private ServiceTelegram serviceTelegram;
public ServiceLinkRequestFailedException(ServiceTelegram telegram)
{
serviceTelegram = telegram;
}
public ServiceLinkRequestFailedException()
{
serviceTelegram = null;
}
public ServiceTelegram getServiceTelegram()
{
return this.serviceTelegram;
}
@Override
public String toString() {
if (getServiceTelegram()!=null)
return String.format("ServiceLinkRequestFailedException: %d.%d:%d",getServiceTelegram().getAchse(),getServiceTelegram().getKnoten(),getServiceTelegram().getRegister());
return "ServiceLinkRequestFailedException";
}
}

View File

@ -1,135 +0,0 @@
package org.hwo.io.servicelink;
import java.io.IOException;
import java.util.Hashtable;
public class ServiceRegisterCache {
public class BaseCacheItem
{
Integer ax,
node,
register;
long lastReadTime;
public BaseCacheItem(int ax,int node,int register)
{
this.ax = ax;
this.node = node;
this.register = register;
}
long age()
{
return System.currentTimeMillis() - lastReadTime;
}
boolean isOld()
{
return age() > 250;
}
}
public class IntegerCacheItem extends BaseCacheItem
{
public IntegerCacheItem(int ax,int node,int register)
{
super(ax,node,register);
intValue = null;
}
Integer intValue;
Integer intValue()
{
if (isOld() && serviceLink.isOpen())
{
try {
intValue = serviceLink.readInt(ax.byteValue(),node.byteValue(),register);
} catch (Exception e) {
e.printStackTrace();
intValue = null;
}
lastReadTime = System.currentTimeMillis();
}
return intValue;
}
}
public class FloatCacheItem extends BaseCacheItem
{
public FloatCacheItem(int ax,int node,int register)
{
super(ax,node,register);
floatValue = 0.0f;
}
Float floatValue;
Float floatValue()
{
if (isOld() && serviceLink.isOpen())
{
try {
floatValue = serviceLink.readFloat(ax.byteValue(),node.byteValue(),register);
} catch (Exception e) {
e.printStackTrace();
floatValue = null;
}
lastReadTime = System.currentTimeMillis();
}
return floatValue;
}
}
int calcHash(int ax,int node,int register)
{
return (ax << 20)|(node << 16)|register;
}
ServiceLink serviceLink;
Hashtable<Integer, IntegerCacheItem>
integerCache;
Hashtable<Integer, FloatCacheItem>
floatCache;
ServiceRegisterCache(ServiceLink serviceLink)
{
this.serviceLink = serviceLink;
this.integerCache = new Hashtable<Integer, ServiceRegisterCache.IntegerCacheItem>();
this.floatCache = new Hashtable<Integer, ServiceRegisterCache.FloatCacheItem>();
}
public synchronized Integer getCachedInteger(int ax,int node,int register)
{
int hash = calcHash(ax, node, register);
IntegerCacheItem ici = integerCache.get(hash);
if (ici == null)
{
ici = new IntegerCacheItem(ax,node,register);
integerCache.put(hash, ici);
}
return ici.intValue();
}
public synchronized Float getCachedFloat(int ax,int node,int register)
{
int hash = calcHash(ax, node, register);
FloatCacheItem ici = floatCache.get(hash);
if (ici == null)
{
ici = new FloatCacheItem(ax,node,register);
floatCache.put(hash, ici);
}
return ici.floatValue();
}
public synchronized void invalidate(int ax,int node,int register)
{
int hash = calcHash(ax, node, register);
integerCache.remove(hash);
floatCache.remove(hash);
}
}

View File

@ -1,8 +0,0 @@
package org.hwo.io.servicelink;
public interface ServiceRegisterListener {
void ServiceRegisterValueUpdated(int ax,int node,int registervalue,Integer value);
void ServiceRegisterValueUpdated(int ax,int node,int registervalue,Float value);
}