commit 67b9da31b86138c1658986a80be37d88580fc371 Author: Harald Wolff Date: Wed Dec 16 16:39:21 2015 +0100 Initial COmmit diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..b6f44cd --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6669990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +bin/* + +/bin diff --git a/.project b/.project new file mode 100644 index 0000000..1c3db16 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + org.hwo.servicelink + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..7341ab1 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/src/org/hwo/servicelink/AsynchronServiceLinkProvider.java b/src/org/hwo/servicelink/AsynchronServiceLinkProvider.java new file mode 100644 index 0000000..1fc589e --- /dev/null +++ b/src/org/hwo/servicelink/AsynchronServiceLinkProvider.java @@ -0,0 +1,85 @@ +package org.hwo.servicelink; + +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; + +public class AsynchronServiceLinkProvider { + + ServiceRegisterCache cache; + Hashtable> serviceRegisterListeners; + + public AsynchronServiceLinkProvider(ServiceRegisterCache cache){ + this.cache = cache; + this.serviceRegisterListeners = new Hashtable>(); + } + + 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 getListeners(Integer hash){ + if (!serviceRegisterListeners.containsKey(hash)) + serviceRegisterListeners.put(hash, new LinkedList()); + + 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> getServiceRegisterListeners() { + return serviceRegisterListeners; + } + public void setServiceRegisterListeners( + Hashtable> 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); + } + } + + } + } + } + } + + +} diff --git a/src/org/hwo/servicelink/ServiceLink.java b/src/org/hwo/servicelink/ServiceLink.java new file mode 100644 index 0000000..c97684d --- /dev/null +++ b/src/org/hwo/servicelink/ServiceLink.java @@ -0,0 +1,342 @@ +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 + * + * �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; + + + 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(); + } + + +} diff --git a/src/org/hwo/servicelink/ServiceLinkException.java b/src/org/hwo/servicelink/ServiceLinkException.java new file mode 100644 index 0000000..64d9ee6 --- /dev/null +++ b/src/org/hwo/servicelink/ServiceLinkException.java @@ -0,0 +1,23 @@ +package org.hwo.servicelink; + +import java.io.IOException; + +public class ServiceLinkException extends Exception { + + public ServiceLinkException() + { + } + + public ServiceLinkException(String message) + { + super(message); + } + + public ServiceLinkException(Throwable e) { + super(e); + } + + + + +} diff --git a/src/org/hwo/servicelink/ServiceLinkRequestFailedException.java b/src/org/hwo/servicelink/ServiceLinkRequestFailedException.java new file mode 100644 index 0000000..6310e6a --- /dev/null +++ b/src/org/hwo/servicelink/ServiceLinkRequestFailedException.java @@ -0,0 +1,30 @@ +package org.hwo.servicelink; + +import org.hwo.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"; + } +} diff --git a/src/org/hwo/servicelink/ServiceRegisterCache.java b/src/org/hwo/servicelink/ServiceRegisterCache.java new file mode 100644 index 0000000..bebd3e0 --- /dev/null +++ b/src/org/hwo/servicelink/ServiceRegisterCache.java @@ -0,0 +1,135 @@ +package org.hwo.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 + integerCache; + Hashtable + floatCache; + + ServiceRegisterCache(ServiceLink serviceLink) + { + this.serviceLink = serviceLink; + this.integerCache = new Hashtable(); + this.floatCache = new Hashtable(); + } + + 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); + } + +} diff --git a/src/org/hwo/servicelink/ServiceRegisterListener.java b/src/org/hwo/servicelink/ServiceRegisterListener.java new file mode 100644 index 0000000..d03f071 --- /dev/null +++ b/src/org/hwo/servicelink/ServiceRegisterListener.java @@ -0,0 +1,8 @@ +package org.hwo.servicelink; + +public interface ServiceRegisterListener { + + void ServiceRegisterValueUpdated(int ax,int node,int registervalue,Integer value); + void ServiceRegisterValueUpdated(int ax,int node,int registervalue,Float value); + +} diff --git a/src/org/hwo/servicelink/register/RegisterType.java b/src/org/hwo/servicelink/register/RegisterType.java new file mode 100644 index 0000000..af33351 --- /dev/null +++ b/src/org/hwo/servicelink/register/RegisterType.java @@ -0,0 +1,100 @@ +package org.hwo.servicelink.register; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class RegisterType implements Cloneable{ + + XPath xpath; + + String name; + String baseName; + + boolean wantsFloat; + + protected RegisterType(String name){ + this.name = name; + this.baseName = ""; + this.wantsFloat = false; + xpath = XPathFactory.newInstance().newXPath(); + } + + protected XPath getXPath(){ + return xpath; + } + + public String getBaseName() { + return baseName; + } + protected void setBaseName(String baseName) { + this.baseName = baseName; + } + public String getName() { + return name; + } + protected void setName(String name) { + this.name = name; + } + public boolean getWantsFloat() { + return wantsFloat; + } + protected void setWantsFloat(boolean wantsFloat) { + this.wantsFloat = wantsFloat; + } + + public void createFromTypeNode(Node typeNode){ + }; + + public RegisterType inherit(String newName){ + try { + RegisterType inherited = (RegisterType)this.clone(); + + inherited.setBaseName(getName()); + inherited.setName(newName); + + return inherited; + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + return null; + } + } + + public RegisterType createRegisterTypeInstance(ServiceRegisterList serviceRegisterList,Node registerNode){ + try { + Node aNode = (Node)getXPath().evaluate("Address", registerNode, XPathConstants.NODE); + RegisterType rt = inherit(String.format("%s/%s/%s",serviceRegisterList.id,getName(),aNode.getFirstChild().getNodeValue())); + return rt; + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + public String getDisplayValue(Object regValue){ + return "-- REGISTER TYPE NOT IMPLEMENTED --"; + } + + + protected java.lang.Integer valueAsInteger(Object regValue){ + if (java.lang.Integer.class.isInstance(regValue)){ + return (java.lang.Integer)regValue; + } else if (java.lang.Float.class.isInstance(regValue)){ + return ((java.lang.Float)regValue).intValue(); + }; + return null; + } + + protected java.lang.Float valueAsFloat(Object regValue){ + if (java.lang.Float.class.isInstance(regValue)){ + return (java.lang.Float)regValue; + } else if (java.lang.Integer.class.isInstance(regValue)){ + return ((java.lang.Integer)regValue).floatValue(); + }; + return null; + } + +} diff --git a/src/org/hwo/servicelink/register/RegisterTypeRegistry.java b/src/org/hwo/servicelink/register/RegisterTypeRegistry.java new file mode 100644 index 0000000..18812da --- /dev/null +++ b/src/org/hwo/servicelink/register/RegisterTypeRegistry.java @@ -0,0 +1,58 @@ +package org.hwo.servicelink.register; + +import java.util.Hashtable; + +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +public class RegisterTypeRegistry { + ServiceRegisterRegistry registry; + Hashtable registeredTypes; + + + public RegisterTypeRegistry(ServiceRegisterRegistry registry) { + this.registry = registry; + this.registeredTypes = new Hashtable(); + + + registerType(new org.hwo.servicelink.register.basetypes.Integer()); + registerType(new org.hwo.servicelink.register.basetypes.Float()); + registerType(new org.hwo.servicelink.register.basetypes.BitField()); + registerType(new org.hwo.servicelink.register.basetypes.IndexedList()); + } + + public void registerType(RegisterType registerType){ + System.err.println(String.format("RegisterTypeRegistry: New type: %s", registerType.getName())); + registeredTypes.put(registerType.getName(),registerType); + } + + void createType(Node typeNode){ + Element typeElement = (Element)typeNode; + + RegisterType baseType = registeredTypes.get(typeElement.getAttribute("basetype")); + if (baseType == null){ + throw new RuntimeException("BaseType not found: " + typeElement.getAttribute("basetype")); + } + RegisterType rt = baseType.inherit(typeElement.getAttribute("id")); + rt.createFromTypeNode(typeNode); + + registerType(rt); + } + + + public RegisterType createRegisterTypeInstance(ServiceRegisterList serviceRegisterList,Node registerNode){ + RegisterType baseType; + Element registerElement = (Element)registerNode; + String id = registerElement.getAttribute("type"); + + if (registeredTypes.containsKey(id)){ + baseType = registeredTypes.get(id); + } else { + baseType = registeredTypes.get("Integer"); + } + return baseType.createRegisterTypeInstance(serviceRegisterList, registerNode); + } + + + +} diff --git a/src/org/hwo/servicelink/register/ServiceRegisterInstance.java b/src/org/hwo/servicelink/register/ServiceRegisterInstance.java new file mode 100644 index 0000000..8e9e589 --- /dev/null +++ b/src/org/hwo/servicelink/register/ServiceRegisterInstance.java @@ -0,0 +1,45 @@ +package org.hwo.servicelink.register; + +import javax.xml.xpath.XPathConstants; + +import org.w3c.dom.Node; + +public class ServiceRegisterInstance { + ServiceRegisterList serviceRegisterList; + + RegisterType registerType; + + String label; + Integer registerAddress; + + + public ServiceRegisterInstance(ServiceRegisterList serviceRegisterList){ + this.serviceRegisterList = serviceRegisterList; + } + + public RegisterType getRegisterType() { + return registerType; + } + public void setRegisterType(RegisterType registerType) { + this.registerType = registerType; + } + + public static ServiceRegisterInstance fromRegisterNode(ServiceRegisterList serviceRegisterList,Node registerNode){ + ServiceRegisterInstance sri = new ServiceRegisterInstance(serviceRegisterList); + RegisterType rti = serviceRegisterList.getRegistry().getTypeRegistry().createRegisterTypeInstance(serviceRegisterList, registerNode); + sri.setRegisterType(rti); + + try { + Node labelNode = (Node)serviceRegisterList.getRegistry().getXpath().evaluate("Label", registerNode, XPathConstants.NODE); + Node addressNode = (Node)serviceRegisterList.getRegistry().getXpath().evaluate("Address", registerNode, XPathConstants.NODE); + sri.label = labelNode.getFirstChild().getNodeValue(); + sri.registerAddress = Integer.decode(addressNode.getFirstChild().getNodeValue()); + + } catch (Exception e){ + e.printStackTrace(); + } + + System.err.println(String.format("ServiceRegisterInstance: created type: %s", rti.getName())); + return sri; + } +} diff --git a/src/org/hwo/servicelink/register/ServiceRegisterList.java b/src/org/hwo/servicelink/register/ServiceRegisterList.java new file mode 100644 index 0000000..a48cd45 --- /dev/null +++ b/src/org/hwo/servicelink/register/ServiceRegisterList.java @@ -0,0 +1,70 @@ +package org.hwo.servicelink.register; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class ServiceRegisterList { + ServiceRegisterRegistry registry; + String label; + String id; + + List serviceRegisterInstances; + + XPath xpath; + + public ServiceRegisterList(ServiceRegisterRegistry registry){ + this.registry = registry; + this.label = "-"; + this.xpath = XPathFactory.newInstance().newXPath(); + this.serviceRegisterInstances = new ArrayList(); + } + + public ServiceRegisterRegistry getRegistry() { + return registry; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getId() { + return id; + } + public void setId(String id) { + this.id = id; + } + + public void createFromNode(Node registerListNode){ + Element registerListElement = (Element)registerListNode; + + setId(registerListElement.getAttribute("id")); + setLabel(registerListElement.getAttribute("label")); + + try { + NodeList serviceRegisterList = (NodeList)xpath.evaluate("Register", registerListNode, XPathConstants.NODESET); + for (Node registerNode: NodeListIterator.create(serviceRegisterList)){ + ServiceRegisterInstance sri = ServiceRegisterInstance.fromRegisterNode(this, registerNode); + this.serviceRegisterInstances.add(sri); + } + + + + } catch (Exception e){ + e.printStackTrace(); + } + + } + +} diff --git a/src/org/hwo/servicelink/register/ServiceRegisterListRegistry.java b/src/org/hwo/servicelink/register/ServiceRegisterListRegistry.java new file mode 100644 index 0000000..8a81b38 --- /dev/null +++ b/src/org/hwo/servicelink/register/ServiceRegisterListRegistry.java @@ -0,0 +1,37 @@ +package org.hwo.servicelink.register; + +import java.util.Hashtable; + +import org.w3c.dom.Node; + +public class ServiceRegisterListRegistry { + ServiceRegisterRegistry registry; + + Hashtable serviceRegisterLists; + + public ServiceRegisterListRegistry(ServiceRegisterRegistry registry){ + this.registry = registry; + this.serviceRegisterLists = new Hashtable(); + } + + public Hashtable getServiceRegisterLists() { + return serviceRegisterLists; + } + + public ServiceRegisterList getServiceRegisterList(String id){ + return this.serviceRegisterLists.get(id); + } + + void addServiceRegisterList(ServiceRegisterList serviceRegisterList){ + System.err.println(String.format("ServiceRegisterListRegistry: adding %s", serviceRegisterList.getId())); + this.serviceRegisterLists.put(serviceRegisterList.getId(), serviceRegisterList); + } + + public void createServiceRegisterList(Node serviceListNode){ + ServiceRegisterList list = new ServiceRegisterList(registry); + list.createFromNode(serviceListNode); + + addServiceRegisterList(list); + } + +} diff --git a/src/org/hwo/servicelink/register/ServiceRegisterRegistry.java b/src/org/hwo/servicelink/register/ServiceRegisterRegistry.java new file mode 100644 index 0000000..3a13c60 --- /dev/null +++ b/src/org/hwo/servicelink/register/ServiceRegisterRegistry.java @@ -0,0 +1,104 @@ +package org.hwo.servicelink.register; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class ServiceRegisterRegistry { + + RegisterTypeRegistry typeRegistry; + ServiceRegisterListRegistry + listRegistry; + + List loadedFiles; + XPath xpath; + + + public ServiceRegisterRegistry(){ + xpath = XPathFactory.newInstance().newXPath(); + loadedFiles = new ArrayList(); + typeRegistry = new RegisterTypeRegistry(this); + listRegistry = new ServiceRegisterListRegistry(this); + } + + public boolean loadRegistryFile(String filename){ + return loadRegistryFile(filename,new File(".").getAbsolutePath()); + } + public boolean loadRegistryFile(String filename,String basePath){ + + File f = new File(filename); + if (!f.exists()){ + f = new File(basePath,filename); + if (!f.exists()){ + System.err.println(String.format("ServiceRegisterRegistry: file not found: %s",filename)); + return false; + } + } + + if (loadedFiles.contains(filename)){ + return true; + } + loadedFiles.add(filename); + + try { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document xmlDoc = db.parse( f ); + + NodeList externalRegistryFiles = (NodeList)xpath.evaluate("/ServiceRegisterFile/ExternalRefs/File",xmlDoc, XPathConstants.NODESET); + for (Node refFile: NodeListIterator.create(externalRegistryFiles)){ + if (!loadRegistryFile(refFile.getFirstChild().getNodeValue(),f.getParent())){ + System.err.println(String.format("ServiceRegisterRegistry: failed to load %s",refFile.getFirstChild().getNodeValue())); + return false; + } + } + + NodeList typesList = (NodeList)xpath.evaluate("ServiceRegisterFile/Types/Type", xmlDoc, XPathConstants.NODESET); + for (Node typeNode: NodeListIterator.create(typesList)){ + typeRegistry.createType(typeNode); + } + + NodeList registerListsList = (NodeList)xpath.evaluate("ServiceRegisterFile/RegisterList", xmlDoc, XPathConstants.NODESET); + for (Node registerListNode: NodeListIterator.create(registerListsList)){ + listRegistry.createServiceRegisterList(registerListNode); + } + + } catch (Exception e){ + e.printStackTrace(); + return false; + } + + + System.err.println(String.format("ServiceRegisterRegistry: loaded %s", f.getAbsolutePath())); + return true; + } + + public XPath getXpath() { + return xpath; + } + + public RegisterTypeRegistry getTypeRegistry() { + return typeRegistry; + } + public ServiceRegisterListRegistry getListRegistry() { + return listRegistry; + } + + + public static void main(String[] args){ + + ServiceRegisterRegistry registry = new ServiceRegisterRegistry(); + registry.loadRegistryFile("/data/src/hf3/service-registers/serviceregisters.xml"); + + } +} diff --git a/src/org/hwo/servicelink/register/basetypes/BitField.java b/src/org/hwo/servicelink/register/basetypes/BitField.java new file mode 100644 index 0000000..c08e6a4 --- /dev/null +++ b/src/org/hwo/servicelink/register/basetypes/BitField.java @@ -0,0 +1,52 @@ +package org.hwo.servicelink.register.basetypes; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.hwo.servicelink.register.RegisterType; +import org.hwo.servicelink.register.ServiceRegisterList; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class BitField extends RegisterType{ + + org.hwo.bitfields.BitField bitfield; + + public BitField() { + super("BitField"); + this.bitfield = new org.hwo.bitfields.BitField(); + } + + @Override + public void createFromTypeNode(Node typeNode) { + try { + Node fieldsNode = (Node)getXPath().evaluate("Fields", typeNode, XPathConstants.NODE); + this.bitfield.fieldsFromXML(fieldsNode); + } catch (Exception e){ + e.printStackTrace(); + } + } + + @Override + public String getDisplayValue(Object regValue) { + return this.bitfield.toText(valueAsInteger(regValue)); + } + + @Override + public RegisterType createRegisterTypeInstance(ServiceRegisterList serviceRegisterList, Node registerNode) { + RegisterType rt = super.createRegisterTypeInstance(serviceRegisterList, registerNode); + try { + Node fieldsNode = (Node)getXPath().evaluate("Fields", registerNode, XPathConstants.NODE); + if (fieldsNode != null){ + bitfield.fieldsFromXML(fieldsNode); + } + } catch (Exception e){ + e.printStackTrace(); + } + + return rt; + } + + +} diff --git a/src/org/hwo/servicelink/register/basetypes/Float.java b/src/org/hwo/servicelink/register/basetypes/Float.java new file mode 100644 index 0000000..3e03f80 --- /dev/null +++ b/src/org/hwo/servicelink/register/basetypes/Float.java @@ -0,0 +1,17 @@ +package org.hwo.servicelink.register.basetypes; + +import org.hwo.servicelink.register.RegisterType; + +public class Float extends RegisterType { + + public Float(){ + super("Float"); + setWantsFloat(true); + } + + @Override + public String getDisplayValue(Object regValue) { + return String.format("[0x%08x] %f", java.lang.Float.floatToIntBits(valueAsFloat(regValue)),valueAsFloat(regValue)); + } + +} diff --git a/src/org/hwo/servicelink/register/basetypes/IndexedList.java b/src/org/hwo/servicelink/register/basetypes/IndexedList.java new file mode 100644 index 0000000..b5a6801 --- /dev/null +++ b/src/org/hwo/servicelink/register/basetypes/IndexedList.java @@ -0,0 +1,56 @@ +package org.hwo.servicelink.register.basetypes; + +import java.util.Hashtable; + +import javax.xml.xpath.XPathConstants; + +import org.hwo.servicelink.register.RegisterType; +import org.hwo.xml.NodeListIterator; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class IndexedList extends RegisterType { + + Hashtable listItems; + + public IndexedList(){ + super("IndexedList"); + listItems = new Hashtable(); + } + + @Override + public void createFromTypeNode(Node typeNode) { + try { + NodeList itemNodes = (NodeList)getXPath().evaluate("List/Item", typeNode, XPathConstants.NODESET); + for (Node itemNode: NodeListIterator.create(itemNodes)){ + Element itemElement = (Element)itemNode; + + java.lang.Integer ind = java.lang.Integer.parseInt( itemElement.getAttribute("index") ); + listItems.put(ind, itemElement.getFirstChild().getNodeValue()); + } + + } catch (Exception e){ + e.printStackTrace(); + } + } + + String getListItem(java.lang.Integer index){ + return listItems.get(index); + } + + Hashtable getListItems(){ + return listItems; + } + + + @Override + public String getDisplayValue(Object regValue) { + if (listItems.containsKey(valueAsInteger(regValue))){ + return listItems.get(valueAsInteger(regValue)); + } else { + return String.format("(%d)", valueAsInteger(regValue)); + } + } + +} diff --git a/src/org/hwo/servicelink/register/basetypes/Integer.java b/src/org/hwo/servicelink/register/basetypes/Integer.java new file mode 100644 index 0000000..0e2fea4 --- /dev/null +++ b/src/org/hwo/servicelink/register/basetypes/Integer.java @@ -0,0 +1,15 @@ +package org.hwo.servicelink.register.basetypes; + +import org.hwo.servicelink.register.RegisterType; + +public class Integer extends RegisterType { + + public Integer(){ + super("Integer"); + } + + @Override + public String getDisplayValue(Object regValue) { + return String.format("[0x%08x] %d", valueAsInteger(regValue),valueAsInteger(regValue)); + } +} diff --git a/src/org/hwo/ui/servicelink/ServiceLinkPlotProvider.java b/src/org/hwo/ui/servicelink/ServiceLinkPlotProvider.java new file mode 100644 index 0000000..b398ee7 --- /dev/null +++ b/src/org/hwo/ui/servicelink/ServiceLinkPlotProvider.java @@ -0,0 +1,122 @@ +package org.hwo.ui.servicelink; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.List; + +import org.hwo.ui.diagram.PlotProvider; +import org.hwo.ui.servicelink.register.ServiceRegister; + +public class ServiceLinkPlotProvider implements PlotProvider{ + + public class Plot{ + ServiceRegister serviceRegister; + Float[] values; + + public Plot(ServiceRegister serviceRegister){ + this.serviceRegister = serviceRegister; + this.values = new Float[samples]; + } + + public Float[] getSamples(){ + return this.values; + } + + public void sample(int pos){ + if (this.serviceRegister.getAsFloat()) + this.values[pos] = this.serviceRegister.readFloatValueSynchron(); + else + this.values[pos] = this.serviceRegister.readIntegerValue().floatValue(); + } + + public void resize(){ + this.values = new Float[samples]; + } + } + + private int samples; + private List plots; + + private int samplePosition; + + public ServiceLinkPlotProvider() { + this.samples = 128; + this.samplePosition = 0; + this.plots = new ArrayList(); + } + + public synchronized void resize(int size){ + + this.samples = size; + this.samplePosition = 0; + + for (Plot p: this.plots){ + p.resize(); + } + + } + + public synchronized void addPlot(ServiceRegister sr){ + Plot p = new Plot(sr); + + this.plots.add(p); + } + + public synchronized void sample(){ + for (Plot p: this.plots){ + p.sample(this.samplePosition); + } + + this.samplePosition++; + if (this.samplePosition == this.samples) + this.samplePosition = 0; + + for (Plot p: this.plots){ + p.getSamples()[this.samplePosition] = null; + } + } + + @Override + public synchronized int getPoints() { + return this.samples; + } + + @Override + public synchronized int getPlots() { + return this.plots.size(); + } + + @Override + public synchronized Float[][] getMatrix() { + Float[][] matrix = new Float[this.plots.size()][]; + + for (int i=0;i items; + + public IndexedListServiceRegister(ServiceLink serviceLink) + { + super(serviceLink,false); + editor = new IndexedListRegisterEditor(); + editor.setServiceRegister(this); + + items = new Hashtable(); + } + + @Override + public void setRegisterNode(Element registerNode) { + super.setRegisterNode(registerNode); + + Element listNode = (Element)registerNode.getElementsByTagName("List").item(0); + + LinkedList items = new LinkedList(); + + for (Element listItem: new NodeListIterator(listNode.getElementsByTagName("Item"))){ + IndexedItem item = new IndexedItem(Integer.parseInt(listItem.getAttribute("index")), listItem.getTextContent()); + items.add(item); + this.items.put(item.getIndex(), item); + } + editor.setItems(items.toArray(new IndexedItem[0])); + } + + private IndexedItem getIndexedItem(Integer index) { + if (this.items.containsKey(index)) { + return this.items.get(index); + } + IndexedItem unknown = new IndexedItem(index, "Unkown"); + return unknown; + } + + @Override + public String getTextRepresentation() { + Integer i = readIntegerValue(); + if (i == null) + return ""; + return getIndexedItem(i).toString(); + } + + @Override + public JComponent getEditorComponent() { + return editor; + } + + @Override + public void acceptEditorValue() { + editor.writeValue(); + } + + @Override + public void updateEditorValue() { + editor.readValue(); + } + +} diff --git a/src/org/hwo/ui/servicelink/register/IntegerRegisterEditor.java b/src/org/hwo/ui/servicelink/register/IntegerRegisterEditor.java new file mode 100644 index 0000000..8952f83 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/IntegerRegisterEditor.java @@ -0,0 +1,66 @@ +package org.hwo.ui.servicelink.register; + +import java.awt.Component; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.math.BigInteger; + +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.hwo.servicelink.ServiceLink; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; + +public class IntegerRegisterEditor extends JPanel implements ServiceRegisterControl { + + private ServiceRegister serviceRegister; + private JTextField tfValue; + + public IntegerRegisterEditor() + { + super(); + GridBagLayout gridBagLayout = new GridBagLayout(); + gridBagLayout.columnWidths = new int[]{0, 0}; + gridBagLayout.rowHeights = new int[]{0, 0}; + gridBagLayout.columnWeights = new double[]{1.0, Double.MIN_VALUE}; + gridBagLayout.rowWeights = new double[]{0.0, Double.MIN_VALUE}; + setLayout(gridBagLayout); + + tfValue = new JTextField(); + GridBagConstraints gbc_tfValue = new GridBagConstraints(); + gbc_tfValue.fill = GridBagConstraints.HORIZONTAL; + gbc_tfValue.gridx = 0; + gbc_tfValue.gridy = 0; + add(tfValue, gbc_tfValue); + tfValue.setColumns(10); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void setServiceRegister(ServiceRegister serviceRegister) { + this.serviceRegister = serviceRegister; + } + + @Override + public void writeValue() { + this.serviceRegister.writeIntegerValue(Integer.decode(tfValue.getText())); + } + + @Override + public void readValue() { + Integer i = this.serviceRegister.readIntegerValue(); + if ( i == null ) + i = 0; + tfValue.setText(i.toString()); + } + + @Override + public boolean requestFocusInWindow() { + return tfValue.requestFocusInWindow(); + } +} diff --git a/src/org/hwo/ui/servicelink/register/IntegerServiceRegister.java b/src/org/hwo/ui/servicelink/register/IntegerServiceRegister.java new file mode 100644 index 0000000..3d410e1 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/IntegerServiceRegister.java @@ -0,0 +1,41 @@ +package org.hwo.ui.servicelink.register; + +import javax.swing.JComponent; + +import org.hwo.servicelink.ServiceLink; + +public class IntegerServiceRegister extends ServiceRegister { + + IntegerRegisterEditor editor; + + public IntegerServiceRegister(ServiceLink serviceLink) + { + super(serviceLink,false); + editor = new IntegerRegisterEditor(); + editor.setServiceRegister(this); + } + + @Override + public String getTextRepresentation() { + Integer i = readIntegerValue(); + if (i == null) + return ""; + return String.format("0x%08x %d", i, i); + } + + @Override + public JComponent getEditorComponent() { + return editor; + } + + @Override + public void acceptEditorValue() { + editor.writeValue(); + } + + @Override + public void updateEditorValue() { + editor.readValue(); + } + +} diff --git a/src/org/hwo/ui/servicelink/register/JServiceRegisterSourceEditor.java b/src/org/hwo/ui/servicelink/register/JServiceRegisterSourceEditor.java new file mode 100644 index 0000000..cc9ed84 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/JServiceRegisterSourceEditor.java @@ -0,0 +1,160 @@ +package org.hwo.ui.servicelink.register; + +import javax.swing.JPanel; + +import java.awt.GridBagLayout; + +import javax.swing.JLabel; + +import java.awt.GridBagConstraints; + +import javax.swing.JSpinner; + +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.LinkedList; +import java.util.List; + +import javax.swing.SpinnerNumberModel; +import javax.swing.JCheckBox; +import javax.swing.event.ChangeListener; +import javax.swing.event.ChangeEvent; + +public class JServiceRegisterSourceEditor extends JPanel { + private JSpinner spRegister; + private JSpinner spNode; + private JSpinner spAx; + + private List actionListeners; + + private ServiceRegister serviceRegister; + + /** + * Create the panel. + */ + public JServiceRegisterSourceEditor() { + GridBagLayout gridBagLayout = new GridBagLayout(); + gridBagLayout.columnWidths = new int[]{0, 0, 0, 0, 0, 0, 0}; + gridBagLayout.rowHeights = new int[]{0, 0}; + gridBagLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 1.0, 0.0, 1.0, Double.MIN_VALUE}; + gridBagLayout.rowWeights = new double[]{1.0, Double.MIN_VALUE}; + setLayout(gridBagLayout); + + JLabel lblAx = new JLabel("AX:"); + GridBagConstraints gbc_lblAx = new GridBagConstraints(); + gbc_lblAx.insets = new Insets(0, 0, 0, 5); + gbc_lblAx.gridx = 0; + gbc_lblAx.gridy = 0; + add(lblAx, gbc_lblAx); + + spAx = new JSpinner(); + spAx.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + fireAction(); + } + }); + spAx.setModel(new SpinnerNumberModel(0, 0, 14, 1)); + GridBagConstraints gbc_spAx = new GridBagConstraints(); + gbc_spAx.fill = GridBagConstraints.HORIZONTAL; + gbc_spAx.insets = new Insets(0, 0, 0, 5); + gbc_spAx.gridx = 1; + gbc_spAx.gridy = 0; + add(spAx, gbc_spAx); + + JLabel lblNode = new JLabel("NODE:"); + GridBagConstraints gbc_lblNode = new GridBagConstraints(); + gbc_lblNode.insets = new Insets(0, 0, 0, 5); + gbc_lblNode.gridx = 2; + gbc_lblNode.gridy = 0; + add(lblNode, gbc_lblNode); + + spNode = new JSpinner(); + spNode.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + fireAction(); + } + }); + spNode.setModel(new SpinnerNumberModel(0, 0, 15, 1)); + GridBagConstraints gbc_spNode = new GridBagConstraints(); + gbc_spNode.fill = GridBagConstraints.HORIZONTAL; + gbc_spNode.insets = new Insets(0, 0, 0, 5); + gbc_spNode.gridx = 3; + gbc_spNode.gridy = 0; + add(spNode, gbc_spNode); + + JLabel lblRegister = new JLabel("REGISTER:"); + GridBagConstraints gbc_lblRegister = new GridBagConstraints(); + gbc_lblRegister.insets = new Insets(0, 0, 0, 5); + gbc_lblRegister.gridx = 4; + gbc_lblRegister.gridy = 0; + add(lblRegister, gbc_lblRegister); + + spRegister = new JSpinner(); + spRegister.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent e) { + fireAction(); + } + }); + spRegister.setModel(new SpinnerNumberModel(0, 0, 65535, 1)); + GridBagConstraints gbc_spRegister = new GridBagConstraints(); + gbc_spRegister.fill = GridBagConstraints.HORIZONTAL; + gbc_spRegister.gridx = 5; + gbc_spRegister.gridy = 0; + add(spRegister, gbc_spRegister); + + this.initialize(); + } + + private void initialize(){ + actionListeners = new LinkedList(); + } + + public void addActionListener(ActionListener actionListener){ + actionListeners.add(actionListener); + } + public void removeActionListener(ActionListener actionListener){ + actionListeners.remove(actionListener); + } + + public ServiceRegister getServiceRegister(){ + return this.serviceRegister; + } + public void setServiceRegister(ServiceRegister serviceRegister){ + this.serviceRegister = serviceRegister; + } + + void fireAction(){ + + if (serviceRegister != null){ + serviceRegister.setAx(getAx()); + serviceRegister.setNode(getNode()); + serviceRegister.setRegister(getRegister()); + } + + for (ActionListener l:actionListeners) + l.actionPerformed(new ActionEvent(this, 0, "")); + } + + public Integer getAx(){ + return (Integer)spAx.getValue(); + } + public void setAx(Integer value){ + spAx.setValue(value); + } + + public Integer getNode(){ + return (Integer)spNode.getValue(); + } + public void setNode(Integer value){ + spNode.setValue(value); + } + + public Integer getRegister(){ + return (Integer)spRegister.getValue(); + } + public void setRegister(Integer value){ + spAx.setValue(value); + } + +} diff --git a/src/org/hwo/ui/servicelink/register/ServiceRegister.java b/src/org/hwo/ui/servicelink/register/ServiceRegister.java new file mode 100644 index 0000000..30c9b46 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/ServiceRegister.java @@ -0,0 +1,258 @@ +package org.hwo.ui.servicelink.register; + +import java.awt.Component; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; + +import javax.swing.JComponent; + +import org.hwo.i18n.Messages; +import org.hwo.interactiveobjects.InteractiveObject; +import org.hwo.servicelink.ServiceLink; +import org.hwo.servicelink.ServiceLink.ServiceTelegram; +import org.hwo.servicelink.ServiceLinkException; +import org.hwo.servicelink.ServiceLinkRequestFailedException; +import org.hwo.servicelink.ServiceRegisterListener; +import org.hwo.models.TableMapper.TableColumn; +import org.hwo.ui.servicelink.register.bitfield.BitFieldEditor; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +@InteractiveObject(editor=ServiceRegisterEditorDialog.class) +public abstract class ServiceRegister implements ServiceRegisterListener { + + static HashMap> serviceRegisterTypes; + public static void addServiceRegisterType(String typename,Class clazz) + { + serviceRegisterTypes.put(typename, clazz); + } + + public static ServiceRegister createServiceRegister(ServiceLink serviceLink,String typeName) + { + ServiceRegister sr = null; + + Class clazz = serviceRegisterTypes.get(typeName); + if (clazz != null) + { + try { + sr = clazz.getDeclaredConstructor(ServiceLink.class).newInstance(serviceLink); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + return sr; + } + public static ServiceRegister createServiceRegister(ServiceLink serviceLink,Element registerNode) + { + ServiceRegister sr = null; + String registerType = registerNode.getAttribute("type"); + + if (registerType == null || registerType.equals("")) + registerType = "Integer"; + + sr = createServiceRegister(serviceLink, registerType); + if (sr != null) + { + sr.setRegisterNode(registerNode); + } + return sr; + } + + private Element registerNode; + + private ServiceLink serviceLink; + private Integer ax, + node, + register; + + private boolean asFloat; + + private String registerType; + private String registerName; + + protected Integer lastAsyncIntValue; + protected Float lastAsyncFloatValue; + + private ServiceRegisterControl + serviceRegisterControl; + + public ServiceRegister(ServiceLink serviceLink,boolean asFloat) + { + this.serviceLink = serviceLink; + this.asFloat = asFloat; + } + + public void dispose(){ + removeServiceRegisterListener(); + } + + private void removeServiceRegisterListener(){ + if ((this.serviceLink != null)&&(ax != null)&&(node != null)&&(register != null)) + this.serviceLink.getAsynchronServiceLinkProvider().removeServiceRegisterListener(this.ax, this.node, this.register, this.asFloat, this); + } + private void addServiceRegisterListener(){ + if ((this.serviceLink != null) &&(ax != null)&&(node != null)&&(register != null)) + this.serviceLink.getAsynchronServiceLinkProvider().addServiceRegisterListener(this.ax, this.node, this.register, this.asFloat, this); + } + + + @TableColumn(label="Bezeichnung",after="Register",width=400) + public String getRegisterName() { + return registerName; + } + public void setRegisterName(String registerName) { + this.registerName = registerName; + } + + @TableColumn(label="Register",firstColumn=true,width=80) + public Integer getRegister() { + return register; + } + public void setRegister(Integer register) { + removeServiceRegisterListener(); + this.register = register; + addServiceRegisterListener(); + } + + @TableColumn(label="Wert",after="Bezeichnung",width=250) + abstract public String getTextRepresentation(); + + abstract public JComponent getEditorComponent(); + abstract public void acceptEditorValue(); + abstract public void updateEditorValue(); + + public Element getRegisterNode() + { + return registerNode; + }; + public void setRegisterNode(Element registerNode) + { + this.registerNode = registerNode; + + if (this.registerNode != null) + { + Element labelNode = (Element)this.registerNode.getElementsByTagName("Label").item(0); + Element addressNode = (Element)this.registerNode.getElementsByTagName("Address").item(0); + + register = Integer.decode(addressNode.getTextContent()); + registerName = Messages.getString(labelNode.getTextContent()); + } + + } + + public void setAsFloat(boolean asFloat) { + removeServiceRegisterListener(); + this.asFloat = asFloat; + addServiceRegisterListener(); + } + public boolean getAsFloat() { + return this.asFloat; + } + + + public ServiceLink getServiceLink() { + return serviceLink; + } + public void setServiceLink(ServiceLink serviceLink) { + this.serviceLink = serviceLink; + } + + + public Integer getAx() { + return ax; + } + public void setAx(Integer ax) { + removeServiceRegisterListener(); + this.ax = ax; + addServiceRegisterListener(); + } + + + public Integer getNode() { + return node; + } + public void setNode(Integer node) { + removeServiceRegisterListener(); + this.node = node; + addServiceRegisterListener(); + } + + public Float readFloatValue() + { + if (lastAsyncFloatValue != null) + return lastAsyncFloatValue; + return 0.0f; + //return serviceLink.getServiceRegisterCache().getCachedFloat(ax, node, register); + } + public void writeFloatValue(Float value) + { + try + { + this.serviceLink.writeFloat(ax.byteValue(), node.byteValue(), register,value); + } catch (Exception e) + { + e.printStackTrace(); + } + } + + public Float readFloatValueSynchron() + { + try { + return serviceLink.readFloat(ax.byteValue(), node.byteValue(), register); + } catch (ServiceLinkRequestFailedException e) { + } catch (IOException e) { + } catch (ServiceLinkException e) { + } + return null; + } + + + public Integer readIntegerValue() + { + if (lastAsyncIntValue != null) + return lastAsyncIntValue; + return 0; + //return serviceLink.getServiceRegisterCache().getCachedInteger(ax, node, register); + } + public void writeIntegerValue(Integer value) + { + try + { + this.serviceLink.writeInt(ax.byteValue(), node.byteValue(), register,value); + } catch (Exception e) + { + e.printStackTrace(); + } + } + + @Override + public void ServiceRegisterValueUpdated(int ax, int node, + int registervalue, Float value) { + this.lastAsyncFloatValue = value; + } + @Override + public void ServiceRegisterValueUpdated(int ax, int node, + int registervalue, Integer value) { + this.lastAsyncIntValue = value; + } + + + static { + serviceRegisterTypes = new HashMap>(); + + serviceRegisterTypes.put("Integer", IntegerServiceRegister.class); + serviceRegisterTypes.put("Float", FloatServiceRegister.class); + serviceRegisterTypes.put("BitField", BitFieldServiceRegister.class); + serviceRegisterTypes.put("IndexedList", IndexedListServiceRegister.class); + } + +} diff --git a/src/org/hwo/ui/servicelink/register/ServiceRegisterControl.java b/src/org/hwo/ui/servicelink/register/ServiceRegisterControl.java new file mode 100644 index 0000000..3ee0d91 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/ServiceRegisterControl.java @@ -0,0 +1,20 @@ +package org.hwo.ui.servicelink.register; + +import java.awt.Component; + +import javax.tools.JavaCompiler; + +import org.hwo.servicelink.ServiceLink; + +public interface ServiceRegisterControl { + + public boolean requestFocusInWindow(); + + public Component getComponent(); + + public void setServiceRegister(ServiceRegister serviceRegister); + + public void writeValue(); + public void readValue(); + +} diff --git a/src/org/hwo/ui/servicelink/register/ServiceRegisterEditorDialog.java b/src/org/hwo/ui/servicelink/register/ServiceRegisterEditorDialog.java new file mode 100644 index 0000000..225a661 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/ServiceRegisterEditorDialog.java @@ -0,0 +1,260 @@ +package org.hwo.ui.servicelink.register; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; + +import org.hwo.interactiveobjects.IInteractiveObjectEditor; +import org.hwo.ui.KeyStrokeHelper; +import org.hwo.ui.KeyStrokeListener; +import org.hwo.ui.KeyStrokeParameters; + +import java.awt.event.ActionListener; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; +import java.awt.Insets; + +import javax.swing.border.TitledBorder; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.BoxLayout; + +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import javax.swing.JScrollPane; + +public class ServiceRegisterEditorDialog extends JDialog implements IInteractiveObjectEditor{ + + private final JPanel contentPanel = new JPanel(); + + private ServiceRegister serviceRegister; + private JTextField tfAx; + private JTextField tfNode; + private JTextField tfRegister; + private JPanel panelEditorControl; + private JTextField tfRegname; + + private KeyStrokeHelper keyStrokeHelper; + private JScrollPane scrollPane; + + /** + * Create the dialog. + */ + public ServiceRegisterEditorDialog() { + addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + if (serviceRegister != null) + serviceRegister.getEditorComponent().requestFocusInWindow(); + } + }); + setBounds(100, 100, 327, 318); + getContentPane().setLayout(new BorderLayout()); + contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + getContentPane().add(contentPanel, BorderLayout.CENTER); + GridBagLayout gbl_contentPanel = new GridBagLayout(); + gbl_contentPanel.columnWidths = new int[]{0, 0}; + gbl_contentPanel.rowHeights = new int[]{0, 0, 0}; + gbl_contentPanel.columnWeights = new double[]{1.0, Double.MIN_VALUE}; + gbl_contentPanel.rowWeights = new double[]{0.0, 1.0, Double.MIN_VALUE}; + contentPanel.setLayout(gbl_contentPanel); + { + JPanel panel = new JPanel(); + panel.setBorder(new TitledBorder(null, "Service Register", TitledBorder.LEADING, TitledBorder.TOP, null, null)); + GridBagConstraints gbc_panel = new GridBagConstraints(); + gbc_panel.insets = new Insets(0, 0, 5, 0); + gbc_panel.fill = GridBagConstraints.BOTH; + gbc_panel.gridx = 0; + gbc_panel.gridy = 0; + contentPanel.add(panel, gbc_panel); + GridBagLayout gbl_panel = new GridBagLayout(); + gbl_panel.columnWidths = new int[]{0, 0, 0}; + gbl_panel.rowHeights = new int[]{0, 0, 0, 0, 0}; + gbl_panel.columnWeights = new double[]{0.0, 1.0, Double.MIN_VALUE}; + gbl_panel.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; + panel.setLayout(gbl_panel); + { + JLabel lblAchse = new JLabel("Achse:"); + GridBagConstraints gbc_lblAchse = new GridBagConstraints(); + gbc_lblAchse.insets = new Insets(0, 0, 5, 5); + gbc_lblAchse.anchor = GridBagConstraints.EAST; + gbc_lblAchse.gridx = 0; + gbc_lblAchse.gridy = 0; + panel.add(lblAchse, gbc_lblAchse); + } + { + tfAx = new JTextField(); + tfAx.setEditable(false); + GridBagConstraints gbc_tfAx = new GridBagConstraints(); + gbc_tfAx.insets = new Insets(0, 0, 5, 0); + gbc_tfAx.fill = GridBagConstraints.HORIZONTAL; + gbc_tfAx.gridx = 1; + gbc_tfAx.gridy = 0; + panel.add(tfAx, gbc_tfAx); + tfAx.setColumns(10); + } + { + JLabel lblKnoten = new JLabel("Knoten:"); + GridBagConstraints gbc_lblKnoten = new GridBagConstraints(); + gbc_lblKnoten.anchor = GridBagConstraints.EAST; + gbc_lblKnoten.insets = new Insets(0, 0, 5, 5); + gbc_lblKnoten.gridx = 0; + gbc_lblKnoten.gridy = 1; + panel.add(lblKnoten, gbc_lblKnoten); + } + { + tfNode = new JTextField(); + tfNode.setEditable(false); + GridBagConstraints gbc_tfNode = new GridBagConstraints(); + gbc_tfNode.insets = new Insets(0, 0, 5, 0); + gbc_tfNode.fill = GridBagConstraints.HORIZONTAL; + gbc_tfNode.gridx = 1; + gbc_tfNode.gridy = 1; + panel.add(tfNode, gbc_tfNode); + tfNode.setColumns(10); + } + { + JLabel lblRegister = new JLabel("Register:"); + GridBagConstraints gbc_lblRegister = new GridBagConstraints(); + gbc_lblRegister.anchor = GridBagConstraints.EAST; + gbc_lblRegister.insets = new Insets(0, 0, 5, 5); + gbc_lblRegister.gridx = 0; + gbc_lblRegister.gridy = 2; + panel.add(lblRegister, gbc_lblRegister); + } + { + tfRegister = new JTextField(); + tfRegister.setEditable(false); + GridBagConstraints gbc_tfRegister = new GridBagConstraints(); + gbc_tfRegister.insets = new Insets(0, 0, 5, 0); + gbc_tfRegister.fill = GridBagConstraints.HORIZONTAL; + gbc_tfRegister.gridx = 1; + gbc_tfRegister.gridy = 2; + panel.add(tfRegister, gbc_tfRegister); + tfRegister.setColumns(10); + } + { + JLabel lblNewLabel = new JLabel("Bezeichnung:"); + GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); + gbc_lblNewLabel.anchor = GridBagConstraints.EAST; + gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5); + gbc_lblNewLabel.gridx = 0; + gbc_lblNewLabel.gridy = 3; + panel.add(lblNewLabel, gbc_lblNewLabel); + } + { + tfRegname = new JTextField(); + tfRegname.setEditable(false); + GridBagConstraints gbc_tfRegname = new GridBagConstraints(); + gbc_tfRegname.fill = GridBagConstraints.HORIZONTAL; + gbc_tfRegname.gridx = 1; + gbc_tfRegname.gridy = 3; + panel.add(tfRegname, gbc_tfRegname); + tfRegname.setColumns(10); + } + } + { + panelEditorControl = new JPanel(); + GridBagConstraints gbc_panelEditorControl = new GridBagConstraints(); + gbc_panelEditorControl.fill = GridBagConstraints.BOTH; + gbc_panelEditorControl.gridx = 0; + gbc_panelEditorControl.gridy = 1; + contentPanel.add(panelEditorControl, gbc_panelEditorControl); + panelEditorControl.setLayout(new BoxLayout(panelEditorControl, BoxLayout.X_AXIS)); + { + scrollPane = new JScrollPane(); + panelEditorControl.add(scrollPane); + } + } + { + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT)); + getContentPane().add(buttonPane, BorderLayout.SOUTH); + { + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + accept(); + } + }); + okButton.setActionCommand("OK"); + buttonPane.add(okButton); + getRootPane().setDefaultButton(okButton); + } + { + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + cancel(); + } + }); + cancelButton.setActionCommand("Cancel"); + buttonPane.add(cancelButton); + } + } + initialize(); + } + + private void initialize() + { + keyStrokeHelper = new KeyStrokeHelper(this.getRootPane()); + keyStrokeHelper.setFocusedWindow(true); + keyStrokeHelper.registerKeyStrokeListener(new KeyStrokeListener() { + + @Override + public void keyStroke(KeyStrokeParameters parameters) { + switch (parameters.getKeyCode()) + { + case KeyEvent.VK_ESCAPE: + cancel(); + break; + } + } + }); + keyStrokeHelper.addKeyCode(KeyEvent.VK_ESCAPE); + } + + private void accept() + { + serviceRegister.acceptEditorValue(); + setVisible(false); + } + + private void cancel() + { + setVisible(false); + } + + private void initializeView() + { + scrollPane.setViewportView(null); + if (serviceRegister != null) + { + tfAx.setText(serviceRegister.getAx().toString()); + tfNode.setText(serviceRegister.getNode().toString()); + tfRegister.setText(serviceRegister.getRegister().toString()); + tfRegname.setText(serviceRegister.getRegisterName()); + scrollPane.setViewportView(serviceRegister.getEditorComponent()); + serviceRegister.updateEditorValue(); + }; + doLayout(); + } + + @Override + public void setInteractiveObject(Object o) { + serviceRegister = (ServiceRegister)o; + initializeView(); + } + + @Override + public Object getInteractiveObject() { + return serviceRegister; + } + +} diff --git a/src/org/hwo/ui/servicelink/register/bitfield/BitFieldEditor.java b/src/org/hwo/ui/servicelink/register/bitfield/BitFieldEditor.java new file mode 100644 index 0000000..09b2d45 --- /dev/null +++ b/src/org/hwo/ui/servicelink/register/bitfield/BitFieldEditor.java @@ -0,0 +1,186 @@ +package org.hwo.ui.servicelink.register.bitfield; + +import java.awt.Component; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import javax.swing.JCheckBox; +import javax.swing.JPanel; + +import org.hwo.servicelink.ServiceLink; +import org.hwo.ui.servicelink.register.ServiceRegister; +import org.hwo.ui.servicelink.register.ServiceRegisterControl; + +import java.awt.FlowLayout; + +import javax.swing.JScrollPane; + +import java.awt.Checkbox; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; + +import javax.swing.BoxLayout; + +public class BitFieldEditor extends JPanel implements ServiceRegisterControl { + + private ServiceRegister serviceRegister; + + private JCheckBox[] checkboxes; + private JScrollPane scrollPane; + private JPanel pBits; + + private Integer intValue; + + private List fields; + + public class Field + { + int start, + len; + + String text; + + JCheckBox checkbox; + + public Field(int start,int len) + { + this.start = start; + this.len = len; + this.text = String.format("B%d",start); + } + + public Field(int start) + { + this.start = start; + this.len = 1; + this.text = String.format("B%d",start); + } + + public void setText(String text) + { + this.text = text; + } + public String getText() + { + return text; + } + + public String getTextRepresentation() + { + if (BitFieldEditor.this.getIntValue() != null) + { + if ((BitFieldEditor.this.getIntValue() & (1<(); + for (int i=0;i<32;i++) + { + Field field = new Field(i); + fields.add(field); + addFieldComponent(field.getComponent()); + } + } + + protected void removeAllFieldComponents() + { + pBits.removeAll(); + } + protected void addFieldComponent(Component component) + { + pBits.add(component); + } + + public void synchronize() + { + + } + + @Override + public Component getComponent() { + return this; + } + + + @Override + public void setServiceRegister(ServiceRegister serviceRegister) { + this.serviceRegister = serviceRegister; + } + + public Integer getIntValue() + { + return this.intValue; + } + public void setIntValue(Integer value) + { + this.intValue = value; + } + + @Override + public void writeValue() { + // TODO Auto-generated method stub + + } + + @Override + public void readValue() { + // TODO Auto-generated method stub + + } + +}