Using the C# API

The libiec61850 source code distribution also contains a clinet/server API for C#/.NET. The C# library should run on .NET and Mono (on Linux and Mac OS X 10.9). Please also refer to the examples provided with the C# API.

The C# code is provided with solution and project files that can be either used with Visual Studio or MonoDevelop (Xamarin Studio).

Build the API and examples on Mono for Linux

To build the tools you can either use MonoDevelop or the xbuild command line tool.

To build on the command line just type:

cd dotnet
xbuild dotnet.sln

On a Windows system you can use Visual Studio or the msbuild command line tool respectively.

The C# API requires the C/native library to be built as a native shared library (.so file or DLL).

The runtime (.NET or Mono) has to be able to find the shared library/DLL. This can be done by copying the library to the respective system directory:
On Linux or Mac OS X this is usually /usr/lib.
On Windows this is the C:/Windows/System32. (Depending on the version of Windows this directory may differ).

Linux: libiec61850.so ==> /usr/lib
Mac OS X: libiec61850.dylib ==> /usr/lib
Windows: iec61850.dll ==> C:/Windows/System32

A simple example application

using System;
using IEC61850.Client;
using IEC61850.Common;

namespace test1
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			var connection = new IedConnection ();

			connection.Connect ("localhost");

			bool stVal = connection.ReadBooleanValue ("simpleIOGenericIO/GGIO1.SPCSO1.stVal", 
				FunctionalConstraint.ST);

			UInt64 t = connection.ReadTimestampValue("simpleIOGenericIO/GGIO1.SPCSO1.t", 
				FunctionalConstraint.ST);

			DateTimeOffset timestamp = MmsValue.MsTimeToDateTimeOffset (t);

			Console.WriteLine ("SPCSO1.stVal: " + stVal.ToString ());
			Console.WriteLine ("SPCSO1.t: " + timestamp.ToString ());

			var spcso1 = connection.CreateControlObject ("simpleIOGenericIO/GGIO1.SPCSO1");

			if (stVal)
				spcso1.Operate (false);
			else
				spcso1.Operate (true);

			connection.Abort ();
		}
	}
}

The C# API is designed to be as close as possible to the C API without compromising the C# coding style. Main differences are the usage of real instance methods instead of static functions and exceptions instead of call by reference error variables.

40 thoughts on “Using the C# API

    1. Michael Zillgith Post author

      GOOSE publishing may be integrated together with the server side API. But there is not yet a schedule when this will be done.

  1. Mladen

    Hello,
    I’m having trouble reading a DPI value. According to the C#/.Net API Ref. manual enum types should be readed with IedConnection.ReadIntegerValue() but this throws exception “Result is not of type integer (MMS_INTEGER)”. I tried getting the type with IedConnection.GetVariableSpecification() and the result is “MMS_BIT_STRING”. Then I tried IedConnection.ReadStringValue() but it throws exception “Result is not of type string”. I’ve also tried IedConnection.ReadValue() but then i get “unknown” value. How should I get the value of a DPI?

    1. Michael Zillgith Post author

      I have seen that the readout of DPS (double point status) values is not yet supported by the C# API. The reason is that stVal of DPS is specified as a “CODED ENUM” that is mapped to an MMS bit string variable. This is different to “ENUMERATED” variables that are mapped to MMS integer variables. I will add support for this with the next release.
      As a workaround you can add a method like bellow to the IedConnection class in IEC61850ClientAPI.cs:

      public int ReadBitStringValue (string objectReference, FunctionalConstraint fc)
      {
      	IntPtr mmsValue = readObjectInternal (objectReference, fc);
      
      	if (MmsValue_getType (mmsValue) == (int)MmsType.MMS_BIT_STRING) {
      		int bitStringValue = (int)MmsValue_getBitStringAsInteger (mmsValue);
      
      		MmsValue_delete (mmsValue);
      		return bitStringValue;
      	} else {
      		MmsValue_delete (mmsValue);
      		throw new IedConnectionException ("Result is not of type bit string", 0);
      	}
      }
      
  2. Mladen

    I didn’t manage to setup the reporting with C# API. What should be the second parameter of the function ReportControlBlock.InstallReportHandler (ReportHandler reportHandler, object parameter)? I am getting “Access Violation exception” when calling IedConnection_installReportHandler() in the body of InstallReportHandler().

    1. Michael Zillgith Post author

      Did you had a look at the provided example (ReportingExample.cs)? Here you can see how to properly set the report handler. The second parameter is just passed to the handler. You can also provide “null” if you don’t need this.

  3. Erdet Nasufi

    I’m trying with simple example, but I’m facing with this terminating error:
    “System.EntryPointNotFoundException: Unable to find an entry point named ‘IedConnection_create’ in DLL ‘iec61850’.
    at IEC61850.Client.IedConnection.IedConnection_create()
    at IEC61850.Client.IedConnection..ctor() in d:\…\libiec61850-0.8.0\libiec61850-0.8.0\dotnet\IEC61850forCSharp\IEC61850ClientAPI.cs:line 161
    at datasets.DataSetExample.Main(String[] args) in d:\….\libiec61850-0.8.0\libiec61850-0.8.0\dotnet\datasets\DataSetExample.cs:line 13”

    1. Michael Zillgith Post author

      This exception is thrown when the native library iec61850.dll (or libiec61850.so on linux) is not found. You have to build the native library first and put it in a folder where the OS can find it. On Windows this is usually “C:\Windows\System32, on linux “/usr/lib”.

    2. lucy

      hello, Can you tell me did you solve the problem already? I have meet this problem too, and i do not know how to resolve it, can you tell me?

  4. bikash

    Hi All,
    I have downloaded the latest version of the application i.e libiec61850-0.8.3.tgz, went to the dotnet folder after extracting, opened the application in VS2013, build project”IEC61850forCSharp” with assembly name as “iec61850” and pasted the dll in System32 folder, started example1 project, i get following error
    Unable to find an entry point named ‘IedConnection_create’ in DLL ‘iec61850’.

    please help, thanks in advance.

        1. Zhu

          Hi,
          Have you tested the example of C# API as shown on this web page? When I copy the codes into my VS2012 C# console application, the compiling result says “iec 61850.dll” is not found. How did you solve the problem? I have built the library and copied the “iec61850.dll” into win32/system directory.

  5. Mladen

    Hello, the new version 0.8.3 can’t connect to real ABB protection relays. The old version 0.8.2 is working. The new version fails to connect to relay at MmsConnection_connect().

    1. Michael Zillgith Post author

      This is most probably due to the changes in the T-selector handling. Version 0.8.3 uses the value 0 instead of 1 that has been used before. It seems that many devices cannot deal with this value. You can try to change the value by API.

  6. Michael

    Hi Michael,

    I seem to be having trouble reading single byte Boolean values. I’ve tried reading with .ReadBooleanValue and with .ReadDataSetValues. With wireshark I can see the response from my ied is (in hex) 83 01 00 (Boolean value, 1 byte, value = false), however both these functions are always returning true.

    1. Michael Zillgith Post author

      Hi, this is a known problem. It is due to the different handling of “bool” type in GCC(C) and VS(C++). It is fixed in the upcoming version (next week). The decorators for native functions with bool return value have to be changed to “[return: MarshalAs(UnmanagedType.I1)]”. If you need the fixed version now you can send me an email.

  7. malg

    Hello, congratulations for such a good job with this library.

    My question is if you are planning to release a C# api for the server part?

    Thanks,

    1. Michael Zillgith Post author

      Yes I am planning that. But it is not of high priority at the moment. So don’t expect anything useful in the next few months.

      1. malg

        Hi, thanks for your answer.

        I will try that myself. If I am lucky, I will give you some feedback about this.

        Thanks!

  8. Varun

    I am facing problem with Enhanced type commands in Windows form application.

    The following code causes error when executed 2nd time in a row:
    private void selectCommandToolStripMenuItem_Click(object sender, EventArgs e)
    {
    /* direct control with enhanced security */
    string objectReference = “simpleIOGenericIO/GGIO1.SPCSO9″;
    Program.control = con.CreateControlObject(objectReference);
    controlModel = Program.control.GetControlModel();
    this.IED_ListBox.Items.Add(objectReference + ” has control model ” + controlModel.ToString());
    Program.control.SetCommandTerminationHandler(commandTerminationHandler, null);
    Program.control.Operate(true);
    Thread.Sleep(1000);
    this.IED_ListBox.SelectedIndex = this.IED_ListBox.Items.Count – 1;
    }

    Following error occurs:
    Managed Debugging Assistant ‘CallbackOnCollectedDelegate’ has detected a problem in
    ‘G:\Projects\libiec61850-0.8.6\dotnet\Test_Application\bin\Debug\Test_Application.exe’.

    Additional Information: A callback was made on a garbage collected delegate of type
    ‘iec61850dotnet!IEC61850.Client.ControlObject+InternalCommandTerminationHandler::Invoke’.
    This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

    Can you please help me out with this.

    1. Varun

      After few hours of debugging, I found a workaround by changing the dotnet “Control.cs” in the following way:

      private InternalCommandTerminationHandler intCommandTerminationHandler;
      //The declaration here prevented Garbage Collection

      internal ControlObject (string objectReference, IntPtr connection, IedConnection iedConnection)
      {
      this.iedConnection = iedConnection;
      this.controlObject = ControlObjectClient_create(objectReference, connection);
      if (this.controlObject == System.IntPtr.Zero)
      throw new IedConnectionException(“Control object not found”, 0);

      intCommandTerminationHandler = new InternalCommandTerminationHandler(MyCommandTerminationHandler);

      ControlObjectClient_setCommandTerminationHandler(controlObject, intCommandTerminationHandler, controlObject);
      }

      Is this the right way?
      Thanks

  9. lua_newer

    In C#, I found when a received MmsValue instance of type MmsType.MMS_STRUCTURE contains q(Quality), the GetType method returns MMS_BIT_STRING of q and I print the value using “Console.WriteLine(q);” it gives me nothing! Is this correct?What‘s the solution if I want to print out the q(Quality)?

  10. lua_newer

    IEC61850.Common.MmsValue
    MmsValue.cs
    warning CS0659
    Not overriding GetHashcode when overriding Equals
    Sometimes developers forget to override GetHashCode even after the overriding
    equals. When we equate two objects, the .NET first calls GetHashCode of each of
    the objects before calling the Equals method. So if the hash code of two objects
    does not match, they will never be considered as equal. Hence, you need to override
    GetHashCode of both the types and return the same value for two objects.

  11. Vikas

    Hi All

    I have downloaded the latest version of the application i.e libiec61850-0.9.2.1.tgz, and tried to use CMAKE to build it. But I am getting several errors.

    CMAKE Message
    ****************************************************************
    The C compiler identification is unknown
    The CXX compiler identification is unknown
    CMake Error at CMakeLists.txt:10 (project):
    No CMAKE_C_COMPILER could be found.

    CMake Error at CMakeLists.txt:10 (project):
    No CMAKE_CXX_COMPILER could be found.

    Configuring incomplete, errors occurred!
    See also “C:/Users/insashe3/Downloads/IEC61850 source code/CMakeFiles/CMakeOutput.log”.
    See also “C:/Users/insashe3/Downloads/IEC61850 source code/CMakeFiles/CMakeError.log”.

    *********************************************************************************
    please help, thanks in advance.

  12. Denis

    Hello,
    How create server with C# to transfer files on client ?
    Or is it only possible for server with C?

    1. Michael Zillgith Post author

      It works exactly the same way as with a server written in C. With the standard configuration you only need a folder “vmd-filestore” containing the files you want to serve in the directory where the server is started.

  13. Dmitriy

    Hi i have some problem with server in libiec61850.
    Every time than i try to write something it response me something like

    30

    3

    programm for exaple

    DataAttribute GGIO1_SPCSO1_oper_ctlVal = (DataAttribute)iedModel.GetModelNodeByShortObjectReference(“GenericIO/GGIO1.SPCSO1.Oper.ctlVal”);
    IedServer iedServer = new IedServer (iedModel);
    iedServer.SetWriteAccessPolicy(FunctionalConstraint.ALL, AccessPolicy.ACCESS_POLICY_ALLOW);

    if (GGIO1_SPCSO1_oper_ctlVal!= null)
    iedServer.HandleWriteAccess(GGIO1_SPCSO1_oper_ctlVal,delegate(DataAttribute attr,MmsValue val,ClientConnection con,object param) {
    iedServer.UnlockDataModel();
    iedServer.UpdateBooleanAttributeValue(attr,val.GetBoolean());
    iedServer.LockDataModel();
    return MmsDataAccessError.SUCCESS;
    },null);
    iedServer.Start (102);
    Console.WriteLine (“Server started”);
    GC.Collect ();
    while (running) {

    Thread.Sleep (100);
    }

    iedServer.Stop ();
    Console.WriteLine (“Server stopped”);

    iedServer.Destroy ();

    What am I doing wrong?

    1. Michael Zillgith Post author

      Hi,
      The line
      iedServer.SetWriteAccessPolicy(FunctionalConstraint.ALL, AccessPolicy.ACCESS_POLICY_ALLOW);
      has no effect. You have to specify the FC (it has to be one of DC, CF, SP, SV, SE).

      You cannot handle writing of controls this way. For controls you have to use a ControlHandler.

  14. Andrew

    From C# can I dynamically create an IedModel or is the only option to load it from a .cfg file using ConfigFileParser.CreateModelFromConfigFile ?

    1. Michael Zillgith Post author

      You can dynamically create an IedModel with C# by using the API. Unfortunately there is no example available yet. But doing it looks like:

      IedModel iedModel = new IedModel("MYIED1");
      LogicalDevice ld1 = new LogicalDevice("LD1", iedModel);
      ...

      1. Andrew

        Michael, Yes that seems much easier than using the .cfg files! I have a prototype up and running as a Windows service and it seems to be working well. What test client do you use? I downloaded a 30 day demo of Omicron’s IEDScout which seems quite good but rather expensive!

  15. reza

    hi Michael , is it possible to use sampled value subscriber with c# api? i want sv subscriber in c# language thank you

  16. João Oliveira

    Download file inside a directory.
    I’m trying to use this library to download files from an IED with 61850 File Transfer protocol. I used GetFile() method from IedConnection class of IEC61850ClientAPI code.

    It runs ok for files on the root path, but it does not work if the file is in a sub-directory.
    How do I pass the full path name to GetFile() method in order to download these files?

Comments are closed.