pull/179/merge
Miguel Ponce de Leon 4 years ago committed by GitHub
commit 7aa6d4d662
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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
@ -102,6 +103,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

@ -0,0 +1,87 @@
/*
* Copyright Waterford Institute of Technology 2017,
* Telecommunications Software and Systems Group (TSSG),
* Author Miguel Ponce de Leon <miguelpdl@tssg.org>.
*
*/
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);
}
}

@ -0,0 +1,68 @@
/*
* Copyright Waterford Institute of Technology 2017,
* Telecommunications Software and Systems Group (TSSG),
* Author Miguel Ponce de Leon <miguelpdl@tssg.org>.
*
*/
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;
}
}
}
}

@ -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 <iec61850_client.h>
#include <iec61850_model.h>
#include <iec61850_server.h>
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 *);

@ -0,0 +1,55 @@
/*
* Copyright Waterford Institute of Technology 2017,
* Telecommunications Software and Systems Group (TSSG),
* Author Miguel Ponce de Leon <miguelpdl@tssg.org>.
*
*/
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();
}
}
}

@ -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 <miguelpdl@tssg.org>
This work is supported by European Unions Horizon 2020 research and innovation programme under grant agreement No 727481, project RE-SERVE (Re- newables in a Stable Electric Grid)

@ -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 <http://www.gnu.org/licenses/>.
*
* 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 /*<MmsNamedVariableList>*/ 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 /*<MmsNamedVariableList>*/ namedVariableLists;
LinkedList /* <MmsJournal> */ 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_ */

@ -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 <http://www.gnu.org/licenses/>.
*
* 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_ */
Loading…
Cancel
Save