From 6cbadb4b459109436e04e748810208b46a1b6c23 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 29 Nov 2019 18:39:09 +0100 Subject: [PATCH] - IED server: added new function ControlAction_isSelect --- dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs | 13 +++++++++++++ dotnet/IEC61850forCSharp/MmsValue.cs | 1 - .../server_example_control.c | 12 ++++++++++-- src/iec61850/inc/iec61850_server.h | 10 ++++++++++ src/iec61850/inc_private/control.h | 17 +++++++++-------- src/iec61850/server/mms_mapping/control.c | 19 +++++++++++++++++++ 6 files changed, 61 insertions(+), 11 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index 882c2251..55f1487c 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -513,6 +513,10 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt64 ControlAction_getControlTime(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ControlAction_isSelect(IntPtr self); + private IntPtr self; private IedServer.ControlHandlerInfo info; private IedServer iedServer; @@ -614,6 +618,15 @@ namespace IEC61850 return con; } + + /// + /// Cehck if the control callback is called by a select or operate command + /// + /// true, if select, false otherwise. + public bool IsSelect() + { + return ControlAction_isSelect(self); + } } public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value, diff --git a/dotnet/IEC61850forCSharp/MmsValue.cs b/dotnet/IEC61850forCSharp/MmsValue.cs index 82670102..0cd46be6 100644 --- a/dotnet/IEC61850forCSharp/MmsValue.cs +++ b/dotnet/IEC61850forCSharp/MmsValue.cs @@ -32,7 +32,6 @@ namespace IEC61850 { namespace Common { - /// /// This class is used to hold MMS data values of different types. /// diff --git a/examples/server_example_control/server_example_control.c b/examples/server_example_control/server_example_control.c index c08fcd30..2aecfe1c 100644 --- a/examples/server_example_control/server_example_control.c +++ b/examples/server_example_control/server_example_control.c @@ -27,11 +27,16 @@ sigint_handler(int signalId) static CheckHandlerResult checkHandler(ControlAction action, void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck) { - printf("check handler called!\n"); + if (ControlAction_isSelect(action)) + printf("check handler called by select command!\n"); + else + printf("check handler called by operate command!\n"); if (interlockCheck) printf(" with interlock check bit set!\n"); + printf(" ctlNum: %i\n", ControlAction_getCtlNum(action)); + if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO1) return CONTROL_ACCEPTED; @@ -55,6 +60,9 @@ controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* v { uint64_t timestamp = Hal_getTimeInMs(); + printf("control handler called\n"); + printf(" ctlNum: %i\n", ControlAction_getCtlNum(action)); + if (parameter == IEDMODEL_GenericIO_GGIO1_SPCSO1) { IedServer_updateUTCTimeAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_t, timestamp); IedServer_updateAttributeValue(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1_stVal, value); @@ -122,7 +130,7 @@ main(int argc, char** argv) /* this is optional - performs operative checks */ IedServer_setPerformCheckHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO2, checkHandler, - IEDMODEL_GenericIO_GGIO1_SPCSO2); + IEDMODEL_GenericIO_GGIO1_SPCSO2); IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO3, (ControlHandler) controlHandlerForBinaryOutput, diff --git a/src/iec61850/inc/iec61850_server.h b/src/iec61850/inc/iec61850_server.h index 35b428ce..1ae85fb8 100644 --- a/src/iec61850/inc/iec61850_server.h +++ b/src/iec61850/inc/iec61850_server.h @@ -1174,6 +1174,16 @@ ControlAction_getOrIdent(ControlAction self, int* orIdentSize); LIB61850_API int ControlAction_getCtlNum(ControlAction self); +/** + * \brief Check if the control callback is called by a select or operate command + * + * \param self the control action instance + * + * \return true, when called by select, false for operate + */ +LIB61850_API bool +ControlAction_isSelect(ControlAction self); + /** * \brief Gets the client object associated with the client that caused the control action * diff --git a/src/iec61850/inc_private/control.h b/src/iec61850/inc_private/control.h index 78b5a3f1..de643624 100644 --- a/src/iec61850/inc_private/control.h +++ b/src/iec61850/inc_private/control.h @@ -43,14 +43,15 @@ struct sControlObject char* lnName; char* name; - int state:4; - int ctlModel:4; - int pendingEvents:8; - int testMode:1; - int interlockCheck:1; - int synchroCheck:1; - int timeActivatedOperate:1; - int operateOnce:1; + unsigned state:4; + unsigned ctlModel:4; + unsigned pendingEvents:8; + unsigned testMode:1; + unsigned interlockCheck:1; + unsigned synchroCheck:1; + unsigned timeActivatedOperate:1; + unsigned operateOnce:1; + unsigned isSelect:1; ControlAddCause addCauseValue:6; #if (CONFIG_MMS_THREADLESS_STACK != 1) diff --git a/src/iec61850/server/mms_mapping/control.c b/src/iec61850/server/mms_mapping/control.c index 56e0820c..cca6d5f3 100644 --- a/src/iec61850/server/mms_mapping/control.c +++ b/src/iec61850/server/mms_mapping/control.c @@ -1270,8 +1270,12 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia if (controlObject->checkHandler != NULL) { /* perform operative tests */ + controlObject->isSelect = 1; + checkResult = controlObject->checkHandler((ControlAction) controlObject, controlObject->checkHandlerParameter, NULL, false, false); + + controlObject->isSelect = 0; } if (checkResult == CONTROL_ACCEPTED) { @@ -1467,8 +1471,12 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari if (controlObject->checkHandler != NULL) { /* perform operative tests */ + controlObject->isSelect = 1; + checkResult = controlObject->checkHandler((ControlAction) controlObject, controlObject->checkHandlerParameter, ctlVal, testCondition, interlockCheck); + + controlObject->isSelect = 0; } if (checkResult == CONTROL_ACCEPTED) { @@ -1761,6 +1769,17 @@ ControlAction_getCtlNum(ControlAction self) return -1; } +bool +ControlAction_isSelect(ControlAction self) +{ + ControlObject* controlObject = (ControlObject*) self; + + if (controlObject->isSelect) + return true; + else + return false; +} + ClientConnection ControlAction_getClientConnection(ControlAction self) {