diff --git a/OPC_Client_Utgard/.classpath b/OPC_Client_Utgard/.classpath index 7136062..850c2f7 100644 --- a/OPC_Client_Utgard/.classpath +++ b/OPC_Client_Utgard/.classpath @@ -1,10 +1,19 @@ - - - - - + + + + + + + + + + + + + + diff --git a/OPC_Client_Utgard/pom.xml b/OPC_Client_Utgard/pom.xml index e23bae9..25e983b 100644 --- a/OPC_Client_Utgard/pom.xml +++ b/OPC_Client_Utgard/pom.xml @@ -4,27 +4,6 @@ com.freud.opc OPC_Client_Utgard 0.0.1-SNAPSHOT - - src - - - src - - **/*.java - - - - - - maven-compiler-plugin - 3.0 - - 1.6 - 1.6 - - - - @@ -37,6 +16,18 @@ j-interop 2.0.5 + + + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + + org.openscada.utgard + org.openscada.opc.lib + 1.1.0.v20130529 + \ No newline at end of file diff --git a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest4.java b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest4.java index 390f9be..ebb3a93 100644 --- a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest4.java +++ b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest4.java @@ -44,7 +44,6 @@ public class OPCTest4 { access.addItem("Random.Real5", new DataCallback() { private int i; - @Override public void changed(Item item, ItemState itemstate) { System.out.println("[" + (++i) + "],ItemName:[" + item.getId() + "],value:" + itemstate.getValue()); diff --git a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest5.java b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest5.java index d37edba..0a6c705 100644 --- a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest5.java +++ b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest5.java @@ -45,7 +45,6 @@ public class OPCTest5 { private int count; - @Override public void changed(Item item, ItemState itemstate) { System.out.println("[" + (++count) + "],ItemName:[" + item.getId() + "],value:" + itemstate.getValue()); diff --git a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest6.java b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest6.java index 3685d6b..593877d 100644 --- a/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest6.java +++ b/OPC_Client_Utgard/src/main/java/com/freud/opc/utgard/cases/OPCTest6.java @@ -47,7 +47,6 @@ public class OPCTest6 { access.addItem("Random.Real5", new DataCallback() { private int i; - @Override public void changed(Item item, ItemState itemstate) { System.out.println("[" + (++i) + "],ItemName:[" + item.getId() + "],value:" + itemstate.getValue()); diff --git a/OPC_Client_Utgard_Performance/.classpath b/OPC_Client_Utgard_Performance/.classpath index 015fbd2..7ed68b1 100644 --- a/OPC_Client_Utgard_Performance/.classpath +++ b/OPC_Client_Utgard_Performance/.classpath @@ -1,10 +1,19 @@ - - - - - + + + + + + + + + + + + + + diff --git a/OPC_Client_Utgard_Performance/.project b/OPC_Client_Utgard_Performance/.project index c6b1fe4..f83eb1b 100644 --- a/OPC_Client_Utgard_Performance/.project +++ b/OPC_Client_Utgard_Performance/.project @@ -3,6 +3,8 @@ OPC_Client_Utgard_Performance + org.openscada.opc.dcom + org.openscada.opc.lib diff --git a/OPC_Client_Utgard_Performance/lib/org.openscada.opc.dcom_1.1.0.v20130529.jar b/OPC_Client_Utgard_Performance/lib/org.openscada.opc.dcom_1.1.0.v20130529.jar deleted file mode 100644 index 11bbdf7..0000000 Binary files a/OPC_Client_Utgard_Performance/lib/org.openscada.opc.dcom_1.1.0.v20130529.jar and /dev/null differ diff --git a/OPC_Client_Utgard_Performance/lib/org.openscada.opc.lib_1.1.0.v20130529.jar b/OPC_Client_Utgard_Performance/lib/org.openscada.opc.lib_1.1.0.v20130529.jar deleted file mode 100644 index 620e03a..0000000 Binary files a/OPC_Client_Utgard_Performance/lib/org.openscada.opc.lib_1.1.0.v20130529.jar and /dev/null differ diff --git a/OPC_Client_Utgard_Performance/pom.xml b/OPC_Client_Utgard_Performance/pom.xml index 8e675c7..0d13b2a 100644 --- a/OPC_Client_Utgard_Performance/pom.xml +++ b/OPC_Client_Utgard_Performance/pom.xml @@ -4,28 +4,8 @@ com.freud.opc OPC_Client_Utgard_Performance 0.0.1-SNAPSHOT - - src - - - maven-compiler-plugin - 3.0 - - 1.6 - 1.6 - - - - - org.slf4j slf4j-log4j12 @@ -42,6 +22,18 @@ j-interop 2.0.5 + + + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + + org.openscada.utgard + org.openscada.opc.lib + 1.1.0.v20130529 + \ No newline at end of file diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/dcom/perf/SyncPerfTest.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/dcom/perf/SyncPerfTest.java index 8554936..ea0f5a7 100644 --- a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/dcom/perf/SyncPerfTest.java +++ b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/dcom/perf/SyncPerfTest.java @@ -47,8 +47,8 @@ public class SyncPerfTest { OPCGroupStateMgt group = server.addGroup("", true, 1000, 1234, 0, 0.0f, 1033); - //group.getSyncIO().read(source, serverHandles) - + // group.getSyncIO().read(source, serverHandles) + OPCITEMDEF item = new OPCITEMDEF(); item.setActive(true); @@ -57,18 +57,13 @@ public class SyncPerfTest { group.attach(new IOPCDataCallback() { - @Override public void writeComplete(int arg0, int arg1, int arg2, ResultSet arg3) { } - - @Override public void readComplete(int arg0, int arg1, int arg2, int arg3, KeyedResultSet arg4) { } - - @Override public void dataChange(int arg0, int arg1, int arg2, int arg3, KeyedResultSet items) { for (KeyedResult item : items) { @@ -76,8 +71,6 @@ public class SyncPerfTest { + item.getValue()); } } - - @Override public void cancelComplete(int arg0, int arg1) { } diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncMultiThreadTest.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncMultiThreadTest.java new file mode 100644 index 0000000..9c72ab8 --- /dev/null +++ b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncMultiThreadTest.java @@ -0,0 +1,118 @@ +package com.freud.opc.utgard.perf; + +import static com.freud.opc.utgard.perf.config.ConfigReader.config; + +import java.util.Date; +import java.util.concurrent.Executors; + +import org.apache.commons.logging.Log; +import org.apache.log4j.Logger; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.da.IOPCDataCallback; +import org.openscada.opc.dcom.da.OPCDATASOURCE; +import org.openscada.opc.dcom.da.ValueData; +import org.openscada.opc.dcom.da.impl.OPCAsyncIO2; +import org.openscada.opc.lib.common.NotConnectedException; +import org.openscada.opc.lib.da.Group; +import org.openscada.opc.lib.da.Item; +import org.openscada.opc.lib.da.Server; + +public class AsyncMultiThreadTest { + + private static final int count = 50; + + public static void main(String[] args) throws Exception { + for (int i = 1; i <= count; i++) { + new Thread(new AsyncMulti(i)).start(); + } + } +} + +class AsyncMulti implements Runnable { + + private static Logger LOGGER = Logger.getLogger(AsyncMulti.class); + + private static final int NUMBER = 4000; + private int count_number; + + private static long start; + private static long read; + private static long end; + + public AsyncMulti(int count_number) { + this.count_number = count_number; + } + + public void run() { + try { + start = System.currentTimeMillis(); + + LOGGER.info("Step-" + count_number * NUMBER + " site:"); + LOGGER.info("StartDate[" + new Date() + "],CurrentMillis:" + start); + + Server server = new Server(config(), + Executors.newScheduledThreadPool(4)); + + server.connect(); + + final Group group = server.addGroup("Group-" + count_number); + group.setActive(true); + Item[] items = new Item[NUMBER]; + + for (int i = (count_number - 1) * NUMBER; i < count_number * NUMBER; i++) { + items[i % NUMBER] = group.addItem("Random.Int" + i); + } + + read = System.currentTimeMillis(); + group.attach(new IOPCDataCallback() { + + public void writeComplete(int arg0, int arg1, int arg2, + ResultSet arg3) { + } + + public void readComplete(int arg0, int arg1, int arg2, + int arg3, KeyedResultSet arg4) { + } + + public void dataChange(int arg0, int arg1, int arg2, int arg3, + KeyedResultSet result) { + int i = 0; + for (final KeyedResult entry : result) { + i++; + } + + if (i == NUMBER) { + end = System.currentTimeMillis(); + LOGGER.info("Total Use[" + (end - start) + + "] and Async Read[" + (end - read) + "]"); + } + + } + + public void cancelComplete(int arg0, int arg1) { + } + }); + + final OPCAsyncIO2 async20 = group.getAsyncIO20(); + if (async20 == null) { + throw new NotConnectedException(); + } + + group.getAsyncIO20().refresh(OPCDATASOURCE.OPC_DS_CACHE, 0); + + group.setActive(false); + + Thread.sleep(3000); + + group.clear(); + group.remove(); + + server.disconnect(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncOPCPerfTest.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncOPCPerfTest.java index c46dc91..f035278 100644 --- a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncOPCPerfTest.java +++ b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/AsyncOPCPerfTest.java @@ -3,7 +3,6 @@ package com.freud.opc.utgard.perf; import static com.freud.opc.utgard.perf.config.ConfigReader.config; import java.util.Date; -import java.util.Iterator; import java.util.concurrent.Executors; import org.apache.log4j.Logger; @@ -16,18 +15,19 @@ import org.openscada.opc.dcom.da.ValueData; import org.openscada.opc.dcom.da.impl.OPCAsyncIO2; import org.openscada.opc.lib.common.NotConnectedException; import org.openscada.opc.lib.da.Group; +import org.openscada.opc.lib.da.Item; import org.openscada.opc.lib.da.Server; public class AsyncOPCPerfTest { private static Logger LOGGER = Logger.getLogger(AsyncOPCPerfTest.class); - private static final int NUMBER = 10; - private static final int count = 1; - public static long start; - - public static void main(String[] args) throws Exception { + private static final int count = 4000; + private static long start; + private static long read; + private static long end; + private static void testSteps(final int count) throws Exception { start = System.currentTimeMillis(); LOGGER.info("Step-" + count + "W:"); @@ -38,62 +38,61 @@ public class AsyncOPCPerfTest { server.connect(); - Group group = server.addGroup("Freud"); - // AsyncResult result = group.getAsyncIO20().read(transactionId, - // serverHandles); + Group group = server.addGroup("Group"); + group.setActive(true); + Item[] items = new Item[count]; - group.addItem("Read Error.Int1"); - group.addItem("Random.Int1"); - - OPCAsyncIO2 async20 = group.getAsyncIO20(); - - if (async20 == null) - throw new NotConnectedException(); - async20.refresh(OPCDATASOURCE.OPC_DS_DEVICE, 0); + for (int i = 1; i <= count; i++) { + items[i - 1] = group.addItem("Random.Int" + i); + } + read = System.currentTimeMillis(); group.attach(new IOPCDataCallback() { - @Override public void writeComplete(int arg0, int arg1, int arg2, ResultSet arg3) { - System.out.println("Write Complete"); } - @Override public void readComplete(int arg0, int arg1, int arg2, int arg3, KeyedResultSet arg4) { - System.out.println("Read Complete"); } - @Override public void dataChange(int arg0, int arg1, int arg2, int arg3, - KeyedResultSet arg4) { - Iterator> ite = arg4.iterator(); + KeyedResultSet result) { int i = 0; - while (ite.hasNext()) { - KeyedResult value = ite.next(); - System.out.println((++i) + "-" + value.getKey() + "--" - + value.getValue().getValue()); + for (final KeyedResult entry : result) { + i++; + } + + if (i == count) { + end = System.currentTimeMillis(); + LOGGER.info("Total Use[" + (end - start) + + "] and Async Read[" + (end - read) + "]"); } } - @Override public void cancelComplete(int arg0, int arg1) { - System.out.println("Cancel Complete"); } }); - // AccessBase access = new SyncAccess(server, 1000); - // - // int limit = count * NUMBER; - // for (int i = 0; i < limit; i++) { - // access.addItem("Random.Real" + i, new DataCallBackListener(limit)); - // } - // - // access.bind(); - Thread.sleep(100000); - // access.unbind(); + final OPCAsyncIO2 async20 = group.getAsyncIO20(); + if (async20 == null) { + throw new NotConnectedException(); + } - server.dispose(); + group.getAsyncIO20().refresh(OPCDATASOURCE.OPC_DS_CACHE, 0); + + group.setActive(false); + + Thread.sleep(3000); + + group.clear(); + group.remove(); + + server.disconnect(); + } + + public static void main(String[] args) throws Exception { + testSteps(count); } } diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/PublishOPCPerfTest.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/PublishOPCPerfTest.java index 843cda7..5c50267 100644 --- a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/PublishOPCPerfTest.java +++ b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/PublishOPCPerfTest.java @@ -3,7 +3,6 @@ package com.freud.opc.utgard.perf; import static com.freud.opc.utgard.perf.config.ConfigReader.config; import java.util.Date; -import java.util.Map; import java.util.concurrent.Executors; import org.apache.log4j.Logger; @@ -11,16 +10,14 @@ import org.openscada.opc.dcom.common.KeyedResultSet; import org.openscada.opc.dcom.common.ResultSet; import org.openscada.opc.dcom.da.IOPCDataCallback; import org.openscada.opc.dcom.da.ValueData; -import org.openscada.opc.lib.da.Async20Access; import org.openscada.opc.lib.da.Group; -import org.openscada.opc.lib.da.Item; import org.openscada.opc.lib.da.Server; public class PublishOPCPerfTest { private static Logger LOGGER = Logger.getLogger(PublishOPCPerfTest.class); - private static final int NUMBER = 10000; + //private static final int NUMBER = 10000; private static final int WAN_NUMBER = 1; public static void main(String[] args) throws Exception { @@ -42,27 +39,23 @@ public class PublishOPCPerfTest { Group group = server.addGroup("Group"); - Map map = group.addItems("Random.int" + 1); + //Map map = group.addItems("Random.int" + 1); group.attach(new IOPCDataCallback() { - @Override public void writeComplete(int i, int j, int k, ResultSet resultset) { } - @Override public void readComplete(int i, int j, int k, int l, KeyedResultSet keyedresultset) { } - @Override public void dataChange(int i, int j, int k, int l, KeyedResultSet keyedresultset) { System.out.println("DataChanged"); } - @Override public void cancelComplete(int i, int j) { } }); diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/Test.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/Test.java deleted file mode 100644 index 9af9079..0000000 --- a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/Test.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.freud.opc.utgard.perf; - -import static com.freud.opc.utgard.perf.config.ConfigReader.config; - -import java.util.Date; -import java.util.concurrent.Executors; - -import org.apache.log4j.Logger; -import org.openscada.opc.dcom.common.KeyedResultSet; -import org.openscada.opc.dcom.common.ResultSet; -import org.openscada.opc.dcom.da.IOPCDataCallback; -import org.openscada.opc.dcom.da.ValueData; -import org.openscada.opc.lib.da.Group; -import org.openscada.opc.lib.da.Item; -import org.openscada.opc.lib.da.Server; - -public class Test { - private static Logger LOGGER = Logger.getLogger(Test.class); - - public static void main(String[] args) throws Exception { - long start = System.currentTimeMillis(); - - LOGGER.info("Step-" + 10 + "W:"); - LOGGER.info("StartDate[" + new Date() + "],CurrentMillis:" + start); - - Server server = new Server(config(), - Executors.newSingleThreadScheduledExecutor()); - - server.connect(); - - Group group = server.addGroup(); - Item item = group.addItem("Random.int4"); - - group.setActive(true); - group.setActive(true, item); - - group.attach(new IOPCDataCallback() { - - @Override - public void writeComplete(int i, int j, int k, - ResultSet resultset) { - System.out.println("Write Complete"); - } - - @Override - public void readComplete(int i, int j, int k, int l, - KeyedResultSet keyedresultset) { - System.out.println("Read Complete"); - } - - @Override - public void dataChange(int i, int j, int k, int l, - KeyedResultSet keyedresultset) { - System.out.println("Data change"); - } - - @Override - public void cancelComplete(int i, int j) { - System.out.println("Cancel Complete"); - } - }); - - Thread.sleep(10 * 1000); - - server.disconnect(); - } -} diff --git a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/common/DataCallBackListener.java b/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/common/DataCallBackListener.java deleted file mode 100644 index de43598..0000000 --- a/OPC_Client_Utgard_Performance/src/main/java/com/freud/opc/utgard/perf/common/DataCallBackListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.freud.opc.utgard.perf.common; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.apache.log4j.Logger; -import org.openscada.opc.lib.da.DataCallback; -import org.openscada.opc.lib.da.Item; -import org.openscada.opc.lib.da.ItemState; - -import com.freud.opc.utgard.perf.AsyncOPCPerfTest; - -public class DataCallBackListener implements DataCallback { - - private static Logger LOGGER = Logger.getLogger(DataCallBackListener.class); - - private static List items = new ArrayList(); - - private int size; - - public DataCallBackListener(int size) { - this.size = size; - } - - @Override - public void changed(Item item, ItemState is) { - LOGGER.info("Item:[" + item.getId() + "], Value:[" + is.getValue() - + "]"); - items.add(item.getId()); - if (items.size() == size) { - long end = System.currentTimeMillis(); - LOGGER.info("EndDate[" + new Date() + "],CurrentMillis:" + end); - LOGGER.info("Total Spend:[" + (end - AsyncOPCPerfTest.start) + "]"); - System.exit(0); - } - } -} diff --git a/OPC_Client_Utgard_Performance/utgard_result.log b/OPC_Client_Utgard_Performance/utgard_result.log index 932497f..0d0b535 100644 --- a/OPC_Client_Utgard_Performance/utgard_result.log +++ b/OPC_Client_Utgard_Performance/utgard_result.log @@ -1,12 +1,101 @@ -2014-12-09 10:18:20,882-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:18:20,885-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:18:20 CST 2014],CurrentMillis:1418091500881 -2014-12-09 10:18:38,649-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:18:38,651-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:18:38 CST 2014],CurrentMillis:1418091518648 -2014-12-09 10:19:05,380-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:19:05,382-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:19:05 CST 2014],CurrentMillis:1418091545379 -2014-12-09 10:21:34,695-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:21:34,698-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:21:34 CST 2014],CurrentMillis:1418091694695 -2014-12-09 10:23:48,822-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:23:48,824-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:23:48 CST 2014],CurrentMillis:1418091828821 -2014-12-09 10:27:05,952-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: -2014-12-09 10:27:05,955-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:27:05 CST 2014],CurrentMillis:1418092025952 +2014-12-10 17:39:43,078-[TS] INFO Thread-0 com.freud.opc.utgard.perf.AsyncMulti - Step-4000 site: +2014-12-10 17:39:43,078-[TS] INFO Thread-1 com.freud.opc.utgard.perf.AsyncMulti - Step-8000 site: +2014-12-10 17:39:43,079-[TS] INFO Thread-3 com.freud.opc.utgard.perf.AsyncMulti - Step-16000 site: +2014-12-10 17:39:43,081-[TS] INFO Thread-0 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383078 +2014-12-10 17:39:43,082-[TS] INFO Thread-1 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383078 +2014-12-10 17:39:43,085-[TS] INFO Thread-3 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383078 +2014-12-10 17:39:43,086-[TS] INFO Thread-4 com.freud.opc.utgard.perf.AsyncMulti - Step-20000 site: +2014-12-10 17:39:43,086-[TS] INFO Thread-4 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383086 +2014-12-10 17:39:43,086-[TS] INFO Thread-5 com.freud.opc.utgard.perf.AsyncMulti - Step-24000 site: +2014-12-10 17:39:43,087-[TS] INFO Thread-5 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383086 +2014-12-10 17:39:43,087-[TS] INFO Thread-7 com.freud.opc.utgard.perf.AsyncMulti - Step-32000 site: +2014-12-10 17:39:43,087-[TS] INFO Thread-7 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383087 +2014-12-10 17:39:43,088-[TS] INFO Thread-8 com.freud.opc.utgard.perf.AsyncMulti - Step-36000 site: +2014-12-10 17:39:43,088-[TS] INFO Thread-8 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383088 +2014-12-10 17:39:43,088-[TS] INFO Thread-9 com.freud.opc.utgard.perf.AsyncMulti - Step-40000 site: +2014-12-10 17:39:43,088-[TS] INFO Thread-9 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383088 +2014-12-10 17:39:43,089-[TS] INFO Thread-2 com.freud.opc.utgard.perf.AsyncMulti - Step-12000 site: +2014-12-10 17:39:43,089-[TS] INFO Thread-6 com.freud.opc.utgard.perf.AsyncMulti - Step-28000 site: +2014-12-10 17:39:43,089-[TS] INFO Thread-10 com.freud.opc.utgard.perf.AsyncMulti - Step-44000 site: +2014-12-10 17:39:43,089-[TS] INFO Thread-14 com.freud.opc.utgard.perf.AsyncMulti - Step-60000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-18 com.freud.opc.utgard.perf.AsyncMulti - Step-76000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-22 com.freud.opc.utgard.perf.AsyncMulti - Step-92000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-26 com.freud.opc.utgard.perf.AsyncMulti - Step-108000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-30 com.freud.opc.utgard.perf.AsyncMulti - Step-124000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-34 com.freud.opc.utgard.perf.AsyncMulti - Step-140000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-38 com.freud.opc.utgard.perf.AsyncMulti - Step-156000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-42 com.freud.opc.utgard.perf.AsyncMulti - Step-172000 site: +2014-12-10 17:39:43,090-[TS] INFO Thread-46 com.freud.opc.utgard.perf.AsyncMulti - Step-188000 site: +2014-12-10 17:39:43,092-[TS] INFO Thread-46 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,092-[TS] INFO Thread-42 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,092-[TS] INFO Thread-38 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,092-[TS] INFO Thread-34 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,092-[TS] INFO Thread-30 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,092-[TS] INFO Thread-26 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,093-[TS] INFO Thread-22 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,093-[TS] INFO Thread-18 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,093-[TS] INFO Thread-14 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383090 +2014-12-10 17:39:43,093-[TS] INFO Thread-11 com.freud.opc.utgard.perf.AsyncMulti - Step-48000 site: +2014-12-10 17:39:43,093-[TS] INFO Thread-10 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383093 +2014-12-10 17:39:43,093-[TS] INFO Thread-11 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383093 +2014-12-10 17:39:43,096-[TS] INFO Thread-12 com.freud.opc.utgard.perf.AsyncMulti - Step-52000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-49 com.freud.opc.utgard.perf.AsyncMulti - Step-200000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-47 com.freud.opc.utgard.perf.AsyncMulti - Step-192000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-44 com.freud.opc.utgard.perf.AsyncMulti - Step-180000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-41 com.freud.opc.utgard.perf.AsyncMulti - Step-168000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-39 com.freud.opc.utgard.perf.AsyncMulti - Step-160000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-36 com.freud.opc.utgard.perf.AsyncMulti - Step-148000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-33 com.freud.opc.utgard.perf.AsyncMulti - Step-136000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-31 com.freud.opc.utgard.perf.AsyncMulti - Step-128000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-28 com.freud.opc.utgard.perf.AsyncMulti - Step-116000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-25 com.freud.opc.utgard.perf.AsyncMulti - Step-104000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-23 com.freud.opc.utgard.perf.AsyncMulti - Step-96000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-20 com.freud.opc.utgard.perf.AsyncMulti - Step-84000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-17 com.freud.opc.utgard.perf.AsyncMulti - Step-72000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-15 com.freud.opc.utgard.perf.AsyncMulti - Step-64000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-45 com.freud.opc.utgard.perf.AsyncMulti - Step-184000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-48 com.freud.opc.utgard.perf.AsyncMulti - Step-196000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-13 com.freud.opc.utgard.perf.AsyncMulti - Step-56000 site: +2014-12-10 17:39:43,096-[TS] INFO Thread-6 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,097-[TS] INFO Thread-13 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-16 com.freud.opc.utgard.perf.AsyncMulti - Step-68000 site: +2014-12-10 17:39:43,097-[TS] INFO Thread-16 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-19 com.freud.opc.utgard.perf.AsyncMulti - Step-80000 site: +2014-12-10 17:39:43,097-[TS] INFO Thread-19 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-21 com.freud.opc.utgard.perf.AsyncMulti - Step-88000 site: +2014-12-10 17:39:43,097-[TS] INFO Thread-21 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-24 com.freud.opc.utgard.perf.AsyncMulti - Step-100000 site: +2014-12-10 17:39:43,097-[TS] INFO Thread-24 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-27 com.freud.opc.utgard.perf.AsyncMulti - Step-112000 site: +2014-12-10 17:39:43,098-[TS] INFO Thread-27 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-29 com.freud.opc.utgard.perf.AsyncMulti - Step-120000 site: +2014-12-10 17:39:43,098-[TS] INFO Thread-29 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-32 com.freud.opc.utgard.perf.AsyncMulti - Step-132000 site: +2014-12-10 17:39:43,098-[TS] INFO Thread-32 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,099-[TS] INFO Thread-48 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-35 com.freud.opc.utgard.perf.AsyncMulti - Step-144000 site: +2014-12-10 17:39:43,099-[TS] INFO Thread-35 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-37 com.freud.opc.utgard.perf.AsyncMulti - Step-152000 site: +2014-12-10 17:39:43,099-[TS] INFO Thread-37 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,099-[TS] INFO Thread-45 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-40 com.freud.opc.utgard.perf.AsyncMulti - Step-164000 site: +2014-12-10 17:39:43,100-[TS] INFO Thread-40 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,100-[TS] INFO Thread-15 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,096-[TS] INFO Thread-43 com.freud.opc.utgard.perf.AsyncMulti - Step-176000 site: +2014-12-10 17:39:43,100-[TS] INFO Thread-43 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,101-[TS] INFO Thread-17 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,101-[TS] INFO Thread-20 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,101-[TS] INFO Thread-23 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,102-[TS] INFO Thread-25 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,102-[TS] INFO Thread-28 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,098-[TS] INFO Thread-2 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,102-[TS] INFO Thread-31 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,102-[TS] INFO Thread-33 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,103-[TS] INFO Thread-36 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,103-[TS] INFO Thread-39 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,104-[TS] INFO Thread-41 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,104-[TS] INFO Thread-44 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,104-[TS] INFO Thread-47 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,105-[TS] INFO Thread-49 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 +2014-12-10 17:39:43,106-[TS] INFO Thread-12 com.freud.opc.utgard.perf.AsyncMulti - StartDate[Wed Dec 10 17:39:43 CST 2014],CurrentMillis:1418204383096 + diff --git a/OPC_Client_Utgard_Performance/utgard_result.log.2014-12-09 b/OPC_Client_Utgard_Performance/utgard_result.log.2014-12-09 new file mode 100644 index 0000000..932497f --- /dev/null +++ b/OPC_Client_Utgard_Performance/utgard_result.log.2014-12-09 @@ -0,0 +1,12 @@ +2014-12-09 10:18:20,882-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:18:20,885-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:18:20 CST 2014],CurrentMillis:1418091500881 +2014-12-09 10:18:38,649-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:18:38,651-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:18:38 CST 2014],CurrentMillis:1418091518648 +2014-12-09 10:19:05,380-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:19:05,382-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:19:05 CST 2014],CurrentMillis:1418091545379 +2014-12-09 10:21:34,695-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:21:34,698-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:21:34 CST 2014],CurrentMillis:1418091694695 +2014-12-09 10:23:48,822-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:23:48,824-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:23:48 CST 2014],CurrentMillis:1418091828821 +2014-12-09 10:27:05,952-[TS] INFO main com.freud.opc.utgard.perf.Test - Step-10W: +2014-12-09 10:27:05,955-[TS] INFO main com.freud.opc.utgard.perf.Test - StartDate[Tue Dec 09 10:27:05 CST 2014],CurrentMillis:1418092025952 diff --git a/org.openscada.opc.dcom.test/.classpath b/org.openscada.opc.dcom.test/.classpath new file mode 100644 index 0000000..8f89c61 --- /dev/null +++ b/org.openscada.opc.dcom.test/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/org.openscada.opc.dcom.test/.gitignore b/org.openscada.opc.dcom.test/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/org.openscada.opc.dcom.test/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/org.openscada.opc.dcom.test/.project b/org.openscada.opc.dcom.test/.project new file mode 100644 index 0000000..d63364b --- /dev/null +++ b/org.openscada.opc.dcom.test/.project @@ -0,0 +1,46 @@ + + + org.openscada.opc.dcom.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.babel.editor.rbeBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.babel.editor.rbeNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/org.openscada.opc.dcom.test/LICENSE b/org.openscada.opc.dcom.test/LICENSE new file mode 100644 index 0000000..0836c46 --- /dev/null +++ b/org.openscada.opc.dcom.test/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/org.openscada.opc.dcom.test/pom.xml b/org.openscada.opc.dcom.test/pom.xml new file mode 100644 index 0000000..aa05f51 --- /dev/null +++ b/org.openscada.opc.dcom.test/pom.xml @@ -0,0 +1,31 @@ + + 4.0.0 + org.openscada.opc.dcom.test + org.openscada.opc.dcom.test + 0.0.1-SNAPSHOT + + + + org.slf4j + slf4j-log4j12 + 1.7.2 + + + commons-logging + commons-logging + 1.2 + + + + org.kohsuke.jinterop + j-interop + 2.0.5 + + + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + \ No newline at end of file diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/common/FiletimeTest1.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/common/FiletimeTest1.java new file mode 100644 index 0000000..78b648e --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/common/FiletimeTest1.java @@ -0,0 +1,86 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.common; + +import junit.framework.Assert; + +import org.junit.Test; + +public class FiletimeTest1 +{ + public static void main ( final String[] args ) + { + FILETIME ft = new FILETIME ( 29949427, 2139800608 ); + System.out.println ( String.format ( "%s, %tc", ft, ft.asCalendar () ) ); + + ft = new FILETIME ( 29949427, -2145016688 ); + System.out.println ( String.format ( "%s, %tc", ft, ft.asCalendar () ) ); + } + + @Test + public void test () + { + assertEquals ( "Thu Aug 14 11:52:43 CEST 2008", new FILETIME ( 29949427, 2139800608 ) ); + assertEquals ( "Thu Aug 14 11:52:44 CEST 2008", new FILETIME ( 29949427, -2145016688 ) ); + } + + protected void assertEquals ( final String expected, final FILETIME actual ) + { + Assert.assertEquals ( expected, String.format ( "%tc", actual.asCalendar () ) ); + } + + @Test + public void test2 () + { + FILETIME last = null; + for ( int i = 0; i < 10000; i++ ) + { + final FILETIME ft = new FILETIME ( 29949427 + i, 2139800608 + i ); + Assert.assertEquals ( ft.asBigDecimalCalendar (), ft.asCalendar () ); + + if ( last != null ) + { + Assert.assertTrue ( last.asCalendar ().before ( ft.asCalendar () ) ); + } + + last = ft; + } + } + + @Test + public void test3a () + { + for ( int i = 0; i < 10000; i++ ) + { + final FILETIME ft = new FILETIME ( 29949427 + i, 2139800608 + i ); + ft.asCalendar (); + } + } + + @Test + public void test3b () + { + for ( int i = 0; i < 10000; i++ ) + { + final FILETIME ft = new FILETIME ( 29949427 + i, 2139800608 + i ); + ft.asBigDecimalCalendar (); + } + } +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/DumpDataCallback.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/DumpDataCallback.java new file mode 100644 index 0000000..6bd8b6a --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/DumpDataCallback.java @@ -0,0 +1,59 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.ResultSet; + +public class DumpDataCallback implements IOPCDataCallback +{ + + public void cancelComplete ( final int transactionId, final int serverGroupHandle ) + { + System.out.println ( String.format ( "cancelComplete: %08X, Group: %08X", transactionId, serverGroupHandle ) ); + } + + public void dataChange ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final KeyedResultSet result ) + { + System.out.println ( String.format ( "dataChange: %d, Group: %08X, MasterQ: %d, Error: %d", transactionId, serverGroupHandle, masterQuality, masterErrorCode ) ); + + for ( final KeyedResult entry : result ) + { + System.out.println ( String.format ( "%08X - Error: %08X, Quality: %d, %Tc - %s", entry.getKey (), entry.getErrorCode (), entry.getValue ().getQuality (), entry.getValue ().getTimestamp (), entry.getValue ().getValue ().toString () ) ); + } + } + + public void readComplete ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final KeyedResultSet result ) + { + System.out.println ( String.format ( "readComplete: %d, Group: %08X, MasterQ: %d, Error: %d", transactionId, serverGroupHandle, masterQuality, masterErrorCode ) ); + + for ( final KeyedResult entry : result ) + { + System.out.println ( String.format ( "%08X - Error: %08X, Quality: %d, %Tc - %s", entry.getKey (), entry.getErrorCode (), entry.getValue ().getQuality (), entry.getValue ().getTimestamp (), entry.getValue ().getValue ().toString () ) ); + } + } + + public void writeComplete ( final int transactionId, final int serverGroupHandle, final int masterErrorCode, final ResultSet result ) + { + // TODO Auto-generated method stub + } + +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/IconicsSimulationServerConfiguration.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/IconicsSimulationServerConfiguration.java new file mode 100644 index 0000000..fbc1e6b --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/IconicsSimulationServerConfiguration.java @@ -0,0 +1,46 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + + +public class IconicsSimulationServerConfiguration implements TestConfiguration +{ + + public String getCLSID () + { + return "A879768A-7387-11D4-B0D8-009027242C59"; + } + + public String getProgId () + { + return "ICONICS.SimulatorOPCDA.2"; + } + + public String[] getReadItems () + { + return new String[] { "Logical._BOOL" }; + } + + public WriteTest[] getWriteItems () + { + return new WriteTest[]{}; + } + +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/MatrikonSimulationServerConfiguration.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/MatrikonSimulationServerConfiguration.java new file mode 100644 index 0000000..9df7b45 --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/MatrikonSimulationServerConfiguration.java @@ -0,0 +1,47 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.core.JIVariant; + +public class MatrikonSimulationServerConfiguration implements TestConfiguration +{ + + public String getCLSID () + { + return "F8582CF2-88FB-11D0-B850-00C0F0104305"; + } + + public String getProgId () + { + return "Matrikon.OPC.Simulation.1"; + } + + public String[] getReadItems () + { + return new String[] { "Saw-toothed Waves.Int2", "Saw-toothed Waves.Int4" }; + } + + public WriteTest[] getWriteItems () + { + return new WriteTest[] { new WriteTest ( "Write Only.Int2", new JIVariant ( (short)1202, false ) ), new WriteTest ( "Write Only.Int4", new JIVariant ( 1202, false ) ) }; + } + +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/SoftingDemoServerConfiguration.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/SoftingDemoServerConfiguration.java new file mode 100644 index 0000000..8daf109 --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/SoftingDemoServerConfiguration.java @@ -0,0 +1,45 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +public class SoftingDemoServerConfiguration implements TestConfiguration +{ + + public String getCLSID () + { + return "2E565242-B238-11D3-842D-0008C779D775"; + } + + public String getProgId () + { + return "Softing.OPCToolboxDemo_ServerDA.1"; + } + + public String[] getReadItems () + { + return new String[] { "increment.I2", "increment.I4" }; + } + + public WriteTest[] getWriteItems () + { + return null; + } + +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test1.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test1.java new file mode 100644 index 0000000..df0f56c --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test1.java @@ -0,0 +1,475 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.common.JISystem; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIComServer; +import org.jinterop.dcom.core.JIProgId; +import org.jinterop.dcom.core.JISession; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.EventHandler; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.OPCCommon; +import org.openscada.opc.dcom.da.impl.OPCBrowseServerAddressSpace; +import org.openscada.opc.dcom.da.impl.OPCGroupStateMgt; +import org.openscada.opc.dcom.da.impl.OPCItemIO; +import org.openscada.opc.dcom.da.impl.OPCItemMgt; +import org.openscada.opc.dcom.da.impl.OPCItemProperties; +import org.openscada.opc.dcom.da.impl.OPCServer; +import org.openscada.opc.dcom.da.impl.OPCSyncIO; + +public class Test1 +{ + private static JISession _session = null; + + public static void showError ( final OPCCommon common, final int errorCode ) throws JIException + { + System.out.println ( String.format ( "Error (%X): '%s'", errorCode, common.getErrorString ( errorCode, 1033 ) ) ); + } + + public static void showError ( final OPCServer server, final int errorCode ) throws JIException + { + showError ( server.getCommon (), errorCode ); + } + + public static void showAccessPaths ( final OPCBrowseServerAddressSpace browser, final String id ) throws IllegalArgumentException, UnknownHostException, JIException + { + for ( final String i : browser.browseAccessPaths ( id ).asCollection () ) + { + System.out.println ( "AccessPath Entry: " + i ); + } + } + + public static void browseTree ( final OPCBrowseServerAddressSpace browser ) throws IllegalArgumentException, UnknownHostException, JIException + { + System.out.println ( "Showing hierarchial address space" ); + System.out.println ( String.format ( "Organization: %s", browser.queryOrganization () ) ); + + if ( !browser.queryOrganization ().equals ( OPCNAMESPACETYPE.OPC_NS_HIERARCHIAL ) ) + { + return; + } + + browser.changePosition ( null, OPCBROWSEDIRECTION.OPC_BROWSE_TO ); + browseTree ( browser, 0 ); + } + + protected static void browseTree ( final OPCBrowseServerAddressSpace browser, final int level ) throws JIException, IllegalArgumentException, UnknownHostException + { + final StringBuilder indent = new StringBuilder ( level ); + for ( int i = 0; i < level; i++ ) + { + indent.append ( '\t' ); + } + for ( final String item : browser.browse ( OPCBROWSETYPE.OPC_LEAF, "", 0, JIVariant.VT_EMPTY ).asCollection () ) + { + System.out.println ( indent + "Leaf: " + item ); + System.out.println ( indent + "\tName: " + browser.getItemID ( item ) ); + } + + for ( final String item : browser.browse ( OPCBROWSETYPE.OPC_BRANCH, "", 0, JIVariant.VT_EMPTY ).asCollection () ) + { + System.out.println ( indent + "Branch: " + item ); + browser.changePosition ( item, OPCBROWSEDIRECTION.OPC_BROWSE_DOWN ); + browseTree ( browser, level + 1 ); + browser.changePosition ( null, OPCBROWSEDIRECTION.OPC_BROWSE_UP ); + } + } + + public static void browseFlat ( final OPCBrowseServerAddressSpace browser ) throws JIException, IllegalArgumentException, UnknownHostException + { + System.out.println ( String.format ( "Organization: %s", browser.queryOrganization () ) ); + browser.changePosition ( null, OPCBROWSEDIRECTION.OPC_BROWSE_TO ); + + System.out.println ( "Showing flat address space" ); + for ( final String id : browser.browse ( OPCBROWSETYPE.OPC_FLAT, "", 0, JIVariant.VT_EMPTY ).asCollection () ) + { + System.out.println ( "Item: " + id ); + //showAccessPaths ( browser, id ); + } + } + + public static void dumpGroupState ( final OPCGroupStateMgt group ) throws JIException + { + final OPCGroupState state = group.getState (); + + System.out.println ( "Name: " + state.getName () ); + System.out.println ( "Active: " + state.isActive () ); + System.out.println ( "Update Rate: " + state.getUpdateRate () ); + System.out.println ( "Time Bias: " + state.getTimeBias () ); + System.out.println ( "Percent Deadband: " + state.getPercentDeadband () ); + System.out.println ( "Locale ID: " + state.getLocaleID () ); + System.out.println ( "Client Handle: " + state.getClientHandle () ); + System.out.println ( "Server Handle: " + state.getServerHandle () ); + } + + public static void dumpItemProperties2 ( final OPCItemProperties itemProperties, final String itemID, final int... ids ) throws JIException + { + final KeyedResultSet values = itemProperties.getItemProperties ( itemID, ids ); + for ( final KeyedResult entry : values ) + { + System.out.println ( String.format ( "ID: %d, Value: %s, Error Code: %08x", entry.getKey (), entry.getValue ().toString (), entry.getErrorCode () ) ); + } + } + + public static void dumpItemPropertiesLookup ( final OPCItemProperties itemProperties, final String itemID, final int... ids ) throws JIException + { + final KeyedResultSet values = itemProperties.lookupItemIDs ( itemID, ids ); + for ( final KeyedResult entry : values ) + { + System.out.println ( String.format ( "ID: %d, Item ID: %s, Error Code: %08x", entry.getKey (), entry.getValue (), entry.getErrorCode () ) ); + } + } + + public static void dumpItemProperties ( final OPCItemProperties itemProperties, final String itemID ) throws JIException + { + final Collection properties = itemProperties.queryAvailableProperties ( itemID ); + final int[] ids = new int[properties.size ()]; + + System.out.println ( String.format ( "Item Properties for '%s' (count:%d)", itemID, properties.size () ) ); + int i = 0; + for ( final PropertyDescription pd : properties ) + { + ids[i] = pd.getId (); + System.out.println ( "ID: " + pd.getId () ); + System.out.println ( "Description: " + pd.getDescription () ); + System.out.println ( "Variable Type: " + pd.getVarType () ); + i++; + } + + System.out.println ( "Lookup" ); + dumpItemPropertiesLookup ( itemProperties, itemID, ids ); + + System.out.println ( "Query" ); + dumpItemProperties2 ( itemProperties, itemID, ids ); + } + + public static void queryItems ( final OPCItemIO itemIO, final String... items ) throws JIException + { + final List requests = new LinkedList (); + for ( final String item : items ) + { + requests.add ( new IORequest ( item, 0 ) ); + } + itemIO.read ( requests.toArray ( new IORequest[0] ) ); + } + + public static boolean dumpOPCITEMRESULT ( final KeyedResultSet result ) + { + int failed = 0; + for ( final KeyedResult resultEntry : result ) + { + System.out.println ( "==================================" ); + System.out.println ( String.format ( "Item: '%s' ", resultEntry.getKey ().getItemID () ) ); + + System.out.println ( String.format ( "Error Code: %08x", resultEntry.getErrorCode () ) ); + if ( !resultEntry.isFailed () ) + { + System.out.println ( String.format ( "Server Handle: %08X", resultEntry.getValue ().getServerHandle () ) ); + System.out.println ( String.format ( "Data Type: %d", resultEntry.getValue ().getCanonicalDataType () ) ); + System.out.println ( String.format ( "Access Rights: %d", resultEntry.getValue ().getAccessRights () ) ); + System.out.println ( String.format ( "Reserved: %d", resultEntry.getValue ().getReserved () ) ); + } + else + { + failed++; + } + } + return failed == 0; + } + + public static void writeItems ( final OPCServer server, final OPCGroupStateMgt group, final WriteTest... writeTests ) throws IllegalArgumentException, UnknownHostException, JIException + { + System.out.println ( "Write items" ); + + final OPCItemMgt itemManagement = group.getItemManagement (); + final OPCITEMDEF[] defs = new OPCITEMDEF[writeTests.length]; + for ( int i = 0; i < writeTests.length; i++ ) + { + final OPCITEMDEF def = new OPCITEMDEF (); + def.setActive ( true ); + def.setItemID ( writeTests[i].getItemID () ); + //def.setRequestedDataType ( (short)writeTests[i].getValue ().getType () ); + defs[i] = def; + + System.out.println ( String.format ( "%s <= (%d) %s", writeTests[i].getItemID (), writeTests[i].getValue ().getType (), writeTests[i].getValue ().toString () ) ); + } + + System.out.println ( "Add to group" ); + final KeyedResultSet result = itemManagement.add ( defs ); + final WriteRequest[] writeRequests = new WriteRequest[writeTests.length]; + final Integer[] serverHandles = new Integer[writeTests.length]; + for ( int i = 0; i < writeTests.length; i++ ) + { + if ( result.get ( i ).getErrorCode () != 0 ) + { + throw new JIException ( result.get ( i ).getErrorCode () ); + } + + writeRequests[i] = new WriteRequest ( result.get ( i ).getValue ().getServerHandle (), writeTests[i].getValue () ); + serverHandles[i] = writeRequests[i].getServerHandle (); + + System.out.println ( String.format ( "Item: %s, VT: %d", writeTests[i].getItemID (), result.get ( i ).getValue ().getCanonicalDataType () ) ); + } + + System.out.println ( "Perform write" ); + final OPCSyncIO syncIO = group.getSyncIO (); + final ResultSet writeResults = syncIO.write ( writeRequests ); + for ( int i = 0; i < writeTests.length; i++ ) + { + final Result writeResult = writeResults.get ( i ); + System.out.println ( String.format ( "ItemID: %s, ErrorCode: %08X", writeTests[i].getItemID (), writeResult.getErrorCode () ) ); + if ( writeResult.getErrorCode () != 0 ) + { + showError ( server, writeResult.getErrorCode () ); + } + } + + // finally remove them again + System.out.println ( "Remove from group" ); + itemManagement.remove ( serverHandles ); + + System.out.println ( "Write items...complete" ); + } + + public static void testItems ( final OPCServer server, final OPCGroupStateMgt group, final String... itemIDs ) throws IllegalArgumentException, UnknownHostException, JIException + { + final OPCItemMgt itemManagement = group.getItemManagement (); + final List items = new ArrayList ( itemIDs.length ); + for ( final String id : itemIDs ) + { + final OPCITEMDEF item = new OPCITEMDEF (); + item.setItemID ( id ); + item.setClientHandle ( new Random ().nextInt () ); + items.add ( item ); + } + + final OPCITEMDEF[] itemArray = items.toArray ( new OPCITEMDEF[0] ); + + System.out.println ( "Validate" ); + KeyedResultSet result = itemManagement.validate ( itemArray ); + if ( !dumpOPCITEMRESULT ( result ) ) + { + return; + } + + // now add them to the group + System.out.println ( "Add" ); + result = itemManagement.add ( itemArray ); + if ( !dumpOPCITEMRESULT ( result ) ) + { + return; + } + + // get the server handle array + final Integer[] serverHandles = new Integer[itemArray.length]; + for ( int i = 0; i < itemArray.length; i++ ) + { + serverHandles[i] = new Integer ( result.get ( i ).getValue ().getServerHandle () ); + } + + // set them active + System.out.println ( "Activate" ); + final ResultSet resultSet = itemManagement.setActiveState ( true, serverHandles ); + for ( final Result resultEntry : resultSet ) + { + System.out.println ( String.format ( "Item: %08X, Error: %08X", resultEntry.getValue (), resultEntry.getErrorCode () ) ); + } + + // set client handles + System.out.println ( "Set client handles" ); + final Integer[] clientHandles = new Integer[serverHandles.length]; + for ( int i = 0; i < serverHandles.length; i++ ) + { + clientHandles[i] = i; + } + itemManagement.setClientHandles ( serverHandles, clientHandles ); + + System.out.println ( "Create async IO 2.0 object" ); + // OPCAsyncIO2 asyncIO2 = group.getAsyncIO2 (); + // connect handler + + System.out.println ( "attach" ); + final EventHandler eventHandler = group.attach ( new DumpDataCallback () ); + /* + System.out.println ( "attach..enable" ); + asyncIO2.setEnable ( true ); + System.out.println ( "attach..refresh" ); + asyncIO2.refresh ( (short)1, 1 ); + */ + // sleep + try + { + System.out.println ( "Waiting..." ); + Thread.sleep ( 10 * 1000 ); + } + catch ( final InterruptedException e ) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + + eventHandler.detach (); + + // sync IO - read + final OPCSyncIO syncIO = group.getSyncIO (); + final KeyedResultSet itemState = syncIO.read ( OPCDATASOURCE.OPC_DS_DEVICE, serverHandles ); + for ( final KeyedResult itemStateEntry : itemState ) + { + final int errorCode = itemStateEntry.getErrorCode (); + System.out.println ( String.format ( "Server ID: %08X, Value: %s, Timestamp: %d/%d (%Tc), Quality: %d, Error: %08X", itemStateEntry.getKey (), itemStateEntry.getValue ().getValue (), itemStateEntry.getValue ().getTimestamp ().getHigh (), itemStateEntry.getValue ().getTimestamp ().getLow (), itemStateEntry.getValue ().getTimestamp ().asCalendar (), itemStateEntry.getValue ().getQuality (), errorCode ) ); + if ( errorCode != 0 ) + { + showError ( server, errorCode ); + } + } + + // set them inactive + System.out.println ( "In-Active" ); + itemManagement.setActiveState ( false, serverHandles ); + + // finally remove them again + System.out.println ( "Remove" ); + itemManagement.remove ( serverHandles ); + } + + public static void dumpServerStatus ( final OPCServer server ) throws JIException + { + final OPCSERVERSTATUS status = server.getStatus (); + + System.out.println ( "===== SERVER STATUS ======" ); + System.out.println ( "State: " + status.getServerState ().toString () ); + System.out.println ( "Vendor: " + status.getVendorInfo () ); + System.out.println ( String.format ( "Version: %d.%d.%d", status.getMajorVersion (), status.getMinorVersion (), status.getBuildNumber () ) ); + System.out.println ( "Groups: " + status.getGroupCount () ); + System.out.println ( "Bandwidth: " + status.getBandWidth () ); + System.out.println ( String.format ( "Start Time: %tc", status.getStartTime ().asCalendar () ) ); + System.out.println ( String.format ( "Current Time: %tc", status.getCurrentTime ().asCalendar () ) ); + System.out.println ( String.format ( "Last Update Time: %tc", status.getLastUpdateTime ().asCalendar () ) ); + System.out.println ( "===== SERVER STATUS ======" ); + } + + public static void enumerateGroups ( final OPCServer server, final OPCENUMSCOPE scope ) throws IllegalArgumentException, UnknownHostException, JIException + { + System.out.println ( "Enum Groups: " + scope.toString () ); + + for ( final String group : server.getGroups ( scope ).asCollection () ) + { + System.out.println ( "Group: " + group ); + } + } + + @SuppressWarnings ( "unused" ) + public static void main ( final String[] args ) throws IllegalArgumentException, UnknownHostException, JIException + { + final TestConfiguration configuration = new MatrikonSimulationServerConfiguration (); + + OPCServer server = null; + try + { + JISystem.setAutoRegisteration ( true ); + + _session = JISession.createSession ( args[1], args[2], args[3] ); + // OPCServer server = new OPCServer ( "127.0.0.1", JIProgId.valueOf + // ( session, "Matrikon.OPC.Simulation.1" ), + // session ); + + //JIComServer comServer = new JIComServer ( JIClsid.valueOf ( configuration.getCLSID () ), args[0], _session ); + final JIComServer comServer = new JIComServer ( JIProgId.valueOf ( configuration.getProgId () ), args[0], _session ); + + final IJIComObject serverObject = comServer.createInstance (); + server = new OPCServer ( serverObject ); + dumpServerStatus ( server ); + + /* + OPCCommon common = server.getCommon (); + common.setLocaleID ( 1033 ); + System.out.println ( String.format ( "LCID: %d", common.getLocaleID () ) ); + common.setClientName ( "test" ); + for ( Integer i : common.queryAvailableLocaleIDs () ) + { + System.out.println ( String.format ( "Available LCID: %d", i ) ); + } + */ + + final OPCBrowseServerAddressSpace serverBrowser = server.getBrowser (); + browseFlat ( serverBrowser ); + /* + browseTree ( serverBrowser ); + */ + + final OPCGroupStateMgt group = server.addGroup ( "test", true, 100, 1234, 60, 0.0f, 1033 ); + /* + group.setName ( "test2" ); + OPCGroupStateMgt group2 = group.clone ( "test" ); + group = server.getGroupByName ( "test2" ); + group.setState ( null, false, null, null, null, null ); + group.setState ( null, true, null, null, null, null ); + dumpGroupState ( group ); + dumpGroupState ( group2 ); + */ + testItems ( server, group, configuration.getReadItems () ); + if ( configuration.getWriteItems () != null ) + { + writeItems ( server, group, configuration.getWriteItems () ); + } + + final OPCItemProperties itemProperties = server.getItemPropertiesService (); + //dumpItemProperties ( itemProperties, "Saw-toothed Waves.Int" ); + + final OPCItemIO itemIO = server.getItemIOService (); + //queryItems ( itemIO, "Saw-toothed Waves.Int" ); + + enumerateGroups ( server, OPCENUMSCOPE.OPC_ENUM_PUBLIC ); + enumerateGroups ( server, OPCENUMSCOPE.OPC_ENUM_PRIVATE ); + enumerateGroups ( server, OPCENUMSCOPE.OPC_ENUM_ALL ); + + // clean up + server.removeGroup ( group, true ); + //server.removeGroup ( group2, true ); + + } + catch ( final JIException e ) + { + e.printStackTrace (); + showError ( server, e.getErrorCode () ); + } + finally + { + if ( _session != null ) + { + JISession.destroySession ( _session ); + } + _session = null; + } + } +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test2.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test2.java new file mode 100644 index 0000000..9223866 --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/Test2.java @@ -0,0 +1,214 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.common.JISystem; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIComServer; +import org.jinterop.dcom.core.JIProgId; +import org.jinterop.dcom.core.JISession; +import org.openscada.opc.dcom.common.EventHandler; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.OPCCommon; +import org.openscada.opc.dcom.da.impl.OPCAsyncIO2; +import org.openscada.opc.dcom.da.impl.OPCGroupStateMgt; +import org.openscada.opc.dcom.da.impl.OPCItemMgt; +import org.openscada.opc.dcom.da.impl.OPCServer; +import org.openscada.opc.dcom.da.impl.OPCAsyncIO2.AsyncResult; + +public class Test2 +{ + private static JISession _session = null; + + public static void showError ( final OPCCommon common, final int errorCode ) throws JIException + { + System.out.println ( String.format ( "Error (%X): '%s'", errorCode, common.getErrorString ( errorCode, 1033 ) ) ); + } + + public static void showError ( final OPCServer server, final int errorCode ) throws JIException + { + showError ( server.getCommon (), errorCode ); + } + + public static boolean dumpOPCITEMRESULT ( final KeyedResultSet result ) + { + int failed = 0; + for ( final KeyedResult resultEntry : result ) + { + System.out.println ( "==================================" ); + System.out.println ( String.format ( "Item: '%s' ", resultEntry.getKey ().getItemID () ) ); + + System.out.println ( String.format ( "Error Code: %08x", resultEntry.getErrorCode () ) ); + if ( !resultEntry.isFailed () ) + { + System.out.println ( String.format ( "Server Handle: %08X", resultEntry.getValue ().getServerHandle () ) ); + System.out.println ( String.format ( "Data Type: %d", resultEntry.getValue ().getCanonicalDataType () ) ); + System.out.println ( String.format ( "Access Rights: %d", resultEntry.getValue ().getAccessRights () ) ); + System.out.println ( String.format ( "Reserved: %d", resultEntry.getValue ().getReserved () ) ); + } + else + { + failed++; + } + } + return failed == 0; + } + + public static void testItems ( final OPCServer server, final OPCGroupStateMgt group, final String... itemIDs ) throws IllegalArgumentException, UnknownHostException, JIException + { + final OPCItemMgt itemManagement = group.getItemManagement (); + final List items = new ArrayList ( itemIDs.length ); + for ( final String id : itemIDs ) + { + final OPCITEMDEF item = new OPCITEMDEF (); + item.setItemID ( id ); + item.setClientHandle ( new Random ().nextInt () ); + items.add ( item ); + } + + final OPCITEMDEF[] itemArray = items.toArray ( new OPCITEMDEF[0] ); + + System.out.println ( "Validate" ); + KeyedResultSet result = itemManagement.validate ( itemArray ); + if ( !dumpOPCITEMRESULT ( result ) ) + { + return; + } + + // now add them to the group + System.out.println ( "Add" ); + result = itemManagement.add ( itemArray ); + if ( !dumpOPCITEMRESULT ( result ) ) + { + return; + } + + // get the server handle array + final Integer[] serverHandles = new Integer[itemArray.length]; + for ( int i = 0; i < itemArray.length; i++ ) + { + serverHandles[i] = new Integer ( result.get ( i ).getValue ().getServerHandle () ); + } + + // set them active + System.out.println ( "Activate" ); + final ResultSet resultSet = itemManagement.setActiveState ( true, serverHandles ); + for ( final Result resultEntry : resultSet ) + { + System.out.println ( String.format ( "Item: %08X, Error: %08X", resultEntry.getValue (), resultEntry.getErrorCode () ) ); + } + + // set client handles + System.out.println ( "Set client handles" ); + final Integer[] clientHandles = new Integer[serverHandles.length]; + for ( int i = 0; i < serverHandles.length; i++ ) + { + clientHandles[i] = i; + } + itemManagement.setClientHandles ( serverHandles, clientHandles ); + + System.out.println ( "Create async IO 2.0 object" ); + final OPCAsyncIO2 asyncIO2 = group.getAsyncIO2 (); + + // connect handler + System.out.println ( "attach" ); + final EventHandler eventHandler = group.attach ( new DumpDataCallback () ); + + System.out.println ( "attach..enable" ); + asyncIO2.setEnable ( true ); + + System.out.println ( "attach..refresh" ); + final int cancelId = asyncIO2.refresh ( OPCDATASOURCE.OPC_DS_DEVICE, 1 ); + System.out.println ( "Cancel ID: " + cancelId ); + + System.out.println ( "attach..read" ); + final AsyncResult asyncResult = asyncIO2.read ( 2, serverHandles ); + System.out.println ( String.format ( "attach..read..cancelId: %08X", asyncResult.getCancelId () ) ); + + // sleep + try + { + System.out.println ( "Waiting..." ); + Thread.sleep ( 10 * 1000 ); + } + catch ( final InterruptedException e ) + { + // TODO Auto-generated catch block + e.printStackTrace (); + } + + System.out.println ( "Detaching" ); + eventHandler.detach (); + + // set them inactive + System.out.println ( "In-Active" ); + itemManagement.setActiveState ( false, serverHandles ); + + // finally remove them again + System.out.println ( "Remove" ); + itemManagement.remove ( serverHandles ); + } + + public static void main ( final String[] args ) throws IllegalArgumentException, UnknownHostException, JIException + { + final TestConfiguration configuration = new MatrikonSimulationServerConfiguration (); + + OPCServer server = null; + try + { + JISystem.setAutoRegisteration ( true ); + + _session = JISession.createSession ( args[1], args[2], args[3] ); + + //JIComServer comServer = new JIComServer ( JIClsid.valueOf ( configuration.getCLSID () ), args[0], _session ); + final JIComServer comServer = new JIComServer ( JIProgId.valueOf ( configuration.getProgId () ), args[0], _session ); + + final IJIComObject serverObject = comServer.createInstance (); + server = new OPCServer ( serverObject ); + + final OPCGroupStateMgt group = server.addGroup ( "test", true, 100, 1234, 60, 0.0f, 1033 ); + + testItems ( server, group, configuration.getReadItems () ); + server.removeGroup ( group, true ); + } + catch ( final JIException e ) + { + e.printStackTrace (); + showError ( server, e.getErrorCode () ); + } + finally + { + if ( _session != null ) + { + JISession.destroySession ( _session ); + } + _session = null; + } + } +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/TestConfiguration.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/TestConfiguration.java new file mode 100644 index 0000000..8a00255 --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/TestConfiguration.java @@ -0,0 +1,31 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +public interface TestConfiguration +{ + public String getCLSID (); + + public String getProgId (); + + public String[] getReadItems (); + + public WriteTest[] getWriteItems (); +} diff --git a/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/WriteTest.java b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/WriteTest.java new file mode 100644 index 0000000..092a992 --- /dev/null +++ b/org.openscada.opc.dcom.test/src/org/openscada/opc/dcom/da/WriteTest.java @@ -0,0 +1,56 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.core.JIVariant; + +public class WriteTest +{ + private String _itemID = ""; + + private JIVariant _value = JIVariant.EMPTY (); + + public WriteTest ( final String itemID, final JIVariant value ) + { + super (); + this._itemID = itemID; + this._value = value; + } + + public String getItemID () + { + return this._itemID; + } + + public void setItemID ( final String itemID ) + { + this._itemID = itemID; + } + + public JIVariant getValue () + { + return this._value; + } + + public void setValue ( final JIVariant value ) + { + this._value = value; + } +} diff --git a/org.openscada.opc.dcom/.classpath b/org.openscada.opc.dcom/.classpath new file mode 100644 index 0000000..2911ff5 --- /dev/null +++ b/org.openscada.opc.dcom/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/org.openscada.opc.dcom/.gitignore b/org.openscada.opc.dcom/.gitignore new file mode 100644 index 0000000..4cc0812 --- /dev/null +++ b/org.openscada.opc.dcom/.gitignore @@ -0,0 +1,2 @@ +bin/ +/target diff --git a/org.openscada.opc.dcom/.project b/org.openscada.opc.dcom/.project new file mode 100644 index 0000000..1274dfa --- /dev/null +++ b/org.openscada.opc.dcom/.project @@ -0,0 +1,46 @@ + + + org.openscada.opc.dcom + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.babel.editor.rbeBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.babel.editor.rbeNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/org.openscada.opc.dcom/build.properties b/org.openscada.opc.dcom/build.properties new file mode 100644 index 0000000..4394f20 --- /dev/null +++ b/org.openscada.opc.dcom/build.properties @@ -0,0 +1 @@ +source.. = src diff --git a/org.openscada.opc.dcom/pom.xml b/org.openscada.opc.dcom/pom.xml new file mode 100644 index 0000000..4d6dcb7 --- /dev/null +++ b/org.openscada.opc.dcom/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + org.slf4j + slf4j-log4j12 + 1.7.2 + + + commons-logging + commons-logging + 1.2 + + + + org.kohsuke.jinterop + j-interop + 2.0.5 + + + + \ No newline at end of file diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Categories.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Categories.java new file mode 100644 index 0000000..32cc414 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Categories.java @@ -0,0 +1,32 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +public interface Categories +{ + public static final String OPCDAServer10 = "63D5F430-CFE4-11d1-B2C8-0060083BA1FB"; + + public static final String OPCDAServer20 = "63D5F432-CFE4-11d1-B2C8-0060083BA1FB"; + + public static final String OPCDAServer30 = "CC603642-66D7-48f1-B69A-B625E73652D7"; + + public static final String XMLDAServer10 = "3098EDA4-A006-48b2-A27F-247453959408"; + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Constants.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Constants.java new file mode 100644 index 0000000..1bb75fa --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Constants.java @@ -0,0 +1,37 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +public interface Constants +{ + public static final String IConnectionPointContainer_IID = "B196B284-BAB4-101A-B69C-00AA00341D07"; + + public static final String IConnectionPoint_IID = "B196B286-BAB4-101A-B69C-00AA00341D07"; + + public static final String IOPCCommon_IID = "F31DFDE2-07B6-11D2-B2D8-0060083BA1FB"; + + public static final String IEnumString_IID = "00000101-0000-0000-C000-000000000046"; + + public static final String IEnumGUID_IID = "0002E000-0000-0000-C000-000000000046"; + + public static final int S_OK = 0; + + public static final int S_FALSE = 1; +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/EventHandler.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/EventHandler.java new file mode 100644 index 0000000..37cab5c --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/EventHandler.java @@ -0,0 +1,32 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; + +public interface EventHandler +{ + public String getIdentifier (); + + public IJIComObject getObject (); + + public void detach () throws JIException; +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/FILETIME.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/FILETIME.java new file mode 100644 index 0000000..57fe74e --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/FILETIME.java @@ -0,0 +1,174 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +import java.math.BigDecimal; +import java.util.Calendar; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIStruct; + +public class FILETIME +{ + private int high = 0; + + private int low = 0; + + public FILETIME () + { + } + + public FILETIME ( final FILETIME arg0 ) + { + this.high = arg0.high; + this.low = arg0.low; + } + + public FILETIME ( final int high, final int low ) + { + this.high = high; + this.low = low; + } + + public int getHigh () + { + return this.high; + } + + public void setHigh ( final int high ) + { + this.high = high; + } + + public int getLow () + { + return this.low; + } + + public void setLow ( final int low ) + { + this.low = low; + } + + @Override + public int hashCode () + { + final int PRIME = 31; + int result = 1; + result = PRIME * result + this.high; + result = PRIME * result + this.low; + return result; + } + + @Override + public boolean equals ( final Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj == null ) + { + return false; + } + if ( getClass () != obj.getClass () ) + { + return false; + } + final FILETIME other = (FILETIME)obj; + if ( this.high != other.high ) + { + return false; + } + if ( this.low != other.low ) + { + return false; + } + return true; + } + + public static JIStruct getStruct () throws JIException + { + final JIStruct struct = new JIStruct (); + + struct.addMember ( Integer.class ); + struct.addMember ( Integer.class ); + + return struct; + } + + public static FILETIME fromStruct ( final JIStruct struct ) + { + final FILETIME ft = new FILETIME (); + + ft.setLow ( (Integer)struct.getMember ( 0 ) ); + ft.setHigh ( (Integer)struct.getMember ( 1 ) ); + + return ft; + } + + public Calendar asCalendar () + { + final Calendar c = Calendar.getInstance (); + + /* + * The following "strange" stuff is needed since we miss a ulong type + */ + long i = 0xFFFFFFFFL & this.high; + i = i << 32; + long j = 0xFFFFFFFFFFFFFFFFL & i; + + i = 0xFFFFFFFFL & this.low; + j += i; + j /= 10000L; + j -= 11644473600000L; + + c.setTimeInMillis ( j ); + + return c; + } + + public Calendar asBigDecimalCalendar () + { + final Calendar c = Calendar.getInstance (); + + /* + * The following "strange" stuff is needed since we miss a ulong type + */ + long i = 0xFFFFFFFFL & this.high; + i = i << 32; + BigDecimal d1 = new BigDecimal ( 0xFFFFFFFFFFFFFFFFL & i ); + + i = 0xFFFFFFFFL & this.low; + d1 = d1.add ( new BigDecimal ( i ) ); + d1 = d1.divide ( new BigDecimal ( 10000L ) ); + d1 = d1.subtract ( new BigDecimal ( 11644473600000L ) ); + + c.setTimeInMillis ( d1.longValue () ); + + return c; + } + + @Override + public String toString () + { + return String.format ( "%s/%s", this.high, this.low ); + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResult.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResult.java new file mode 100644 index 0000000..e65c30b --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResult.java @@ -0,0 +1,46 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +public class KeyedResult extends Result +{ + private K key; + + public KeyedResult () + { + super (); + } + + public KeyedResult ( final K key, final V value, final int errorCode ) + { + super ( value, errorCode ); + this.key = key; + } + + public K getKey () + { + return this.key; + } + + public void setKey ( final K key ) + { + this.key = key; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResultSet.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResultSet.java new file mode 100644 index 0000000..5780a56 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/KeyedResultSet.java @@ -0,0 +1,37 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2012 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +import java.util.ArrayList; + +public class KeyedResultSet extends ArrayList> +{ + private static final long serialVersionUID = 1L; + + public KeyedResultSet () + { + super (); + } + + public KeyedResultSet ( final int size ) + { + super ( size ); // me + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Result.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Result.java new file mode 100644 index 0000000..d76b6f7 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/Result.java @@ -0,0 +1,64 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +public class Result +{ + private T value; + + private int errorCode; + + public Result () + { + } + + public Result ( final T value, final int errorCode ) + { + this.value = value; + this.errorCode = errorCode; + } + + public int getErrorCode () + { + return this.errorCode; + } + + public void setErrorCode ( final int errorCode ) + { + this.errorCode = errorCode; + } + + public T getValue () + { + return this.value; + } + + public void setValue ( final T value ) + { + this.value = value; + } + + public boolean isFailed () + { + return this.errorCode != 0; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/ResultSet.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/ResultSet.java new file mode 100644 index 0000000..8573e3a --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/ResultSet.java @@ -0,0 +1,38 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common; + +import java.util.ArrayList; + +public class ResultSet extends ArrayList> +{ + + private static final long serialVersionUID = 6392417310208978252L; + + public ResultSet () + { + super (); + } + + public ResultSet ( final int size ) + { + super ( size ); // me + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/BaseCOMObject.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/BaseCOMObject.java new file mode 100644 index 0000000..e64f707 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/BaseCOMObject.java @@ -0,0 +1,45 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import org.jinterop.dcom.core.IJIComObject; + +public class BaseCOMObject +{ + private IJIComObject comObject = null; + + /** + * Create a new base COM object + * + * @param comObject + * The COM object to wrap but be addRef'ed + */ + public BaseCOMObject ( final IJIComObject comObject ) + { + this.comObject = comObject; + } + + protected synchronized IJIComObject getCOMObject () + { + return this.comObject; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumGUID.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumGUID.java new file mode 100644 index 0000000..37ccad9 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumGUID.java @@ -0,0 +1,134 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; + +import rpc.core.UUID; + +public class EnumGUID extends BaseCOMObject +{ + public static final int DEFAULT_BATCH_SIZE = Integer.getInteger ( "openscada.dcom.enum-batch-size", 10 ); + + public EnumGUID ( final IJIComObject enumStringObject ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( enumStringObject.queryInterface ( org.openscada.opc.dcom.common.Constants.IEnumGUID_IID ) ); + } + + public int next ( final List list, final int num ) throws JIException + { + if ( num <= 0 ) + { + return 0; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIArray ( UUID.class, null, 1, true, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + UUID[] resultData = (UUID[]) ( (JIArray)result[0] ).getArrayInstance (); + Integer cnt = (Integer)result[1]; + + for ( int i = 0; i < cnt; i++ ) + { + list.add ( resultData[i] ); + } + return cnt; + } + + public Collection next ( final int num ) throws JIException + { + List list = new ArrayList ( num ); + next ( list, num ); + return list; + } + + public void skip ( final int num ) throws JIException + { + if ( num <= 0 ) + { + return; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public void reset () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + getCOMObject ().call ( callObject ); + } + + public EnumGUID cloneObject () throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + IJIComObject object = (IJIComObject)result[0]; + + return new EnumGUID ( object ); + } + + public Collection asCollection ( final int batchSize ) throws JIException + { + reset (); + + List data = new ArrayList (); + int i = 0; + do + { + i = next ( data, batchSize ); + } while ( i == batchSize ); + + return data; + } + + public Collection asCollection () throws JIException + { + return asCollection ( DEFAULT_BATCH_SIZE ); + } + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumString.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumString.java new file mode 100644 index 0000000..431060f --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EnumString.java @@ -0,0 +1,136 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIString; + +public class EnumString extends BaseCOMObject +{ + public static final int DEFAULT_BATCH_SIZE = Integer.getInteger ( "openscada.dcom.enum-batch-size", 10 ); + + public EnumString ( final IJIComObject enumStringObject ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( enumStringObject.queryInterface ( org.openscada.opc.dcom.common.Constants.IEnumString_IID ) ); + } + + public int next ( final List list, final int num ) throws JIException + { + if ( num <= 0 ) + { + return 0; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + //callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + //callObject.addOutParamAsObject ( new JIArray ( new JIPointer ( new JIString ( + // JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), null, 1, true, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIArray ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ), null, 1, true, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + //JIPointer[] resultData = (JIPointer[]) ( (JIArray) ( result[0] ) ).getArrayInstance (); + JIString[] resultData = (JIString[]) ( (JIArray)result[0] ).getArrayInstance (); + Integer cnt = (Integer)result[1]; + + for ( int i = 0; i < cnt; i++ ) + { + //list.add ( ( (JIString)resultData[i].getReferent () ).getString () ); + list.add ( resultData[i].getString () ); + } + return cnt; + } + + public Collection next ( final int num ) throws JIException + { + List list = new ArrayList ( num ); + next ( list, num ); + return list; + } + + public void skip ( final int num ) throws JIException + { + if ( num <= 0 ) + { + return; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsInt ( num, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public void reset () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + getCOMObject ().call ( callObject ); + } + + public EnumString cloneObject () throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + IJIComObject object = (IJIComObject)result[0]; + return new EnumString ( object ); + } + + public Collection asCollection ( final int batchSize ) throws JIException + { + reset (); + + List data = new ArrayList (); + int i = 0; + do + { + i = next ( data, batchSize ); + } while ( i == batchSize ); + + return data; + } + + public Collection asCollection () throws JIException + { + return asCollection ( DEFAULT_BATCH_SIZE ); + } + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EventHandlerImpl.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EventHandlerImpl.java new file mode 100644 index 0000000..cad1e84 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/EventHandlerImpl.java @@ -0,0 +1,65 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIFrameworkHelper; +import org.openscada.opc.dcom.common.EventHandler; + +public class EventHandlerImpl implements EventHandler +{ + private String identifier = null; + + private IJIComObject object = null; + + public String getIdentifier () + { + return this.identifier; + } + + public synchronized IJIComObject getObject () + { + return this.object; + } + + public synchronized void setInfo ( final IJIComObject object, final String identifier ) + { + this.object = object; + this.identifier = identifier; + } + + public synchronized void detach () throws JIException + { + if ( this.object != null && this.identifier != null ) + { + try + { + JIFrameworkHelper.detachEventHandler ( this.object, this.identifier ); + } + finally + { + this.object = null; + this.identifier = null; + } + } + } + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/Helper.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/Helper.java new file mode 100644 index 0000000..17e2381 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/Helper.java @@ -0,0 +1,71 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIVariant; + +public class Helper +{ + /** + * Make the COM call but do not treat S_FALSE as error condition for the whole call + * @param object the object to make to call on + * @param callObject the call object + * @return the result of the call + * @throws JIException + */ + public static Object[] callRespectSFALSE ( final IJIComObject object, final JICallBuilder callObject ) throws JIException + { + try + { + return object.call ( callObject ); + } + catch ( JIException e ) + { + if ( e.getErrorCode () != org.openscada.opc.dcom.common.Constants.S_FALSE ) + { + throw e; + } + return callObject.getResultsInCaseOfException (); + } + } + + /** + * Perform some fixes on the variant when writing it to OPC items. This method + * only changes control information on the variant and not the value itself! + * @param value the value to fix + * @return the fixed value + * @throws JIException In case something goes wrong + */ + public static JIVariant fixVariant ( final JIVariant value ) throws JIException + { + if ( value.isArray () ) + { + if ( value.getObjectAsArray ().getArrayInstance () instanceof Boolean[] ) + { + value.setFlag ( JIFlags.FLAG_REPRESENTATION_VARIANT_BOOL ); + } + } + return value; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/OPCCommon.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/OPCCommon.java new file mode 100644 index 0000000..a65372e --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/common/impl/OPCCommon.java @@ -0,0 +1,101 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.common.impl; + +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Collection; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; + +public class OPCCommon extends BaseCOMObject +{ + public OPCCommon ( final IJIComObject opcObject ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcObject.queryInterface ( org.openscada.opc.dcom.common.Constants.IOPCCommon_IID ) ); + } + + public void setLocaleID ( final int localeID ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsInt ( localeID, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public int getLocaleID () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addOutParamAsObject ( Integer.class, JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + return (Integer)result[0]; + } + + public String getErrorString ( final int errorCode, final int localeID ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addInParamAsInt ( errorCode, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( localeID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + return ( (JIString) ( (JIPointer)result[0] ).getReferent () ).getString (); + } + + public void setClientName ( final String clientName ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 4 ); + + callObject.addInParamAsString ( clientName, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + + getCOMObject ().call ( callObject ); + } + + public Collection queryAvailableLocaleIDs () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + JIArray resultArray = (JIArray) ( (JIPointer)result[1] ).getReferent (); + Integer[] intArray = (Integer[])resultArray.getArrayInstance (); + + return Arrays.asList ( intArray ); + } + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/Constants.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/Constants.java new file mode 100644 index 0000000..0c11e45 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/Constants.java @@ -0,0 +1,43 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public interface Constants extends org.openscada.opc.dcom.common.Constants +{ + public static final String IOPCServer_IID = "39C13A4D-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCGroupStateMgt_IID = "39C13A50-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCBrowse_IID = "39227004-A18F-4B57-8B0A-5235670F4468"; + + public static final String IOPCBrowseServerAddressSpace_IID = "39C13A4F-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCItemMgt_IID = "39C13A54-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCItemProperties_IID = "39C13A72-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCItemIO_IID = "85C0B427-2893-4CBC-BD78-E5FC5146F08F"; + + public static final String IOPCDataCallback_IID = "39C13A70-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCAsyncIO2_IID = "39C13A71-011E-11D0-9675-0020AFD8ADB3"; + + public static final String IOPCSyncIO_IID = "39C13A52-011E-11D0-9675-0020AFD8ADB3"; +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IOPCDataCallback.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IOPCDataCallback.java new file mode 100644 index 0000000..84f1286 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IOPCDataCallback.java @@ -0,0 +1,34 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.ResultSet; + +public interface IOPCDataCallback +{ + public void dataChange ( int transactionId, int serverGroupHandle, int masterQuality, int masterErrorCode, KeyedResultSet result ); + + public void readComplete ( int transactionId, int serverGroupHandle, int masterQuality, int masterErrorCode, KeyedResultSet result ); + + public void writeComplete ( int transactionId, int serverGroupHandle, int masterErrorCode, ResultSet result ); + + public void cancelComplete ( int transactionId, int serverGroupHandle ); +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IORequest.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IORequest.java new file mode 100644 index 0000000..7d43435 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/IORequest.java @@ -0,0 +1,56 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public class IORequest +{ + private String itemID; + + private int maxAge; + + public IORequest ( final String itemID, final int maxAge ) + { + this.itemID = itemID; + this.maxAge = maxAge; + } + + public String getItemID () + { + return this.itemID; + } + + public void setItemID ( final String itemID ) + { + this.itemID = itemID; + } + + public int getMaxAge () + { + return this.maxAge; + } + + public void setMaxAge ( final int maxAge ) + { + this.maxAge = maxAge; + } + +} \ No newline at end of file diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSEDIRECTION.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSEDIRECTION.java new file mode 100644 index 0000000..1ba83e6 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSEDIRECTION.java @@ -0,0 +1,55 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCBROWSEDIRECTION +{ + OPC_BROWSE_UP ( 1 ), + OPC_BROWSE_DOWN ( 2 ), + OPC_BROWSE_TO ( 3 ), + OPC_BROWSE_UNKNOWN ( 0 ); + + private int _id; + + private OPCBROWSEDIRECTION ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCBROWSEDIRECTION fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_BROWSE_UP; + case 2: + return OPC_BROWSE_DOWN; + case 3: + return OPC_BROWSE_TO; + default: + return OPC_BROWSE_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSETYPE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSETYPE.java new file mode 100644 index 0000000..500adfa --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCBROWSETYPE.java @@ -0,0 +1,55 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCBROWSETYPE +{ + OPC_BRANCH ( 1 ), + OPC_LEAF ( 2 ), + OPC_FLAT ( 3 ), + OPC_UNKNOWN ( 0 ); + + private int _id; + + private OPCBROWSETYPE ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCBROWSETYPE fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_BRANCH; + case 2: + return OPC_LEAF; + case 3: + return OPC_FLAT; + default: + return OPC_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCDATASOURCE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCDATASOURCE.java new file mode 100644 index 0000000..dfce9e3 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCDATASOURCE.java @@ -0,0 +1,52 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCDATASOURCE +{ + OPC_DS_CACHE ( 1 ), + OPC_DS_DEVICE ( 2 ), + OPC_DS_UNKNOWN ( 0 ); + + private int _id; + + private OPCDATASOURCE ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCDATASOURCE fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_DS_CACHE; + case 2: + return OPC_DS_DEVICE; + default: + return OPC_DS_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCENUMSCOPE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCENUMSCOPE.java new file mode 100644 index 0000000..1fd8163 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCENUMSCOPE.java @@ -0,0 +1,64 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCENUMSCOPE +{ + OPC_ENUM_PRIVATE_CONNECTIONS ( 1 ), + OPC_ENUM_PUBLIC_CONNECTIONS ( 2 ), + OPC_ENUM_ALL_CONNECTIONS ( 3 ), + OPC_ENUM_PRIVATE ( 4 ), + OPC_ENUM_PUBLIC ( 5 ), + OPC_ENUM_ALL ( 6 ), + OPC_ENUM_UNKNOWN ( 0 ); + + private int _id; + + private OPCENUMSCOPE ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCENUMSCOPE fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_ENUM_PRIVATE_CONNECTIONS; + case 2: + return OPC_ENUM_PUBLIC_CONNECTIONS; + case 3: + return OPC_ENUM_ALL_CONNECTIONS; + case 4: + return OPC_ENUM_PRIVATE; + case 5: + return OPC_ENUM_PUBLIC; + case 6: + return OPC_ENUM_ALL; + default: + return OPC_ENUM_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCGroupState.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCGroupState.java new file mode 100644 index 0000000..42c0101 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCGroupState.java @@ -0,0 +1,119 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public class OPCGroupState +{ + private int _updateRate = 1000; + + private boolean _active = true; + + private String _name = ""; + + private int _timeBias = 0; + + private float _percentDeadband = 0.0f; + + private int _localeID = 0; + + private int _clientHandle = 0; + + private int _serverHandle = 0; + + public boolean isActive () + { + return this._active; + } + + public void setActive ( final boolean active ) + { + this._active = active; + } + + public int getClientHandle () + { + return this._clientHandle; + } + + public void setClientHandle ( final int clientHandle ) + { + this._clientHandle = clientHandle; + } + + public int getLocaleID () + { + return this._localeID; + } + + public void setLocaleID ( final int localeID ) + { + this._localeID = localeID; + } + + public String getName () + { + return this._name; + } + + public void setName ( final String name ) + { + this._name = name; + } + + public float getPercentDeadband () + { + return this._percentDeadband; + } + + public void setPercentDeadband ( final float percentDeadband ) + { + this._percentDeadband = percentDeadband; + } + + public int getServerHandle () + { + return this._serverHandle; + } + + public void setServerHandle ( final int serverHandle ) + { + this._serverHandle = serverHandle; + } + + public int getTimeBias () + { + return this._timeBias; + } + + public void setTimeBias ( final int timeBias ) + { + this._timeBias = timeBias; + } + + public int getUpdateRate () + { + return this._updateRate; + } + + public void setUpdateRate ( final int updateRate ) + { + this._updateRate = updateRate; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMDEF.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMDEF.java new file mode 100644 index 0000000..206b9fa --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMDEF.java @@ -0,0 +1,124 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2012 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIStruct; +import org.jinterop.dcom.core.JIVariant; + +public class OPCITEMDEF +{ + private String accessPath = ""; + + private String itemID = ""; + + private boolean active = true; + + private int clientHandle; + + private short requestedDataType = JIVariant.VT_EMPTY; + + private short reserved; + + public String getAccessPath () + { + return this.accessPath; + } + + public void setAccessPath ( final String accessPath ) + { + this.accessPath = accessPath; + } + + public int getClientHandle () + { + return this.clientHandle; + } + + public void setClientHandle ( final int clientHandle ) + { + this.clientHandle = clientHandle; + } + + public boolean isActive () + { + return this.active; + } + + public void setActive ( final boolean active ) + { + this.active = active; + } + + public String getItemID () + { + return this.itemID; + } + + public void setItemID ( final String itemID ) + { + this.itemID = itemID; + } + + public short getRequestedDataType () + { + return this.requestedDataType; + } + + public void setRequestedDataType ( final short requestedDataType ) + { + this.requestedDataType = requestedDataType; + } + + public short getReserved () + { + return this.reserved; + } + + public void setReserved ( final short reserved ) + { + this.reserved = reserved; + } + + /** + * Convert to structure to a J-Interop structure + * + * @return the j-interop structe + * @throws JIException + */ + public JIStruct toStruct () throws JIException + { + final JIStruct struct = new JIStruct (); + struct.addMember ( new JIString ( getAccessPath (), JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ); + struct.addMember ( new JIString ( getItemID (), JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ); + struct.addMember ( new Integer ( isActive () ? 1 : 0 ) ); + struct.addMember ( Integer.valueOf ( getClientHandle () ) ); + + struct.addMember ( Integer.valueOf ( 0 ) ); // blob size + struct.addMember ( new JIPointer ( null ) ); // blob + + struct.addMember ( Short.valueOf ( getRequestedDataType () ) ); + struct.addMember ( Short.valueOf ( getReserved () ) ); + return struct; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMRESULT.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMRESULT.java new file mode 100644 index 0000000..6e1d9fc --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMRESULT.java @@ -0,0 +1,104 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIStruct; +import org.jinterop.dcom.core.JIVariant; + +public class OPCITEMRESULT +{ + private int _serverHandle = 0; + + private short _canonicalDataType = JIVariant.VT_EMPTY; + + private short _reserved = 0; + + private int _accessRights = 0; + + public int getAccessRights () + { + return this._accessRights; + } + + public void setAccessRights ( final int accessRights ) + { + this._accessRights = accessRights; + } + + public short getCanonicalDataType () + { + return this._canonicalDataType; + } + + public void setCanonicalDataType ( final short canonicalDataType ) + { + this._canonicalDataType = canonicalDataType; + } + + public short getReserved () + { + return this._reserved; + } + + public void setReserved ( final short reserved ) + { + this._reserved = reserved; + } + + public int getServerHandle () + { + return this._serverHandle; + } + + public void setServerHandle ( final int serverHandle ) + { + this._serverHandle = serverHandle; + } + + public static JIStruct getStruct () throws JIException + { + JIStruct struct = new JIStruct (); + + struct.addMember ( Integer.class ); // Server handle + struct.addMember ( Short.class ); // data type + struct.addMember ( Short.class ); // reserved + struct.addMember ( Integer.class ); // access rights + struct.addMember ( Integer.class ); // blob size + // grab the normally unused byte array + struct.addMember ( new JIPointer ( new JIArray ( Byte.class, null, 1, true, false ) ) ); + + return struct; + } + + public static OPCITEMRESULT fromStruct ( final JIStruct struct ) + { + OPCITEMRESULT result = new OPCITEMRESULT (); + + result.setServerHandle ( new Integer ( (Integer)struct.getMember ( 0 ) ) ); + result.setCanonicalDataType ( new Short ( (Short)struct.getMember ( 1 ) ) ); + result.setReserved ( new Short ( (Short)struct.getMember ( 2 ) ) ); + result.setAccessRights ( new Integer ( (Integer)struct.getMember ( 3 ) ) ); + + return result; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMSTATE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMSTATE.java new file mode 100644 index 0000000..040fa84 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCITEMSTATE.java @@ -0,0 +1,114 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIStruct; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.FILETIME; + +public class OPCITEMSTATE +{ + private int _clientHandle = 0; + + private FILETIME _timestamp = null; + + private short _quality = 0; + + private short _reserved = 0; + + private JIVariant _value = null; + + public int getClientHandle () + { + return this._clientHandle; + } + + public void setClientHandle ( final int clientHandle ) + { + this._clientHandle = clientHandle; + } + + public short getQuality () + { + return this._quality; + } + + public void setQuality ( final short quality ) + { + this._quality = quality; + } + + public short getReserved () + { + return this._reserved; + } + + public void setReserved ( final short reserved ) + { + this._reserved = reserved; + } + + public FILETIME getTimestamp () + { + return this._timestamp; + } + + public void setTimestamp ( final FILETIME timestamp ) + { + this._timestamp = timestamp; + } + + public JIVariant getValue () + { + return this._value; + } + + public void setValue ( final JIVariant value ) + { + this._value = value; + } + + public static JIStruct getStruct () throws JIException + { + JIStruct struct = new JIStruct (); + + struct.addMember ( Integer.class ); + struct.addMember ( FILETIME.getStruct () ); + struct.addMember ( Short.class ); + struct.addMember ( Short.class ); + struct.addMember ( JIVariant.class ); + + return struct; + } + + public static OPCITEMSTATE fromStruct ( final JIStruct struct ) + { + OPCITEMSTATE itemState = new OPCITEMSTATE (); + + itemState.setClientHandle ( (Integer)struct.getMember ( 0 ) ); + itemState.setTimestamp ( FILETIME.fromStruct ( (JIStruct)struct.getMember ( 1 ) ) ); + itemState.setQuality ( (Short)struct.getMember ( 2 ) ); + itemState.setReserved ( (Short)struct.getMember ( 3 ) ); + itemState.setValue ( (JIVariant)struct.getMember ( 4 ) ); + + return itemState; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCNAMESPACETYPE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCNAMESPACETYPE.java new file mode 100644 index 0000000..ab5f375 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCNAMESPACETYPE.java @@ -0,0 +1,52 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCNAMESPACETYPE +{ + OPC_NS_HIERARCHIAL ( 1 ), + OPC_NS_FLAT ( 2 ), + OPC_NS_UNKNOWN ( 0 ); + + private int _id; + + private OPCNAMESPACETYPE ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCNAMESPACETYPE fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_NS_HIERARCHIAL; + case 2: + return OPC_NS_FLAT; + default: + return OPC_NS_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATE.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATE.java new file mode 100644 index 0000000..81f6267 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATE.java @@ -0,0 +1,64 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public enum OPCSERVERSTATE +{ + OPC_STATUS_RUNNING ( 1 ), + OPC_STATUS_FAILED ( 2 ), + OPC_STATUS_NOCONFIG ( 3 ), + OPC_STATUS_SUSPENDED ( 4 ), + OPC_STATUS_TEST ( 5 ), + OPC_STATUS_COMM_FAULT ( 6 ), + OPC_STATUS_UNKNOWN ( 0 ); + + private int _id; + + private OPCSERVERSTATE ( final int id ) + { + this._id = id; + } + + public int id () + { + return this._id; + } + + public static OPCSERVERSTATE fromID ( final int id ) + { + switch ( id ) + { + case 1: + return OPC_STATUS_RUNNING; + case 2: + return OPC_STATUS_FAILED; + case 3: + return OPC_STATUS_NOCONFIG; + case 4: + return OPC_STATUS_SUSPENDED; + case 5: + return OPC_STATUS_TEST; + case 6: + return OPC_STATUS_COMM_FAULT; + default: + return OPC_STATUS_UNKNOWN; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATUS.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATUS.java new file mode 100644 index 0000000..2633d14 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/OPCSERVERSTATUS.java @@ -0,0 +1,201 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIStruct; +import org.openscada.opc.dcom.common.FILETIME; + +public class OPCSERVERSTATUS +{ + private FILETIME _startTime = null; + + private FILETIME _currentTime = null; + + private FILETIME _lastUpdateTime = null; + + private OPCSERVERSTATE _serverState = null; + + private int _groupCount = -1; + + private int _bandWidth = -1; + + private short _majorVersion = -1; + + private short _minorVersion = -1; + + private short _buildNumber = -1; + + private short _reserved = 0; + + private String _vendorInfo = null; + + public int getBandWidth () + { + return this._bandWidth; + } + + public void setBandWidth ( final int bandWidth ) + { + this._bandWidth = bandWidth; + } + + public short getBuildNumber () + { + return this._buildNumber; + } + + public void setBuildNumber ( final short buildNumber ) + { + this._buildNumber = buildNumber; + } + + public FILETIME getCurrentTime () + { + return this._currentTime; + } + + public void setCurrentTime ( final FILETIME currentTime ) + { + this._currentTime = currentTime; + } + + public int getGroupCount () + { + return this._groupCount; + } + + public void setGroupCount ( final int groupCount ) + { + this._groupCount = groupCount; + } + + public FILETIME getLastUpdateTime () + { + return this._lastUpdateTime; + } + + public void setLastUpdateTime ( final FILETIME lastUpdateTime ) + { + this._lastUpdateTime = lastUpdateTime; + } + + public short getMajorVersion () + { + return this._majorVersion; + } + + public void setMajorVersion ( final short majorVersion ) + { + this._majorVersion = majorVersion; + } + + public short getMinorVersion () + { + return this._minorVersion; + } + + public void setMinorVersion ( final short minorVersion ) + { + this._minorVersion = minorVersion; + } + + public short getReserved () + { + return this._reserved; + } + + public void setReserved ( final short reserved ) + { + this._reserved = reserved; + } + + public FILETIME getStartTime () + { + return this._startTime; + } + + public void setStartTime ( final FILETIME startTime ) + { + this._startTime = startTime; + } + + public String getVendorInfo () + { + return this._vendorInfo; + } + + public void setVendorInfo ( final String vendorInfo ) + { + this._vendorInfo = vendorInfo; + } + + public OPCSERVERSTATE getServerState () + { + return this._serverState; + } + + public void setServerState ( final OPCSERVERSTATE dwServerState ) + { + this._serverState = dwServerState; + } + + public static JIStruct getStruct () throws JIException + { + JIStruct struct = new JIStruct (); + + struct.addMember ( FILETIME.getStruct () ); + struct.addMember ( FILETIME.getStruct () ); + struct.addMember ( FILETIME.getStruct () ); + struct.addMember ( Short.class ); // enum: OPCSERVERSTATE + struct.addMember ( Integer.class ); + struct.addMember ( Integer.class ); + struct.addMember ( Short.class ); + struct.addMember ( Short.class ); + struct.addMember ( Short.class ); + struct.addMember ( Short.class ); + struct.addMember ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ) ); + + return struct; + } + + public static OPCSERVERSTATUS fromStruct ( final JIStruct struct ) + { + OPCSERVERSTATUS status = new OPCSERVERSTATUS (); + + status._startTime = FILETIME.fromStruct ( (JIStruct)struct.getMember ( 0 ) ); + status._currentTime = FILETIME.fromStruct ( (JIStruct)struct.getMember ( 1 ) ); + status._lastUpdateTime = FILETIME.fromStruct ( (JIStruct)struct.getMember ( 2 ) ); + + status._serverState = OPCSERVERSTATE.fromID ( (Short)struct.getMember ( 3 ) ); + status._groupCount = (Integer)struct.getMember ( 4 ); + status._bandWidth = (Integer)struct.getMember ( 5 ); + status._majorVersion = (Short)struct.getMember ( 6 ); + status._minorVersion = (Short)struct.getMember ( 7 ); + status._buildNumber = (Short)struct.getMember ( 8 ); + status._reserved = (Short)struct.getMember ( 9 ); + status._vendorInfo = ( (JIString) ( (JIPointer)struct.getMember ( 10 ) ).getReferent () ).getString (); + + return status; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/PropertyDescription.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/PropertyDescription.java new file mode 100644 index 0000000..eab7c9f --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/PropertyDescription.java @@ -0,0 +1,59 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +public class PropertyDescription +{ + private int _id = -1; + + private String _description = ""; + + private short _varType = 0; + + public String getDescription () + { + return this._description; + } + + public void setDescription ( final String description ) + { + this._description = description; + } + + public int getId () + { + return this._id; + } + + public void setId ( final int id ) + { + this._id = id; + } + + public short getVarType () + { + return this._varType; + } + + public void setVarType ( final short varType ) + { + this._varType = varType; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/ValueData.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/ValueData.java new file mode 100644 index 0000000..ed44aa3 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/ValueData.java @@ -0,0 +1,65 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import java.util.Calendar; + +import org.jinterop.dcom.core.JIVariant; + +public class ValueData +{ + private JIVariant value; + + private short quality; + + private Calendar timestamp; + + public short getQuality () + { + return this.quality; + } + + public void setQuality ( final short quality ) + { + this.quality = quality; + } + + public Calendar getTimestamp () + { + return this.timestamp; + } + + public void setTimestamp ( final Calendar timestamp ) + { + this.timestamp = timestamp; + } + + public JIVariant getValue () + { + return this.value; + } + + public void setValue ( final JIVariant value ) + { + this.value = value; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/WriteRequest.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/WriteRequest.java new file mode 100644 index 0000000..acb656a --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/WriteRequest.java @@ -0,0 +1,80 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da; + +import org.jinterop.dcom.core.JIVariant; + +/** + * Data for a write request to the server + * + * @author Jens Reimann + */ +public class WriteRequest +{ + private int serverHandle = 0; + + private JIVariant value = JIVariant.EMPTY (); + + public WriteRequest () + { + } + + public WriteRequest ( final WriteRequest request ) + { + this.serverHandle = request.serverHandle; + this.value = request.value; + } + + /** + * Create a new write request with pre-fille data + * + * @param serverHandle + * the server handle of the item to write to + * @param value + * the value to write. + */ + public WriteRequest ( final int serverHandle, final JIVariant value ) + { + this.serverHandle = serverHandle; + this.value = value; + } + + public int getServerHandle () + { + return this.serverHandle; + } + + public void setServerHandle ( final int serverHandle ) + { + this.serverHandle = serverHandle; + } + + public JIVariant getValue () + { + return this.value; + } + + public void setValue ( final JIVariant value ) + { + this.value = value; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCAsyncIO2.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCAsyncIO2.java new file mode 100644 index 0000000..d4138f6 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCAsyncIO2.java @@ -0,0 +1,141 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.OPCDATASOURCE; + +public class OPCAsyncIO2 extends BaseCOMObject +{ + public class AsyncResult + { + private final ResultSet result; + + private final Integer cancelId; + + public AsyncResult () + { + super (); + this.result = new ResultSet (); + this.cancelId = null; + } + + public AsyncResult ( final ResultSet result, final Integer cancelId ) + { + super (); + this.result = result; + this.cancelId = cancelId; + } + + public Integer getCancelId () + { + return this.cancelId; + } + + public ResultSet getResult () + { + return this.result; + } + } + + public OPCAsyncIO2 ( final IJIComObject opcAsyncIO2 ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcAsyncIO2.queryInterface ( Constants.IOPCAsyncIO2_IID ) ); + } + + public void setEnable ( final boolean state ) throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 4 ); + + callObject.addInParamAsInt ( state ? 1 : 0, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public int refresh ( final OPCDATASOURCE dataSource, final int transactionID ) throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsShort ( (short)dataSource.id (), JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( transactionID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + final Object result[] = getCOMObject ().call ( callObject ); + + return (Integer)result[0]; + } + + public void cancel ( final int cancelId ) throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addInParamAsInt ( cancelId, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public AsyncResult read ( final int transactionId, final Integer... serverHandles ) throws JIException + { + if ( serverHandles == null || serverHandles.length == 0 ) + { + return new AsyncResult (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsInt ( serverHandles.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( serverHandles, true ), JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( transactionId, JIFlags.FLAG_NULL ); + + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object[] result = getCOMObject ().call ( callObject ); + + final Integer cancelId = (Integer)result[0]; + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + final ResultSet resultSet = new ResultSet (); + + for ( int i = 0; i < serverHandles.length; i++ ) + { + resultSet.add ( new Result ( serverHandles[i], errorCodes[i] ) ); + } + + return new AsyncResult ( resultSet, cancelId ); + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowse.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowse.java new file mode 100644 index 0000000..8a640d2 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowse.java @@ -0,0 +1,35 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.da.Constants; + +public class OPCBrowse extends BaseCOMObject +{ + public OPCBrowse ( final IJIComObject opcServer ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcServer.queryInterface ( Constants.IOPCBrowse_IID ) ); + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowseServerAddressSpace.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowseServerAddressSpace.java new file mode 100644 index 0000000..f21c82e --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCBrowseServerAddressSpace.java @@ -0,0 +1,157 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.EnumString; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.OPCBROWSEDIRECTION; +import org.openscada.opc.dcom.da.OPCBROWSETYPE; +import org.openscada.opc.dcom.da.OPCNAMESPACETYPE; + +/** + * Implementation for IOPCBrowseServerAddressSpace + * @author Jens Reimann + * + */ +public class OPCBrowseServerAddressSpace extends BaseCOMObject +{ + public OPCBrowseServerAddressSpace ( final IJIComObject opcServer ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcServer.queryInterface ( Constants.IOPCBrowseServerAddressSpace_IID ) ); + } + + /** + * Get the information how the namespace is organized + * @return the organization of the namespace + * @throws JIException + */ + public OPCNAMESPACETYPE queryOrganization () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addOutParamAsType ( Short.class, JIFlags.FLAG_NULL ); + + Object result[] = getCOMObject ().call ( callObject ); + + return OPCNAMESPACETYPE.fromID ( (Short)result[0] ); + } + + /** + * Direct the browser to another position + * + * Depending on the direction the new position will be set based on the provided + * position information. If the direction is {@link OPCBROWSEDIRECTION#OPC_BROWSE_TO} then + * the position is the item to go to. If the direction is {@link OPCBROWSEDIRECTION#OPC_BROWSE_DOWN} + * the browser will descent into the tree down (not to) the branch item in position. + * Passing {@link OPCBROWSEDIRECTION#OPC_BROWSE_UP} won't need a position (pass null) + * and will ascent in the tree one level. + * + * Passing {@link OPCBROWSEDIRECTION#OPC_BROWSE_TO} and null as position will + * go to the first root entry of the namespace. + * + * @param position The item position reference for the direction + * @param direction The direction to go based on the position + * @throws JIException + */ + public void changePosition ( final String position, final OPCBROWSEDIRECTION direction ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsShort ( (short)direction.id (), JIFlags.FLAG_NULL ); + callObject.addInParamAsString ( position, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + + getCOMObject ().call ( callObject ); + + } + + public EnumString browse ( final OPCBROWSETYPE browseType, final String filterCriteria, final int accessRights, final int dataType ) throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsShort ( (short)browseType.id (), JIFlags.FLAG_NULL ); + callObject.addInParamAsString ( filterCriteria, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsShort ( (short)dataType, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( accessRights, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + return new EnumString ( (IJIComObject)result[0] ); + } + + /** + * Return the possible access paths for an item + * @param itemID the item to query + * @return A string enumerator for the possible access paths + * @throws JIException + * @throws IllegalArgumentException + * @throws UnknownHostException + */ + public EnumString browseAccessPaths ( final String itemID ) throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 4 ); + + callObject.addInParamAsString ( itemID, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + return new EnumString ( (IJIComObject)result[0] ); + } + + /** + * Get the complete item id from an item at the local position. + * + * Browsing a hierarchical namespace the browse method will return items based on the + * local level in the namespace. So actually only the last part of the item ID hierarchy + * is returned. In order to convert this to the full item ID one can use this method. It + * will only work if the browser is still at the position in question. + * + * @param item the local item + * @return the complete item ID + * @throws JIException + */ + public String getItemID ( final String item ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addInParamAsString ( item, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addOutParamAsObject ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + return ( (JIString) ( (JIPointer)result[0] ).getReferent () ).getString (); + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCDataCallback.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCDataCallback.java new file mode 100644 index 0000000..d940777 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCDataCallback.java @@ -0,0 +1,259 @@ +/* + * This file is part of the OpenSCADA project + * + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * Copyright (C) 2013 Jens Reimann (ctron@dentrassi.de) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.util.LinkedList; +import java.util.List; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JILocalCoClass; +import org.jinterop.dcom.core.JILocalInterfaceDefinition; +import org.jinterop.dcom.core.JILocalMethodDescriptor; +import org.jinterop.dcom.core.JILocalParamsDescriptor; +import org.jinterop.dcom.core.JIStruct; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.FILETIME; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.EventHandlerImpl; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.IOPCDataCallback; +import org.openscada.opc.dcom.da.ValueData; + +public class OPCDataCallback extends EventHandlerImpl +{ + private IOPCDataCallback callback = null; + + private JILocalCoClass coClass = null; + + public OPCDataCallback () + { + super (); + } + + public Object[] OnDataChange ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final int count, final JIArray clientHandles, final JIArray values, final JIArray qualities, final JIArray timestamps, final JIArray errors ) + { + final IOPCDataCallback callback = this.callback; + if ( callback == null ) + { + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + // get arrays for more readable code later ;-) + final Integer[] errorCodes = (Integer[])errors.getArrayInstance (); + final Integer[] itemHandles = (Integer[])clientHandles.getArrayInstance (); + final Short[] qualitiesArray = (Short[])qualities.getArrayInstance (); + final JIVariant[] valuesArray = (JIVariant[])values.getArrayInstance (); + final JIStruct[] timestampArray = (JIStruct[])timestamps.getArrayInstance (); + + // create result data + final KeyedResultSet result = new KeyedResultSet (); + for ( int i = 0; i < count; i++ ) + { + final ValueData vd = new ValueData (); + vd.setQuality ( qualitiesArray[i] ); + vd.setTimestamp ( FILETIME.fromStruct ( timestampArray[i] ).asCalendar () ); + vd.setValue ( valuesArray[i] ); + result.add ( new KeyedResult ( itemHandles[i], vd, errorCodes[i] ) ); + } + + // fire event + try + { + callback.dataChange ( transactionId, serverGroupHandle, masterQuality, masterErrorCode, result ); + } + catch ( final Throwable e ) + { + e.printStackTrace (); + } + + // The client must always return S_OK + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + public synchronized Object[] OnReadComplete ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final int count, final JIArray clientHandles, final JIArray values, final JIArray qualities, final JIArray timestamps, final JIArray errors ) + { + if ( this.callback == null ) + { + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + // get arrays for more readable code later ;-) + final Integer[] errorCodes = (Integer[])errors.getArrayInstance (); + final Integer[] itemHandles = (Integer[])clientHandles.getArrayInstance (); + final Short[] qualitiesArray = (Short[])qualities.getArrayInstance (); + final JIVariant[] valuesArray = (JIVariant[])values.getArrayInstance (); + final JIStruct[] timestampArray = (JIStruct[])timestamps.getArrayInstance (); + + // create result data + final KeyedResultSet result = new KeyedResultSet (); + for ( int i = 0; i < count; i++ ) + { + final ValueData vd = new ValueData (); + vd.setQuality ( qualitiesArray[i] ); + vd.setTimestamp ( FILETIME.fromStruct ( timestampArray[i] ).asCalendar () ); + vd.setValue ( valuesArray[i] ); + result.add ( new KeyedResult ( itemHandles[i], vd, errorCodes[i] ) ); + } + + // fire event + try + { + this.callback.readComplete ( transactionId, serverGroupHandle, masterQuality, masterErrorCode, result ); + } + catch ( final Throwable e ) + { + e.printStackTrace (); + } + + // The client must always return S_OK + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + public synchronized Object[] OnWriteComplete ( final int transactionId, final int serverGroupHandle, final int masterErrorCode, final int count, final JIArray clientHandles, final JIArray errors ) + { + if ( this.callback == null ) + { + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + // get arrays for more readable code later ;-) + final Integer[] errorCodes = (Integer[])errors.getArrayInstance (); + final Integer[] itemHandles = (Integer[])clientHandles.getArrayInstance (); + + // create result data + final ResultSet result = new ResultSet (); + for ( int i = 0; i < count; i++ ) + { + result.add ( new Result ( itemHandles[i], errorCodes[i] ) ); + } + + // fire event + try + { + this.callback.writeComplete ( transactionId, serverGroupHandle, masterErrorCode, result ); + } + catch ( final Throwable e ) + { + e.printStackTrace (); + } + + // The client must always return S_OK + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + public synchronized Object[] OnCancelComplete ( final int transactionId, final int serverGroupHandle ) + { + if ( this.callback == null ) + { + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + this.callback.cancelComplete ( transactionId, serverGroupHandle ); + + // The client must always return S_OK + return new Object[] { org.openscada.opc.dcom.common.Constants.S_OK }; + } + + public synchronized JILocalCoClass getCoClass () throws JIException + { + if ( this.coClass != null ) + { + return this.coClass; + } + + this.coClass = new JILocalCoClass ( new JILocalInterfaceDefinition ( Constants.IOPCDataCallback_IID, false ), this, false ); + + JILocalParamsDescriptor params; + JILocalMethodDescriptor method; + + // OnDataChange + params = new JILocalParamsDescriptor (); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); // trans id + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); // group handle + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); // master quality + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); // master error + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); // count + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); // item handles + params.addInParamAsObject ( new JIArray ( JIVariant.class, null, 1, true ), JIFlags.FLAG_NULL ); // values + params.addInParamAsObject ( new JIArray ( Short.class, null, 1, true ), JIFlags.FLAG_NULL ); // qualities + params.addInParamAsObject ( new JIArray ( FILETIME.getStruct (), null, 1, true ), JIFlags.FLAG_NULL ); // timestamps + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); // errors + + method = new JILocalMethodDescriptor ( "OnDataChange", params ); + this.coClass.getInterfaceDefinition ().addMethodDescriptor ( method ); + + // OnReadComplete + params = new JILocalParamsDescriptor (); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( JIVariant.class, null, 1, true ), JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( Short.class, null, 1, true ), JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( FILETIME.getStruct (), null, 1, true ), JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); + method = new JILocalMethodDescriptor ( "OnReadComplete", params ); + this.coClass.getInterfaceDefinition ().addMethodDescriptor ( method ); + + // OnWriteComplete + params = new JILocalParamsDescriptor (); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); + params.addInParamAsObject ( new JIArray ( Integer.class, null, 1, true ), JIFlags.FLAG_NULL ); + method = new JILocalMethodDescriptor ( "OnWriteComplete", params ); + this.coClass.getInterfaceDefinition ().addMethodDescriptor ( method ); + + // OnCancelComplete + params = new JILocalParamsDescriptor (); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + params.addInParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + method = new JILocalMethodDescriptor ( "OnCancelComplete", params ); + this.coClass.getInterfaceDefinition ().addMethodDescriptor ( method ); + + // Add supported event interfaces + final List eventInterfaces = new LinkedList (); + eventInterfaces.add ( Constants.IOPCDataCallback_IID ); + this.coClass.setSupportedEventInterfaces ( eventInterfaces ); + + return this.coClass; + } + + public void setCallback ( final IOPCDataCallback callback ) + { + this.callback = callback; + } + + public IOPCDataCallback getCallback () + { + return this.callback; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCGroupStateMgt.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCGroupStateMgt.java new file mode 100644 index 0000000..e78e45d --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCGroupStateMgt.java @@ -0,0 +1,218 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIFrameworkHelper; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.impls.JIObjectFactory; +import org.openscada.opc.dcom.common.EventHandler; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.IOPCDataCallback; +import org.openscada.opc.dcom.da.OPCGroupState; + +/** + * Implementation of IOPCGroupStateMgt + * + * @author Jens Reimann + */ +public class OPCGroupStateMgt extends BaseCOMObject +{ + public OPCGroupStateMgt ( final IJIComObject opcGroup ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcGroup.queryInterface ( Constants.IOPCGroupStateMgt_IID ) ); + } + + public OPCGroupState getState () throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Boolean.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Float.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + final Object result[] = getCOMObject ().call ( callObject ); + + final OPCGroupState state = new OPCGroupState (); + state.setUpdateRate ( (Integer)result[0] ); + state.setActive ( (Boolean)result[1] ); + state.setName ( ( (JIString) ( (JIPointer)result[2] ).getReferent () ).getString () ); + state.setTimeBias ( (Integer)result[3] ); + state.setPercentDeadband ( (Float)result[4] ); + state.setLocaleID ( (Integer)result[5] ); + state.setClientHandle ( (Integer)result[6] ); + state.setServerHandle ( (Integer)result[7] ); + + return state; + } + + /** + * Set the group state Leaving any of the parameters null will keep the current value untouched. + * + * @param requestedUpdateRate + * the requested update rate + * @param active + * Flag if the group is active or not + * @param timeBias + * The time bias + * @param percentDeadband + * the deadband percent + * @param localeID + * the locale ID + * @param clientHandle + * the client handle + * @return the granted update rate + * @throws JIException + */ + public int setState ( final Integer requestedUpdateRate, final Boolean active, final Integer timeBias, final Float percentDeadband, final Integer localeID, final Integer clientHandle ) throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsPointer ( new JIPointer ( requestedUpdateRate ), JIFlags.FLAG_NULL ); + if ( active != null ) + { + callObject.addInParamAsPointer ( new JIPointer ( Integer.valueOf ( active.booleanValue () ? 1 : 0 ) ), JIFlags.FLAG_NULL ); + } + else + { + callObject.addInParamAsPointer ( new JIPointer ( null ), JIFlags.FLAG_NULL ); + } + callObject.addInParamAsPointer ( new JIPointer ( timeBias ), JIFlags.FLAG_NULL ); + callObject.addInParamAsPointer ( new JIPointer ( percentDeadband ), JIFlags.FLAG_NULL ); + callObject.addInParamAsPointer ( new JIPointer ( localeID ), JIFlags.FLAG_NULL ); + callObject.addInParamAsPointer ( new JIPointer ( clientHandle ), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + final Object[] result = getCOMObject ().call ( callObject ); + + return (Integer)result[0]; + } + + public OPCItemMgt getItemManagement () throws JIException + { + return new OPCItemMgt ( getCOMObject () ); + } + + /** + * Rename to group + * + * @param name + * the new name + * @throws JIException + */ + public void setName ( final String name ) throws JIException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsString ( name, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + + getCOMObject ().call ( callObject ); + } + + /** + * Clone the group + * + * @param name + * the name of the cloned group + * @return The cloned group + * @throws JIException + * @throws UnknownHostException + * @throws IllegalArgumentException + */ + public OPCGroupStateMgt clone ( final String name ) throws JIException, IllegalArgumentException, UnknownHostException + { + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addInParamAsString ( name, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsUUID ( Constants.IOPCGroupStateMgt_IID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + final Object[] result = getCOMObject ().call ( callObject ); + return new OPCGroupStateMgt ( (IJIComObject)result[0] ); + } + + /** + * Attach a new callback to the group + * + * @param callback + * The callback to attach + * @return The event handler information + * @throws JIException + */ + public EventHandler attach ( final IOPCDataCallback callback ) throws JIException + { + final OPCDataCallback callbackObject = new OPCDataCallback (); + + callbackObject.setCallback ( callback ); + + // sync the callback object so that no calls get through the callback + // until the callback information is set + // If happens in some cases that the callback is triggered before + // the method attachEventHandler returns. + synchronized ( callbackObject ) + { + final String id = JIFrameworkHelper.attachEventHandler ( getCOMObject (), Constants.IOPCDataCallback_IID, JIObjectFactory.buildObject ( getCOMObject ().getAssociatedSession (), callbackObject.getCoClass () ) ); + + callbackObject.setInfo ( getCOMObject (), id ); + } + return callbackObject; + } + + public OPCAsyncIO2 getAsyncIO2 () + { + try + { + return new OPCAsyncIO2 ( getCOMObject () ); + } + catch ( final Exception e ) + { + return null; + } + } + + public OPCSyncIO getSyncIO () + { + try + { + return new OPCSyncIO ( getCOMObject () ); + } + catch ( final Exception e ) + { + return null; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemIO.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemIO.java new file mode 100644 index 0000000..53916a4 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemIO.java @@ -0,0 +1,73 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.FILETIME; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.IORequest; + +public class OPCItemIO extends BaseCOMObject +{ + public OPCItemIO ( final IJIComObject opcItemIO ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcItemIO.queryInterface ( Constants.IOPCItemIO_IID ) ); + } + + public void read ( final IORequest[] requests ) throws JIException + { + if ( requests.length == 0 ) + { + return; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + JIString itemIDs[] = new JIString[requests.length]; + Integer maxAges[] = new Integer[requests.length]; + for ( int i = 0; i < requests.length; i++ ) + { + itemIDs[i] = new JIString ( requests[i].getItemID (), JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + maxAges[i] = new Integer ( requests[i].getMaxAge () ); + } + + callObject.addInParamAsInt ( requests.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( itemIDs, true ), JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( maxAges, true ), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( JIVariant.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( FILETIME.getStruct (), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemMgt.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemMgt.java new file mode 100644 index 0000000..5932270 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemMgt.java @@ -0,0 +1,211 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2012 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIStruct; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.OPCITEMDEF; +import org.openscada.opc.dcom.da.OPCITEMRESULT; + +public class OPCItemMgt extends BaseCOMObject +{ + public OPCItemMgt ( final IJIComObject opcGroup ) throws JIException + { + super ( opcGroup.queryInterface ( Constants.IOPCItemMgt_IID ) ); + } + + public KeyedResultSet validate ( final OPCITEMDEF... items ) throws JIException + { + if ( items.length == 0 ) + { + return new KeyedResultSet (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + final JIStruct struct[] = new JIStruct[items.length]; + for ( int i = 0; i < items.length; i++ ) + { + struct[i] = items[i].toStruct (); + } + final JIArray itemArray = new JIArray ( struct, true ); + + callObject.addInParamAsInt ( items.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( itemArray, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( 0, JIFlags.FLAG_NULL ); // don't update blobs + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( OPCITEMRESULT.getStruct (), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + final JIStruct[] results = (JIStruct[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + final KeyedResultSet resultList = new KeyedResultSet ( items.length ); + for ( int i = 0; i < items.length; i++ ) + { + final OPCITEMRESULT itemResult = OPCITEMRESULT.fromStruct ( results[i] ); + final KeyedResult resultEntry = new KeyedResult ( items[i], itemResult, errorCodes[i] ); + resultList.add ( resultEntry ); + } + + return resultList; + } + + public KeyedResultSet add ( final OPCITEMDEF... items ) throws JIException + { + if ( items.length == 0 ) + { + return new KeyedResultSet (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + final JIStruct struct[] = new JIStruct[items.length]; + for ( int i = 0; i < items.length; i++ ) + { + struct[i] = items[i].toStruct (); + } + final JIArray itemArray = new JIArray ( struct, true ); + + callObject.addInParamAsInt ( items.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( itemArray, JIFlags.FLAG_NULL ); + + /* + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( OPCITEMRESULT.getStruct (), null, 1, true ) ), + JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), + JIFlags.FLAG_NULL ); + */ + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( OPCITEMRESULT.getStruct (), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + final JIStruct[] results = (JIStruct[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + final KeyedResultSet resultList = new KeyedResultSet ( items.length ); + for ( int i = 0; i < items.length; i++ ) + { + final OPCITEMRESULT itemResult = OPCITEMRESULT.fromStruct ( results[i] ); + final KeyedResult resultEntry = new KeyedResult ( items[i], itemResult, errorCodes[i] ); + resultList.add ( resultEntry ); + } + + return resultList; + } + + public ResultSet remove ( final Integer... serverHandles ) throws JIException + { + if ( serverHandles.length == 0 ) + { + return new ResultSet (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsInt ( serverHandles.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( serverHandles, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + final ResultSet results = new ResultSet ( serverHandles.length ); + for ( int i = 0; i < serverHandles.length; i++ ) + { + results.add ( new Result ( serverHandles[i], errorCodes[i] ) ); + } + return results; + } + + public ResultSet setActiveState ( final boolean state, final Integer... items ) throws JIException + { + if ( items.length == 0 ) + { + return new ResultSet (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addInParamAsInt ( items.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( items, true ), JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( state ? 1 : 0, JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + final ResultSet results = new ResultSet ( items.length ); + for ( int i = 0; i < items.length; i++ ) + { + results.add ( new Result ( items[i], errorCodes[i] ) ); + } + return results; + } + + public ResultSet setClientHandles ( final Integer[] serverHandles, final Integer[] clientHandles ) throws JIException + { + if ( serverHandles.length != clientHandles.length ) + { + throw new JIException ( 0, "Array sizes don't match" ); + } + if ( serverHandles.length == 0 ) + { + return new ResultSet (); + } + + final JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 4 ); + + callObject.addInParamAsInt ( serverHandles.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( serverHandles, true ), JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( clientHandles, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + final Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + final Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + final ResultSet results = new ResultSet ( serverHandles.length ); + for ( int i = 0; i < serverHandles.length; i++ ) + { + results.add ( new Result ( serverHandles[i], errorCodes[i] ) ); + } + return results; + } + +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemProperties.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemProperties.java new file mode 100644 index 0000000..424a32c --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCItemProperties.java @@ -0,0 +1,154 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.PropertyDescription; + +public class OPCItemProperties extends BaseCOMObject +{ + public OPCItemProperties ( final IJIComObject opcItemProperties ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcItemProperties.queryInterface ( Constants.IOPCItemProperties_IID ) ); + } + + public Collection queryAvailableProperties ( final String itemID ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsString ( itemID, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_BSTR ), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Short.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object result[] = getCOMObject ().call ( callObject ); + + List properties = new LinkedList (); + + int len = (Integer)result[0]; + Integer[] ids = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + JIString[] descriptions = (JIString[]) ( (JIArray) ( (JIPointer)result[2] ).getReferent () ).getArrayInstance (); + Short[] variableTypes = (Short[]) ( (JIArray) ( (JIPointer)result[3] ).getReferent () ).getArrayInstance (); + + for ( int i = 0; i < len; i++ ) + { + PropertyDescription pd = new PropertyDescription (); + pd.setId ( ids[i] ); + pd.setDescription ( descriptions[i].getString () ); + pd.setVarType ( variableTypes[i] ); + properties.add ( pd ); + } + return properties; + } + + public KeyedResultSet getItemProperties ( final String itemID, final int... properties ) throws JIException + { + if ( properties.length == 0 ) + { + return new KeyedResultSet (); + } + + Integer[] ids = new Integer[properties.length]; + for ( int i = 0; i < properties.length; i++ ) + { + ids[i] = properties[i]; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsString ( itemID, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsInt ( properties.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( ids, true ), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( JIVariant.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + JIVariant[] values = (JIVariant[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + KeyedResultSet results = new KeyedResultSet (); + for ( int i = 0; i < properties.length; i++ ) + { + results.add ( new KeyedResult ( properties[i], values[i], errorCodes[i] ) ); + } + return results; + } + + public KeyedResultSet lookupItemIDs ( final String itemID, final int... properties ) throws JIException + { + if ( properties.length == 0 ) + { + return new KeyedResultSet (); + } + + Integer[] ids = new Integer[properties.length]; + for ( int i = 0; i < properties.length; i++ ) + { + ids[i] = properties[i]; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsString ( itemID, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsInt ( properties.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( ids, true ), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + JIPointer[] itemIDs = (JIPointer[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + KeyedResultSet results = new KeyedResultSet (); + + for ( int i = 0; i < properties.length; i++ ) + { + results.add ( new KeyedResult ( properties[i], ( (JIString)itemIDs[i].getReferent () ).getString (), errorCodes[i] ) ); + } + return results; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCServer.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCServer.java new file mode 100644 index 0000000..f55e59d --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCServer.java @@ -0,0 +1,191 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIStruct; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.EnumString; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.common.impl.OPCCommon; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.OPCENUMSCOPE; +import org.openscada.opc.dcom.da.OPCSERVERSTATUS; + +public class OPCServer extends BaseCOMObject +{ + public OPCServer ( final IJIComObject opcServer ) throws IllegalArgumentException, UnknownHostException, JIException + { + super ( opcServer.queryInterface ( Constants.IOPCServer_IID ) ); + } + + /** + * Retrieve the current server status + * @return the current server status + * @throws JIException + */ + public OPCSERVERSTATUS getStatus () throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 3 ); + + callObject.addOutParamAsObject ( new JIPointer ( OPCSERVERSTATUS.getStruct () ), JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + return OPCSERVERSTATUS.fromStruct ( (JIStruct) ( (JIPointer)result[0] ).getReferent () ); + } + + public OPCGroupStateMgt addGroup ( final String name, final boolean active, final int updateRate, final int clientHandle, final Integer timeBias, final Float percentDeadband, final int localeID ) throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsString ( name, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsInt ( active ? 1 : 0, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( updateRate, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( clientHandle, JIFlags.FLAG_NULL ); + callObject.addInParamAsPointer ( new JIPointer ( timeBias ), JIFlags.FLAG_NULL ); + callObject.addInParamAsPointer ( new JIPointer ( percentDeadband ), JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( localeID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( Integer.class, JIFlags.FLAG_NULL ); + callObject.addInParamAsUUID ( Constants.IOPCGroupStateMgt_IID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + return new OPCGroupStateMgt ( (IJIComObject)result[2] ); + } + + public void removeGroup ( final int serverHandle, final boolean force ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 4 ); + + callObject.addInParamAsInt ( serverHandle, JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( force ? 1 : 0, JIFlags.FLAG_NULL ); + + getCOMObject ().call ( callObject ); + } + + public void removeGroup ( final OPCGroupStateMgt group, final boolean force ) throws JIException + { + removeGroup ( group.getState ().getServerHandle (), force ); + } + + public OPCGroupStateMgt getGroupByName ( final String name ) throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsString ( name, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addInParamAsUUID ( Constants.IOPCGroupStateMgt_IID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = getCOMObject ().call ( callObject ); + + return new OPCGroupStateMgt ( (IJIComObject)result[0] ); + } + + /** + * Get the groups + * @param scope The scope to get + * @return A string enumerator with the groups + * @throws JIException + * @throws IllegalArgumentException + * @throws UnknownHostException + */ + public EnumString getGroups ( final OPCENUMSCOPE scope ) throws JIException, IllegalArgumentException, UnknownHostException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 5 ); + + callObject.addInParamAsShort ( (short)scope.id (), JIFlags.FLAG_NULL ); + callObject.addInParamAsUUID ( org.openscada.opc.dcom.common.Constants.IEnumString_IID, JIFlags.FLAG_NULL ); + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + return new EnumString ( (IJIComObject)result[0] ); + } + + public OPCItemProperties getItemPropertiesService () + { + try + { + return new OPCItemProperties ( getCOMObject () ); + } + catch ( Exception e ) + { + return null; + } + } + + public OPCItemIO getItemIOService () + { + try + { + return new OPCItemIO ( getCOMObject () ); + } + catch ( Exception e ) + { + return null; + } + } + + /** + * Get the browser object (IOPCBrowseServerAddressSpace) from the server instance + * @return the browser object + */ + public OPCBrowseServerAddressSpace getBrowser () + { + try + { + return new OPCBrowseServerAddressSpace ( getCOMObject () ); + } + catch ( Exception e ) + { + return null; + } + } + + /** + * Get the common interface if supported + * @return the common interface or null if it is not supported + */ + public OPCCommon getCommon () + { + try + { + return new OPCCommon ( getCOMObject () ); + } + catch ( Exception e ) + { + return null; + } + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCSyncIO.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCSyncIO.java new file mode 100644 index 0000000..1bf90ad --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/da/impl/OPCSyncIO.java @@ -0,0 +1,113 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.da.impl; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIStruct; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.da.Constants; +import org.openscada.opc.dcom.da.OPCDATASOURCE; +import org.openscada.opc.dcom.da.OPCITEMSTATE; +import org.openscada.opc.dcom.da.WriteRequest; + +public class OPCSyncIO extends BaseCOMObject +{ + public OPCSyncIO ( final IJIComObject opcSyncIO ) throws JIException + { + super ( opcSyncIO.queryInterface ( Constants.IOPCSyncIO_IID ) ); + } + + public KeyedResultSet read ( final OPCDATASOURCE source, final Integer... serverHandles ) throws JIException + { + if ( serverHandles == null || serverHandles.length == 0 ) + { + return new KeyedResultSet (); + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + callObject.addInParamAsShort ( (short)source.id (), JIFlags.FLAG_NULL ); + callObject.addInParamAsInt ( serverHandles.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( serverHandles, true ), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( OPCITEMSTATE.getStruct (), null, 1, true ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + KeyedResultSet results = new KeyedResultSet (); + JIStruct[] states = (JIStruct[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[1] ).getReferent () ).getArrayInstance (); + + for ( int i = 0; i < serverHandles.length; i++ ) + { + results.add ( new KeyedResult ( serverHandles[i], OPCITEMSTATE.fromStruct ( states[i] ), errorCodes[i] ) ); + } + + return results; + } + + public ResultSet write ( final WriteRequest... requests ) throws JIException + { + if ( requests.length == 0 ) + { + return new ResultSet (); + } + + Integer[] items = new Integer[requests.length]; + JIVariant[] values = new JIVariant[requests.length]; + for ( int i = 0; i < requests.length; i++ ) + { + items[i] = requests[i].getServerHandle (); + values[i] = Helper.fixVariant ( requests[i].getValue () ); + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsInt ( requests.length, JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( items, true ), JIFlags.FLAG_NULL ); + callObject.addInParamAsArray ( new JIArray ( values, true ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIArray ( Integer.class, null, 1, true ) ), JIFlags.FLAG_NULL ); + + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + Integer[] errorCodes = (Integer[]) ( (JIArray) ( (JIPointer)result[0] ).getReferent () ).getArrayInstance (); + + ResultSet results = new ResultSet (); + for ( int i = 0; i < requests.length; i++ ) + { + results.add ( new Result ( requests[i], errorCodes[i] ) ); + } + return results; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/ClassDetails.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/ClassDetails.java new file mode 100644 index 0000000..93e57b2 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/ClassDetails.java @@ -0,0 +1,64 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.list; + +/** + * Details about an OPC server class + * @author Jens Reimann <jens.reimann@th4-systems.com> + * @since 0.1.8 + */ +public class ClassDetails +{ + private String _clsId; + + private String _progId; + + private String _description; + + public String getClsId () + { + return this._clsId; + } + + public void setClsId ( final String clsId ) + { + this._clsId = clsId; + } + + public String getDescription () + { + return this._description; + } + + public void setDescription ( final String description ) + { + this._description = description; + } + + public String getProgId () + { + return this._progId; + } + + public void setProgId ( final String progId ) + { + this._progId = progId; + } +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/Constants.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/Constants.java new file mode 100644 index 0000000..af4863e --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/Constants.java @@ -0,0 +1,27 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.list; + +public interface Constants extends org.openscada.opc.dcom.common.Constants +{ + public static final String IOPCServerList_IID = "13486D50-4821-11D2-A494-3CB306C10000"; + + public static final String OPCServerList_CLSID = "13486D51-4821-11D2-A494-3CB306C10000"; +} diff --git a/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/impl/OPCServerList.java b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/impl/OPCServerList.java new file mode 100644 index 0000000..69ab911 --- /dev/null +++ b/org.openscada.opc.dcom/src/org/openscada/opc/dcom/list/impl/OPCServerList.java @@ -0,0 +1,168 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.dcom.list.impl; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.IJIComObject; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JICallBuilder; +import org.jinterop.dcom.core.JIClsid; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIPointer; +import org.jinterop.dcom.core.JIString; +import org.openscada.opc.dcom.common.impl.BaseCOMObject; +import org.openscada.opc.dcom.common.impl.EnumGUID; +import org.openscada.opc.dcom.common.impl.Helper; +import org.openscada.opc.dcom.list.ClassDetails; +import org.openscada.opc.dcom.list.Constants; + +import rpc.core.UUID; + +/** + * This class implements the IOPCServerList (aka OPCEnum) service. + * @author Jens Reimann <jens.reimann@th4-systems.com> + * + */ +public class OPCServerList extends BaseCOMObject +{ + public OPCServerList ( final IJIComObject listObject ) throws JIException + { + super ( listObject.queryInterface ( Constants.IOPCServerList_IID ) ); + } + + public JIClsid getCLSIDFromProgID ( final String progId ) throws JIException + { + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 2 ); + + callObject.addInParamAsString ( progId, JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ); + callObject.addOutParamAsType ( UUID.class, JIFlags.FLAG_NULL ); + + try + { + Object[] result = getCOMObject ().call ( callObject ); + return JIClsid.valueOf ( ( (UUID)result[0] ).toString () ); + } + catch ( JIException e ) + { + if ( e.getErrorCode () == 0x800401F3 ) + { + return null; + } + throw e; + } + } + + /** + * Return details about a serve class + * @param clsId A server class + * @throws JIException + */ + public ClassDetails getClassDetails ( final JIClsid clsId ) throws JIException + { + if ( clsId == null ) + { + return null; + } + + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 1 ); + + callObject.addInParamAsUUID ( clsId.getCLSID (), JIFlags.FLAG_NULL ); + + callObject.addOutParamAsObject ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), JIFlags.FLAG_NULL ); + callObject.addOutParamAsObject ( new JIPointer ( new JIString ( JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR ) ), JIFlags.FLAG_NULL ); + + Object[] result = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + ClassDetails cd = new ClassDetails (); + cd.setClsId ( clsId.getCLSID () ); + cd.setProgId ( ( (JIString) ( (JIPointer)result[0] ).getReferent () ).getString () ); + cd.setDescription ( ( (JIString) ( (JIPointer)result[1] ).getReferent () ).getString () ); + + return cd; + } + + /* + HRESULT EnumClassesOfCategories( + [in] ULONG cImplemented, + [in,size_is(cImplemented)] CATID rgcatidImpl[], + [in] ULONG cRequired, + [in,size_is(cRequired)] CATID rgcatidReq[], + [out] IEnumGUID ** ppenumClsid + ); + */ + + public EnumGUID enumClassesOfCategories ( final String[] implemented, final String[] required ) throws IllegalArgumentException, UnknownHostException, JIException + { + UUID[] u1 = new UUID[implemented.length]; + UUID[] u2 = new UUID[required.length]; + + for ( int i = 0; i < implemented.length; i++ ) + { + u1[i] = new UUID ( implemented[i] ); + } + + for ( int i = 0; i < required.length; i++ ) + { + u2[i] = new UUID ( required[i] ); + } + + return enumClassesOfCategories ( u1, u2 ); + } + + public EnumGUID enumClassesOfCategories ( final UUID[] implemented, final UUID[] required ) throws IllegalArgumentException, UnknownHostException, JIException + { + // ** CALL + JICallBuilder callObject = new JICallBuilder ( true ); + callObject.setOpnum ( 0 ); + + // ** IN + callObject.addInParamAsInt ( implemented.length, JIFlags.FLAG_NULL ); + if ( implemented.length == 0 ) + { + callObject.addInParamAsPointer ( new JIPointer ( null ), JIFlags.FLAG_NULL ); + } + else + { + callObject.addInParamAsArray ( new JIArray ( implemented, true ), JIFlags.FLAG_NULL ); + } + + callObject.addInParamAsInt ( required.length, JIFlags.FLAG_NULL ); + if ( required.length == 0 ) + { + callObject.addInParamAsPointer ( new JIPointer ( null ), JIFlags.FLAG_NULL ); + } + else + { + callObject.addInParamAsArray ( new JIArray ( required, true ), JIFlags.FLAG_NULL ); + } + + // ** OUT + callObject.addOutParamAsType ( IJIComObject.class, JIFlags.FLAG_NULL ); + + // ** RESULT + Object result[] = Helper.callRespectSFALSE ( getCOMObject (), callObject ); + + return new EnumGUID ( (IJIComObject)result[0] ); + } +} diff --git a/org.openscada.opc.dcom/src/progIdVsClsidDB.properties b/org.openscada.opc.dcom/src/progIdVsClsidDB.properties new file mode 100644 index 0000000..b6dc3ef --- /dev/null +++ b/org.openscada.opc.dcom/src/progIdVsClsidDB.properties @@ -0,0 +1,13 @@ +#progId Vs ClsidDB +#Tue Nov 28 21:56:16 IST 2006 +Word.Application=000209ff-0000-0000-c000-000000000046 +TestCOM123.TestServer2=92a065a9-106a-4cc3-8d67-43e3a1e73df3 +SYSINFO.SysInfo=6fba474b-43ac-11ce-9a0e-00aa0062bb4c +ADODB.Connection=00000514-0000-0010-8000-00aa006d2ea4 +TestJavaServer.TestServer2=617d5a31-a3bf-440f-a58f-1f57f6ac7527 +TestJavaServer.TestServer1=56bad610-0fcb-418a-b25e-174159a4adce +InternetExplorer.Application=0002df01-0000-0000-c000-000000000046 +Excel.Application=00024500-0000-0000-c000-000000000046 +StdCollection.VBCollection=4b738074-ea47-11d2-b25a-00105a022091 +WbemScripting.SWbemLocator=76a64158-cb41-11d1-8b02-00600806d9b6 +PowerPoint.Application=91493441-5a91-11cf-8700-00aa0060263b diff --git a/org.openscada.opc.lib.test/.classpath b/org.openscada.opc.lib.test/.classpath new file mode 100644 index 0000000..00cb339 --- /dev/null +++ b/org.openscada.opc.lib.test/.classpath @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/org.openscada.opc.lib.test/.gitignore b/org.openscada.opc.lib.test/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/org.openscada.opc.lib.test/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/org.openscada.opc.lib.test/.project b/org.openscada.opc.lib.test/.project new file mode 100644 index 0000000..38a8d42 --- /dev/null +++ b/org.openscada.opc.lib.test/.project @@ -0,0 +1,46 @@ + + + org.openscada.opc.lib.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.babel.editor.rbeBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.babel.editor.rbeNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/org.openscada.opc.lib.test/LICENSE b/org.openscada.opc.lib.test/LICENSE new file mode 100644 index 0000000..0836c46 --- /dev/null +++ b/org.openscada.opc.lib.test/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/org.openscada.opc.lib.test/pom.xml b/org.openscada.opc.lib.test/pom.xml new file mode 100644 index 0000000..d37aea4 --- /dev/null +++ b/org.openscada.opc.lib.test/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + org.openscada.opc.lib.test + org.openscada.opc.lib.test + 0.0.1-SNAPSHOT + + + + org.slf4j + slf4j-log4j12 + 1.7.2 + + + commons-logging + commons-logging + 1.2 + + + + org.kohsuke.jinterop + j-interop + 2.0.5 + + + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + org.openscada.utgard + org.openscada.opc.lib + 1.1.0.v20130529 + + + + \ No newline at end of file diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/DataCallbackDumper.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/DataCallbackDumper.java new file mode 100644 index 0000000..ee32769 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/DataCallbackDumper.java @@ -0,0 +1,45 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.da.DataCallback; +import org.openscada.opc.lib.da.Item; +import org.openscada.opc.lib.da.ItemState; + +public class DataCallbackDumper implements DataCallback +{ + + public void changed ( final Item item, final ItemState itemState ) + { + System.out.println ( String.format ( "Item: %s, Value: %s, Timestamp: %tc, Quality: %d", item.getId (), itemState.getValue (), itemState.getTimestamp (), itemState.getQuality () ) ); + + try + { + VariantDumper.dumpValue ( "\t", itemState.getValue () ); + } + catch ( final JIException e ) + { + e.printStackTrace (); + } + + } + +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest1.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest1.java new file mode 100644 index 0000000..f5471a7 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest1.java @@ -0,0 +1,112 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.Map; +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.Group; +import org.openscada.opc.lib.da.Item; +import org.openscada.opc.lib.da.ItemState; +import org.openscada.opc.lib.da.Server; +import org.openscada.opc.lib.da.browser.Branch; +import org.openscada.opc.lib.da.browser.Leaf; + +public class OPCTest1 +{ + public static void dumpItemState ( final Item item, final ItemState state ) + { + System.out.println ( String.format ( "Item: %s, Value: %s, Timestamp: %tc, Quality: %d", item.getId (), state.getValue (), state.getTimestamp (), state.getQuality () ) ); + } + + public static void dumpTree ( final Branch branch, final int level ) + { + final StringBuilder sb = new StringBuilder (); + for ( int i = 0; i < level; i++ ) + { + sb.append ( " " ); + } + final String indent = sb.toString (); + + for ( final Leaf leaf : branch.getLeaves () ) + { + System.out.println ( indent + "Leaf: " + leaf.getName () + " [" + leaf.getItemId () + "]" ); + } + for ( final Branch subBranch : branch.getBranches () ) + { + System.out.println ( indent + "Branch: " + subBranch.getName () ); + dumpTree ( subBranch, level + 1 ); + } + } + + @SuppressWarnings ( "unused" ) + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + try + { + // connect to server + server.connect (); + + // browse + dumpTree ( server.getTreeBrowser ().browse (), 0 ); + + // add sync reader + + // Add a new group + Group group = server.addGroup ( "test" ); + // group is initially active ... just for demonstration + group.setActive ( true ); + + // We already have our group ... just for demonstration + group = server.findGroup ( "test" ); + + // Add a new item to the group + final Item item = group.addItem ( "Saw-toothed Waves.Int2" ); + // Items are initially active ... just for demonstration + item.setActive ( true ); + + // Add some more items ... including one that is already existing + final Map items = group.addItems ( "Saw-toothed Waves.Int2", "Saw-toothed Waves.Int4" ); + + // sync-read some values + for ( int i = 0; i < 10; i++ ) + { + Thread.sleep ( 100 ); + dumpItemState ( item, item.read ( false ) ); + } + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest2.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest2.java new file mode 100644 index 0000000..ee0620b --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest2.java @@ -0,0 +1,79 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.AccessBase; +import org.openscada.opc.lib.da.Server; +import org.openscada.opc.lib.da.SyncAccess; + +/** + * Another test showing the "Access" interface with the SyncAccess implementation. + * @author Jens Reimann + * + */ +public class OPCTest2 +{ + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + String itemId = "Saw-toothed Waves.Int2"; + if ( args.length >= 6 ) + { + itemId = args[5]; + } + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + try + { + // connect to server + server.connect (); + + // add sync access + + final AccessBase access = new SyncAccess ( server, 100 ); + access.addItem ( itemId, new DataCallbackDumper () ); + + // start reading + access.bind (); + + // wait a little bit + Thread.sleep ( 10 * 1000 ); + + // stop reading + access.unbind (); + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest3.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest3.java new file mode 100644 index 0000000..3730bc1 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest3.java @@ -0,0 +1,130 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.net.UnknownHostException; +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.Server; +import org.openscada.opc.lib.da.browser.BaseBrowser; +import org.openscada.opc.lib.da.browser.Branch; +import org.openscada.opc.lib.da.browser.Leaf; +import org.openscada.opc.lib.da.browser.TreeBrowser; + +/** + * Another test showing the browser interfaces + * @author Jens Reimann + * + */ +public class OPCTest3 +{ + + private static void dumpLeaf ( final String prefix, final Leaf leaf ) + { + System.out.println ( prefix + "Leaf: " + leaf.getName () + " [" + leaf.getItemId () + "]" ); + } + + private static void dumpBranch ( final String prefix, final Branch branch ) + { + System.out.println ( prefix + "Branch: " + branch.getName () ); + } + + public static void dumpTree ( final Branch branch, final int level ) + { + final StringBuilder sb = new StringBuilder (); + for ( int i = 0; i < level; i++ ) + { + sb.append ( " " ); + } + final String indent = sb.toString (); + + for ( final Leaf leaf : branch.getLeaves () ) + { + dumpLeaf ( indent, leaf ); + } + for ( final Branch subBranch : branch.getBranches () ) + { + dumpBranch ( indent, subBranch ); + dumpTree ( subBranch, level + 1 ); + } + } + + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + try + { + // connect to server + server.connect (); + + // browse flat + final BaseBrowser flatBrowser = server.getFlatBrowser (); + if ( flatBrowser != null ) + { + for ( final String item : server.getFlatBrowser ().browse ( "" ) ) + { + System.out.println ( item ); + } + } + + // browse tree + final TreeBrowser treeBrowser = server.getTreeBrowser (); + if ( treeBrowser != null ) + { + dumpTree ( treeBrowser.browse (), 0 ); + } + + // browse tree manually + browseTree ( "", treeBrowser, new Branch () ); + } + catch ( final JIException e ) + { + e.printStackTrace (); + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } + + private static void browseTree ( final String prefix, final TreeBrowser treeBrowser, final Branch branch ) throws IllegalArgumentException, UnknownHostException, JIException + { + treeBrowser.fillLeaves ( branch ); + treeBrowser.fillBranches ( branch ); + + for ( final Leaf leaf : branch.getLeaves () ) + { + dumpLeaf ( "M - " + prefix + " ", leaf ); + } + for ( final Branch subBranch : branch.getBranches () ) + { + dumpBranch ( "M - " + prefix + " ", subBranch ); + browseTree ( prefix + " ", treeBrowser, subBranch ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest4.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest4.java new file mode 100644 index 0000000..3c019dc --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest4.java @@ -0,0 +1,93 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.AccessBase; +import org.openscada.opc.lib.da.Async20Access; +import org.openscada.opc.lib.da.Server; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Another test showing the "Access" interface with the Async20Access implementation. + * @author Jens Reimann + * + */ +public class OPCTest4 +{ + private static Logger _log = LoggerFactory.getLogger ( OPCTest4.class ); + + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + final Set items = new HashSet (); + for ( int i = 5; i < args.length; i++ ) + { + items.add ( args[i] ); + } + if ( items.isEmpty () ) + { + items.add ( "Saw-toothed Waves.Int2" ); + } + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + try + { + // connect to server + server.connect (); + + // add sync access + final AccessBase access = new Async20Access ( server, 100, false ); + for ( final String itemId : items ) + { + access.addItem ( itemId, new DataCallbackDumper () ); + } + + // start reading + access.bind (); + + // wait a little bit + _log.info ( "Sleep for some seconds to give events a chance..." ); + Thread.sleep ( 10 * 1000 ); + _log.info ( "Returned from sleep" ); + + // stop reading + access.unbind (); + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest5.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest5.java new file mode 100644 index 0000000..fc1128e --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest5.java @@ -0,0 +1,80 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.Async20Access; +import org.openscada.opc.lib.da.Server; + +/** + * Another test showing the "Access" interface with + * the Async20Access implementation. Testing two connections at the same time. + * + * @author Jens Reimann + */ +public class OPCTest5 +{ + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation baseInfo = new ConnectionInformation (); + baseInfo.setHost ( args[0] ); + baseInfo.setDomain ( args[1] ); + baseInfo.setUser ( args[2] ); + baseInfo.setPassword ( args[3] ); + + final List testInfo = new LinkedList (); + int i = 0; + + try + { + + while ( args.length > i * 2 + 4 ) + { + final ConnectionInformation ci = new ConnectionInformation ( baseInfo ); + ci.setClsid ( args[i * 2 + 4] ); + final OPCTestInfo ti = new OPCTestInfo (); + ti._info = ci; + ti._itemId = args[i * 2 + 5]; + ti._server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + + ti._server.connect (); + ti._access = new Async20Access ( ti._server, 100, false ); + ti._access.addItem ( ti._itemId, new DataCallbackDumper () ); + ti._access.bind (); + + testInfo.add ( ti ); + i++; + } + + // wait a little bit + Thread.sleep ( 10 * 1000 ); + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X", e.getErrorCode () ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest6.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest6.java new file mode 100644 index 0000000..8707f11 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest6.java @@ -0,0 +1,92 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.AccessBase; +import org.openscada.opc.lib.da.AutoReconnectController; +import org.openscada.opc.lib.da.Server; +import org.openscada.opc.lib.da.SyncAccess; + +/** + * Another test showing the "Access" interface with the SyncAccess implementation + * including the AutoReconnectController which should re-establish the connection + * if it breaks. + * @author Jens Reimann + * + */ +public class OPCTest6 +{ + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + String itemId = "Saw-toothed Waves.Int2"; + if ( args.length >= 6 ) + { + itemId = args[5]; + } + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + final AutoReconnectController autoReconnectController = new AutoReconnectController ( server ); + try + { + // connect to server + autoReconnectController.connect (); + + // add sync access + + final AccessBase access = new SyncAccess ( server, 100 ); + access.addItem ( itemId, new DataCallbackDumper () ); + + // start reading + access.bind (); + + // run forever + final boolean running = true; + while ( running ) + { + Thread.sleep ( 10 * 1000 ); + } + + /* + // stop reading + access.unbind (); + + // disconnect + autoReconnectController.disconnect (); + */ + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest7.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest7.java new file mode 100644 index 0000000..a216ec7 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest7.java @@ -0,0 +1,110 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.concurrent.Executors; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.Group; +import org.openscada.opc.lib.da.Item; +import org.openscada.opc.lib.da.ItemState; +import org.openscada.opc.lib.da.Server; + +/** + * A sample that reads an item and writes back the result. You will need a + * read/write item for this to work. + * @author Jens Reimann <jens.reimann@th4-systems.com> + * + */ +public class OPCTest7 +{ + @SuppressWarnings ( "unused" ) + public static void main ( final String[] args ) throws Throwable + { + // create connection information + final ConnectionInformation ci = new ConnectionInformation (); + ci.setHost ( args[0] ); + ci.setDomain ( args[1] ); + ci.setUser ( args[2] ); + ci.setPassword ( args[3] ); + ci.setClsid ( args[4] ); + + final String itemName = args[5]; + + // create a new server + final Server server = new Server ( ci, Executors.newSingleThreadScheduledExecutor () ); + try + { + // connect to server + server.connect (); + + // Add a new group + final Group group = server.addGroup ( "test" ); + + // Add a new item to the group + final Item item = group.addItem ( itemName ); + + final JIString[] sdata = new JIString[] { new JIString ( "ab", JIFlags.FLAG_REPRESENTATION_STRING_BSTR ), new JIString ( "cd", JIFlags.FLAG_REPRESENTATION_STRING_BSTR ), new JIString ( "ef", JIFlags.FLAG_REPRESENTATION_STRING_BSTR ) }; + final Double[] ddata = new Double[] { 1.1, 2.2, 3.3 }; + final Boolean[] bdata = new Boolean[] { true, false, true, false }; + final Integer[] idata = new Integer[] { 1202, 1203, 1204 }; + final Long[] ldata = new Long[] { 12020001L, 12030001L, 12040001L }; + final Float[] fdata = new Float[] { 1.1f, 1.2f, 1.3f }; + final Byte[] bydata = new Byte[] { 1, 2, 3 }; + final Character[] cdata = new Character[] { 'A', 'B', 'C' }; + + final JIArray array = new JIArray ( ddata, true ); + final JIVariant value = new JIVariant ( array ); + + System.out.println ( "============= PHASE 1 ============= " ); + + // dump the value + VariantDumper.dumpValue ( value ); + + System.out.println ( "============= PHASE 2 ============= " ); + + // now write it to the item + item.write ( value ); + Thread.sleep ( 2500 ); + + System.out.println ( "============= PHASE 3 ============= " ); + + // now read the value back and dump it + final ItemState itemState = item.read ( true ); + VariantDumper.dumpValue ( itemState.getValue () ); + + System.out.println ( "============= PHASE 4 ============= " ); + + // and write the value just read in + item.write ( itemState.getValue () ); + + System.out.println ( "============= COMPLETE ============= " ); + } + catch ( final JIException e ) + { + System.out.println ( String.format ( "%08X: %s", e.getErrorCode (), server.getErrorMessage ( e.getErrorCode () ) ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest8.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest8.java new file mode 100644 index 0000000..b3476aa --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTest8.java @@ -0,0 +1,67 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import java.util.Collection; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.dcom.list.ClassDetails; +import org.openscada.opc.lib.list.Categories; +import org.openscada.opc.lib.list.Category; +import org.openscada.opc.lib.list.ServerList; + +/** + * A sample that queries the server browser interface + * @author Jens Reimann <jens.reimann@th4-systems.com> + * + */ +public class OPCTest8 +{ + protected static void showDetails ( final ServerList serverList, final String clsid ) throws JIException + { + final ClassDetails cd = serverList.getDetails ( clsid ); + if ( cd != null ) + { + System.out.println ( cd.getProgId () + " = " + cd.getDescription () ); + } + else + { + System.out.println ( "unknown" ); + } + } + + public static void main ( final String[] args ) throws Throwable + { + final ServerList serverList = new ServerList ( args[0], args[2], args[3], args[1] ); + + final String cls = serverList.getClsIdFromProgId ( "Matrikon.OPC.Simulation.1" ); + System.out.println ( "Matrikon OPC Simulation Server: " + cls ); + showDetails ( serverList, cls ); + + final Collection detailsList = serverList.listServersWithDetails ( new Category[] { Categories.OPCDAServer20 }, new Category[] {} ); + + for ( final ClassDetails details : detailsList ) + { + System.out.println ( String.format ( "Found: %s", details.getClsId () ) ); + System.out.println ( String.format ( "\tProgID: %s", details.getProgId () ) ); + System.out.println ( String.format ( "\tDescription: %s", details.getDescription () ) ); + } + } +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTestInfo.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTestInfo.java new file mode 100644 index 0000000..d27258f --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/OPCTestInfo.java @@ -0,0 +1,35 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.da.AccessBase; +import org.openscada.opc.lib.da.Server; + +class OPCTestInfo +{ + ConnectionInformation _info = null; + + String _itemId = null; + + Server _server = null; + + AccessBase _access = null; +} diff --git a/org.openscada.opc.lib.test/src/org/openscada/opc/lib/VariantDumper.java b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/VariantDumper.java new file mode 100644 index 0000000..6026b76 --- /dev/null +++ b/org.openscada.opc.lib.test/src/org/openscada/opc/lib/VariantDumper.java @@ -0,0 +1,134 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2009 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +package org.openscada.opc.lib; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIArray; +import org.jinterop.dcom.core.JIFlags; +import org.jinterop.dcom.core.JIString; +import org.jinterop.dcom.core.JIVariant; + +public class VariantDumper +{ + + static protected void dumpArray ( final String prefix, final JIArray array ) throws JIException + { + System.out.println ( prefix + String.format ( "IsConformant: %s, IsVarying: %s", array.isConformant () ? "yes" : "no", array.isVarying () ? "yes" : "no" ) ); + System.out.println ( prefix + String.format ( "Dimensions: %d", array.getDimensions () ) ); + for ( int i = 0; i < array.getDimensions (); i++ ) + { + System.out.println ( prefix + String.format ( "Dimension #%d: Upper Bound: %d", i, array.getUpperBounds ()[i] ) ); + } + + final Object o = array.getArrayInstance (); + System.out.println ( prefix + "Array Instance: " + o.getClass () ); + final Object[] a = (Object[])o; + System.out.println ( prefix + "Array Size: " + a.length ); + + for ( final Object value : a ) + { + dumpValue ( prefix + "\t", value ); + } + } + + static public void dumpValue ( final Object value ) throws JIException + { + dumpValue ( "", value ); + } + + static protected void dumpValue ( final String prefix, final Object value ) throws JIException + { + if ( value instanceof JIVariant ) + { + System.out.println ( prefix + "JIVariant" ); + final JIVariant variant = (JIVariant)value; + System.out.println ( prefix + String.format ( "IsArray: %s, IsByRef: %s, IsNull: %s", variant.isArray () ? "yes" : "no", variant.isByRefFlagSet () ? "yes" : "no", variant.isNull () ? "yes" : "no" ) ); + + if ( variant.isArray () ) + { + dumpArray ( prefix, variant.getObjectAsArray () ); + } + else + { + dumpValue ( prefix + "\t", variant.getObject () ); + } + } + else if ( value instanceof JIString ) + { + final JIString string = (JIString)value; + + String strType; + switch ( string.getType () ) + { + case JIFlags.FLAG_REPRESENTATION_STRING_BSTR: + strType = "BSTR"; + break; + case JIFlags.FLAG_REPRESENTATION_STRING_LPCTSTR: + strType = "LPCSTR"; + break; + case JIFlags.FLAG_REPRESENTATION_STRING_LPWSTR: + strType = "LPWSTR"; + break; + default: + strType = "unknown"; + break; + } + System.out.println ( prefix + String.format ( "JIString: '%s' (%s)", string.getString (), strType ) ); + } + else if ( value instanceof Double ) + { + System.out.println ( prefix + "Double: " + value ); + } + else if ( value instanceof Float ) + { + System.out.println ( prefix + "Float: " + value ); + } + else if ( value instanceof Byte ) + { + System.out.println ( prefix + "Byte: " + value ); + } + else if ( value instanceof Character ) + { + System.out.println ( prefix + "Character: " + value ); + } + else if ( value instanceof Integer ) + { + System.out.println ( prefix + "Integer: " + value ); + } + else if ( value instanceof Short ) + { + System.out.println ( prefix + "Short: " + value ); + } + else if ( value instanceof Long ) + { + System.out.println ( prefix + "Long: " + value ); + } + else if ( value instanceof Boolean ) + { + System.out.println ( prefix + "Boolean: " + value ); + } + + else + { + System.out.println ( prefix + String.format ( "Unknown value type (%s): %s", value.getClass (), value.toString () ) ); + } + } + +} diff --git a/org.openscada.opc.lib/.classpath b/org.openscada.opc.lib/.classpath new file mode 100644 index 0000000..6821461 --- /dev/null +++ b/org.openscada.opc.lib/.classpath @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/org.openscada.opc.lib/.gitignore b/org.openscada.opc.lib/.gitignore new file mode 100644 index 0000000..4cc0812 --- /dev/null +++ b/org.openscada.opc.lib/.gitignore @@ -0,0 +1,2 @@ +bin/ +/target diff --git a/org.openscada.opc.lib/.project b/org.openscada.opc.lib/.project new file mode 100644 index 0000000..95eda57 --- /dev/null +++ b/org.openscada.opc.lib/.project @@ -0,0 +1,46 @@ + + + org.openscada.opc.lib + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.babel.editor.rbeBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + org.eclipse.babel.editor.rbeNature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/org.openscada.opc.lib/LICENSE b/org.openscada.opc.lib/LICENSE new file mode 100644 index 0000000..0836c46 --- /dev/null +++ b/org.openscada.opc.lib/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/org.openscada.opc.lib/build.properties b/org.openscada.opc.lib/build.properties new file mode 100644 index 0000000..4394f20 --- /dev/null +++ b/org.openscada.opc.lib/build.properties @@ -0,0 +1 @@ +source.. = src diff --git a/org.openscada.opc.lib/pom.xml b/org.openscada.opc.lib/pom.xml new file mode 100644 index 0000000..de7f48f --- /dev/null +++ b/org.openscada.opc.lib/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + org.openscada.utgard + org.openscada.opc.lib + 1.1.0.v20130529 + + + + org.slf4j + slf4j-log4j12 + 1.7.2 + + + commons-logging + commons-logging + 1.2 + + + + org.kohsuke.jinterop + j-interop + 2.0.5 + + + org.openscada.opc.dcom + org.openscada.opc.dcom + 0.0.1-SNAPSHOT + + + + \ No newline at end of file diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/common/AlreadyConnectedException.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/AlreadyConnectedException.java new file mode 100644 index 0000000..1b279f8 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/AlreadyConnectedException.java @@ -0,0 +1,30 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.common; + +public class AlreadyConnectedException extends Exception +{ + + /** + * + */ + private static final long serialVersionUID = -6494637563117314114L; + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/common/ConnectionInformation.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/ConnectionInformation.java new file mode 100644 index 0000000..1012360 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/ConnectionInformation.java @@ -0,0 +1,149 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.common; + +/** + * Holds the connection information + * @author Jens Reimann + * + * If both clsId and progId are set then clsId + * has priority! + */ +public class ConnectionInformation +{ + private String _host = "localhost"; + + private String _domain = "localhost"; + + private String _user = ""; + + private String _password = ""; + + private String _clsid = null; + + private String _progId = null; + + public ConnectionInformation () + { + super (); + } + + public ConnectionInformation ( final String user, final String password ) + { + super (); + this._user = user; + this._password = password; + } + + public ConnectionInformation ( final ConnectionInformation arg0 ) + { + super (); + this._user = arg0._user; + this._password = arg0._password; + this._domain = arg0._domain; + this._host = arg0._host; + this._progId = arg0._progId; + this._clsid = arg0._clsid; + } + + public String getDomain () + { + return this._domain; + } + + /** + * Set the domain of the user used for logging on + * @param domain + */ + public void setDomain ( final String domain ) + { + this._domain = domain; + } + + public String getHost () + { + return this._host; + } + + /** + * Set the host on which the server is located + * @param host The host to use, either an IP address oder hostname + */ + public void setHost ( final String host ) + { + this._host = host; + } + + public String getPassword () + { + return this._password; + } + + public void setPassword ( final String password ) + { + this._password = password; + } + + public String getUser () + { + return this._user; + } + + public void setUser ( final String user ) + { + this._user = user; + } + + public String getClsid () + { + return this._clsid; + } + + public void setClsid ( final String clsid ) + { + this._clsid = clsid; + } + + public String getProgId () + { + return this._progId; + } + + public void setProgId ( final String progId ) + { + this._progId = progId; + } + + public String getClsOrProgId () + { + if ( this._clsid != null ) + { + return this._clsid; + } + else if ( this._progId != null ) + { + return this._progId; + } + else + { + return null; + } + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/common/NotConnectedException.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/NotConnectedException.java new file mode 100644 index 0000000..d20ccdb --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/common/NotConnectedException.java @@ -0,0 +1,30 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.common; + +public class NotConnectedException extends Exception +{ + + /** + * + */ + private static final long serialVersionUID = -3745147771605524635L; + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessBase.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessBase.java new file mode 100644 index 0000000..d06e0a8 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessBase.java @@ -0,0 +1,359 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.NotConnectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AccessBase implements ServerConnectionStateListener +{ + private static Logger logger = LoggerFactory.getLogger ( AccessBase.class ); + + protected Server server = null; + + protected Group group = null; + + protected boolean active = false; + + private final List stateListeners = new CopyOnWriteArrayList (); + + private boolean bound = false; + + /** + * Holds the item to callback assignment + */ + protected Map items = new HashMap (); + + protected Map itemMap = new HashMap (); + + protected Map itemCache = new HashMap (); + + private int period = 0; + + protected Map itemSet = new HashMap (); + + protected String logTag = null; + + protected Logger dataLogger = null; + + public AccessBase ( final Server server, final int period ) throws IllegalArgumentException, UnknownHostException, NotConnectedException, JIException, DuplicateGroupException + { + super (); + this.server = server; + this.period = period; + } + + public AccessBase ( final Server server, final int period, final String logTag ) + { + super (); + this.server = server; + this.period = period; + this.logTag = logTag; + if ( this.logTag != null ) + { + this.dataLogger = LoggerFactory.getLogger ( "opc.data." + logTag ); + } + } + + public boolean isBound () + { + return this.bound; + } + + public synchronized void bind () + { + if ( isBound () ) + { + return; + } + + this.server.addStateListener ( this ); + this.bound = true; + } + + public synchronized void unbind () throws JIException + { + if ( !isBound () ) + { + return; + } + + this.server.removeStateListener ( this ); + this.bound = false; + + stop (); + } + + public boolean isActive () + { + return this.active; + } + + public void addStateListener ( final AccessStateListener listener ) + { + this.stateListeners.add ( listener ); + listener.stateChanged ( isActive () ); + } + + public void removeStateListener ( final AccessStateListener listener ) + { + this.stateListeners.remove ( listener ); + } + + protected void notifyStateListenersState ( final boolean state ) + { + final List list = new ArrayList ( this.stateListeners ); + + for ( final AccessStateListener listener : list ) + { + listener.stateChanged ( state ); + } + } + + protected void notifyStateListenersError ( final Throwable t ) + { + final List list = new ArrayList ( this.stateListeners ); + + for ( final AccessStateListener listener : list ) + { + listener.errorOccured ( t ); + } + } + + public int getPeriod () + { + return this.period; + } + + public synchronized void addItem ( final String itemId, final DataCallback dataCallback ) throws JIException, AddFailedException + { + if ( this.itemSet.containsKey ( itemId ) ) + { + return; + } + + this.itemSet.put ( itemId, dataCallback ); + + if ( isActive () ) + { + realizeItem ( itemId ); + } + } + + public synchronized void removeItem ( final String itemId ) + { + if ( !this.itemSet.containsKey ( itemId ) ) + { + return; + } + + this.itemSet.remove ( itemId ); + + if ( isActive () ) + { + unrealizeItem ( itemId ); + } + } + + public void connectionStateChanged ( final boolean connected ) + { + try + { + if ( connected ) + { + start (); + } + else + { + stop (); + } + } + catch ( final Exception e ) + { + logger.error ( String.format ( "Failed to change state (%s)", connected ), e ); + } + } + + protected synchronized void start () throws JIException, IllegalArgumentException, UnknownHostException, NotConnectedException, DuplicateGroupException + { + if ( isActive () ) + { + return; + } + + logger.debug ( "Create a new group" ); + this.group = this.server.addGroup (); + this.group.setActive ( true ); + this.active = true; + + notifyStateListenersState ( true ); + + realizeAll (); + } + + protected void realizeItem ( final String itemId ) throws JIException, AddFailedException + { + logger.debug ( "Realizing item: {}", itemId ); + + final DataCallback dataCallback = this.itemSet.get ( itemId ); + if ( dataCallback == null ) + { + return; + } + + final Item item = this.group.addItem ( itemId ); + this.items.put ( item, dataCallback ); + this.itemMap.put ( itemId, item ); + } + + protected void unrealizeItem ( final String itemId ) + { + final Item item = this.itemMap.remove ( itemId ); + this.items.remove ( item ); + this.itemCache.remove ( item ); + + try + { + this.group.removeItem ( itemId ); + } + catch ( final Throwable e ) + { + logger.error ( String.format ( "Failed to unrealize item '%s'", itemId ), e ); + } + } + + /* + * FIXME: need some perfomance boost: subscribe all in one call + */ + protected void realizeAll () + { + for ( final String itemId : this.itemSet.keySet () ) + { + try + { + realizeItem ( itemId ); + } + catch ( final AddFailedException e ) + { + Integer rc = e.getErrors ().get ( itemId ); + if ( rc == null ) + { + rc = -1; + } + logger.warn ( String.format ( "Failed to add item: %s (%08X)", itemId, rc ) ); + + } + catch ( final Exception e ) + { + logger.warn ( "Failed to realize item: " + itemId, e ); + } + } + } + + protected void unrealizeAll () + { + this.items.clear (); + this.itemCache.clear (); + try + { + this.group.clear (); + } + catch ( final JIException e ) + { + logger.info ( "Failed to clear group. No problem if we already lost the connection", e ); + } + } + + protected synchronized void stop () throws JIException + { + if ( !isActive () ) + { + return; + } + + unrealizeAll (); + + this.active = false; + notifyStateListenersState ( false ); + + try + { + this.group.remove (); + } + catch ( final Throwable t ) + { + logger.warn ( "Failed to disable group. No problem if we already lost connection" ); + } + this.group = null; + } + + public synchronized void clear () + { + this.itemSet.clear (); + this.items.clear (); + this.itemMap.clear (); + this.itemCache.clear (); + } + + protected void updateItem ( final Item item, final ItemState itemState ) + { + if ( this.dataLogger != null ) + { + this.dataLogger.debug ( "Update item: {}, {}", item.getId (), itemState ); + } + + final DataCallback dataCallback = this.items.get ( item ); + if ( dataCallback == null ) + { + return; + } + + final ItemState cachedState = this.itemCache.get ( item ); + if ( cachedState == null ) + { + this.itemCache.put ( item, itemState ); + dataCallback.changed ( item, itemState ); + } + else + { + if ( !cachedState.equals ( itemState ) ) + { + this.itemCache.put ( item, itemState ); + dataCallback.changed ( item, itemState ); + } + } + } + + protected void handleError ( final Throwable e ) + { + notifyStateListenersError ( e ); + this.server.dispose (); + } + +} \ No newline at end of file diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessStateListener.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessStateListener.java new file mode 100644 index 0000000..ea20aad --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AccessStateListener.java @@ -0,0 +1,27 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public interface AccessStateListener +{ + public abstract void stateChanged ( boolean state ); + + public abstract void errorOccured ( Throwable t ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AddFailedException.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AddFailedException.java new file mode 100644 index 0000000..ac383fc --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AddFailedException.java @@ -0,0 +1,61 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.util.HashMap; +import java.util.Map; + +public class AddFailedException extends Exception +{ + + /** + * + */ + private static final long serialVersionUID = 5299486640366935298L; + + private Map _errors = new HashMap (); + + private Map _items = new HashMap (); + + public AddFailedException ( final Map errors, final Map items ) + { + super (); + this._errors = errors; + this._items = items; + } + + /** + * Get the map of item id to error code + * @return the result map containing the failed items + */ + public Map getErrors () + { + return this._errors; + } + + /** + * Get the map of item it to item object + * @return the result map containing the succeeded items + */ + public Map getItems () + { + return this._items; + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Async20Access.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Async20Access.java new file mode 100644 index 0000000..f6f0533 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Async20Access.java @@ -0,0 +1,136 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.net.UnknownHostException; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.dcom.common.EventHandler; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.da.IOPCDataCallback; +import org.openscada.opc.dcom.da.OPCDATASOURCE; +import org.openscada.opc.dcom.da.ValueData; +import org.openscada.opc.dcom.da.impl.OPCAsyncIO2; +import org.openscada.opc.lib.common.NotConnectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Async20Access extends AccessBase implements IOPCDataCallback +{ + private static Logger logger = LoggerFactory.getLogger ( Async20Access.class ); + + private EventHandler eventHandler = null; + + private boolean initialRefresh = false; + + public Async20Access ( final Server server, final int period, final boolean initialRefresh ) throws IllegalArgumentException, UnknownHostException, NotConnectedException, JIException, DuplicateGroupException + { + super ( server, period ); + this.initialRefresh = initialRefresh; + } + + public Async20Access ( final Server server, final int period, final boolean initialRefresh, final String logTag ) throws IllegalArgumentException, UnknownHostException, NotConnectedException, JIException, DuplicateGroupException + { + super ( server, period, logTag ); + this.initialRefresh = initialRefresh; + } + + @Override + protected synchronized void start () throws JIException, IllegalArgumentException, UnknownHostException, NotConnectedException, DuplicateGroupException + { + if ( isActive () ) + { + return; + } + + super.start (); + + this.eventHandler = this.group.attach ( this ); + if ( !this.items.isEmpty () && this.initialRefresh ) + { + final OPCAsyncIO2 async20 = this.group.getAsyncIO20 (); + if ( async20 == null ) + { + throw new NotConnectedException (); + } + + this.group.getAsyncIO20 ().refresh ( OPCDATASOURCE.OPC_DS_CACHE, 0 ); + } + } + + @Override + protected synchronized void stop () throws JIException + { + if ( !isActive () ) + { + return; + } + + if ( this.eventHandler != null ) + { + try + { + this.eventHandler.detach (); + } + catch ( final Throwable e ) + { + logger.warn ( "Failed to detach group", e ); + } + + this.eventHandler = null; + } + + super.stop (); + } + + public void cancelComplete ( final int transactionId, final int serverGroupHandle ) + { + } + + public void dataChange ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final KeyedResultSet result ) + { + logger.debug ( "dataChange - transId {}, items: {}", transactionId, result.size () ); + + final Group group = this.group; + if ( group == null ) + { + return; + } + + for ( final KeyedResult entry : result ) + { + final Item item = group.findItemByClientHandle ( entry.getKey () ); + logger.debug ( "Update for '{}'", item.getId () ); + updateItem ( item, new ItemState ( entry.getErrorCode (), entry.getValue ().getValue (), entry.getValue ().getTimestamp (), entry.getValue ().getQuality () ) ); + } + } + + public void readComplete ( final int transactionId, final int serverGroupHandle, final int masterQuality, final int masterErrorCode, final KeyedResultSet result ) + { + logger.debug ( "readComplete - transId {}", transactionId ); + } + + public void writeComplete ( final int transactionId, final int serverGroupHandle, final int masterErrorCode, final ResultSet result ) + { + logger.debug ( "writeComplete - transId {}", transactionId ); + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectController.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectController.java new file mode 100644 index 0000000..3e4ce52 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectController.java @@ -0,0 +1,230 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AutoReconnectController implements ServerConnectionStateListener +{ + private static Logger _log = LoggerFactory.getLogger ( AutoReconnectController.class ); + + private static final int DEFAULT_DELAY = 5 * 1000; + + private int _delay; + + private final Server _server; + + private final Set _listeners = new CopyOnWriteArraySet (); + + private AutoReconnectState _state = AutoReconnectState.DISABLED; + + private Thread _connectTask = null; + + public AutoReconnectController ( final Server server ) + { + this ( server, DEFAULT_DELAY ); + } + + public AutoReconnectController ( final Server server, final int delay ) + { + super (); + setDelay ( delay ); + + this._server = server; + this._server.addStateListener ( this ); + } + + public void addListener ( final AutoReconnectListener listener ) + { + if ( listener != null ) + { + this._listeners.add ( listener ); + listener.stateChanged ( this._state ); + } + } + + public void removeListener ( final AutoReconnectListener listener ) + { + this._listeners.remove ( listener ); + } + + protected void notifyStateChange ( final AutoReconnectState state ) + { + this._state = state; + for ( AutoReconnectListener listener : this._listeners ) + { + listener.stateChanged ( state ); + } + } + + public int getDelay () + { + return this._delay; + } + + /** + * Set the reconnect delay. If the delay less than or equal to zero it will be + * the default delay time. + * @param delay The delay to use + */ + public void setDelay ( int delay ) + { + if ( delay <= 0 ) + { + delay = DEFAULT_DELAY; + } + this._delay = delay; + } + + public synchronized void connect () + { + if ( isRequested () ) + { + return; + } + + _log.debug ( "Requesting connection" ); + notifyStateChange ( AutoReconnectState.DISCONNECTED ); + + triggerReconnect ( false ); + } + + public synchronized void disconnect () + { + if ( !isRequested () ) + { + return; + } + + _log.debug ( "Un-Requesting connection" ); + + notifyStateChange ( AutoReconnectState.DISABLED ); + this._server.disconnect (); + } + + public boolean isRequested () + { + return this._state != AutoReconnectState.DISABLED; + } + + public synchronized void connectionStateChanged ( final boolean connected ) + { + _log.debug ( "Connection state changed: " + connected ); + + if ( !connected ) + { + if ( isRequested () ) + { + notifyStateChange ( AutoReconnectState.DISCONNECTED ); + triggerReconnect ( true ); + } + } + else + { + if ( !isRequested () ) + { + this._server.disconnect (); + } + else + { + notifyStateChange ( AutoReconnectState.CONNECTED ); + } + } + } + + private synchronized void triggerReconnect ( final boolean wait ) + { + if ( this._connectTask != null ) + { + _log.info ( "Connect thread already running" ); + return; + } + + _log.debug ( "Trigger reconnect" ); + + this._connectTask = new Thread ( new Runnable () { + + public void run () + { + boolean result = false; + try + { + result = performReconnect ( wait ); + } + finally + { + AutoReconnectController.this._connectTask = null; + _log.debug ( String.format ( "performReconnect completed : %s", result ) ); + if ( !result ) + { + triggerReconnect ( true ); + } + } + } + }, "OPCReconnectThread" ); + this._connectTask.setDaemon ( true ); + this._connectTask.start (); + } + + private boolean performReconnect ( final boolean wait ) + { + try + { + if ( wait ) + { + notifyStateChange ( AutoReconnectState.WAITING ); + _log.debug ( String.format ( "Delaying (%s)...", this._delay ) ); + Thread.sleep ( this._delay ); + } + } + catch ( InterruptedException e ) + { + } + + if ( !isRequested () ) + { + _log.debug ( "Request canceled during delay" ); + return true; + } + + try + { + _log.debug ( "Connecting to server" ); + notifyStateChange ( AutoReconnectState.CONNECTING ); + synchronized ( this ) + { + this._server.connect (); + return true; + } + // CONNECTED state will be set by server callback + } + catch ( Throwable e ) + { + _log.info ( "Re-connect failed", e ); + notifyStateChange ( AutoReconnectState.DISCONNECTED ); + return false; + } + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectListener.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectListener.java new file mode 100644 index 0000000..a94c3dc --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectListener.java @@ -0,0 +1,25 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public interface AutoReconnectListener +{ + public abstract void stateChanged ( AutoReconnectState state ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectState.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectState.java new file mode 100644 index 0000000..f23fa2e --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/AutoReconnectState.java @@ -0,0 +1,51 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +/** + * A state for the auto-reconnect controller + * @author Jens Reimann + * + */ +public enum AutoReconnectState +{ + /** + * Auto reconnect is disabled. + */ + DISABLED, + /** + * Auto reconnect is enabled, but the connection is currently not established. + */ + DISCONNECTED, + /** + * Auto reconnect is enabled, the connection is not established and the controller + * is currently waiting the delay until it will reconnect. + */ + WAITING, + /** + * Auto reconnect is enabled, the connection is not established but the controller + * currently tries to establish the connection. + */ + CONNECTING, + /** + * Auto reconnect is enabled and the connection is established. + */ + CONNECTED +} \ No newline at end of file diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DataCallback.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DataCallback.java new file mode 100644 index 0000000..71c618c --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DataCallback.java @@ -0,0 +1,25 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public interface DataCallback +{ + void changed ( Item item, ItemState itemState ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DuplicateGroupException.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DuplicateGroupException.java new file mode 100644 index 0000000..1fb20cd --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/DuplicateGroupException.java @@ -0,0 +1,30 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public class DuplicateGroupException extends Exception +{ + + /** + * + */ + private static final long serialVersionUID = 826553520690295478L; + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ErrorMessageResolver.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ErrorMessageResolver.java new file mode 100644 index 0000000..da0d96d --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ErrorMessageResolver.java @@ -0,0 +1,80 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.util.HashMap; +import java.util.Map; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.dcom.common.impl.OPCCommon; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An error message resolver that will lookup the error code using the + * server interface and will cache the result locally. + * @author Jens Reimann + * + */ +public class ErrorMessageResolver +{ + private static Logger _log = LoggerFactory.getLogger ( ErrorMessageResolver.class ); + + private OPCCommon _opcCommon = null; + + private final Map _messageCache = new HashMap (); + + private int _localeId = 0; + + public ErrorMessageResolver ( final OPCCommon opcCommon, final int localeId ) + { + super (); + this._opcCommon = opcCommon; + this._localeId = localeId; + } + + /** + * Get an error message from an error code + * @param errorCode The error code to look up + * @return the error message or null if no message could be looked up + */ + public synchronized String getMessage ( final int errorCode ) + { + String message = this._messageCache.get ( Integer.valueOf ( errorCode ) ); + + if ( message == null ) + { + try + { + message = this._opcCommon.getErrorString ( errorCode, this._localeId ); + _log.info ( String.format ( "Resolved %08X to '%s'", errorCode, message ) ); + } + catch ( JIException e ) + { + _log.warn ( String.format ( "Failed to resolve error code for %08X", errorCode ), e ); + } + if ( message != null ) + { + this._messageCache.put ( errorCode, message ); + } + } + return message; + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Group.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Group.java new file mode 100644 index 0000000..36fdfcc --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Group.java @@ -0,0 +1,437 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.dcom.common.EventHandler; +import org.openscada.opc.dcom.common.KeyedResult; +import org.openscada.opc.dcom.common.KeyedResultSet; +import org.openscada.opc.dcom.common.Result; +import org.openscada.opc.dcom.common.ResultSet; +import org.openscada.opc.dcom.da.IOPCDataCallback; +import org.openscada.opc.dcom.da.OPCDATASOURCE; +import org.openscada.opc.dcom.da.OPCITEMDEF; +import org.openscada.opc.dcom.da.OPCITEMRESULT; +import org.openscada.opc.dcom.da.OPCITEMSTATE; +import org.openscada.opc.dcom.da.impl.OPCAsyncIO2; +import org.openscada.opc.dcom.da.impl.OPCGroupStateMgt; +import org.openscada.opc.dcom.da.impl.OPCItemMgt; +import org.openscada.opc.dcom.da.impl.OPCSyncIO; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Group +{ + private static Logger _log = LoggerFactory.getLogger ( Group.class ); + + private static Random _random = new Random (); + + private Server _server = null; + + private final int _serverHandle; + + private OPCGroupStateMgt _group = null; + + private OPCItemMgt _items = null; + + private OPCSyncIO _syncIO = null; + + private final Map _itemHandleMap = new HashMap (); + + private final Map _itemMap = new HashMap (); + + private final Map _itemClientMap = new HashMap (); + + Group ( final Server server, final int serverHandle, final OPCGroupStateMgt group ) throws IllegalArgumentException, UnknownHostException, JIException + { + _log.debug ( "Creating new group instance with COM group " + group ); + this._server = server; + this._serverHandle = serverHandle; + this._group = group; + this._items = group.getItemManagement (); + this._syncIO = group.getSyncIO (); + } + + public void setActive ( final boolean state ) throws JIException + { + this._group.setState ( null, state, null, null, null, null ); + } + + /** + * remove the group from the server + * @throws JIException + * + */ + public void remove () throws JIException + { + this._server.removeGroup ( this, true ); + } + + public boolean isActive () throws JIException + { + return this._group.getState ().isActive (); + } + + /** + * Get the group name from the server + * @return The group name fetched from the server + * @throws JIException + */ + public String getName () throws JIException + { + return this._group.getState ().getName (); + } + + /** + * Change the group name + * @param name the new name of the group + * @throws JIException + */ + public void setName ( final String name ) throws JIException + { + this._group.setName ( name ); + } + + /** + * Add a single item. Actually calls {@link #addItems(String[])} with only + * one paraemter + * @param item The item to add + * @return The added item + * @throws JIException The add operation failed + * @throws AddFailedException The item was not added due to an error + */ + public Item addItem ( final String item ) throws JIException, AddFailedException + { + Map items = addItems ( item ); + return items.get ( item ); + } + + /** + * Validate item ids and get additional information to them. + *
+ * According to the OPC specification you should first validate + * the items and the add them. The spec also says that when a server + * lets the item pass validation it must also let them pass the add operation. + * @param items The items to validate + * @return A result map of item id to result information (including error code). + * @throws JIException + */ + public synchronized Map> validateItems ( final String... items ) throws JIException + { + OPCITEMDEF[] defs = new OPCITEMDEF[items.length]; + for ( int i = 0; i < items.length; i++ ) + { + defs[i] = new OPCITEMDEF (); + defs[i].setItemID ( items[i] ); + } + + KeyedResultSet result = this._items.validate ( defs ); + + Map> resultMap = new HashMap> (); + for ( KeyedResult resultEntry : result ) + { + resultMap.put ( resultEntry.getKey ().getItemID (), new Result ( resultEntry.getValue (), resultEntry.getErrorCode () ) ); + } + + return resultMap; + } + + /** + * Add new items to the group + * @param items The items (by string id) to add + * @return A result map of id to item object + * @throws JIException The add operation completely failed. No item was added. + * @throws AddFailedException If one or more item could not be added. Item without error where added. + */ + public synchronized Map addItems ( final String... items ) throws JIException, AddFailedException + { + // Find which items we already have + Map handles = findItems ( items ); + + List foundItems = new ArrayList ( items.length ); + List missingItems = new ArrayList (); + + // separate missing items from the found ones + for ( Map.Entry entry : handles.entrySet () ) + { + if ( entry.getValue () == null ) + { + missingItems.add ( entry.getKey () ); + } + else + { + foundItems.add ( entry.getValue () ); + } + } + + // now fetch missing items from OPC server + Set newClientHandles = new HashSet (); + OPCITEMDEF[] itemDef = new OPCITEMDEF[missingItems.size ()]; + for ( int i = 0; i < missingItems.size (); i++ ) + { + OPCITEMDEF def = new OPCITEMDEF (); + def.setItemID ( missingItems.get ( i ) ); + def.setActive ( true ); + + Integer clientHandle; + do + { + clientHandle = _random.nextInt (); + } while ( this._itemClientMap.containsKey ( clientHandle ) || newClientHandles.contains ( clientHandle ) ); + newClientHandles.add ( clientHandle ); + def.setClientHandle ( clientHandle ); + + itemDef[i] = def; + } + + // check the result and add new items + Map failedItems = new HashMap (); + KeyedResultSet result = this._items.add ( itemDef ); + int i = 0; + for ( KeyedResult entry : result ) + { + if ( entry.getErrorCode () == 0 ) + { + Item item = new Item ( this, entry.getValue ().getServerHandle (), itemDef[i].getClientHandle (), entry.getKey ().getItemID () ); + addItem ( item ); + foundItems.add ( item.getServerHandle () ); + } + else + { + failedItems.put ( entry.getKey ().getItemID (), entry.getErrorCode () ); + } + i++; + } + + // if we have failed items then throw an exception with the result + if ( failedItems.size () != 0 ) + { + throw new AddFailedException ( failedItems, findItems ( foundItems ) ); + } + + // simply return the result in case of success + return findItems ( foundItems ); + } + + private synchronized void addItem ( final Item item ) + { + _log.debug ( String.format ( "Adding item: '%s', %d", item.getId (), item.getServerHandle () ) ); + + this._itemHandleMap.put ( item.getId (), item.getServerHandle () ); + this._itemMap.put ( item.getServerHandle (), item ); + this._itemClientMap.put ( item.getClientHandle (), item ); + } + + private synchronized void removeItem ( final Item item ) + { + this._itemHandleMap.remove ( item.getId () ); + this._itemMap.remove ( item.getServerHandle () ); + this._itemClientMap.remove ( item.getClientHandle () ); + } + + protected Item getItemByOPCItemId ( final String opcItemId ) + { + Integer serverHandle = this._itemHandleMap.get ( opcItemId ); + if ( serverHandle == null ) + { + _log.debug ( String.format ( "Failed to locate item with id '%s'", opcItemId ) ); + return null; + } + _log.debug ( String.format ( "Item '%s' has server id '%d'", opcItemId, serverHandle ) ); + return this._itemMap.get ( serverHandle ); + } + + private synchronized Map findItems ( final String[] items ) + { + Map data = new HashMap (); + + for ( int i = 0; i < items.length; i++ ) + { + data.put ( items[i], this._itemHandleMap.get ( items[i] ) ); + } + + return data; + } + + private synchronized Map findItems ( final Collection handles ) + { + Map itemMap = new HashMap (); + for ( Integer i : handles ) + { + Item item = this._itemMap.get ( i ); + if ( item != null ) + { + itemMap.put ( item.getId (), item ); + } + } + return itemMap; + } + + protected void checkItems ( final Item[] items ) + { + for ( Item item : items ) + { + if ( item.getGroup () != this ) + { + throw new IllegalArgumentException ( "Item does not belong to this group" ); + } + } + } + + public void setActive ( final boolean state, final Item... items ) throws JIException + { + checkItems ( items ); + + Integer[] handles = new Integer[items.length]; + for ( int i = 0; i < items.length; i++ ) + { + handles[i] = items[i].getServerHandle (); + } + + this._items.setActiveState ( state, handles ); + } + + protected Integer[] getServerHandles ( final Item[] items ) + { + checkItems ( items ); + + Integer[] handles = new Integer[items.length]; + + for ( int i = 0; i < items.length; i++ ) + { + handles[i] = items[i].getServerHandle (); + } + + return handles; + } + + public synchronized Map write ( final WriteRequest... requests ) throws JIException + { + Item[] items = new Item[requests.length]; + + for ( int i = 0; i < requests.length; i++ ) + { + items[i] = requests[i].getItem (); + } + + Integer[] handles = getServerHandles ( items ); + + org.openscada.opc.dcom.da.WriteRequest[] wr = new org.openscada.opc.dcom.da.WriteRequest[items.length]; + for ( int i = 0; i < items.length; i++ ) + { + wr[i] = new org.openscada.opc.dcom.da.WriteRequest ( handles[i], requests[i].getValue () ); + } + + ResultSet resultSet = this._syncIO.write ( wr ); + + Map result = new HashMap (); + for ( int i = 0; i < requests.length; i++ ) + { + Result entry = resultSet.get ( i ); + result.put ( requests[i].getItem (), entry.getErrorCode () ); + } + + return result; + } + + public synchronized Map read ( final boolean device, final Item... items ) throws JIException + { + Integer[] handles = getServerHandles ( items ); + + KeyedResultSet states = this._syncIO.read ( device ? OPCDATASOURCE.OPC_DS_DEVICE : OPCDATASOURCE.OPC_DS_CACHE, handles ); + + Map data = new HashMap (); + for ( KeyedResult entry : states ) + { + Item item = this._itemMap.get ( entry.getKey () ); + ItemState state = new ItemState ( entry.getErrorCode (), entry.getValue ().getValue (), entry.getValue ().getTimestamp ().asCalendar (), entry.getValue ().getQuality () ); + data.put ( item, state ); + } + return data; + } + + public Server getServer () + { + return this._server; + } + + public synchronized void clear () throws JIException + { + Integer[] handles = this._itemMap.keySet ().toArray ( new Integer[0] ); + try + { + this._items.remove ( handles ); + } + finally + { + // in any case clear our maps + this._itemHandleMap.clear (); + this._itemMap.clear (); + this._itemClientMap.clear (); + } + } + + public synchronized OPCAsyncIO2 getAsyncIO20 () + { + return this._group.getAsyncIO2 (); + } + + public synchronized EventHandler attach ( final IOPCDataCallback dataCallback ) throws JIException + { + return this._group.attach ( dataCallback ); + } + + public Item findItemByClientHandle ( final int clientHandle ) + { + return this._itemClientMap.get ( clientHandle ); + } + + public int getServerHandle () + { + return this._serverHandle; + } + + public synchronized void removeItem ( final String opcItemId ) throws IllegalArgumentException, UnknownHostException, JIException + { + _log.debug ( String.format ( "Removing item '%s'", opcItemId ) ); + Item item = getItemByOPCItemId ( opcItemId ); + if ( item != null ) + { + this._group.getItemManagement ().remove ( item.getServerHandle () ); + removeItem ( item ); + _log.debug ( String.format ( "Removed item '%s'", opcItemId ) ); + } + else + { + _log.warn ( String.format ( "Unable to find item '%s'", opcItemId ) ); + } + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Item.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Item.java new file mode 100644 index 0000000..0f72462 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Item.java @@ -0,0 +1,83 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIVariant; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Item +{ + private static Logger _log = LoggerFactory.getLogger ( Item.class ); + + private Group _group = null; + + private int _serverHandle = 0; + + private int _clientHandle = 0; + + private String _id = null; + + Item ( final Group group, final int serverHandle, final int clientHandle, final String id ) + { + super (); + _log.debug ( String.format ( "Adding new item '%s' (0x%08X) for group %s", id, serverHandle, group.toString () ) ); + this._group = group; + this._serverHandle = serverHandle; + this._clientHandle = clientHandle; + this._id = id; + } + + public Group getGroup () + { + return this._group; + } + + public int getServerHandle () + { + return this._serverHandle; + } + + public int getClientHandle () + { + return this._clientHandle; + } + + public String getId () + { + return this._id; + } + + public void setActive ( final boolean state ) throws JIException + { + this._group.setActive ( state, this ); + } + + public ItemState read ( final boolean device ) throws JIException + { + return this._group.read ( device, this ).get ( this ); + } + + public Integer write ( final JIVariant value ) throws JIException + { + return this._group.write ( new WriteRequest[] { new WriteRequest ( this, value ) } ).get ( this ); + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ItemState.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ItemState.java new file mode 100644 index 0000000..74ce707 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ItemState.java @@ -0,0 +1,163 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.util.Calendar; + +import org.jinterop.dcom.core.JIVariant; + +public class ItemState +{ + private int _errorCode = 0; + + private JIVariant _value = null; + + private Calendar _timestamp = null; + + private Short _quality = null; + + public ItemState ( final int errorCode, final JIVariant value, final Calendar timestamp, final Short quality ) + { + super (); + this._errorCode = errorCode; + this._value = value; + this._timestamp = timestamp; + this._quality = quality; + } + + public ItemState () + { + super (); + } + + @Override + public String toString () + { + return String.format ( "Value: %s, Timestamp: %tc, Quality: %s, ErrorCode: %08x", this._value, this._timestamp, this._quality, this._errorCode ); + } + + public Short getQuality () + { + return this._quality; + } + + public void setQuality ( final Short quality ) + { + this._quality = quality; + } + + public Calendar getTimestamp () + { + return this._timestamp; + } + + public void setTimestamp ( final Calendar timestamp ) + { + this._timestamp = timestamp; + } + + public JIVariant getValue () + { + return this._value; + } + + public void setValue ( final JIVariant value ) + { + this._value = value; + } + + public int getErrorCode () + { + return this._errorCode; + } + + public void setErrorCode ( final int errorCode ) + { + this._errorCode = errorCode; + } + + @Override + public int hashCode () + { + final int PRIME = 31; + int result = 1; + result = PRIME * result + this._errorCode; + result = PRIME * result + ( this._quality == null ? 0 : this._quality.hashCode () ); + result = PRIME * result + ( this._timestamp == null ? 0 : this._timestamp.hashCode () ); + result = PRIME * result + ( this._value == null ? 0 : this._value.hashCode () ); + return result; + } + + @Override + public boolean equals ( final Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj == null ) + { + return false; + } + if ( getClass () != obj.getClass () ) + { + return false; + } + final ItemState other = (ItemState)obj; + if ( this._errorCode != other._errorCode ) + { + return false; + } + if ( this._quality == null ) + { + if ( other._quality != null ) + { + return false; + } + } + else if ( !this._quality.equals ( other._quality ) ) + { + return false; + } + if ( this._timestamp == null ) + { + if ( other._timestamp != null ) + { + return false; + } + } + else if ( !this._timestamp.equals ( other._timestamp ) ) + { + return false; + } + if ( this._value == null ) + { + if ( other._value != null ) + { + return false; + } + } + else if ( !this._value.equals ( other._value ) ) + { + return false; + } + return true; + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Server.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Server.java new file mode 100644 index 0000000..9e01248 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/Server.java @@ -0,0 +1,445 @@ +/* + * This file is part of the openSCADA project + * Copyright (C) 2006-2011 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * openSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * openSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with openSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledExecutorService; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIClsid; +import org.jinterop.dcom.core.JIComServer; +import org.jinterop.dcom.core.JIProgId; +import org.jinterop.dcom.core.JISession; +import org.openscada.opc.dcom.da.OPCNAMESPACETYPE; +import org.openscada.opc.dcom.da.OPCSERVERSTATUS; +import org.openscada.opc.dcom.da.impl.OPCBrowseServerAddressSpace; +import org.openscada.opc.dcom.da.impl.OPCGroupStateMgt; +import org.openscada.opc.dcom.da.impl.OPCServer; +import org.openscada.opc.lib.common.AlreadyConnectedException; +import org.openscada.opc.lib.common.ConnectionInformation; +import org.openscada.opc.lib.common.NotConnectedException; +import org.openscada.opc.lib.da.browser.FlatBrowser; +import org.openscada.opc.lib.da.browser.TreeBrowser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Server { + private static Logger logger = LoggerFactory.getLogger(Server.class); + + private final ConnectionInformation connectionInformation; + + private JISession session; + + private JIComServer comServer; + + private OPCServer server; + + private boolean defaultActive = true; + + private int defaultUpdateRate = 1000; + + private Integer defaultTimeBias; + + private Float defaultPercentDeadband; + + private int defaultLocaleID = 0; + + private ErrorMessageResolver errorMessageResolver; + + private final Map groups = new HashMap(); + + private final List stateListeners = new CopyOnWriteArrayList(); + + private final ScheduledExecutorService scheduler; + + public Server(final ConnectionInformation connectionInformation, + final ScheduledExecutorService scheduler) { + super(); + this.connectionInformation = connectionInformation; + this.scheduler = scheduler; + } + + /** + * Gets the scheduler for the server. Note that this scheduler might get + * blocked for a short time if the connection breaks. It should not be used + * for time critical operations. + * + * @return the scheduler for the server + */ + public ScheduledExecutorService getScheduler() { + return this.scheduler; + } + + protected synchronized boolean isConnected() { + return this.session != null; + } + + public synchronized void connect() throws IllegalArgumentException, + UnknownHostException, JIException, AlreadyConnectedException { + if (isConnected()) { + throw new AlreadyConnectedException(); + } + + final int socketTimeout = Integer.getInteger("rpc.socketTimeout", 0); + logger.info(String.format("Socket timeout: %s ", socketTimeout)); + + try { + if (this.connectionInformation.getClsid() != null) { + this.session = JISession.createSession( + this.connectionInformation.getDomain(), + this.connectionInformation.getUser(), + this.connectionInformation.getPassword()); + this.session.setGlobalSocketTimeout(socketTimeout); + this.comServer = new JIComServer( + JIClsid.valueOf(this.connectionInformation.getClsid()), + this.connectionInformation.getHost(), this.session); + } else if (this.connectionInformation.getProgId() != null) { + this.session = JISession.createSession( + this.connectionInformation.getDomain(), + this.connectionInformation.getUser(), + this.connectionInformation.getPassword()); + this.session.setGlobalSocketTimeout(socketTimeout); + this.comServer = new JIComServer( + JIProgId.valueOf(this.connectionInformation.getProgId()), + this.connectionInformation.getHost(), this.session); + } else { + throw new IllegalArgumentException( + "Neither clsid nor progid is valid!"); + } + + this.server = new OPCServer(this.comServer.createInstance()); + this.errorMessageResolver = new ErrorMessageResolver( + this.server.getCommon(), this.defaultLocaleID); + } catch (final UnknownHostException e) { + logger.info("Unknown host when connecting to server", e); + cleanup(); + throw e; + } catch (final JIException e) { + logger.info("Failed to connect to server", e); + cleanup(); + throw e; + } catch (final Throwable e) { + logger.warn("Unknown error", e); + cleanup(); + throw new RuntimeException(e); + } + + notifyConnectionStateChange(true); + } + + /** + * cleanup after the connection is closed + */ + protected void cleanup() { + logger.info("Destroying DCOM session..."); + final JISession destructSession = this.session; + final Thread destructor = new Thread(new Runnable() { + + public void run() { + final long ts = System.currentTimeMillis(); + try { + logger.debug("Starting destruction of DCOM session"); + JISession.destroySession(destructSession); + logger.info("Destructed DCOM session"); + } catch (final Throwable e) { + logger.warn("Failed to destruct DCOM session", e); + } finally { + logger.info(String.format("Session destruction took %s ms", + System.currentTimeMillis() - ts)); + } + } + }, "UtgardSessionDestructor"); + destructor.setName("OPCSessionDestructor"); + destructor.setDaemon(true); + destructor.start(); + logger.info("Destroying DCOM session... forked"); + + this.errorMessageResolver = null; + this.session = null; + this.comServer = null; + this.server = null; + + this.groups.clear(); + } + + /** + * Disconnect the connection if it is connected + */ + public synchronized void disconnect() { + if (!isConnected()) { + return; + } + + try { + notifyConnectionStateChange(false); + } catch (final Throwable t) { + } + + cleanup(); + } + + /** + * Dispose the connection in the case of an error + */ + public void dispose() { + disconnect(); + } + + protected synchronized Group getGroup(final OPCGroupStateMgt groupMgt) + throws JIException, IllegalArgumentException, UnknownHostException { + final Integer serverHandle = groupMgt.getState().getServerHandle(); + if (this.groups.containsKey(serverHandle)) { + return this.groups.get(serverHandle); + } else { + final Group group = new Group(this, serverHandle, groupMgt); + this.groups.put(serverHandle, group); + return group; + } + } + + /** + * Add a new named group to the server + * + * @param name + * The name of the group to use. Must be unique or + * null so that the server creates a unique name. + * @return The new group + * @throws NotConnectedException + * If the server is not connected using {@link Server#connect()} + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + * @throws DuplicateGroupException + * If a group with this name already exists + */ + public synchronized Group addGroup(final String name) + throws NotConnectedException, IllegalArgumentException, + UnknownHostException, JIException, DuplicateGroupException { + if (!isConnected()) { + throw new NotConnectedException(); + } + + try { + final OPCGroupStateMgt groupMgt = this.server.addGroup(name, + this.defaultActive, this.defaultUpdateRate, 0, + this.defaultTimeBias, this.defaultPercentDeadband, + this.defaultLocaleID); + return getGroup(groupMgt); + } catch (final JIException e) { + switch (e.getErrorCode()) { + case 0xC004000C: + throw new DuplicateGroupException(); + default: + throw e; + } + } + } + + /** + * Add a new group and let the server generate a group name + * + * Actually this method only calls {@link Server#addGroup(String)} with + * null as parameter. + * + * @return the new group + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws NotConnectedException + * @throws JIException + * @throws DuplicateGroupException + */ + public Group addGroup() throws IllegalArgumentException, + UnknownHostException, NotConnectedException, JIException, + DuplicateGroupException { + return addGroup(null); + } + + /** + * Find a group by its name + * + * @param name + * The name to look for + * @return The group + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + * @throws UnknownGroupException + * If the group was not found + * @throws NotConnectedException + * If the server is not connected + */ + public Group findGroup(final String name) throws IllegalArgumentException, + UnknownHostException, JIException, UnknownGroupException, + NotConnectedException { + if (!isConnected()) { + throw new NotConnectedException(); + } + + try { + final OPCGroupStateMgt groupMgt = this.server.getGroupByName(name); + return getGroup(groupMgt); + } catch (final JIException e) { + switch (e.getErrorCode()) { + case 0x80070057: + throw new UnknownGroupException(name); + default: + throw e; + } + } + } + + public int getDefaultLocaleID() { + return this.defaultLocaleID; + } + + public void setDefaultLocaleID(final int defaultLocaleID) { + this.defaultLocaleID = defaultLocaleID; + } + + public Float getDefaultPercentDeadband() { + return this.defaultPercentDeadband; + } + + public void setDefaultPercentDeadband(final Float defaultPercentDeadband) { + this.defaultPercentDeadband = defaultPercentDeadband; + } + + public Integer getDefaultTimeBias() { + return this.defaultTimeBias; + } + + public void setDefaultTimeBias(final Integer defaultTimeBias) { + this.defaultTimeBias = defaultTimeBias; + } + + public int getDefaultUpdateRate() { + return this.defaultUpdateRate; + } + + public void setDefaultUpdateRate(final int defaultUpdateRate) { + this.defaultUpdateRate = defaultUpdateRate; + } + + public boolean isDefaultActive() { + return this.defaultActive; + } + + public void setDefaultActive(final boolean defaultActive) { + this.defaultActive = defaultActive; + } + + /** + * Get the flat browser + * + * @return The flat browser or null if the functionality is not + * supported + */ + public FlatBrowser getFlatBrowser() { + final OPCBrowseServerAddressSpace browser = this.server.getBrowser(); + if (browser == null) { + return null; + } + + return new FlatBrowser(browser); + } + + /** + * Get the tree browser + * + * @return The tree browser or null if the functionality is not + * supported + * @throws JIException + */ + public TreeBrowser getTreeBrowser() throws JIException { + final OPCBrowseServerAddressSpace browser = this.server.getBrowser(); + if (browser == null) { + return null; + } + + if (browser.queryOrganization() != OPCNAMESPACETYPE.OPC_NS_HIERARCHIAL) { + return null; + } + + return new TreeBrowser(browser); + } + + public synchronized String getErrorMessage(final int errorCode) { + if (this.errorMessageResolver == null) { + return String.format("Unknown error (%08X)", errorCode); + } + + // resolve message + final String message = this.errorMessageResolver.getMessage(errorCode); + + // and return if successfull + if (message != null) { + return message; + } + + // return default message + return String.format("Unknown error (%08X)", errorCode); + } + + public synchronized void addStateListener( + final ServerConnectionStateListener listener) { + this.stateListeners.add(listener); + listener.connectionStateChanged(isConnected()); + } + + public synchronized void removeStateListener( + final ServerConnectionStateListener listener) { + this.stateListeners.remove(listener); + } + + protected void notifyConnectionStateChange(final boolean connected) { + final List list = new ArrayList( + this.stateListeners); + for (final ServerConnectionStateListener listener : list) { + listener.connectionStateChanged(connected); + } + } + + public OPCSERVERSTATUS getServerState(final int timeout) throws Throwable { + return new ServerStateOperation(this.server).getServerState(timeout); + } + + public OPCSERVERSTATUS getServerState() { + try { + return getServerState(2500); + } catch (final Throwable e) { + logger.info("Server connection failed", e); + dispose(); + return null; + } + } + + public void removeGroup(final Group group, final boolean force) + throws JIException { + if (this.groups.containsKey(group.getServerHandle())) { + this.server.removeGroup(group.getServerHandle(), force); + this.groups.remove(group.getServerHandle()); + } + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerConnectionStateListener.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerConnectionStateListener.java new file mode 100644 index 0000000..ce867dc --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerConnectionStateListener.java @@ -0,0 +1,25 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public interface ServerConnectionStateListener +{ + public abstract void connectionStateChanged ( boolean connected ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateListener.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateListener.java new file mode 100644 index 0000000..9193a48 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateListener.java @@ -0,0 +1,27 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import org.openscada.opc.dcom.da.OPCSERVERSTATUS; + +public interface ServerStateListener +{ + public void stateUpdate ( OPCSERVERSTATUS state ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateOperation.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateOperation.java new file mode 100644 index 0000000..1ec7981 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateOperation.java @@ -0,0 +1,123 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import org.openscada.opc.dcom.da.OPCSERVERSTATUS; +import org.openscada.opc.dcom.da.impl.OPCServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A server state operation which can be interruped + * @author Jens Reimann + * + */ +public class ServerStateOperation implements Runnable +{ + private static Logger _log = LoggerFactory.getLogger ( ServerStateOperation.class ); + + public OPCSERVERSTATUS _serverStatus = null; + + public OPCServer _server; + + public Throwable _error; + + public Object _lock = new Object (); + + public boolean _running = false; + + public ServerStateOperation ( final OPCServer server ) + { + super (); + this._server = server; + } + + /** + * Perform the operation. + *

+ * This method will block until either the serve state has been aquired or the + * timeout triggers cancels the call. + *

+ */ + public void run () + { + synchronized ( this._lock ) + { + this._running = true; + } + try + { + this._serverStatus = this._server.getStatus (); + synchronized ( this._lock ) + { + this._running = false; + this._lock.notify (); + } + } + catch ( Throwable e ) + { + _log.info ( "Failed to get server state", e ); + this._error = e; + this._running = false; + synchronized ( this._lock ) + { + this._lock.notify (); + } + } + + } + + /** + * Get the server state with a timeout. + * @return the server state or null if the server is not set. + * @param timeout the timeout in ms + * @throws Throwable any error that occurred + */ + public OPCSERVERSTATUS getServerState ( final int timeout ) throws Throwable + { + if ( this._server == null ) + { + _log.debug ( "No connection to server. Skipping..." ); + return null; + } + + Thread t = new Thread ( this, "OPCServerStateReader" ); + + synchronized ( this._lock ) + { + t.start (); + this._lock.wait ( timeout ); + if ( this._running ) + { + _log.warn ( "State operation still running. Interrupting..." ); + t.interrupt (); + throw new InterruptedException ( "Interrupted getting server state" ); + } + } + if ( this._error != null ) + { + _log.warn ( "An error occurred while getting server state", this._error ); + throw this._error; + } + + return this._serverStatus; + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateReader.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateReader.java new file mode 100644 index 0000000..6b8f9a7 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/ServerStateReader.java @@ -0,0 +1,108 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.openscada.opc.dcom.da.OPCSERVERSTATUS; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServerStateReader +{ + private static Logger _log = LoggerFactory.getLogger ( ServerStateReader.class ); + + private Server _server = null; + + private ScheduledExecutorService _scheduler = null; + + private final List _listeners = new CopyOnWriteArrayList (); + + private ScheduledFuture _job = null; + + public ServerStateReader ( final Server server ) + { + super (); + this._server = server; + this._scheduler = this._server.getScheduler (); + } + + /** + * Create a new server state reader. Please note that the scheduler might get + * blocked for a short period of time in case of a connection failure! + * @param server the server to check + * @param scheduler the scheduler to use + */ + public ServerStateReader ( final Server server, final ScheduledExecutorService scheduler ) + { + super (); + this._server = server; + this._scheduler = scheduler; + } + + public synchronized void start () + { + if ( this._job != null ) + { + return; + } + + this._job = this._scheduler.scheduleAtFixedRate ( new Runnable () { + + public void run () + { + once (); + } + }, 1000, 1000, TimeUnit.MILLISECONDS ); + } + + public synchronized void stop () + { + this._job.cancel ( false ); + this._job = null; + } + + protected void once () + { + _log.debug ( "Reading server state" ); + + final OPCSERVERSTATUS state = this._server.getServerState (); + + for ( final ServerStateListener listener : new ArrayList ( this._listeners ) ) + { + listener.stateUpdate ( state ); + } + } + + public void addListener ( final ServerStateListener listener ) + { + this._listeners.add ( listener ); + } + + public void removeListener ( final ServerStateListener listener ) + { + this._listeners.remove ( listener ); + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/SyncAccess.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/SyncAccess.java new file mode 100644 index 0000000..6d13f53 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/SyncAccess.java @@ -0,0 +1,120 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import java.net.UnknownHostException; +import java.util.Map; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.lib.common.NotConnectedException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SyncAccess extends AccessBase implements Runnable +{ + private static Logger logger = LoggerFactory.getLogger ( SyncAccess.class ); + + private Thread runner = null; + + private Throwable lastError = null; + + public SyncAccess ( final Server server, final int period ) throws IllegalArgumentException, UnknownHostException, NotConnectedException, JIException, DuplicateGroupException + { + super ( server, period ); + } + + public SyncAccess ( final Server server, final int period, final String logTag ) throws IllegalArgumentException, UnknownHostException, NotConnectedException, JIException, DuplicateGroupException + { + super ( server, period, logTag ); + } + + public void run () + { + while ( this.active ) + { + try + { + runOnce (); + if ( this.lastError != null ) + { + this.lastError = null; + handleError ( null ); + } + } + catch ( Throwable e ) + { + logger.error ( "Sync read failed", e ); + handleError ( e ); + this.server.disconnect (); + } + + try + { + Thread.sleep ( getPeriod () ); + } + catch ( InterruptedException e ) + { + } + } + } + + protected void runOnce () throws JIException + { + if ( !this.active || this.group == null ) + { + return; + } + + Map result; + + // lock only this section since we could get into a deadlock otherwise + // calling updateItem + synchronized ( this ) + { + Item[] items = this.items.keySet ().toArray ( new Item[this.items.size ()] ); + result = this.group.read ( false, items ); + } + + for ( Map.Entry entry : result.entrySet () ) + { + updateItem ( entry.getKey (), entry.getValue () ); + } + + } + + @Override + protected synchronized void start () throws JIException, IllegalArgumentException, UnknownHostException, NotConnectedException, DuplicateGroupException + { + super.start (); + + this.runner = new Thread ( this, "UtgardSyncReader" ); + this.runner.setDaemon ( true ); + this.runner.start (); + } + + @Override + protected synchronized void stop () throws JIException + { + super.stop (); + + this.runner = null; + this.items.clear (); + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/UnknownGroupException.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/UnknownGroupException.java new file mode 100644 index 0000000..6694fe7 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/UnknownGroupException.java @@ -0,0 +1,47 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +public class UnknownGroupException extends Exception +{ + private String _name = null; + + public UnknownGroupException ( final String name ) + { + super (); + this._name = name; + } + + /** + * + */ + private static final long serialVersionUID = 1771564928794033075L; + + public String getName () + { + return this._name; + } + + public void setName ( final String name ) + { + this._name = name; + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/WriteRequest.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/WriteRequest.java new file mode 100644 index 0000000..88e6b8a --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/WriteRequest.java @@ -0,0 +1,46 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da; + +import org.jinterop.dcom.core.JIVariant; + +public class WriteRequest +{ + private Item _item = null; + + private JIVariant _value = null; + + public WriteRequest ( final Item item, final JIVariant value ) + { + super (); + this._item = item; + this._value = value; + } + + public Item getItem () + { + return this._item; + } + + public JIVariant getValue () + { + return this._value; + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Access.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Access.java new file mode 100644 index 0000000..fa9e4cc --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Access.java @@ -0,0 +1,38 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +public enum Access +{ + READ ( 1 ), + WRITE ( 2 ); + + private int _code = 0; + + private Access ( final int code ) + { + this._code = code; + } + + public int getCode () + { + return this._code; + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/BaseBrowser.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/BaseBrowser.java new file mode 100644 index 0000000..76e1d54 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/BaseBrowser.java @@ -0,0 +1,124 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.EnumSet; + +import org.jinterop.dcom.common.JIException; +import org.openscada.opc.dcom.common.impl.EnumString; +import org.openscada.opc.dcom.da.OPCBROWSETYPE; +import org.openscada.opc.dcom.da.impl.OPCBrowseServerAddressSpace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A class implementing base browsing + * @author Jens Reimann + * + */ +public class BaseBrowser +{ + private static Logger _log = LoggerFactory.getLogger ( BaseBrowser.class ); + + protected OPCBrowseServerAddressSpace _browser; + + /** + * The batch size is the number of entries that will be requested with one call + * from the server. Sometimes too big batch sizes will cause an exception. And + * smaller batch sizes degrade perfomance. The default is set by {@link EnumString#DEFAULT_BATCH_SIZE} + * and can be overridden by the java property openscada.dcom.enum-batch-size. + */ + protected int _batchSize; + + public BaseBrowser ( final OPCBrowseServerAddressSpace browser ) + { + this ( browser, EnumString.DEFAULT_BATCH_SIZE ); + } + + public BaseBrowser ( final OPCBrowseServerAddressSpace browser, final int batchSize ) + { + super (); + this._browser = browser; + this._batchSize = batchSize; + } + + /** + * Set the batch size + * @param batchSize The new batch size + */ + public void setBatchSize ( final int batchSize ) + { + this._batchSize = batchSize; + } + + /** + * Get the batch size + * @return the current batch size + */ + public int getBatchSize () + { + return this._batchSize; + } + + /** + * Perform the browse operation. + * @param type + * @param filterCriteria + * @param accessMask + * @param variantType + * @return The browse result + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + protected Collection browse ( final OPCBROWSETYPE type, final String filterCriteria, final EnumSet accessMask, final int variantType ) throws IllegalArgumentException, UnknownHostException, JIException + { + int accessMaskValue = 0; + + if ( accessMask.contains ( Access.READ ) ) + { + accessMaskValue |= Access.READ.getCode (); + } + if ( accessMask.contains ( Access.WRITE ) ) + { + accessMaskValue |= Access.WRITE.getCode (); + } + + _log.debug ( "Browsing with a batch size of " + this._batchSize ); + + return this._browser.browse ( type, filterCriteria, accessMaskValue, variantType ).asCollection ( this._batchSize ); + } + + /** + * Browse the access paths for one item. + * @param itemId The item ID to look up the access paths + * @return The collection of the access paths + * @throws JIException + * @throws UnknownHostException + * @throws IllegalArgumentException + */ + public Collection getAccessPaths ( final String itemId ) throws IllegalArgumentException, UnknownHostException, JIException + { + return this._browser.browseAccessPaths ( itemId ).asCollection ( this._batchSize ); + } + +} \ No newline at end of file diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Branch.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Branch.java new file mode 100644 index 0000000..e09eb22 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Branch.java @@ -0,0 +1,123 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; + +public class Branch +{ + private Branch _parent = null; + + private String _name = null; + + private Collection _branches = new LinkedList (); + + private Collection _leaves = new LinkedList (); + + /** + * Create a branch to the virtual root folder + * + */ + public Branch () + { + super (); + } + + /** + * Create a branch with a parent branch and a name of this branch. + * @param parent The parent of this branch + * @param name The name of this branch + */ + public Branch ( final Branch parent, final String name ) + { + super (); + this._name = name; + this._parent = parent; + } + + /** + * Get all branches. + *
+ * They must be filled first with a fill method from the {@link TreeBrowser} + * @return The list of branches + */ + public Collection getBranches () + { + return this._branches; + } + + public void setBranches ( final Collection branches ) + { + this._branches = branches; + } + + /** + * Get all leaves. + *
+ * They must be filled first with a fill method from the {@link TreeBrowser} + * @return The list of leaves + */ + public Collection getLeaves () + { + return this._leaves; + } + + public void setLeaves ( final Collection leaves ) + { + this._leaves = leaves; + } + + public String getName () + { + return this._name; + } + + public void setName ( final String name ) + { + this._name = name; + } + + public Branch getParent () + { + return this._parent; + } + + /** + * Get the list of names from the parent up to this branch + * @return The stack of branch names from the parent up this one + */ + public Collection getBranchStack () + { + LinkedList branches = new LinkedList (); + + Branch currentBranch = this; + while ( currentBranch.getParent () != null ) + { + branches.add ( currentBranch.getName () ); + currentBranch = currentBranch.getParent (); + } + + Collections.reverse ( branches ); + return branches; + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/FlatBrowser.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/FlatBrowser.java new file mode 100644 index 0000000..f06d03e --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/FlatBrowser.java @@ -0,0 +1,78 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.EnumSet; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.da.OPCBROWSETYPE; +import org.openscada.opc.dcom.da.impl.OPCBrowseServerAddressSpace; + +/** + * Browse through the flat server namespace + * @author Jens Reimann + * + */ +public class FlatBrowser extends BaseBrowser +{ + public FlatBrowser ( final OPCBrowseServerAddressSpace browser ) + { + super ( browser ); + } + + public FlatBrowser ( final OPCBrowseServerAddressSpace browser, final int batchSize ) + { + super ( browser, batchSize ); + } + + /** + * Perform a flat browse operation + * @param filterCriteria The filter criteria. Use an empty string if you don't need one. + * @param accessMask The access mask. An empty set will search for all. + * @param variantType The variant type. Must be one of the VT_ constants of {@link JIVariant}. Use {@link JIVariant#VT_EMPTY} if you want to browse for all. + * @return The list of entries + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public Collection browse ( final String filterCriteria, final EnumSet accessMask, final int variantType ) throws IllegalArgumentException, UnknownHostException, JIException + { + return browse ( OPCBROWSETYPE.OPC_FLAT, filterCriteria, accessMask, variantType ); + } + + public Collection browse ( final String filterCriteria ) throws IllegalArgumentException, UnknownHostException, JIException + { + return browse ( filterCriteria, EnumSet.noneOf ( Access.class ), JIVariant.VT_EMPTY ); + } + + public Collection browse () throws IllegalArgumentException, UnknownHostException, JIException + { + return browse ( "", EnumSet.noneOf ( Access.class ), JIVariant.VT_EMPTY ); + } + + public Collection browse ( final EnumSet accessMask ) throws IllegalArgumentException, UnknownHostException, JIException + { + return browse ( "", accessMask, JIVariant.VT_EMPTY ); + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Leaf.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Leaf.java new file mode 100644 index 0000000..ffc8c04 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/Leaf.java @@ -0,0 +1,68 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +public class Leaf +{ + private Branch _parent = null; + + private String _name = ""; + + private String _itemId = null; + + public Leaf ( final Branch parent, final String name ) + { + this._parent = parent; + this._name = name; + } + + public Leaf ( final Branch parent, final String name, final String itemId ) + { + this._parent = parent; + this._name = name; + this._itemId = itemId; + } + + public String getItemId () + { + return this._itemId; + } + + public void setItemId ( final String itemId ) + { + this._itemId = itemId; + } + + public String getName () + { + return this._name; + } + + public void setName ( final String name ) + { + this._name = name; + } + + public Branch getParent () + { + return this._parent; + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/TreeBrowser.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/TreeBrowser.java new file mode 100644 index 0000000..3070965 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/da/browser/TreeBrowser.java @@ -0,0 +1,240 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.da.browser; + +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedList; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIVariant; +import org.openscada.opc.dcom.da.OPCBROWSEDIRECTION; +import org.openscada.opc.dcom.da.OPCBROWSETYPE; +import org.openscada.opc.dcom.da.impl.OPCBrowseServerAddressSpace; + +/** + * Browse through the hierarchical server namespace. + *
+ * The operations on the address space browser browser are not synchronized + * as is the TreeBrowser itself. The user must take care of preventing + * simultanious access to this instance and the server address space browser. + * @author Jens Reimann + * + */ +public class TreeBrowser extends BaseBrowser +{ + + private String _filterCriteria = ""; + + private EnumSet _accessMask = EnumSet.noneOf ( Access.class ); + + private int _variantType = JIVariant.VT_EMPTY; + + /** + * Browse for all items without search parameters. + *
+ * This will actually call: + *
+ * + * TreeBrowser ( browser, "", EnumSet.noneOf ( Access.class ), JIVariant.VT_EMPTY ); + * + * @param browser The browser to use for browsing + */ + public TreeBrowser ( final OPCBrowseServerAddressSpace browser ) + { + super ( browser ); + } + + /** + * Browse for items with search parameters. + * @param browser The browser to use + * @param filterCriteria The filter criteria. It is specific to the server you use. + * @param accessMask The access mask (use EnumSet.noneOf ( Access.class ) for all) + * @param variantType The variant type (use JIVariant.VT_EMPTY for all) + */ + public TreeBrowser ( final OPCBrowseServerAddressSpace browser, final String filterCriteria, final EnumSet accessMask, final int variantType ) + { + super ( browser ); + this._filterCriteria = filterCriteria; + this._accessMask = accessMask; + this._variantType = variantType; + } + + /** + * Move the tree browser to the root folder + * @throws JIException + */ + protected void moveToRoot () throws JIException + { + this._browser.changePosition ( null, OPCBROWSEDIRECTION.OPC_BROWSE_TO ); + } + + /** + * Move the tree browser to a branch + * @param branch The branch to move to + * @throws JIException + */ + protected void moveToBranch ( final Branch branch ) throws JIException + { + Collection branchStack = branch.getBranchStack (); + + moveToRoot (); + for ( String branchName : branchStack ) + { + this._browser.changePosition ( branchName, OPCBROWSEDIRECTION.OPC_BROWSE_DOWN ); + } + } + + /** + * Browse the root branch for its sub-branches. + * @return The list of sub branches + * @throws JIException + * @throws IllegalArgumentException + * @throws UnknownHostException + */ + public Branch browseBranches () throws JIException, IllegalArgumentException, UnknownHostException + { + Branch branch = new Branch (); + fillBranches ( branch ); + return branch; + } + + /** + * Browse the root branch for this leaves. + * @return The list of leaves + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public Branch browseLeaves () throws IllegalArgumentException, UnknownHostException, JIException + { + Branch branch = new Branch (); + fillLeaves ( branch ); + return branch; + } + + /** + * Fill the branch list of the provided branch. + * @param branch The branch to fill. + * @throws JIException + * @throws IllegalArgumentException + * @throws UnknownHostException + */ + public void fillBranches ( final Branch branch ) throws JIException, IllegalArgumentException, UnknownHostException + { + moveToBranch ( branch ); + browse ( branch, false, true, false ); + } + + /** + * Fill the leaf list of the provided branch. + * @param branch The branch to fill. + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public void fillLeaves ( final Branch branch ) throws IllegalArgumentException, UnknownHostException, JIException + { + moveToBranch ( branch ); + browse ( branch, true, false, false ); + } + + /** + * Browse through all levels of the tree browser. + * @return The whole expanded server address space + * @throws JIException + * @throws IllegalArgumentException + * @throws UnknownHostException + */ + public Branch browse () throws JIException, IllegalArgumentException, UnknownHostException + { + Branch branch = new Branch (); + fill ( branch ); + return branch; + } + + /** + * Fill the leaves and branches of the branch provided branches including + * alls sub-branches. + * @param branch The branch to fill. + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public void fill ( final Branch branch ) throws IllegalArgumentException, UnknownHostException, JIException + { + moveToBranch ( branch ); + browse ( branch, true, true, true ); + } + + /** + * Fill the branch object with the leaves of this currently selected branch. + *
+ * The server object is not located to the branch before browsing! + * @param branch The branch to fill + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + protected void browseLeaves ( final Branch branch ) throws IllegalArgumentException, UnknownHostException, JIException + { + branch.setLeaves ( new LinkedList () ); + + for ( String item : browse ( OPCBROWSETYPE.OPC_LEAF, this._filterCriteria, this._accessMask, this._variantType ) ) + { + Leaf leaf = new Leaf ( branch, item, this._browser.getItemID ( item ) ); + branch.getLeaves ().add ( leaf ); + } + } + + protected void browseBranches ( final Branch branch, final boolean leaves, final boolean descend ) throws IllegalArgumentException, UnknownHostException, JIException + { + branch.setBranches ( new LinkedList () ); + + for ( String item : browse ( OPCBROWSETYPE.OPC_BRANCH, this._filterCriteria, this._accessMask, this._variantType ) ) + { + Branch subBranch = new Branch ( branch, item ); + // descend only if we should + if ( descend ) + { + this._browser.changePosition ( item, OPCBROWSEDIRECTION.OPC_BROWSE_DOWN ); + browse ( subBranch, leaves, true, true ); + this._browser.changePosition ( null, OPCBROWSEDIRECTION.OPC_BROWSE_UP ); + } + branch.getBranches ().add ( subBranch ); + } + } + + protected void browse ( final Branch branch, final boolean leaves, final boolean branches, final boolean descend ) throws IllegalArgumentException, UnknownHostException, JIException + { + // process leaves + if ( leaves ) + { + browseLeaves ( branch ); + } + + // process branches + if ( branches ) + { + browseBranches ( branch, leaves, descend ); + } + } +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Categories.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Categories.java new file mode 100644 index 0000000..c2b0a41 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Categories.java @@ -0,0 +1,43 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.list; + +public interface Categories +{ + /** + * Category of the OPC DA 1.0 Servers + */ + public final static Category OPCDAServer10 = new Category ( org.openscada.opc.dcom.common.Categories.OPCDAServer10 ); + + /** + * Category of the OPC DA 2.0 Servers + */ + public final static Category OPCDAServer20 = new Category ( org.openscada.opc.dcom.common.Categories.OPCDAServer20 ); + + /** + * Category of the OPC DA 3.0 Servers + */ + public final static Category OPCDAServer30 = new Category ( org.openscada.opc.dcom.common.Categories.OPCDAServer30 ); + + /** + * Category of the XML DA 1.0 Servers + */ + public final static Category XMLDAServer10 = new Category ( org.openscada.opc.dcom.common.Categories.XMLDAServer10 ); +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Category.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Category.java new file mode 100644 index 0000000..b304d15 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/Category.java @@ -0,0 +1,76 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.list; + +public class Category +{ + private String _catId = null; + + public Category ( final String catId ) + { + this._catId = catId; + } + + @Override + public String toString () + { + return this._catId; + } + + @Override + public int hashCode () + { + final int PRIME = 31; + int result = 1; + result = PRIME * result + ( this._catId == null ? 0 : this._catId.hashCode () ); + return result; + } + + @Override + public boolean equals ( final Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( obj == null ) + { + return false; + } + if ( getClass () != obj.getClass () ) + { + return false; + } + final Category other = (Category)obj; + if ( this._catId == null ) + { + if ( other._catId != null ) + { + return false; + } + } + else if ( !this._catId.equals ( other._catId ) ) + { + return false; + } + return true; + } + +} diff --git a/org.openscada.opc.lib/src/org/openscada/opc/lib/list/ServerList.java b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/ServerList.java new file mode 100644 index 0000000..538fd71 --- /dev/null +++ b/org.openscada.opc.lib/src/org/openscada/opc/lib/list/ServerList.java @@ -0,0 +1,179 @@ +/* + * This file is part of the OpenSCADA project + * Copyright (C) 2006-2010 TH4 SYSTEMS GmbH (http://th4-systems.com) + * + * OpenSCADA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenSCADA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenSCADA. If not, see + * for a copy of the LGPLv3 License. + */ + +package org.openscada.opc.lib.list; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jinterop.dcom.common.JIException; +import org.jinterop.dcom.core.JIClsid; +import org.jinterop.dcom.core.JIComServer; +import org.jinterop.dcom.core.JISession; +import org.openscada.opc.dcom.list.ClassDetails; +import org.openscada.opc.dcom.list.Constants; +import org.openscada.opc.dcom.list.impl.OPCServerList; + +import rpc.core.UUID; + +/** + * A wrapper around the {@link OPCServerList} class which makes the handling somewhat easier. + * @author Jens Reimann <jens.reimann@th4-systems.com> + * @since 0.1.8 + * + */ +public class ServerList +{ + private final JISession _session; + + private final OPCServerList _serverList; + + /** + * Create a new instance with an already existing session + * @param session the DCOM session + * @param host the host to query + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public ServerList ( final JISession session, final String host ) throws IllegalArgumentException, UnknownHostException, JIException + { + this._session = session; + JIComServer comServer = new JIComServer ( JIClsid.valueOf ( Constants.OPCServerList_CLSID ), host, this._session ); + this._serverList = new OPCServerList ( comServer.createInstance () ); + } + + /** + * Create a new instance and a new DCOM session + * @param host the host to contact + * @param user the user to use for authentication + * @param password the password to use for authentication + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public ServerList ( final String host, final String user, final String password ) throws IllegalArgumentException, UnknownHostException, JIException + { + this ( host, user, password, null ); + } + + /** + * Create a new instance and a new DCOM session + * @param host the host to contact + * @param user the user to use for authentication + * @param password the password to use for authentication + * @param domain The domain to use for authentication + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public ServerList ( final String host, final String user, final String password, final String domain ) throws IllegalArgumentException, UnknownHostException, JIException + { + this ( JISession.createSession ( domain, user, password ), host ); + } + + /** + * Get the details of a opc class + * @param clsId the class to request details for + * @return The class details + * @throws JIException + */ + public ClassDetails getDetails ( final String clsId ) throws JIException + { + return this._serverList.getClassDetails ( JIClsid.valueOf ( clsId ) ); + } + + /** + * Fetch the class id of a prog id + * @param progId The prog id to look up + * @return the class id or null if none could be found. + * @throws JIException + */ + public String getClsIdFromProgId ( final String progId ) throws JIException + { + JIClsid cls = this._serverList.getCLSIDFromProgID ( progId ); + if ( cls == null ) + { + return null; + } + return cls.getCLSID (); + } + + /** + * List all servers that match the requirements + * @param implemented All implemented categories + * @param required All required categories + * @return A collection of class ids + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public Collection listServers ( final Category[] implemented, final Category[] required ) throws IllegalArgumentException, UnknownHostException, JIException + { + // convert the type safe categories to plain UUIDs + UUID[] u1 = new UUID[implemented.length]; + UUID[] u2 = new UUID[required.length]; + + for ( int i = 0; i < implemented.length; i++ ) + { + u1[i] = new UUID ( implemented[i].toString () ); + } + + for ( int i = 0; i < required.length; i++ ) + { + u2[i] = new UUID ( required[i].toString () ); + } + + // get them as UUIDs + Collection resultU = this._serverList.enumClassesOfCategories ( u1, u2 ).asCollection (); + + // and convert to easier usable strings + Collection result = new ArrayList ( resultU.size () ); + for ( UUID uuid : resultU ) + { + result.add ( uuid.toString () ); + } + return result; + } + + /** + * List all servers that match the requirements and return the class details + * @param implemented All implemented categories + * @param required All required categories + * @return a collection of matching server and their class information + * @throws IllegalArgumentException + * @throws UnknownHostException + * @throws JIException + */ + public Collection listServersWithDetails ( final Category[] implemented, final Category[] required ) throws IllegalArgumentException, UnknownHostException, JIException + { + Collection resultString = listServers ( implemented, required ); + + List result = new ArrayList ( resultString.size () ); + + for ( String clsId : resultString ) + { + result.add ( getDetails ( clsId ) ); + } + + return result; + } +}