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)
{