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)