From 2ef6cdb76d2796507dcac7d61528c2dfd1e7126c Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Wed, 9 Oct 2019 12:18:48 +0100 Subject: [PATCH 1/8] Adding in Java bindings for libiec61850 using SWIG --- javaiec61850/IEC61850Client.java | 87 +++++++++++++++++++++++++++++ javaiec61850/IEC61850Server.java | 68 ++++++++++++++++++++++ javaiec61850/iec61850.i | 40 +++++++++++++ javaiec61850/test_javaiec61850.java | 55 ++++++++++++++++++ 4 files changed, 250 insertions(+) create mode 100644 javaiec61850/IEC61850Client.java create mode 100644 javaiec61850/IEC61850Server.java create mode 100644 javaiec61850/iec61850.i create mode 100644 javaiec61850/test_javaiec61850.java diff --git a/javaiec61850/IEC61850Client.java b/javaiec61850/IEC61850Client.java new file mode 100644 index 00000000..e3a7c53c --- /dev/null +++ b/javaiec61850/IEC61850Client.java @@ -0,0 +1,87 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +public class IEC61850Client { + + private int tcpPort = 8102; + private SWIGTYPE_p_sIedConnection con; + + // List of int values for Client Side errors from iec61850_client.h + private int[] error = {0, 1, 2,3, 4, 5, 10, 11, 12, 13, 21, 22, 23, 24,25,26, 27, 28, 29, 30, 31, 32, 33, 98, 99}; + private IedConnectionState conState = null; + private String theVal = null; + private FunctionalConstraint theValType = null; + private float temperatureValue; + private float newValue; + private LastApplError err = null; + private int theExpectedError = 21; + private float temperatureSetpoint; + + IEC61850Client() { + + if (con == null) { + con = iec61850.IedConnection_create(); + } + + iec61850.IedConnection_connect(con, error, "localhost", tcpPort); + + conState = iec61850.IedConnection_getState(con); + + if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { + System.out.println("IEC61850Client has connected to the IEC61850Server" ); + + //Accessing to SAV values + theVal = "testmodelSENSORS/TTMP1.TmpSv.instMag.f"; + theValType = FunctionalConstraint.IEC61850_FC_MX; + + temperatureValue = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + + if (temperatureValue == 0) { + System.out.println("IEC61850Client has read testmodelSENSORS" ); + } + + newValue = temperatureValue + 10; + + iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); + + err = iec61850.IedConnection_getLastApplError(con); + + if (err.getError() == theExpectedError) { + System.out.println("IEC61850Client caught the expected client error = " + err.getError() ); + } else { + System.out.println("IEC61850Client caught a error = " + err.getError() ); + } + + // Accessing to ASG values + theVal = "testmodelSENSORS/TTMP1.TmpSp.setMag.f"; + theValType = FunctionalConstraint.IEC61850_FC_SP; + temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); + + newValue = temperatureValue + 10; + iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); + + temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + + if (temperatureSetpoint == newValue) { + System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); + } + + //Must close the connection at the end of the test. + iec61850.IedConnection_close(con); + + } else { + System.out.println("IEC61850Client connection error " + conState ); + + iec61850.IedConnection_close(con); + + } + //Destroy the connection at the end of the test. + iec61850.IedConnection_destroy(con); + + } +} diff --git a/javaiec61850/IEC61850Server.java b/javaiec61850/IEC61850Server.java new file mode 100644 index 00000000..7f805627 --- /dev/null +++ b/javaiec61850/IEC61850Server.java @@ -0,0 +1,68 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +public class IEC61850Server extends Thread { + + private sIedModel model = null; + private SWIGTYPE_p_sIedServer iedServer = null; + private int tcpPort = 8102; + + @Override + public void interrupt() { + try { + iec61850.IedServer_stop(iedServer); + iec61850.IedServer_destroy(iedServer); + iec61850.IedModel_destroy(model); + System.out.println("IEC61850Server has been Interrupted and STOPPED" ); + } catch (Exception ignored) { + } finally { + super.interrupt(); + } + } + + @Override + public void run() { + + System.out.println("MyThread for IEC61850Server has STARTED" ); + //Create a iec61850.IedModel + model = iec61850.IedModel_create("testmodel"); + + //Create a logical device + sLogicalDevice lDevice1 = iec61850.LogicalDevice_create("SENSORS", model); + + //Create nodes off this logical device + sLogicalNode lln0 = iec61850.LogicalNode_create("LLN0", lDevice1); + sLogicalNode ttmp1 = iec61850.LogicalNode_create("TTMP1", lDevice1); + + sDataObject cdc_sav = iec61850.CDC_SAV_create("TmpSv", iec61850.toModelNode(ttmp1), 0, false); + sDataObject cdc_asg = iec61850.CDC_ASG_create("TmpSp", iec61850.toModelNode(ttmp1), 0, false); + + // Create a iec61850.IedServer based on a test IedModel node + iedServer = iec61850.IedServer_create(model); + iec61850.IedServer_start(iedServer, tcpPort); + + if (!iec61850.IedServer_isRunning(iedServer)) { + System.out.println("Starting server failed! Exit.\n"); + iec61850.IedServer_destroy(iedServer); + iec61850.IedModel_destroy(model); + System.exit(0); + } + + System.out.println("IEC61850Server has STARTED" ); + + while (true) { + try { + Thread.sleep((long) 100); + } catch (InterruptedException e) { + break; + } + } + + + + } + } diff --git a/javaiec61850/iec61850.i b/javaiec61850/iec61850.i new file mode 100644 index 00000000..54087631 --- /dev/null +++ b/javaiec61850/iec61850.i @@ -0,0 +1,40 @@ +/* File : iec61850.i */ +%module iec61850 +%ignore ControlObjectClient_setTestMode(ControlObjectClient self); +%ignore CDA_OperBoolean(ModelNode* parent, bool isTImeActivated); +%ignore LogicalNode_hasBufferedReports(LogicalNode* node); +%ignore LogicalNode_hasUnbufferedReports(LogicalNode* node); +%ignore MmsConnection_setIsoConnectionParameters(MmsConnection self, IsoConnectionParameters* params); +%include "stdint.i" +%include "typemaps.i" +%{ +#include +#include +#include +ModelNode* toModelNode(LogicalNode * ln) +{ + return (ModelNode*) ln; +} +char* toCharP(void * v) +{ + return (char *) v; +} +DataAttribute* toDataAttribute(ModelNode * MN) +{ return (DataAttribute*)MN;} +%} +%apply int *OUTPUT {IedClientError* error}; + +%include "iec61850_client.h" +%include "iso_connection_parameters.h" +%include "mms_client_connection.h" +%include "iso_connection_parameters.h" +%include "iec61850_common.h" +%include "mms_value.h" +%include "iec61850_model.h" +%include "iec61850_server.h" +%include "iec61850_dynamic_model.h" +%include "iec61850_cdc.h" +%include "linked_list.h" +ModelNode* toModelNode(LogicalNode *); +DataAttribute* toDataAttribute(ModelNode *); +char* toCharP(void *); diff --git a/javaiec61850/test_javaiec61850.java b/javaiec61850/test_javaiec61850.java new file mode 100644 index 00000000..adf35d6c --- /dev/null +++ b/javaiec61850/test_javaiec61850.java @@ -0,0 +1,55 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +import java.lang.System; +import java.lang.Throwable; +import java.lang.Thread; +import java.lang.String; +import java.io.*; + +/** + * This test programme should mirror the functionality laid out in the Python + * equivalent. + * + * @author Miguel Ponce de Leon + */ + +public class test_javaiec61850 { + + static { + try { + //Using loadLibrary means that LD_LIBRARY_PATH must be set + System.load("/opt/libiec61850/javaiec61850/libiec61850.so"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library libiec61850 failed to load.\n" + e); + System.exit(1); + } + } + + /** + * main is the main entry point into this tester application. IEC61850Server runs + * as a server in a waiting Thread and then a IEC61850Client interacts with that + * servers model. + */ + + public static void main (String[] args) throws Throwable { + + IEC61850Server iec61850Server = new IEC61850Server(); + + iec61850Server.start(); + + Thread.sleep((long) 200); + //Run the test IEC Client + IEC61850Client testIECClient = new IEC61850Client(); + + //Stop the iec61850Server + if (iec61850Server != null) { + iec61850Server.interrupt(); + } + } + +} From 619d12011b410c264af087f77bed042a85ab6a4a Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Wed, 9 Oct 2019 13:39:11 +0100 Subject: [PATCH 2/8] Added a tutorial file to explain how to build the Java library of IEC61850. --- javaiec61850/iec61850.i | 1 + javaiec61850/tutorial.md | 76 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 javaiec61850/tutorial.md diff --git a/javaiec61850/iec61850.i b/javaiec61850/iec61850.i index 54087631..eebe5e79 100644 --- a/javaiec61850/iec61850.i +++ b/javaiec61850/iec61850.i @@ -24,6 +24,7 @@ DataAttribute* toDataAttribute(ModelNode * MN) %} %apply int *OUTPUT {IedClientError* error}; +%include "libiec61850_common_api.h" %include "iec61850_client.h" %include "iso_connection_parameters.h" %include "mms_client_connection.h" diff --git a/javaiec61850/tutorial.md b/javaiec61850/tutorial.md new file mode 100644 index 00000000..36181011 --- /dev/null +++ b/javaiec61850/tutorial.md @@ -0,0 +1,76 @@ +# Building +Before building you should install swig and java. + +From the root directory of the libiec61850 project you have to build some of the dependant libraries + +> cd .. +> +> make clean +> +> make INSTALL_PREFIX=/usr/local install +> +> make clean +> +> make INSTALL_PREFIX=/usr/local dynlib + +Now change into the Java project subdirectory + +> cd javaiec61850 +> +> swig -java -I/usr/local/include iec61850.i +> +> gcc -fpic -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux -c iec61850_wrap.c +> +> ld -shared ../build/libiec61850.so iec61850_wrap.o -o libiec61850.so +> +> javac test_javaiec61850.java +> +> java test_javaiec61850 + +This test programme should show an out put of + +```sh +MyThread for IEC61850Server has STARTED +IEC61850Server has STARTED +IEC61850Client has connected to the IEC61850Server +IEC61850Client has read testmodelSENSORS +IEC61850Client caught a error = 0 +IEC61850Client read a temperature set point of = 0.0 +IEC61850Client read a temperature set point of = 10.0 +IEC61850Server has been Interrupted and STOPPED + +``` + +The CMakeLists file does not exist yet, however it would be a nice to have a build of the java bindings by turning on a BUILD\_JAVA\_BINDINGS flag in CMake from cmake-gui or in command line: +```sh +$ cmake -DBUILD_JAVA_BINDINGS=ON . +``` +Then compile the library and install it. + +javaiec61850 library is to be imported calling +```java +import iec61850 +``` + +# Client tutorial + +The java bindings works similarly to the python and basic C library ones. + +Have a look at the Client, Server and test programme. + +For example to create a connection, call: + +```java + if (con == null) { + con = iec61850.IedConnection_create(); + } + + iec61850.IedConnection_connect(con, error, "localhost", tcpPort); + + conState = iec61850.IedConnection_getState(con); + + if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { + System.out.println("IEC61850Client has connected to the IEC61850Server" ); + } + +``` From 2fb92229c3682c9590f065f3e6f6d7fbb0c17409 Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Wed, 9 Oct 2019 14:00:56 +0100 Subject: [PATCH 3/8] Updating the Tutortial text. --- javaiec61850/tutorial.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/javaiec61850/tutorial.md b/javaiec61850/tutorial.md index 36181011..bf7fbc4d 100644 --- a/javaiec61850/tutorial.md +++ b/javaiec61850/tutorial.md @@ -74,3 +74,6 @@ For example to create a connection, call: } ``` + +Copyright Waterford Institute of Technology 2017~2019, Telecommunications Software and Systems Group (TSSG), Author Miguel Ponce de Leon +This work is supported by European Union’s Horizon 2020 research and innovation programme under grant agreement No 727481, project RE-SERVE (Re- newables in a Stable Electric Grid) From 89c994b45903ea5fc6d95effdcd68e69c6b48fec Mon Sep 17 00:00:00 2001 From: David Ryan Date: Thu, 10 Oct 2019 12:55:09 +0100 Subject: [PATCH 4/8] Revert "Create java bindings for libiec61850" --- javaiec61850/IEC61850Client.java | 87 ----------------------------- javaiec61850/IEC61850Server.java | 68 ---------------------- javaiec61850/iec61850.i | 41 -------------- javaiec61850/test_javaiec61850.java | 55 ------------------ javaiec61850/tutorial.md | 79 -------------------------- 5 files changed, 330 deletions(-) delete mode 100644 javaiec61850/IEC61850Client.java delete mode 100644 javaiec61850/IEC61850Server.java delete mode 100644 javaiec61850/iec61850.i delete mode 100644 javaiec61850/test_javaiec61850.java delete mode 100644 javaiec61850/tutorial.md diff --git a/javaiec61850/IEC61850Client.java b/javaiec61850/IEC61850Client.java deleted file mode 100644 index e3a7c53c..00000000 --- a/javaiec61850/IEC61850Client.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright Waterford Institute of Technology 2017, - * Telecommunications Software and Systems Group (TSSG), - * Author Miguel Ponce de Leon . - * -*/ - -public class IEC61850Client { - - private int tcpPort = 8102; - private SWIGTYPE_p_sIedConnection con; - - // List of int values for Client Side errors from iec61850_client.h - private int[] error = {0, 1, 2,3, 4, 5, 10, 11, 12, 13, 21, 22, 23, 24,25,26, 27, 28, 29, 30, 31, 32, 33, 98, 99}; - private IedConnectionState conState = null; - private String theVal = null; - private FunctionalConstraint theValType = null; - private float temperatureValue; - private float newValue; - private LastApplError err = null; - private int theExpectedError = 21; - private float temperatureSetpoint; - - IEC61850Client() { - - if (con == null) { - con = iec61850.IedConnection_create(); - } - - iec61850.IedConnection_connect(con, error, "localhost", tcpPort); - - conState = iec61850.IedConnection_getState(con); - - if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { - System.out.println("IEC61850Client has connected to the IEC61850Server" ); - - //Accessing to SAV values - theVal = "testmodelSENSORS/TTMP1.TmpSv.instMag.f"; - theValType = FunctionalConstraint.IEC61850_FC_MX; - - temperatureValue = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); - - if (temperatureValue == 0) { - System.out.println("IEC61850Client has read testmodelSENSORS" ); - } - - newValue = temperatureValue + 10; - - iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); - - err = iec61850.IedConnection_getLastApplError(con); - - if (err.getError() == theExpectedError) { - System.out.println("IEC61850Client caught the expected client error = " + err.getError() ); - } else { - System.out.println("IEC61850Client caught a error = " + err.getError() ); - } - - // Accessing to ASG values - theVal = "testmodelSENSORS/TTMP1.TmpSp.setMag.f"; - theValType = FunctionalConstraint.IEC61850_FC_SP; - temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); - System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); - - newValue = temperatureValue + 10; - iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); - - temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); - - if (temperatureSetpoint == newValue) { - System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); - } - - //Must close the connection at the end of the test. - iec61850.IedConnection_close(con); - - } else { - System.out.println("IEC61850Client connection error " + conState ); - - iec61850.IedConnection_close(con); - - } - //Destroy the connection at the end of the test. - iec61850.IedConnection_destroy(con); - - } -} diff --git a/javaiec61850/IEC61850Server.java b/javaiec61850/IEC61850Server.java deleted file mode 100644 index 7f805627..00000000 --- a/javaiec61850/IEC61850Server.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright Waterford Institute of Technology 2017, - * Telecommunications Software and Systems Group (TSSG), - * Author Miguel Ponce de Leon . - * -*/ - -public class IEC61850Server extends Thread { - - private sIedModel model = null; - private SWIGTYPE_p_sIedServer iedServer = null; - private int tcpPort = 8102; - - @Override - public void interrupt() { - try { - iec61850.IedServer_stop(iedServer); - iec61850.IedServer_destroy(iedServer); - iec61850.IedModel_destroy(model); - System.out.println("IEC61850Server has been Interrupted and STOPPED" ); - } catch (Exception ignored) { - } finally { - super.interrupt(); - } - } - - @Override - public void run() { - - System.out.println("MyThread for IEC61850Server has STARTED" ); - //Create a iec61850.IedModel - model = iec61850.IedModel_create("testmodel"); - - //Create a logical device - sLogicalDevice lDevice1 = iec61850.LogicalDevice_create("SENSORS", model); - - //Create nodes off this logical device - sLogicalNode lln0 = iec61850.LogicalNode_create("LLN0", lDevice1); - sLogicalNode ttmp1 = iec61850.LogicalNode_create("TTMP1", lDevice1); - - sDataObject cdc_sav = iec61850.CDC_SAV_create("TmpSv", iec61850.toModelNode(ttmp1), 0, false); - sDataObject cdc_asg = iec61850.CDC_ASG_create("TmpSp", iec61850.toModelNode(ttmp1), 0, false); - - // Create a iec61850.IedServer based on a test IedModel node - iedServer = iec61850.IedServer_create(model); - iec61850.IedServer_start(iedServer, tcpPort); - - if (!iec61850.IedServer_isRunning(iedServer)) { - System.out.println("Starting server failed! Exit.\n"); - iec61850.IedServer_destroy(iedServer); - iec61850.IedModel_destroy(model); - System.exit(0); - } - - System.out.println("IEC61850Server has STARTED" ); - - while (true) { - try { - Thread.sleep((long) 100); - } catch (InterruptedException e) { - break; - } - } - - - - } - } diff --git a/javaiec61850/iec61850.i b/javaiec61850/iec61850.i deleted file mode 100644 index eebe5e79..00000000 --- a/javaiec61850/iec61850.i +++ /dev/null @@ -1,41 +0,0 @@ -/* File : iec61850.i */ -%module iec61850 -%ignore ControlObjectClient_setTestMode(ControlObjectClient self); -%ignore CDA_OperBoolean(ModelNode* parent, bool isTImeActivated); -%ignore LogicalNode_hasBufferedReports(LogicalNode* node); -%ignore LogicalNode_hasUnbufferedReports(LogicalNode* node); -%ignore MmsConnection_setIsoConnectionParameters(MmsConnection self, IsoConnectionParameters* params); -%include "stdint.i" -%include "typemaps.i" -%{ -#include -#include -#include -ModelNode* toModelNode(LogicalNode * ln) -{ - return (ModelNode*) ln; -} -char* toCharP(void * v) -{ - return (char *) v; -} -DataAttribute* toDataAttribute(ModelNode * MN) -{ return (DataAttribute*)MN;} -%} -%apply int *OUTPUT {IedClientError* error}; - -%include "libiec61850_common_api.h" -%include "iec61850_client.h" -%include "iso_connection_parameters.h" -%include "mms_client_connection.h" -%include "iso_connection_parameters.h" -%include "iec61850_common.h" -%include "mms_value.h" -%include "iec61850_model.h" -%include "iec61850_server.h" -%include "iec61850_dynamic_model.h" -%include "iec61850_cdc.h" -%include "linked_list.h" -ModelNode* toModelNode(LogicalNode *); -DataAttribute* toDataAttribute(ModelNode *); -char* toCharP(void *); diff --git a/javaiec61850/test_javaiec61850.java b/javaiec61850/test_javaiec61850.java deleted file mode 100644 index adf35d6c..00000000 --- a/javaiec61850/test_javaiec61850.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Waterford Institute of Technology 2017, - * Telecommunications Software and Systems Group (TSSG), - * Author Miguel Ponce de Leon . - * -*/ - -import java.lang.System; -import java.lang.Throwable; -import java.lang.Thread; -import java.lang.String; -import java.io.*; - -/** - * This test programme should mirror the functionality laid out in the Python - * equivalent. - * - * @author Miguel Ponce de Leon - */ - -public class test_javaiec61850 { - - static { - try { - //Using loadLibrary means that LD_LIBRARY_PATH must be set - System.load("/opt/libiec61850/javaiec61850/libiec61850.so"); - } catch (UnsatisfiedLinkError e) { - System.err.println("Native code library libiec61850 failed to load.\n" + e); - System.exit(1); - } - } - - /** - * main is the main entry point into this tester application. IEC61850Server runs - * as a server in a waiting Thread and then a IEC61850Client interacts with that - * servers model. - */ - - public static void main (String[] args) throws Throwable { - - IEC61850Server iec61850Server = new IEC61850Server(); - - iec61850Server.start(); - - Thread.sleep((long) 200); - //Run the test IEC Client - IEC61850Client testIECClient = new IEC61850Client(); - - //Stop the iec61850Server - if (iec61850Server != null) { - iec61850Server.interrupt(); - } - } - -} diff --git a/javaiec61850/tutorial.md b/javaiec61850/tutorial.md deleted file mode 100644 index bf7fbc4d..00000000 --- a/javaiec61850/tutorial.md +++ /dev/null @@ -1,79 +0,0 @@ -# Building -Before building you should install swig and java. - -From the root directory of the libiec61850 project you have to build some of the dependant libraries - -> cd .. -> -> make clean -> -> make INSTALL_PREFIX=/usr/local install -> -> make clean -> -> make INSTALL_PREFIX=/usr/local dynlib - -Now change into the Java project subdirectory - -> cd javaiec61850 -> -> swig -java -I/usr/local/include iec61850.i -> -> gcc -fpic -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux -c iec61850_wrap.c -> -> ld -shared ../build/libiec61850.so iec61850_wrap.o -o libiec61850.so -> -> javac test_javaiec61850.java -> -> java test_javaiec61850 - -This test programme should show an out put of - -```sh -MyThread for IEC61850Server has STARTED -IEC61850Server has STARTED -IEC61850Client has connected to the IEC61850Server -IEC61850Client has read testmodelSENSORS -IEC61850Client caught a error = 0 -IEC61850Client read a temperature set point of = 0.0 -IEC61850Client read a temperature set point of = 10.0 -IEC61850Server has been Interrupted and STOPPED - -``` - -The CMakeLists file does not exist yet, however it would be a nice to have a build of the java bindings by turning on a BUILD\_JAVA\_BINDINGS flag in CMake from cmake-gui or in command line: -```sh -$ cmake -DBUILD_JAVA_BINDINGS=ON . -``` -Then compile the library and install it. - -javaiec61850 library is to be imported calling -```java -import iec61850 -``` - -# Client tutorial - -The java bindings works similarly to the python and basic C library ones. - -Have a look at the Client, Server and test programme. - -For example to create a connection, call: - -```java - if (con == null) { - con = iec61850.IedConnection_create(); - } - - iec61850.IedConnection_connect(con, error, "localhost", tcpPort); - - conState = iec61850.IedConnection_getState(con); - - if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { - System.out.println("IEC61850Client has connected to the IEC61850Server" ); - } - -``` - -Copyright Waterford Institute of Technology 2017~2019, Telecommunications Software and Systems Group (TSSG), Author Miguel Ponce de Leon -This work is supported by European Union’s Horizon 2020 research and innovation programme under grant agreement No 727481, project RE-SERVE (Re- newables in a Stable Electric Grid) From 12364e2a624af9615a2461b17cbff2f3860df324 Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Thu, 10 Oct 2019 14:09:21 +0100 Subject: [PATCH 5/8] Adding back in mms_device_model.h --- src/mms/inc/mms_device_model.h | 216 +++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/mms/inc/mms_device_model.h diff --git a/src/mms/inc/mms_device_model.h b/src/mms/inc/mms_device_model.h new file mode 100644 index 00000000..f4c9be1d --- /dev/null +++ b/src/mms/inc/mms_device_model.h @@ -0,0 +1,216 @@ +/* + * mms_model.h + * + * Copyright 2013 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 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 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 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 libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#ifndef MMS_DEVICE_MODEL_H_ +#define MMS_DEVICE_MODEL_H_ + +#include "libiec61850_common_api.h" + +#include "mms_type_spec.h" +#include "mms_common.h" +#include "mms_named_variable_list.h" +#include "logging_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char* deviceName; + + /* MMS VMD scope variables support */ + int namedVariablesCount; + MmsVariableSpecification** namedVariables; + + /* MMS VMD scope named variables list support */ + LinkedList /**/ namedVariableLists; + + /* MMS domain support */ + int domainCount; + MmsDomain** domains; +} MmsDevice; + + +struct sMmsJournal { + char* name; + LogStorage logStorage; +}; + +typedef struct sMmsJournal* MmsJournal; + +/* + * Server side data structure to hold information of an MMS domain (Logical Device) + */ +struct sMmsDomain { + char* domainName; + int namedVariablesCount; + MmsVariableSpecification** namedVariables; + LinkedList /**/ namedVariableLists; + LinkedList /* */ journals; +}; + +/** + * @defgroup mms_server_api_group MMS server API (for IEC 61850 use IEC 61850 server API instead!) + * + * @{ + */ + +/** + * \brief Create a new MmsDomain instance + * + * This method should not be invoked by client code! + * + * \param domainName the name of the MMS domain + * + * \return the new MmsDomain instance + */ +MmsDomain* +MmsDomain_create(char* domainName); + +char* +MmsDomain_getName(MmsDomain* self); + +void +MmsDomain_addJournal(MmsDomain* self, const char* name); + +MmsJournal +MmsDomain_getJournal(MmsDomain* self, const char* name); + +/** + * Delete a MmsDomain instance + * + * This method should not be invoked by client code! + */ +void +MmsDomain_destroy(MmsDomain* self); + +/** + * \brief Add a new MMS Named Variable List (Data set) to a MmsDomain instance + * + * The passed MmsNamedVariableList instance will be handled by the MmsDomain instance + * and will be destroyed if the MmsDomain_destroy function on this MmsDomain instance + * is called. + * + * \param self instance of MmsDomain to operate on + * \param variableList new named variable list that will be added to this MmsDomain + * + * \return true if operation was successful. + */ +bool +MmsDomain_addNamedVariableList(MmsDomain* self, MmsNamedVariableList variableList); + +/** + * \brief Delete a MMS Named Variable List from this MmsDomain instance + * + * A call to this function will also destroy the MmsNamedVariableList instance. + * + * \param self instance of MmsDomain to operate on + * \param variableListName the name of the variable list to delete. + * + */ +void +MmsDomain_deleteNamedVariableList(MmsDomain* self, char* variableListName); + +MmsNamedVariableList +MmsDomain_getNamedVariableList(MmsDomain* self, const char* variableListName); + +LinkedList +MmsDomain_getNamedVariableLists(MmsDomain* self); + +LinkedList +MmsDomain_getNamedVariableListValues(MmsDomain* self, char* variableListName); + +LinkedList +MmsDomain_createNamedVariableListValues(MmsDomain* self, char* variableListName); + +/** + * \brief Get the MmsTypeSpecification instance of a MMS named variable + * + * \param self instance of MmsDomain to operate on + * \param nameId name of the named variable + * + * \return MmsTypeSpecification instance of the named variable + */ +MmsVariableSpecification* +MmsDomain_getNamedVariable(MmsDomain* self, char* nameId); + +/** + * \brief Create a new MmsDevice instance. + * + * MmsDevice objects are the root objects of the address space of an MMS server. + * + * An MmsDevice object can contain one or more MmsDomain instances. + * + * \param deviceName the name of the MMS device or NULL if the device has no name. + * + * \return the new MmsDevice instance + */ +MmsDevice* +MmsDevice_create(char* deviceName); + +/** + * \brief Delete the MmsDevice instance + */ +void +MmsDevice_destroy(MmsDevice* self); + +/** + * \brief Get the MmsDomain object with the specified MMS domain name. + * + * \param deviceName the name of the MMS device or NULL if the device has no name. + * + * \return the new MmsDevice instance + */ +MmsDomain* +MmsDevice_getDomain(MmsDevice* self, char* domainId); + +/** + * \brief Get the MmsTypeSpecification instance of a MMS named variable of VMD scope + * + * \param self instance of MmsDevice to operate on + * \param variableName name of the named variable + * + * \return MmsTypeSpecification instance of the named variable + */ +MmsVariableSpecification* +MmsDevice_getNamedVariable(MmsDevice* self, char* variableName); + +LinkedList +MmsDevice_getNamedVariableLists(MmsDevice* self); + +MmsNamedVariableList +MmsDevice_getNamedVariableListWithName(MmsDevice* self, const char* variableListName); + +MmsJournal +MmsJournal_create(const char* name); + +void +MmsJournal_destroy(MmsJournal self); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_DEVICE_MODEL_H_ */ From d1dcf954e8a05055aa201d6795aed9c594b9fa33 Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Thu, 10 Oct 2019 14:12:59 +0100 Subject: [PATCH 6/8] Adding back in mms_named_variable_list.h --- src/mms/inc/mms_named_variable_list.h | 85 +++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/mms/inc/mms_named_variable_list.h diff --git a/src/mms/inc/mms_named_variable_list.h b/src/mms/inc/mms_named_variable_list.h new file mode 100644 index 00000000..15e7d16a --- /dev/null +++ b/src/mms/inc/mms_named_variable_list.h @@ -0,0 +1,85 @@ +/* + * mms_named_variable_list.h + * + * Copyright 2013 Michael Zillgith + * + * This file is part of libIEC61850. + * + * libIEC61850 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 3 of the License, or + * (at your option) any later version. + * + * libIEC61850 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 libIEC61850. If not, see . + * + * See COPYING file for the complete license text. + */ + +#ifndef MMS_NAMED_VARIABLE_LIST_H_ +#define MMS_NAMED_VARIABLE_LIST_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup mms_server_api_group + * @{ + */ + +#include "libiec61850_common_api.h" +#include "linked_list.h" +#include "mms_common.h" + +struct sMmsNamedVariableList { + bool deletable; + MmsDomain* domain; + char* name; + LinkedList listOfVariables; +}; + +MmsNamedVariableListEntry +MmsNamedVariableListEntry_create(MmsAccessSpecifier accessSpecifier); + +void +MmsNamedVariableListEntry_destroy(MmsNamedVariableListEntry self); + +MmsDomain* +MmsNamedVariableListEntry_getDomain(MmsNamedVariableListEntry self); + +char* +MmsNamedVariableListEntry_getVariableName(MmsNamedVariableListEntry self); + +MmsNamedVariableList +MmsNamedVariableList_create(MmsDomain* domain, char* name, bool deletable); + +char* +MmsNamedVariableList_getName(MmsNamedVariableList self); + +MmsDomain* +MmsNamedVariableList_getDomain(MmsNamedVariableList self); + +bool +MmsNamedVariableList_isDeletable(MmsNamedVariableList self); + +void +MmsNamedVariableList_addVariable(MmsNamedVariableList self, MmsNamedVariableListEntry variable); + +LinkedList +MmsNamedVariableList_getVariableList(MmsNamedVariableList self); + +void +MmsNamedVariableList_destroy(MmsNamedVariableList self); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* MMS_NAMED_VARIABLE_LIST_H_ */ From ac339397fb94b1491ecfe09c901cbfb658e33ad2 Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Thu, 10 Oct 2019 14:20:54 +0100 Subject: [PATCH 7/8] Update to Makefile to place header files into correct location. --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 65d61364..cf144ee7 100644 --- a/Makefile +++ b/Makefile @@ -86,6 +86,7 @@ INSTALL_PREFIX = ./.install endif LIB_API_HEADER_FILES = hal/inc/hal_time.h +LIB_API_HEADER_FILES += hal/inc/hal_base.h LIB_API_HEADER_FILES += hal/inc/hal_thread.h LIB_API_HEADER_FILES += hal/inc/hal_filesystem.h LIB_API_HEADER_FILES += hal/inc/tls_config.h @@ -101,6 +102,9 @@ LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_dynamic_model.h LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_config_file_parser.h LIB_API_HEADER_FILES += src/mms/inc/mms_value.h LIB_API_HEADER_FILES += src/mms/inc/mms_common.h +LIB_API_HEADER_FILES += src/mms/inc/mms_server.h +LIB_API_HEADER_FILES += src/mms/inc/mms_device_model.h +LIB_API_HEADER_FILES += src/mms/inc/mms_named_variable_list.h LIB_API_HEADER_FILES += src/mms/inc/mms_types.h LIB_API_HEADER_FILES += src/mms/inc/mms_type_spec.h LIB_API_HEADER_FILES += src/mms/inc/mms_client_connection.h From f43e9f1947e924b4f764507be295b12e013996a5 Mon Sep 17 00:00:00 2001 From: Miguel Ponce de Leon Date: Mon, 14 Oct 2019 16:41:26 +0100 Subject: [PATCH 8/8] Adding back in the javaiec61850 folder to this branch. --- javaiec61850/IEC61850Client.java | 87 +++++++++++++++++++++++++++++ javaiec61850/IEC61850Server.java | 68 ++++++++++++++++++++++ javaiec61850/iec61850.i | 41 ++++++++++++++ javaiec61850/test_javaiec61850.java | 55 ++++++++++++++++++ javaiec61850/tutorial.md | 79 ++++++++++++++++++++++++++ 5 files changed, 330 insertions(+) create mode 100644 javaiec61850/IEC61850Client.java create mode 100644 javaiec61850/IEC61850Server.java create mode 100644 javaiec61850/iec61850.i create mode 100644 javaiec61850/test_javaiec61850.java create mode 100644 javaiec61850/tutorial.md diff --git a/javaiec61850/IEC61850Client.java b/javaiec61850/IEC61850Client.java new file mode 100644 index 00000000..e3a7c53c --- /dev/null +++ b/javaiec61850/IEC61850Client.java @@ -0,0 +1,87 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +public class IEC61850Client { + + private int tcpPort = 8102; + private SWIGTYPE_p_sIedConnection con; + + // List of int values for Client Side errors from iec61850_client.h + private int[] error = {0, 1, 2,3, 4, 5, 10, 11, 12, 13, 21, 22, 23, 24,25,26, 27, 28, 29, 30, 31, 32, 33, 98, 99}; + private IedConnectionState conState = null; + private String theVal = null; + private FunctionalConstraint theValType = null; + private float temperatureValue; + private float newValue; + private LastApplError err = null; + private int theExpectedError = 21; + private float temperatureSetpoint; + + IEC61850Client() { + + if (con == null) { + con = iec61850.IedConnection_create(); + } + + iec61850.IedConnection_connect(con, error, "localhost", tcpPort); + + conState = iec61850.IedConnection_getState(con); + + if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { + System.out.println("IEC61850Client has connected to the IEC61850Server" ); + + //Accessing to SAV values + theVal = "testmodelSENSORS/TTMP1.TmpSv.instMag.f"; + theValType = FunctionalConstraint.IEC61850_FC_MX; + + temperatureValue = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + + if (temperatureValue == 0) { + System.out.println("IEC61850Client has read testmodelSENSORS" ); + } + + newValue = temperatureValue + 10; + + iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); + + err = iec61850.IedConnection_getLastApplError(con); + + if (err.getError() == theExpectedError) { + System.out.println("IEC61850Client caught the expected client error = " + err.getError() ); + } else { + System.out.println("IEC61850Client caught a error = " + err.getError() ); + } + + // Accessing to ASG values + theVal = "testmodelSENSORS/TTMP1.TmpSp.setMag.f"; + theValType = FunctionalConstraint.IEC61850_FC_SP; + temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); + + newValue = temperatureValue + 10; + iec61850.IedConnection_writeFloatValue(con, error, theVal, theValType, newValue); + + temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, error, theVal, theValType); + + if (temperatureSetpoint == newValue) { + System.out.println("IEC61850Client read a temperature set point of = " + temperatureSetpoint ); + } + + //Must close the connection at the end of the test. + iec61850.IedConnection_close(con); + + } else { + System.out.println("IEC61850Client connection error " + conState ); + + iec61850.IedConnection_close(con); + + } + //Destroy the connection at the end of the test. + iec61850.IedConnection_destroy(con); + + } +} diff --git a/javaiec61850/IEC61850Server.java b/javaiec61850/IEC61850Server.java new file mode 100644 index 00000000..7f805627 --- /dev/null +++ b/javaiec61850/IEC61850Server.java @@ -0,0 +1,68 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +public class IEC61850Server extends Thread { + + private sIedModel model = null; + private SWIGTYPE_p_sIedServer iedServer = null; + private int tcpPort = 8102; + + @Override + public void interrupt() { + try { + iec61850.IedServer_stop(iedServer); + iec61850.IedServer_destroy(iedServer); + iec61850.IedModel_destroy(model); + System.out.println("IEC61850Server has been Interrupted and STOPPED" ); + } catch (Exception ignored) { + } finally { + super.interrupt(); + } + } + + @Override + public void run() { + + System.out.println("MyThread for IEC61850Server has STARTED" ); + //Create a iec61850.IedModel + model = iec61850.IedModel_create("testmodel"); + + //Create a logical device + sLogicalDevice lDevice1 = iec61850.LogicalDevice_create("SENSORS", model); + + //Create nodes off this logical device + sLogicalNode lln0 = iec61850.LogicalNode_create("LLN0", lDevice1); + sLogicalNode ttmp1 = iec61850.LogicalNode_create("TTMP1", lDevice1); + + sDataObject cdc_sav = iec61850.CDC_SAV_create("TmpSv", iec61850.toModelNode(ttmp1), 0, false); + sDataObject cdc_asg = iec61850.CDC_ASG_create("TmpSp", iec61850.toModelNode(ttmp1), 0, false); + + // Create a iec61850.IedServer based on a test IedModel node + iedServer = iec61850.IedServer_create(model); + iec61850.IedServer_start(iedServer, tcpPort); + + if (!iec61850.IedServer_isRunning(iedServer)) { + System.out.println("Starting server failed! Exit.\n"); + iec61850.IedServer_destroy(iedServer); + iec61850.IedModel_destroy(model); + System.exit(0); + } + + System.out.println("IEC61850Server has STARTED" ); + + while (true) { + try { + Thread.sleep((long) 100); + } catch (InterruptedException e) { + break; + } + } + + + + } + } diff --git a/javaiec61850/iec61850.i b/javaiec61850/iec61850.i new file mode 100644 index 00000000..eebe5e79 --- /dev/null +++ b/javaiec61850/iec61850.i @@ -0,0 +1,41 @@ +/* File : iec61850.i */ +%module iec61850 +%ignore ControlObjectClient_setTestMode(ControlObjectClient self); +%ignore CDA_OperBoolean(ModelNode* parent, bool isTImeActivated); +%ignore LogicalNode_hasBufferedReports(LogicalNode* node); +%ignore LogicalNode_hasUnbufferedReports(LogicalNode* node); +%ignore MmsConnection_setIsoConnectionParameters(MmsConnection self, IsoConnectionParameters* params); +%include "stdint.i" +%include "typemaps.i" +%{ +#include +#include +#include +ModelNode* toModelNode(LogicalNode * ln) +{ + return (ModelNode*) ln; +} +char* toCharP(void * v) +{ + return (char *) v; +} +DataAttribute* toDataAttribute(ModelNode * MN) +{ return (DataAttribute*)MN;} +%} +%apply int *OUTPUT {IedClientError* error}; + +%include "libiec61850_common_api.h" +%include "iec61850_client.h" +%include "iso_connection_parameters.h" +%include "mms_client_connection.h" +%include "iso_connection_parameters.h" +%include "iec61850_common.h" +%include "mms_value.h" +%include "iec61850_model.h" +%include "iec61850_server.h" +%include "iec61850_dynamic_model.h" +%include "iec61850_cdc.h" +%include "linked_list.h" +ModelNode* toModelNode(LogicalNode *); +DataAttribute* toDataAttribute(ModelNode *); +char* toCharP(void *); diff --git a/javaiec61850/test_javaiec61850.java b/javaiec61850/test_javaiec61850.java new file mode 100644 index 00000000..adf35d6c --- /dev/null +++ b/javaiec61850/test_javaiec61850.java @@ -0,0 +1,55 @@ +/* + * Copyright Waterford Institute of Technology 2017, + * Telecommunications Software and Systems Group (TSSG), + * Author Miguel Ponce de Leon . + * +*/ + +import java.lang.System; +import java.lang.Throwable; +import java.lang.Thread; +import java.lang.String; +import java.io.*; + +/** + * This test programme should mirror the functionality laid out in the Python + * equivalent. + * + * @author Miguel Ponce de Leon + */ + +public class test_javaiec61850 { + + static { + try { + //Using loadLibrary means that LD_LIBRARY_PATH must be set + System.load("/opt/libiec61850/javaiec61850/libiec61850.so"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library libiec61850 failed to load.\n" + e); + System.exit(1); + } + } + + /** + * main is the main entry point into this tester application. IEC61850Server runs + * as a server in a waiting Thread and then a IEC61850Client interacts with that + * servers model. + */ + + public static void main (String[] args) throws Throwable { + + IEC61850Server iec61850Server = new IEC61850Server(); + + iec61850Server.start(); + + Thread.sleep((long) 200); + //Run the test IEC Client + IEC61850Client testIECClient = new IEC61850Client(); + + //Stop the iec61850Server + if (iec61850Server != null) { + iec61850Server.interrupt(); + } + } + +} diff --git a/javaiec61850/tutorial.md b/javaiec61850/tutorial.md new file mode 100644 index 00000000..bf7fbc4d --- /dev/null +++ b/javaiec61850/tutorial.md @@ -0,0 +1,79 @@ +# Building +Before building you should install swig and java. + +From the root directory of the libiec61850 project you have to build some of the dependant libraries + +> cd .. +> +> make clean +> +> make INSTALL_PREFIX=/usr/local install +> +> make clean +> +> make INSTALL_PREFIX=/usr/local dynlib + +Now change into the Java project subdirectory + +> cd javaiec61850 +> +> swig -java -I/usr/local/include iec61850.i +> +> gcc -fpic -I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux -c iec61850_wrap.c +> +> ld -shared ../build/libiec61850.so iec61850_wrap.o -o libiec61850.so +> +> javac test_javaiec61850.java +> +> java test_javaiec61850 + +This test programme should show an out put of + +```sh +MyThread for IEC61850Server has STARTED +IEC61850Server has STARTED +IEC61850Client has connected to the IEC61850Server +IEC61850Client has read testmodelSENSORS +IEC61850Client caught a error = 0 +IEC61850Client read a temperature set point of = 0.0 +IEC61850Client read a temperature set point of = 10.0 +IEC61850Server has been Interrupted and STOPPED + +``` + +The CMakeLists file does not exist yet, however it would be a nice to have a build of the java bindings by turning on a BUILD\_JAVA\_BINDINGS flag in CMake from cmake-gui or in command line: +```sh +$ cmake -DBUILD_JAVA_BINDINGS=ON . +``` +Then compile the library and install it. + +javaiec61850 library is to be imported calling +```java +import iec61850 +``` + +# Client tutorial + +The java bindings works similarly to the python and basic C library ones. + +Have a look at the Client, Server and test programme. + +For example to create a connection, call: + +```java + if (con == null) { + con = iec61850.IedConnection_create(); + } + + iec61850.IedConnection_connect(con, error, "localhost", tcpPort); + + conState = iec61850.IedConnection_getState(con); + + if ( conState.toString() == "IED_STATE_CONNECTED" || conState.toString() == "IED_STATE_IDLE") { + System.out.println("IEC61850Client has connected to the IEC61850Server" ); + } + +``` + +Copyright Waterford Institute of Technology 2017~2019, Telecommunications Software and Systems Group (TSSG), Author Miguel Ponce de Leon +This work is supported by European Union’s Horizon 2020 research and innovation programme under grant agreement No 727481, project RE-SERVE (Re- newables in a Stable Electric Grid)