Control tutorial

This tutorial is aimed to guide you in using the IEC 61850 control facilities with libIEC61850. The client and server control APIs are designed to be simple to use while providing access to all aspects of the different IEC 61850 control models. A very short general overview of the control functions of IEC 61850 can also be found here.

The library supports the following control operations: select, select-with-value, operate, time-activated-operate and cancel. These control operations can be applied to controllable data objects that have their control model (ctlModel attribute) set to other values than status-only (0). Depending on the selected control model also only a subset of these operations are allowed. E.g. in direct-control only the operate, time-activated-operate and cancel operations are allowed.

Using control server side

For using the control model server side you have to install callback handlers for the controllable data object for which you want to enable control support.

iedServer = IedServer_create(&iedModel);

   (ControlHandler) controlHandler,

LibIEC61850 knows three different types of control related callback functions. They will be invoked by the server stack in the different states of the IEC 61850 control model (see figure 1 for the basic control states and the related callback functions).

Basic control states of IEC 61850 and associated callbacks.
Figure 1: The basic state machine of IEC 61850 control models and related callback functions.

If not operated the control state machine is in the ready state. Once operated (after receiving an operate request from a client the state machine switches to the PerformCheck state. In this state the server application can perform “static” tests to check if the process state allows an operation of the control. In case of an error the server sends a negative response and switches back to the ready state. In case of success the control state machine switches to the WaitForExecution state. In this state “dynamic” tests can be performed.

In most cases only one callback function (of type ControlHandler) is required. If only this callback handler is present the server stack assumes that the “PerformTest” and “WaitForExecution” states were successfully finished.

Here you can see the definitions of the control callback functions (from iec61850_server.h):

typedef CheckHandlerResult (*ControlPerformCheckHandler) (void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck,
        ClientConnection connection);

typedef ControlHandlerResult (*ControlWaitForExecutionHandler) (void* parameter, MmsValue* ctlVal, bool test, bool synchroCheck);

typedef ControlHandlerResult (*ControlHandler) (void* parameter, MmsValue* ctlVal, bool test);

The callback functions are shown in the order they are executed by the server stack. Each of the functions has a user provided parameter as the first argument. This can e.g. be used to distinguish between different control objects (here you can simply pass the reference to the control object node when installing the callback function). The second parameter (ctlVal) is the control value (set point value) of the operate or select-with-value request from the client. This is of course the most important parameter. The third parameter (test) indicates if the client indicates that this control operation is for test purposes only and should not be applied to the controlled process.

The ControlPerformCheckHandler and ControlWaitForExecutionHandler both have an additional parameter. The first has the interlockCheck parameter that is intended to indicate that the server should check the interlocking conditions for this control object prior to performing the control action. Interlock check means that the server has to check the state of other control objects to decide if the control operation is allowed. The latter has the synchroCheck parameter. This parameter indicates that some synchronization conditions have to be met prior to switching a circuit.

Note: The control handler is always executed inside the thread context of the server. This means the callback handlers should always return immediately. Otherwise important stack functions like report and GOOSE processing will not work properly. If the control handlers have to perform long running tasks they have to return CONTROL_RESULT_WAITING. Then the handler will be called again later until the control task is completed. This behavior is different to library versions prior to 0.8!

The control handler is responsible to inform the server if a timeout or other error condition happens. In this case the handler has to return with CONTROL_RESULT_FAILED.

Client side control functions

The usage of control client side is illustrated by the iec61850_client_example3 in the source distribution. Here is a code snippet:

IedClientError error;

IedConnection con = IedConnection_create();

IedConnection_connect(con, &error, hostname, tcpPort);

ControlObjectClient control
 = ControlObjectClient_create("simpleIOGenericIO/GGIO1.SPCSO1", con);

The first step is to create and open a connection to the server. In the next step a ControlObjectClient instance has to be created. The first argument is the object reference of the control object. The second parameter is the connection object of the server connection.

If the control object’s control model is set to direct-control (this can be checked by inspecting the ctlModel attribute value, 1 = direct-control) an operate command can be issued. This is done by creating an MmsValue instance that represents the control value (ctlVal is the target or set point value of the control operation). This instance has to be passed to the operate method:

MmsValue* ctlVal = MmsValue_newBoolean(true);

ControlObjectClient_operate(control, ctlVal, 0)

The last parameter of the ControlObjectClient_operate method is the execution time. This parameter is used to specify the time of execution as milliseconds since 01/01/1970 UTC. If set to 0 this will cause an immediate execution. If set to a value in the future the execution is performed later. The latter is called “time activated control”.

Control states of IEC 61850 select-before-operate control model and associated callbacks.
Figure 2: The state machine of IEC 61850 select-before-operate control model.

If the control object is configured for select-before-operate (ctlModel = 2) a select command has to be sent to the server prior to the operate command. After a successful select command the server side control object is reserved (selected) for the client that issued the select command. Other clients are not allowed to operate the control if it is selected.

control = ControlObjectClient_create(
     "simpleIOGenericIO/GGIO1.SPCSO2", con);

if (ControlObjectClient_select(control)) {
  ctlVal = MmsValue_newBoolean(true);

  ControlObjectClient_operate(control, ctlVal, 0);

The select state can timeout after a defined time if the sboTimeout attribute is present in the control object and set to a value different from 0. After performing the operation the select state is either leaved if the sboClass attribute is set to operate-once (0) or maintained if sboClass is set to operate-many (1).

The selected state will also be left if the clients sends a cancel request:


The cancel request can also be used to cancel time activated control tasks at the server.

Control objects and properties

IEC 61850-7-3 defines different types of controllable objects. These types are called controllable common data classes (CDC). An overview over these object types and some basic properties can be found in table 1. The most important properties for the user are the types of the stVal and ctlVal attributes. It should be noted that the IEC 61850 ENUM types are mapped to MMS_INTEGER variables in libIEC61850.

The AnalogueValue type is mapped to an MMS_STRUCTURE with a single element being either an MMS_INTEGER or an MMS_FLOAT variable. Note: In the case that the status of a CDC is of type AnalogueValue the status attribute is named mxVal instead of stVal and has the functional constraint MX instead of ST!

The ValWithTrans type is mapped to an MMS_STRUCTURE with one or two members. The first is the position indication and is an MMS_INTEGER variable in the range -64 to 63. The second is an MMS_BOOLEAN indicating that the position is in a transient state. Note: In the case that the status of a CDC is of type ValWithTrans the status attribute is named valWTr instead of stVal!

SPCControllable Single PointA simple boolean control (e.g. a simple switch or a LED)BOOLEANBOOLEAN
DPCControllable Double PointA boolean control with intermediate states (e.g. a slow moving switch)ENUMBOOLEAN
INCControllable Integer StatusAn integer type controlINT32INT32
ENCControllable Enumerated StatusENUMENUM
BSCBinary Controlled Step Position InformationValWithTransENUM (stop | lower | higher | reserved)
ISCInteger Controlled Step Position InformationValWithTransINT8 (-64 ... 63)
APCControllable Analog Process ValueA control for analog values.AnalogueValueAnalogueValue
BACBinary Controlled Analog Process ValueAnalogueValueENUM (stop | lower | higher | reserved)

Table 1: The controllable common data classes in IEC 61850-7-3.

Table 2 gives an overview of the data attributes that are relevant for control operations. Some of the attributes are mandatory for every controllable data object (M), some are only mandatory for specific CDCs (C) and some are optional (O). Some attributes have to be handled by the user (API client) when the control handlers are invoked. Other attributes are handles automatically by the libIEC61850 server stack.

NameO/M/Chandled by userhandled by stackDescription
stVal / valWTr / mxValOX-status or measurement value of the controlled process value
sboTimeoutO-Xtimeout of the select operation. The value is in milliseconds. There is no timeout if set to 0.
ctlModelM-XThe control model of the controllable object. Either status-only, direct-control, select-before-operate, direct control with enhanced security, select-before-operate with enhanced security
sboClassO-Xeither operate-once or operate-many. Indicates if the select state is leaved after an operation
operTimeoutOX-timeout of the operate state in ms.

Table 2: The attributes of controllable data objects.

8 thoughts on “Control tutorial

  1. said

    I have tried to use “Client side control functions” of liebiec61850 on real IED (Alstom BCUC264) for double command (DPC), but there is an error “ACCESS_VIOLATION” >> “OR_CAT_NOT_SUPPORTED” ( I saw the error using sniffer of IEDSCout). For comparison then I tried “Client side control functions” using IED Scout, and it’s success. The different is the parameter of Pos.SBOw.origin.orCat. When I make controlling, “Client side control functions” of liebiec61850 sent Pos.SBOw.origin.orCat = 0 (“not supported”), but “Client side control functions” of IEDScout sent Pos.SBOw.origin.orCat = 2 (“station control”). Wheter liebiec61850 able to send Pos.SBOw.origin.orCat = 2 like IEDScout? How to do that?Please tell me where is the parameter of Pos.SBOw.origin.orCat. Thank You.

  2. said

    Hi Michael. I have found the parameter. I add ” ControlObjectClient_setOrigin(control, “TES” , 2); ”
    And it works. Thank you

      1. said

        Hi Max, it’s my code for DPC :
        * client_example3.c
        * How to control a device … intended to be used with server_example_control

        #include “iec61850_client.h”
        #include “hal_thread.h”


        static void commandTerminationHandler(void *parameter, ControlObjectClient connection)

        LastApplError lastApplError = ControlObjectClient_getLastApplError(connection);

        // if lastApplError.error != 0 this indicates a CommandTermination-
        if (lastApplError.error != 0) {
        printf(“Received CommandTermination-.\n”);
        printf(” LastApplError: %i\n”, lastApplError.error);
        printf(” addCause: %i\n”, lastApplError.addCause);
        printf(“Received CommandTermination+.\n”);

        int main(int argc, char** argv) {

        char* hostname;
        int tcpPort = 102;

        if (argc > 1)
        hostname = argv[1];
        hostname = “localhost”;

        if (argc > 2)
        tcpPort = atoi(argv[2]);

        IedClientError error;

        IedConnection con = IedConnection_create();

        IedConnection_connect(con, &error, hostname, tcpPort);

        if (error == IED_ERROR_OK) {

        * Direct control

        ControlObjectClient control
        = ControlObjectClient_create(“SE_C264CONTROL/CSWI1.Pos”, con);

        MmsValue* ctlVal = MmsValue_newBoolean(true);

        * Select before operate with enhanced security

        control = ControlObjectClient_create(“SE_C264CONTROL/CSWI1.Pos”, con);

        // Tambahan utk menge-set orCat=2 (station control)
        ControlObjectClient_setOrigin(control, “TES” , 2);

        ControlObjectClient_setCommandTerminationHandler(control, commandTerminationHandler, NULL);

        ctlVal = MmsValue_newBoolean(true);

        if (ControlObjectClient_selectWithValue(control, ctlVal)) {

        if (ControlObjectClient_operate(control, ctlVal, 0 /* operate now */)) {
        printf(“SE_C264CONTROL/CSWI1.Pos operated successfully\n”);
        else {
        printf(“failed to operate SE_C264CONTROL/CSWI1.Pos!\n”);

        else {
        printf(“failed to select SE_C264CONTROL/CSWI1.Pos!\n”);


        /* Wait for command termination message */


        else {
        printf(“Connection failed!\n”);


  3. bin

    Hi Michael.How to use ‘General dynamic model’ way to realize ‘INC’ & ‘ASG’ control in the server side?

  4. Is

    I’m trying to control BSC and a APC Data objects.
    Can anyone help me with the server side callback handler.


  5. Jonhson

    I can’t select my DataObject from my client, but it exists when i make a readObject. How can i select or operate in this case please?

  6. Mooo

    SelectWithValue & Oper a SBOes object:
    1.if IED return a respone- for client’s Oper ,and a CommandTermination- with “error=1 addcause=16 ctlnum=1”. commandTerminationHandler get “error=1 addcause=16 ctlnum=1”
    2.if IED return a respone+ for client’s Oper ,and a CommandTermination- with “error=1 addcause=16 ctlnum=1”. commandTerminationHandler get “error=0 addcause=0 ctlnum=0” not as expect.
    How to get expected lastApplError in case 2 ?

Comments are closed.