WIP161212
parent
0d07076547
commit
984dd94fd1
|
@ -3,6 +3,8 @@ package org.hwo.servicelink;
|
|||
import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import static org.hwo.logging.Logging.*;
|
||||
import static org.hwo.logging.LogLevel.*;
|
||||
|
||||
public class AsynchronServiceLinkProvider {
|
||||
|
||||
|
@ -13,23 +15,7 @@ public class AsynchronServiceLinkProvider {
|
|||
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))
|
||||
|
@ -39,10 +25,10 @@ public class AsynchronServiceLinkProvider {
|
|||
}
|
||||
|
||||
public void addServiceRegisterListener(int ax,int node,int registerno,boolean asFloat,ServiceRegisterListener listener){
|
||||
getListeners(calcRegisterHash(ax, node, registerno,asFloat)).add(listener);
|
||||
getListeners(cache.calcHash(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);
|
||||
getListeners(cache.calcHash(ax, node, registerno,asFloat)).remove(listener);
|
||||
}
|
||||
|
||||
public Hashtable<Integer, List<ServiceRegisterListener>> getServiceRegisterListeners() {
|
||||
|
@ -53,24 +39,61 @@ public class AsynchronServiceLinkProvider {
|
|||
this.serviceRegisterListeners = serviceRegisterListeners;
|
||||
}
|
||||
|
||||
public void telegramReceived(ServiceLinkTelegram telegram){
|
||||
|
||||
if ((telegram.getOpcode() & ServiceLinkTelegram.REQ_READ) != 0){
|
||||
int hash = cache.calcHash(telegram.getAddress(), ((telegram.getOpcode() & ServiceLinkTelegram.REQ_FLOAT) == ServiceLinkTelegram.REQ_FLOAT));
|
||||
log(DEBUGDETAIL,"servicelink cache update %s = %s", telegram.getAddress(), telegram.getValue());
|
||||
|
||||
cache.updateValue(hash, telegram.getValue());
|
||||
|
||||
//fireUpdates(hash);
|
||||
}
|
||||
}
|
||||
|
||||
public void fireUpdates(int hash){
|
||||
ServiceLinkAddress sla = cache.getAddress(hash);
|
||||
Object v = cache.getCachedValue(hash);
|
||||
|
||||
if (Integer.class.isInstance(v)){
|
||||
Integer i = (Integer)v;
|
||||
|
||||
for (ServiceRegisterListener listener: getListeners(hash)){
|
||||
listener.ServiceRegisterValueUpdated(sla.getAx(),sla.getNode(),sla.getRegister(),i);
|
||||
}
|
||||
}
|
||||
if (Float.class.isInstance(v)){
|
||||
Float f = (Float)v;
|
||||
|
||||
for (ServiceRegisterListener listener: getListeners(hash)){
|
||||
listener.ServiceRegisterValueUpdated(sla.getAx(),sla.getNode(),sla.getRegister(),f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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));
|
||||
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));
|
||||
for (ServiceRegisterListener listener: getListeners(hash)){
|
||||
listener.ServiceRegisterValueUpdated(axFromHash(hash),nodeFromHash(hash),regFromHash(hash),i);
|
||||
}
|
||||
|
||||
cache.updateValue(hash);
|
||||
fireUpdates(hash);
|
||||
|
||||
/*
|
||||
int opcode = ServiceLinkTelegram.REQ_READ;
|
||||
if ((hash & 0x40000000)!=0){
|
||||
opcode |= ServiceLinkTelegram.REQ_FLOAT;
|
||||
}
|
||||
|
||||
ServiceLinkTelegram telegram = cache.getServiceLink().createTelegram(cache.axFromHash(hash), cache.nodeFromHash(hash), cache.regFromHash(hash), opcode, null);
|
||||
|
||||
log(DEBUGDETAIL,"non-pending request: %s", telegram.getAddress() );
|
||||
|
||||
cache.getServiceLink().queueRequestNonPending(telegram);
|
||||
|
||||
cache.getServiceLink().queueRequest(telegram);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.hwo.servicelink;
|
|||
|
||||
import static org.hwo.logging.Logging.log;
|
||||
|
||||
import java.awt.DisplayMode;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
|
@ -64,7 +65,7 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
|
||||
public ServiceLink(NewSerialPort serialPort)
|
||||
{
|
||||
this.requestTimeOut = 500;
|
||||
this.requestTimeOut = 50;
|
||||
|
||||
this.serviceLinkListeners = new LinkedList<ServiceLinkListener>();
|
||||
this.retries = 3;
|
||||
|
@ -142,6 +143,13 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
|
||||
/** Handling der Queues **/
|
||||
|
||||
public boolean isUseV2() {
|
||||
return useV2;
|
||||
}
|
||||
public void setUseV2(boolean useV2) {
|
||||
this.useV2 = useV2;
|
||||
}
|
||||
|
||||
private void addPendingRequest(ServiceLinkTelegram request){
|
||||
synchronized (pendingRequests) {
|
||||
if (!pendingRequests.containsKey(request.getAddress())){
|
||||
|
@ -174,7 +182,16 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
removePendingRequest(request);
|
||||
}
|
||||
|
||||
public void queueRequestNonPending(ServiceLinkTelegram request){
|
||||
synchronized (txQueue) {
|
||||
txQueue.add(request);
|
||||
txQueue.notify();
|
||||
}
|
||||
}
|
||||
|
||||
public void queueRequest(ServiceLinkTelegram request){
|
||||
long ts_start = System.currentTimeMillis();
|
||||
|
||||
appendRequest(request);
|
||||
|
||||
synchronized (request) {
|
||||
|
@ -187,6 +204,8 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
|
||||
removeRequest(request);
|
||||
|
||||
requestTime.cycle( (int)(System.currentTimeMillis() - ts_start) );
|
||||
|
||||
log(DEBUG,"ServiceLink: queuedRequest: %s Value: %s",request.getAddress().toString(),request.value);
|
||||
|
||||
}
|
||||
|
@ -197,15 +216,21 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
if (pendingRequests.containsKey(rx.getAddress())){
|
||||
for (ServiceLinkTelegram pending: pendingRequests.get(rx.getAddress())){
|
||||
log(DEBUGDETAIL,"Found Pending: %s", pending);
|
||||
|
||||
if ((pending.getOpcode() & (REQ_INT | REQ_FLOAT))==(rx.getOpcode() & (REQ_INT | REQ_FLOAT))){
|
||||
synchronized (pending) {
|
||||
pending.setValue(rx.getValue());
|
||||
|
||||
log(DEBUGDETAIL,"req.handling time: %d",rx.getTimestamp() - pending.getTimestamp());
|
||||
|
||||
pending.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asynchronServiceLinkProvider.telegramReceived(rx);
|
||||
}
|
||||
|
||||
/** ENDE: Handling der Queues **/
|
||||
|
@ -253,6 +278,15 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
serialPort.close();
|
||||
}
|
||||
|
||||
public ServiceLinkTelegram createTelegram(int achse,int knoten,int register,int opcode,Object value){
|
||||
|
||||
ServiceLinkTelegram request = useV2 ?
|
||||
new ServiceLinkV2Telegram(opcode, achse, knoten, register, value) :
|
||||
new ServiceLinkV1Telegram(opcode, achse, knoten, register, value);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public Integer readInt(int achse,int knoten,int register) throws IOException, ServiceLinkException, ServiceLinkRequestFailedException
|
||||
{
|
||||
ServiceLinkTelegram request = useV2 ?
|
||||
|
@ -397,6 +431,13 @@ public class ServiceLink implements NewSerialPortListener {
|
|||
try {
|
||||
log(DEBUGDETAIL,"TX BYTES: %s",ByteArrayHexlifier.byteArrayToString(txbytes));
|
||||
serialPort.getOutputStream().write(txbytes);
|
||||
|
||||
/* try {
|
||||
sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
log(e);
|
||||
}
|
||||
*/
|
||||
} catch (IOException e) {
|
||||
log(e);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,10 @@ public abstract class ServiceLinkTelegram {
|
|||
Object
|
||||
value;
|
||||
|
||||
long timestamp;
|
||||
|
||||
protected ServiceLinkTelegram(){
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected ServiceLinkTelegram(int operation,int achse,int knoten,int register,Object value){
|
||||
|
@ -34,6 +37,8 @@ public abstract class ServiceLinkTelegram {
|
|||
this.value = value;
|
||||
|
||||
this.checkPlausible();
|
||||
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
private void checkPlausible(){
|
||||
|
@ -85,5 +90,8 @@ public abstract class ServiceLinkTelegram {
|
|||
return (getAddress().getAx()==0) && (getAddress().getNode()==0) && (getAddress().getRegister()==0) && (opcode == 0) && value.equals(0);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,10 +54,8 @@ public class ServiceLinkV2Telegram extends ServiceLinkTelegram {
|
|||
ByteBuffer bb = ByteBuffer.wrap(buffer);
|
||||
|
||||
if ((op & REQ_FLOAT)==REQ_FLOAT){
|
||||
log(DEBUGDETAIL,"############################################################");
|
||||
setValue( bb.order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer().get(1) );
|
||||
} else {
|
||||
log(DEBUGDETAIL,"*************************************************************");
|
||||
setValue( bb.order(ByteOrder.LITTLE_ENDIAN).asIntBuffer().get(1) );
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.hwo.servicelink;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import static org.hwo.logging.Logging.*;
|
||||
import static org.hwo.logging.LogLevel.*;
|
||||
|
||||
public class ServiceRegisterCache {
|
||||
|
||||
|
@ -11,13 +13,27 @@ public class ServiceRegisterCache {
|
|||
node,
|
||||
register;
|
||||
|
||||
boolean isFloat;
|
||||
|
||||
long lastReadTime;
|
||||
|
||||
public BaseCacheItem(int ax,int node,int register)
|
||||
Object value;
|
||||
|
||||
public BaseCacheItem(int hash){
|
||||
this.ax = axFromHash(hash);
|
||||
this.node = nodeFromHash(hash);
|
||||
this.register = regFromHash(hash);
|
||||
this.isFloat = ((hash & 0x40000000) != 0);
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
public BaseCacheItem(int ax,int node,int register, boolean isFloat)
|
||||
{
|
||||
this.ax = ax;
|
||||
this.node = node;
|
||||
this.register = register;
|
||||
this.isFloat = isFloat;
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
long age()
|
||||
|
@ -29,107 +45,123 @@ public class ServiceRegisterCache {
|
|||
{
|
||||
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()
|
||||
{
|
||||
private void fetchValue(){
|
||||
if (isOld() && serviceLink.isOpen())
|
||||
{
|
||||
try {
|
||||
intValue = serviceLink.readInt(ax.byteValue(),node.byteValue(),register);
|
||||
if (isFloat){
|
||||
Float f = serviceLink.readFloat(ax.byteValue(),node.byteValue(),register);
|
||||
} else {
|
||||
Integer i = serviceLink.readInt(ax.byteValue(),node.byteValue(),register);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
intValue = null;
|
||||
}
|
||||
lastReadTime = System.currentTimeMillis();
|
||||
}
|
||||
return intValue;
|
||||
}
|
||||
|
||||
public Object getValue(){
|
||||
if (isOld())
|
||||
fetchValue();
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value){
|
||||
this.value = value;
|
||||
this.lastReadTime = System.currentTimeMillis();
|
||||
log(DEBUGDETAIL,"cached value update: [%02d:%02d:%04d] = %s", ax,node,register,value);
|
||||
}
|
||||
|
||||
public void invalidate(){
|
||||
this.lastReadTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class FloatCacheItem extends BaseCacheItem
|
||||
{
|
||||
public FloatCacheItem(int ax,int node,int register)
|
||||
{
|
||||
super(ax,node,register);
|
||||
floatValue = null;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
public Integer axFromHash(Integer hash){
|
||||
return (hash >> 20) & 0x0F;
|
||||
}
|
||||
public Integer nodeFromHash(Integer hash){
|
||||
return (hash >> 16) & 0x0F;
|
||||
}
|
||||
public Integer regFromHash(Integer hash){
|
||||
return (hash) & 0xFFFF;
|
||||
}
|
||||
|
||||
int calcHash(int ax,int node,int register)
|
||||
public int calcHash(int ax,int node,int register,boolean isFloat)
|
||||
{
|
||||
return (ax << 20)|(node << 16)|register;
|
||||
return (isFloat ? 0x40000000 : 0) | (ax << 20) | (node << 16) | register;
|
||||
}
|
||||
|
||||
public int calcHash(ServiceLinkAddress sla,boolean isFloat){
|
||||
Integer hash = (sla.getAx() << 20) | (sla.getNode() << 16) | sla.getRegister();
|
||||
if (isFloat)
|
||||
hash |= 0x40000000;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public ServiceLinkAddress getAddress(int hash){
|
||||
return new ServiceLinkAddress( axFromHash(hash), nodeFromHash(hash), regFromHash(hash) );
|
||||
}
|
||||
|
||||
ServiceLink serviceLink;
|
||||
|
||||
Hashtable<Integer, IntegerCacheItem>
|
||||
integerCache;
|
||||
Hashtable<Integer, FloatCacheItem>
|
||||
floatCache;
|
||||
Hashtable<Integer, BaseCacheItem>
|
||||
cache;
|
||||
|
||||
ServiceRegisterCache(ServiceLink serviceLink)
|
||||
{
|
||||
this.serviceLink = serviceLink;
|
||||
this.integerCache = new Hashtable<Integer, ServiceRegisterCache.IntegerCacheItem>();
|
||||
this.floatCache = new Hashtable<Integer, ServiceRegisterCache.FloatCacheItem>();
|
||||
this.cache = new Hashtable<>();
|
||||
}
|
||||
|
||||
public ServiceLink getServiceLink() {
|
||||
return serviceLink;
|
||||
}
|
||||
|
||||
private BaseCacheItem getCacheItem(int hash){
|
||||
BaseCacheItem bci;
|
||||
|
||||
if (!cache.contains(hash)){
|
||||
cache.put(hash, new BaseCacheItem(hash));
|
||||
}
|
||||
return cache.get(hash);
|
||||
}
|
||||
|
||||
public void updateValue(int hash){
|
||||
BaseCacheItem bci = getCacheItem(hash);
|
||||
bci.invalidate();
|
||||
bci.getValue();
|
||||
}
|
||||
|
||||
public void updateValue(int hash,Object value){
|
||||
getCacheItem(hash).setValue(value);
|
||||
}
|
||||
|
||||
public synchronized Object getCachedValue(int hash){
|
||||
return getCacheItem(hash).getValue();
|
||||
}
|
||||
public synchronized Object getCachedValue(int ax,int node,int register,boolean isFloat){
|
||||
int hash = calcHash(ax, node, register, isFloat);
|
||||
return getCacheItem(hash).getValue();
|
||||
}
|
||||
|
||||
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();
|
||||
return (Integer)getCachedValue(ax, node, register, false);
|
||||
}
|
||||
|
||||
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();
|
||||
return (Float)getCachedValue(ax, node, register, true);
|
||||
}
|
||||
|
||||
public synchronized void invalidate(int ax,int node,int register)
|
||||
public synchronized void invalidate(int ax,int node,int register,boolean isFloat)
|
||||
{
|
||||
int hash = calcHash(ax, node, register);
|
||||
integerCache.remove(hash);
|
||||
floatCache.remove(hash);
|
||||
cache.remove(calcHash(ax, node, register,isFloat));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue