Merge branch 'python-bindings'

pull/6/head
Michael Zillgith 9 years ago
commit 6c306870e9

@ -8,6 +8,7 @@ if(DEFINED ENV{TOOLCHAIN})
endif() endif()
project(libiec61850) project(libiec61850)
ENABLE_TESTING()
set(LIB_VERSION_MAJOR "0") set(LIB_VERSION_MAJOR "0")
set(LIB_VERSION_MINOR "9") set(LIB_VERSION_MINOR "9")
@ -25,6 +26,7 @@ set(CONFIG_MMS_MAXIMUM_PDU_SIZE "65000" CACHE STRING "Configure the maximum size
set(CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5 CACHE STRING "Configure the maximum number of clients allowed to connect to the server") set(CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5 CACHE STRING "Configure the maximum number of clients allowed to connect to the server")
option(BUILD_EXAMPLES "Build the examples" ON) option(BUILD_EXAMPLES "Build the examples" ON)
option(BUILD_PYTHON_BINDINGS "Build Python bindings" OFF)
option(CONFIG_MMS_SINGLE_THREADED "Compile for single threaded version" OFF) option(CONFIG_MMS_SINGLE_THREADED "Compile for single threaded version" OFF)
option(CONFIG_MMS_THREADLESS_STACK "Optimize stack for threadless operation (warning: single- or multi-threaded server will not work!)" OFF) option(CONFIG_MMS_THREADLESS_STACK "Optimize stack for threadless operation (warning: single- or multi-threaded server will not work!)" OFF)
@ -102,11 +104,11 @@ set(API_HEADERS
src/sampled_values/sv_publisher.h src/sampled_values/sv_publisher.h
) )
IF(WIN32) IF(MSVC)
include_directories( include_directories(
src/vs src/vs
) )
ENDIF(WIN32) ENDIF(MSVC)
# write the detected stuff to this file # write the detected stuff to this file
configure_file(config/stack_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h) configure_file(config/stack_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config/stack_config.h)
@ -119,6 +121,9 @@ add_subdirectory(src)
INSTALL(FILES ${API_HEADERS} DESTINATION include/libiec61850) INSTALL(FILES ${API_HEADERS} DESTINATION include/libiec61850)
IF(BUILD_PYTHON_BINDINGS)
add_subdirectory(pyiec61850)
ENDIF(BUILD_PYTHON_BINDINGS)
IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") IF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
INCLUDE(InstallRequiredSystemLibraries) INCLUDE(InstallRequiredSystemLibraries)
@ -144,6 +149,3 @@ SET(CPACK_COMPONENTS_ALL Libraries ApplicationData)
INCLUDE(CPack) INCLUDE(CPack)
ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake") ENDIF(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")

@ -137,11 +137,11 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat); private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_enableInterlockCheck(IntPtr self); private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_enableSynchroCheck(IntPtr self); private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalCommandTerminationHandler(IntPtr parameter,IntPtr controlClient); private delegate void InternalCommandTerminationHandler(IntPtr parameter,IntPtr controlClient);
@ -373,19 +373,37 @@ namespace IEC61850
/// <summary> /// <summary>
/// Enables the synchro check for operate commands /// Enables the synchro check for operate commands
/// </summary> /// </summary>
[Obsolete("use SetSynchroCheck instead")]
public void EnableSynchroCheck () public void EnableSynchroCheck ()
{ {
ControlObjectClient_enableSynchroCheck(controlObject); ControlObjectClient_setSynchroCheck (controlObject, true);
} }
/// <summary> /// <summary>
/// Enables the interlock check for operate and select commands /// Enables the interlock check for operate and select commands
/// </summary> /// </summary>
public void EnableInterlockCheck () [Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck ()
{ {
ControlObjectClient_enableInterlockCheck(controlObject); ControlObjectClient_setInterlockCheck (controlObject, true);
} }
/// <summary>
/// Sets the value of the interlock check flag for operate and select commands
/// </summary>
public void SetInterlockCheck (bool value)
{
ControlObjectClient_setInterlockCheck (controlObject, value);
}
/// <summary>
/// Sets the value of the synchro check flag for operate command
/// </summary>
public void SetSynchroCheck (bool value)
{
ControlObjectClient_setSynchroCheck (controlObject, value);
}
/// <summary> /// <summary>
/// Gets the last received LastApplError (Additional Cause Diagnostics) value. /// Gets the last received LastApplError (Additional Cause Diagnostics) value.
/// </summary> /// </summary>

@ -24,7 +24,7 @@ namespace example3
{ {
IsoConnectionParameters parameters = con.GetConnectionParameters(); IsoConnectionParameters parameters = con.GetConnectionParameters();
parameters.SetRemoteAddresses(1,1, new byte[] {0x00, 0x01, 0x02, 0x03}); parameters.SetRemoteAddresses(1, new byte[] {0x00, 0x01}, new byte[] {0x00, 0x01, 0x02, 0x03});
con.ConnectTimeout = 10000; con.ConnectTimeout = 10000;

@ -3,10 +3,10 @@ set(iec61850_client_example4_SRCS
client_example4.c client_example4.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${iec61850_client_example4_SRCS} set_source_files_properties(${iec61850_client_example4_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(iec61850_client_example4 add_executable(iec61850_client_example4
${iec61850_client_example4_SRCS} ${iec61850_client_example4_SRCS}

@ -3,10 +3,10 @@ set(iec61850_client_example_files_SRCS
client_example_files.c client_example_files.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${iec61850_client_example_files_SRCS} set_source_files_properties(${iec61850_client_example_files_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(iec61850_client_example_files add_executable(iec61850_client_example_files
${iec61850_client_example_files_SRCS} ${iec61850_client_example_files_SRCS}

@ -3,10 +3,10 @@ set(iec61850_client_example_reporting_SRCS
client_example_reporting.c client_example_reporting.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${iec61850_client_example_reporting_SRCS} set_source_files_properties(${iec61850_client_example_reporting_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(iec61850_client_example_reporting add_executable(iec61850_client_example_reporting
${iec61850_client_example_reporting_SRCS} ${iec61850_client_example_reporting_SRCS}

@ -3,10 +3,10 @@ set(mms_client_example2_SRCS
mms_client_example2.c mms_client_example2.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${mms_client_example2_SRCS} set_source_files_properties(${mms_client_example2_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(mms_client_example2 add_executable(mms_client_example2
${mms_client_example2_SRCS} ${mms_client_example2_SRCS}

@ -3,10 +3,10 @@ set(mms_client_example3_SRCS
mms_client_example3.c mms_client_example3.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${mms_client_example3_SRCS} set_source_files_properties(${mms_client_example3_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(mms_client_example3 add_executable(mms_client_example3
${mms_client_example3_SRCS} ${mms_client_example3_SRCS}

@ -3,10 +3,10 @@ set(mms_client_example4_SRCS
mms_client_example4.c mms_client_example4.c
) )
IF(WIN32) IF(MSVC)
set_source_files_properties(${mms_client_example4_SRCS} set_source_files_properties(${mms_client_example4_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF(WIN32) ENDIF(MSVC)
add_executable(mms_client_example4 add_executable(mms_client_example4
${mms_client_example4_SRCS} ${mms_client_example4_SRCS}

@ -0,0 +1,23 @@
FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
FIND_PACKAGE(PythonLibs REQUIRED)
FIND_PACKAGE ( PythonInterp REQUIRED )
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")
SET_PROPERTY(SOURCE iec61850.i PROPERTY CPLUSPLUS ON)
SWIG_ADD_MODULE(iec61850 python iec61850.i)
IF(WIN32)
SWIG_LINK_LIBRARIES(iec61850 ${PYTHON_LIBRARIES} iec61850 ws2_32)
ELSE()
SWIG_LINK_LIBRARIES(iec61850 ${PYTHON_LIBRARIES} iec61850-shared)
ENDIF(WIN32)
EXECUTE_PROCESS ( #Finding python modules install path
COMMAND ${PYTHON_EXECUTABLE} -c
"import site, sys; sys.stdout.write(site.getsitepackages()[-1])"
OUTPUT_VARIABLE PYTHON_SITE_DIR
)
INSTALL ( FILES ${CMAKE_BINARY_DIR}/iec61850.py DESTINATION ${PYTHON_SITE_DIR})
INSTALL ( TARGETS _iec61850 LIBRARY DESTINATION ${PYTHON_SITE_DIR})
add_test(test_pyiec61850 ${PYTHON_EXECUTABLE} test_pyiec61850.py)

@ -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 <iec61850_client.h>
#include <iec61850_model.h>
#include <iec61850_server.h>
ModelNode* toModelNode(LogicalNode * ln)
{
return (ModelNode*) ln;
}
ModelNode* toModelNode(DataObject * DO)
{
return (ModelNode*) DO;
}
DataAttribute* toDataAttribute(DataObject * DO)
{ return (DataAttribute*)DO;}
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"
ModelNode* toModelNode(LogicalNode *);
ModelNode* toModelNode(DataObject *);
DataAttribute* toDataAttribute(DataObject *);
DataAttribute* toDataAttribute(ModelNode *);

@ -0,0 +1,82 @@
#!/usr/bin/python
import sys
import time
import iec61850
import threading
import traceback
import signal
import sys
def signal_handler(signal, frame):
global running
running =0
print('You pressed Ctrl+C!')
#sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
tcpPort = 8102
running = 1
class myIECServer():
def __init__(self):
self.__model = iec61850.IedModel_create("testmodel")
lDevice1 = iec61850.LogicalDevice_create("SENSORS", self.__model);
lln0 = iec61850.LogicalNode_create("LLN0", lDevice1);
ttmp1 = iec61850.LogicalNode_create("TTMP1", lDevice1);
iec61850.CDC_SAV_create("TmpSv", iec61850.toModelNode(ttmp1), 0, False)
iec61850.CDC_ASG_create("TmpSp", iec61850.toModelNode(ttmp1), 0, False)
self.__iedServer = iec61850.IedServer_create(self.__model)
iec61850.IedServer_start(self.__iedServer, tcpPort);
if not(iec61850.IedServer_isRunning(self.__iedServer)) :
print("Starting server failed! Exit.\n")
iec61850.IedServer_destroy(self.__iedServer)
sys.exit(-1)
def run(self):
global running
while running:
time.sleep(0.1)
self.stop()
def stop(self):
iec61850.IedServer_stop(self.__iedServer)
iec61850.IedServer_destroy(self.__iedServer)
iec61850.IedModel_destroy(self.__model)
def testClient():
con = iec61850.IedConnection_create()
error = iec61850.IedConnection_connect(con, "localhost", tcpPort)
if (error == iec61850.IED_ERROR_OK):
# Accessing to SAV values
theVal = "testmodelSENSORS/TTMP1.TmpSv.instMag.f"
theValType = iec61850.IEC61850_FC_MX
temperatureValue = iec61850.IedConnection_readFloatValue(con, theVal, theValType)
assert(temperatureValue[1]==0)
newValue= temperatureValue[0]+10
err = iec61850.IedConnection_writeFloatValue(con, theVal, theValType, newValue)
assert(err==21)
# Accessing to ASG values
theVal = "testmodelSENSORS/TTMP1.TmpSp.setMag.f"
theValType = iec61850.IEC61850_FC_SP
temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, theVal, theValType)
print temperatureSetpoint
assert(temperatureValue[1]==0)
newValue= temperatureValue[0]+10
err = iec61850.IedConnection_writeFloatValue(con, theVal, theValType, newValue)
assert(err==0)
temperatureSetpoint = iec61850.IedConnection_readFloatValue(con, theVal, theValType)
print temperatureSetpoint
assert(temperatureSetpoint[0]==newValue)
iec61850.IedConnection_close(con)
else:
print "Connection error"
sys.exit(-1)
iec61850.IedConnection_destroy(con)
print "client ok"
try:
srv=myIECServer()
srvThread = threading.Thread(target = srv.run)
srvThread.start()
testClient()
running = 0
#signal.pause()
except:
running = 0
print "Error :"
traceback.print_exc(file=sys.stdout)
sys.exit(-1)

@ -213,14 +213,18 @@ endif()
set_source_files_properties(${lib_asn1c_SRCS} set_source_files_properties(${lib_asn1c_SRCS}
PROPERTIES LANGUAGE C) PROPERTIES LANGUAGE C)
IF(MSVC)
set_source_files_properties(${lib_common_SRCS} ${lib_windows_SRCS} set_source_files_properties(${lib_common_SRCS} ${lib_windows_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF()
IF(WITH_WPCAP) IF(WITH_WPCAP)
IF(MSVC)
set_source_files_properties(${lib_goose_SRCS} set_source_files_properties(${lib_goose_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
set_source_files_properties(${lib_sv_SRCS} set_source_files_properties(${lib_sv_SRCS}
PROPERTIES LANGUAGE CXX) PROPERTIES LANGUAGE CXX)
ENDIF()
ELSE() ELSE()
add_definitions(-DEXCLUDE_ETHERNET_WINDOWS) add_definitions(-DEXCLUDE_ETHERNET_WINDOWS)
ENDIF() ENDIF()
@ -311,8 +315,10 @@ IF(UNIX)
) )
ENDIF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME) ENDIF (CONFIG_SYSTEM_HAS_CLOCK_GETTIME)
ENDIF(UNIX) ENDIF(UNIX)
IF(MINGW)
target_link_libraries(iec61850-shared ws2_32 iphlpapi)
target_link_libraries(iec61850 ws2_32 iphlpapi)
ENDIF(MINGW)
iF(WITH_WPCAP) iF(WITH_WPCAP)
target_link_libraries(iec61850 target_link_libraries(iec61850
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/lib/wpcap.lib ${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/lib/wpcap.lib
@ -330,7 +336,6 @@ if(MSVC)
) )
endif() endif()
ELSE(WITH_WPCAP) ELSE(WITH_WPCAP)
if(MSVC) if(MSVC)
set_target_properties(iec61850-shared PROPERTIES set_target_properties(iec61850-shared PROPERTIES

@ -848,12 +848,25 @@ ControlObjectClient_enableInterlockCheck(ControlObjectClient self)
self->interlockCheck = true; self->interlockCheck = true;
} }
void
ControlObjectClient_setInterlockCheck(ControlObjectClient self, bool value)
{
self->interlockCheck = value;
}
void void
ControlObjectClient_enableSynchroCheck(ControlObjectClient self) ControlObjectClient_enableSynchroCheck(ControlObjectClient self)
{ {
self->synchroCheck = true; self->synchroCheck = true;
} }
void
ControlObjectClient_setSynchroCheck(ControlObjectClient self, bool value)
{
self->synchroCheck = value;
}
void void
ControlObjectClient_setLastApplError(ControlObjectClient self, LastApplError lastApplError) ControlObjectClient_setLastApplError(ControlObjectClient self, LastApplError lastApplError)
{ {

@ -1510,12 +1510,36 @@ ControlObjectClient_setOrigin(ControlObjectClient self, const char* orIdent, int
void void
ControlObjectClient_useConstantT(ControlObjectClient self, bool useConstantT); ControlObjectClient_useConstantT(ControlObjectClient self, bool useConstantT);
/**
* \deprecated use ControlObjectClient_setInterlockCheck instead
*/
void void
ControlObjectClient_enableInterlockCheck(ControlObjectClient self); ControlObjectClient_enableInterlockCheck(ControlObjectClient self);
/**
* \deprecated use ControlObjectClient_setSynchroCheck instead
*/
void void
ControlObjectClient_enableSynchroCheck(ControlObjectClient self); ControlObjectClient_enableSynchroCheck(ControlObjectClient self);
/**
* \brief Set the value of the interlock check flag when a control command is sent
*
* \param self the ControlObjectClient instance
* \param value if true the server will perform a interlock check if supported
*/
void
ControlObjectClient_setInterlockCheck(ControlObjectClient self, bool value);
/**
* \brief Set the value of the synchro check flag when a control command is sent
*
* \param self the ControlObjectClient instance
* \param value if true the server will perform a synchro check if supported
*/
void
ControlObjectClient_setSynchroCheck(ControlObjectClient self, bool value);
/** /**
* \brief Private a callback handler that is invoked when a command termination message is received. * \brief Private a callback handler that is invoked when a command termination message is received.

@ -1,7 +1,7 @@
/* /*
* mms_client_connection.h * mms_client_connection.h
* *
* Copyright 2013 Michael Zillgith * Copyright 2013-2016 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *
@ -49,6 +49,7 @@ typedef struct sMmsConnectionParameters {
int maxServOutstandingCalled; int maxServOutstandingCalled;
int dataStructureNestingLevel; int dataStructureNestingLevel;
int maxPduSize; /* local detail */ int maxPduSize; /* local detail */
uint8_t servicesSupported[11];
} MmsConnectionParameters; } MmsConnectionParameters;
typedef struct { typedef struct {
@ -112,7 +113,7 @@ MmsConnection_setInformationReportHandler(MmsConnection self, MmsInformationRepo
void* parameter); void* parameter);
/** /**
* \brief Get the connection parameters for an MmsConnection instance * \brief Get the ISO connection parameters for an MmsConnection instance
* *
* \param self MmsConnection instance to operate on * \param self MmsConnection instance to operate on
* \return params the to be used by this connection * \return params the to be used by this connection
@ -120,6 +121,15 @@ MmsConnection_setInformationReportHandler(MmsConnection self, MmsInformationRepo
IsoConnectionParameters IsoConnectionParameters
MmsConnection_getIsoConnectionParameters(MmsConnection self); MmsConnection_getIsoConnectionParameters(MmsConnection self);
/**
* \brief Get the MMS specific connection parameters for an MmsConnection instance
*
* \param self MmsConnection instance to operate on
* \return params the to be used by this connection
*/
MmsConnectionParameters
MmsConnection_getMmsConnectionParameters(MmsConnection self);
/** /**
* \brief User provided handler function that will be called if the connection to the server is lost * \brief User provided handler function that will be called if the connection to the server is lost
* *

@ -841,6 +841,12 @@ MmsConnection_getIsoConnectionParameters(MmsConnection self)
return self->isoParameters; return self->isoParameters;
} }
MmsConnectionParameters
MmsConnection_getMmsConnectionParameters(MmsConnection self)
{
return self->parameters;
}
static void static void
waitForConnectResponse(MmsConnection self) waitForConnectResponse(MmsConnection self)
{ {

@ -130,6 +130,11 @@ mmsClient_parseInitiateResponse(MmsConnection self)
self->parameters.maxServOutstandingCalling = initiateResponse->negotiatedMaxServOutstandingCalling; self->parameters.maxServOutstandingCalling = initiateResponse->negotiatedMaxServOutstandingCalling;
int i;
for (i = 0; i < 11; i++)
self->parameters.servicesSupported[i] = initiateResponse->mmsInitResponseDetail.servicesSupportedCalled.buf[i];
result = true; result = true;
} }
else else

@ -526,4 +526,6 @@ EXPORTS
MmsValue_setUtcTimeQuality MmsValue_setUtcTimeQuality
MmsValue_decodeMmsData MmsValue_decodeMmsData
MmsValue_encodeMmsData MmsValue_encodeMmsData
ControlObjectClient_setInterlockCheck
ControlObjectClient_setSynchroCheck

@ -600,4 +600,7 @@ EXPORTS
MmsValue_getUtcTimeQuality MmsValue_getUtcTimeQuality
MmsValue_decodeMmsData MmsValue_decodeMmsData
MmsValue_encodeMmsData MmsValue_encodeMmsData
MmsConnection_getMmsConnectionParameters
IedServer_updateVisibleStringAttributeValue
ControlObjectClient_setInterlockCheck
ControlObjectClient_setSynchroCheck

Loading…
Cancel
Save