Giter VIP home page Giter VIP logo

mz-automation / libiec61850 Goto Github PK

View Code? Open in Web Editor NEW
820.0 94.0 443.0 6.7 MB

Official repository for libIEC61850, the open-source library for the IEC 61850 protocols

Home Page: http://libiec61850.com/libiec61850

License: GNU General Public License v3.0

CMake 0.83% Makefile 0.24% C 77.47% C# 13.63% Python 0.34% C++ 0.69% CSS 1.14% HTML 0.06% Shell 0.02% Java 5.45% SWIG 0.12%
iec-61850 mms goose

libiec61850's Introduction

README libIEC61850

Build Status

This file is part of the documentation of libIEC61850. More documentation can be found online at http://libiec61850.com.

The API documentation can be found here:

Also consider to review the examples to understand how to use the library.

Content:

Overview

libiec61850 is an open-source (GPLv3) implementation of an IEC 61850 client and server library implementing the protocols MMS, GOOSE and SV. It is implemented in C (according to the C99 standard) to provide maximum portability. It can be used to implement IEC 61850 compliant client and server applications on embedded systems and PCs running Linux, Windows, and MacOS. Included is a set of simple example applications that can be used as a starting point to implement own IEC 61850 compliant devices or to communicate with IEC 61850 devices. The library has been successfully used in many commercial software products and devices.

For commercial projects licenses and support is provided by MZ Automation GmbH. Please contact [email protected] for more details on licensing options.

Features

The library support the following IEC 61850 protocol features:

  • MMS client/server, GOOSE (IEC 61850-8-1)
  • Sampled Values (SV - IEC 61850-9-2)
  • Support for buffered and unbuffered reports
  • Online report control block configuration
  • Data access service (get data, set data)
  • online data model discovery and browsing
  • all data set services (get values, set values, browse)
  • dynamic data set services (create and delete)
  • log service ** flexible API to connect custom data bases ** comes with sqlite implementation
  • MMS file services (browse, get file, set file, delete/rename file) ** required to download COMTRADE files
  • Setting group handling
  • Support for service tracking
  • GOOSE and SV control block handling
  • TLS support
  • C and C#/.NET API

Examples

The examples are built automatically when CMake is used to build the library.

NOTE: Most examples are intended to show a specific function of the library. They are designed to show this function as simple as possible and may miss error handling that has to be present in real applications!

Building and running the examples with the provided makefiles

In the project root directory type

make examples

If the build succeeds you can find a few binary files in the projects root directory. You can also find a binary version of the library ("libiec61850.a") in the "build" directory.

Run the sample applications in the example folders. E.g.:

cd examples/server_example_basic_io
sudo ./server_example_basic_io

on the Linux command line.

You can test the server examples by using a generic client or the provided client example applications.

Building the library with TLS support

Download, unpack, and copy mbedtls-2.28 into the third_party/mbedtls folder.

NOTE: The current version support mbedtls version 2.28. When you download the source archive from https://tls.mbed.org/ you have to rename the extracted folder to "mbedtls-2.28".

In the main libiec61850 folder run

make WITH_MBEDTLS=1

When using CMake the library is built automatically with TLS support when the folder third_party/mbedtls/mbedtls-2.28 is present.

Installing the library and the API headers

The make and cmake build scripts provide an install target. This target copies the API header files and the static library to a single directory for the headers (INSTALL_PREFIX/include) and the static library (INSTALL_PREFIX/lib). With this feature it is more easy to integrate libiec61850 in an external application since you only have to add a simple include directory to the build tool of your choice.

This can be invoked with

make install

The default install directory for the make build script is ".install".

You can modify this by setting the INSTALL_PREFIX environment variable (e.g.):

make INSTALL_PREFIX=/usr/local install

For the cmake build script you have to provide the CMAKE_INSTALL_PREFIX variable

Building on windows with GOOSE support

To build the library and run libiec61850 applications with GOOSE support on Windows (7/8/10) the use of a third-party library (winpcap) is required. This is necessary because current versions of Windows have no working support for raw sockets. You can download winpcap here (http://www.winpcap.org).

  1. Download and install winpcap. Make sure that the winpcap driver is loaded at boot time (you can choose this option at the last screen of the winpcap installer).
  2. Reboot the system (you can do this also later, but you need to reboot or load the winpcap driver before running any llibiec61850 applications that use GOOSE).
  3. Download the winpcap developers pack from here (http://www.winpcap.org/install/bin/WpdPack_4_1_2.zip)
  4. Unpack the zip file. Copy the folders Lib and Include from the WpdPack directory in the third_party/winpcap directory of libiec61850

Building with the cmake build script

With the help of the cmake build script it is possible to create platform independent project descriptions and let cmake create specific project or build files for other tools like Make or Visual Studio.

If you have cmake installed fire up a command line (cmd.exe) and create a new subdirectory in the libiec61850 folder. Change to this subdirectory. Then you can invoke cmake. As an command line argument you have to supply a "generator" that is used by cmake to create the project file for the actual build tool (in our case Visual Studio 2015).

cmake -G "Visual Studio 14 2015" ..

will instruct cmake to create a "solution" for Visual Studio 2015. The resulting project files will be 32 bit.

To build 64 bit libraries the "Win64" generator option has to be added.

cmake -G "Visual Studio 14 2015 Win64" ..

Note: The ".." at the end of the command line tells cmake where to find the main build script file (called CMakeLists.txt). This should point to the folder libiec61850 which is in our case the parent directory (..).

Depending on the system you don't have to provide a generator to the cmake command.

To select some configuration options you can use ccmake or cmake-gui.

For newer version of Visual Studio you can use one of the following commands (for 64 bit builds):

For Visual Studio 2017:

cmake -G "Visual Studio 15 2017 Win64" ..

For Visual Studio 2019 (new way to specify the x64 platform):

cmake -G "Visual Studio 16 2019" .. -A x64

Using the log service with sqlite

The library provides support for the IEC 61850 log service. It provides an abstract interface for a logging database. Included is a driver for using sqlite for logging. This driver can be seen as an example on how to use the abstract logging interface.

You can use the driver by including the src/logging/drivers/sqlite/log_storage_sqlite.c file into your application build.

On Ubuntu Linux (and simpilar Linux distributions) it is enough to install the sqlite dev packages from the standard repository. For other OSes (e.g. Windows) and cross-compiling it is recomended to download the amalagation source code (from https://www.sqlite.org/download.html) of sqlite and copy them to the third_party/sqlite folder.

On windows the cmake skript will detect the sqlite source code and also creates the example project for logging.

C# API

A C#/.NET wrapper and examples and Visual Studio/MonoDevelop project files can be found in the dotnet folder. The examples and the C# wrapper API can be build and run on .NET or Mono.

Experimental Python bindings

The experimental Python binding can be created using SWIG with cmake.

To enable the bindings you have to select the phyton configuration option with ccmake of cmake-gui.

We don't provide any support for the Python bindings!

Commercial licenses and support

Support and commercial license options are provided by MZ Automation GmbH. Please contact [email protected] for more details.

Contributing

If you want to contribute to the improvement and development of the library please send me comments, feature requests, bug reports, or patches. For more than trivial contributions I require you to sign a Contributor License Agreement. Please contact [email protected].

Please don't send pull requests before signing the Contributor License Agreement! Such pull requests may be silently ignored.

libiec61850's People

Contributors

aaribaud avatar amoorcroft-nortech avatar andy1547 avatar cedricboudinet avatar cngkaygusuz avatar davideandreuzza avatar davidkorczynski avatar fedepell avatar jamieslome avatar kiralypeterprolan avatar mbourhis avatar mzillgith avatar rm5248 avatar romainnaour avatar stv0g avatar vermeulenthi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libiec61850's Issues

server_example1 missing

The following directory is missing in the latest version of the repository, but it is mentioned in the Readme.md

cd examples/server_example1
sudo ./server_example1

[C#] Control Operate (MMS_FLOAT) (CAUSE_UNKNOWN)

Hi,

I have already been able to use the operation method on boolean, integer and bit_string control points.
I am trying to use the command operate for float point. But, I am getting an error.

Model: DIRECT_NORMAL
image

[Code]

IedConnection connection = new IedConnection();
connection.Connect("192.168.0.108", 102);

ControlObject control = connection.CreateControlObject("Xtorm_ServerLogicalDevice/YEFN1.ColPos");
control.SetOrigin("192.168.0.249", OrCat.REMOTE_CONTROL);

MmsValue value = new MmsValue(1.0f);
bool isOperated = control.Operate(value);

LastApplError result = control.GetLastApplError();

The Operate method returns: false
image

Wireshark:
image

image

image

image

Am I doing something wrong?

Embedded environment, multi-client connection, system deadlock.

Problem description:
I used ieclib61850 1.2.1 to run the server in an embedded Linux environment (arm bigendian). The first client can connect normally. Connect to the second client and the system will deadlock (the console will not respond). At this point, disconnect the first client, the second client will be immediately connected, and the system will return to normal.

Configuration:
Stack_config.h adds a macro definition of the bigendian:
# define PLATFORM_IS_BIGENDIAN 1

The rest are default and unchanged. The key parts are as follows:

/* Maximum MMS PDU SIZE - default is 65000 */
# define CONFIG_MMS_MAXIMUM_PDU_SIZE 120000

/ *
* Enable single threaded mode
*
* 1 ==> server runs in single threaded mode (a single thread for the server and all client connections)
* 0 => server runs in multi-threaded mode (one thread for each connection and)
* one server background thread)
* /
# define CONFIG_MMS_SINGLE_THREADED 0

/ *
* Optimize stack for threadless oper-don't semt use aphores
*
* WARNING: If set to 1 normal single- and multi-threaded server are no longer working!
* /
# define CONFIG_MMS_THREADLESS_STACK 0

/* number of concurrent MMS client connections the server accepts, -1 for no limit */
# define CONFIG_MAXIMUM_TCP_CLIENT_CONNECTIONS 5

/* activate TCP keep alive mechanism. 1-> activate */
# define CONFIG_ACTIVATE_TCP_KEEPALIVE 1

/* time (in s) between last message and first keepalive message */
# define CONFIG_TCP_KEEPALIVE_IDLE 5

After that, we kept alive messages if no ack received */
# define CONFIG_TCP_KEEPALIVE_INTERVAL 2

/* number of not missing keepalive responses until socket is considered dead */
# define CONFIG_TCP_KEEPALIVE_CNT 2

/* maximum COTP (ISO 8073) TPDU size-valid range is 1024-8192 */
# define CONFIG_COTP_MAX_TPDU_SIZE 8192

/* timeout while reading from TCP stream in ms */
# define CONFIG_TCP_READ_TIMEOUT_MS 1000

/* Ethernet interface ID for GOOSE and SV */
# define CONFIG_ETHERNET_INTERFACE_ID "eth0"

Cause analysis:
I compared the debug print for the first and second client connections and found that the Socket_read function always returns 0 for the second client connection. That is, "recv(self->fd, buf, size, MSG_DONTWAIT)" always returns -1, and errno = EAGAIN. Causes the CotpConnection_readToTpktBuffer() function to return TPKT_WAITING all the time, system deadlock.
This is not the case with the previous version of 0.7.6. A comparison of socket_linux.c shows that version 0.7.6 USES "read(self->fd, buf, size)" here.
So, when I change the recv to read, I can connect multiple clients. In addition, I tried to change this to block mode "recv(self->fd, buf, size, MSG_WAITALL)", which also solves this problem.

The first time I mentioned a bug on github, if there is anything wrong, please give me more advice. ^_^

Memory growth when using Report

Hi @mzillgith

I was testing report. I realized that some IED can disable a report without a disconnection. I need to constantly check if the report is enabled. I noticed a memory growth while checking if the report is enabled. This occurs with or without receiving reports. Is this way to verify and enable report correct?

while (running)
{
	ReportControlBlock report = connection.GetReportControlBlock(address);
	report.GetRCBValues();

	bool isReportEnabled = report.GetRptEna();

	if (!isReportEnabled)
	{
		//var a = report.GetOptFlds();
		//var b = report.GetTrgOps();
		//var c = report.GetIntgPd();
		//var d = report.GetGI();
		//var e = report.GetPurgeBuf();
		//var f = report.GetResv();

		//report.SetOptFlds();
		//report.SetTrgOps();
		//report.SetEntryID();

		report.InstallReportHandler(ReportHandler, point);
		report.SetRptEna(true);
		report.SetRCBValues();
	}
}  

I was also thinking of using the method connection.ReadValue instead of report.GetRCBValues to check if RptEna attribute is true or false.

Can you check if a memory leak is occurring when methods are called?

Obs: Wireshark log attached.

wireshark.zip

Unnecessary delay in SVReceiver

The SVReceive loop uses Thread_sleep() to wait 1 millisecond in case no packet is currently in the input buffer. This time is lost and can increase the worst case latency to receive a SV packet to 1 ms.

This is mainly because Ethernet_receivePacket() does not block and immediately returns using the MSG_DONTWAIT flag.

I propose to add a poll() / select() compatible interface.

Failed to generate the DLL

When generating the project iec61850 tells me: Can not open file include: 'inttypes.h': No such file or directory.

What do I do wrong?

Delete

I was wrong about the doubt. Please, delete.

ReportControl and rptID is empty

Hi Michael,

I made some testing together with Anvil from Triangle MicroWorks (IEC61850 Test Suite). There is one case file TMWSample.icd where prtID is not set inside ReportControl.
You can register as client the reports but the callback function is not executed.

I found small problem in private_IedConnection_handleReport(IedConnection self, MmsValue* value)
(file client_report.c)


while (element != NULL) {
    ClientReport report = (ClientReport) element->data;
    char repID[129];
    char* rptId = report->rptId;

    if (rptId == NULL || (rptId && (strlen(rptId)== 0)))
    {
        strcpy(repID, report->rcbReference);
        StringUtils_replace(repID, '.', '$');
        rptId = repID;
    }


    if (strcmp(MmsValue_toString(rptIdValue), rptId) == 0) {
        matchingReport = report;
        break;
    }

    element = LinkedList_getNext(element);
}

More or less rptId pointer was not NULL but the string was empty.
Regards,

Boris

Problem testing Goose Publisher/Subscriber examples on Ubuntu 16.04 LTS

Hi!

I was able to compile the goose_publisher and goose_subscriber under the examples. When I run the programs, I don't see the subscriber receiving any messages. I do see a three packets generated by the publisher on the interface.

Could you kindly point to how to test if the subscriber is working correctly? There is nothing printed on the shell and I don't see any log files in its folder.

Thanks,

Rakesh

Harmonisation of Sampled Values subscriber / publisher

Hi,

I noticed that the API of Sampled Values subscriber and publisher both use ASDU's as their central entity for storing exchanged measurements.

Both APIs have their own implementations of this data structure: SVClientASDU vs SV_ASDU.

I also noticed that the publisher uses a different naming scheme than the subscriber: SampledValuesPublisher vs SVSubscriber.

I would volunteer to clean up the API by:

  • renaming the publisher code to use the SV prefix
  • Combine the two implementations of Sampled Values ASDUs into one

I would like to know what other users of the library think about these changes and whether they might be merged?

Renaming the functions will break ABI compatibility.

IedConnection_writeObject(...) won't work

I'm running iec61850_client_example1 and server_example_basic_io.

IedConnection_writeObject(...) always outputs

failed to write simpleIOGenericIO/GGIO1.NamPlt.vendor!

Is it supposed to happen?

I followed the client tutorial but I can't get IedConnection_writeObject(...) to work either. Am I missing something?

[C#] [Windows] Project Platform Target only works on x86 ?

Hi,

I realized that if the project platform target is not x86.

image

I get the exception:

image

System.BadImageFormatException was unhandled HResult=-2147024885 Message=An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B) Source=iec61850dotnet StackTrace: at IEC61850.Client.IedConnection.IedConnection_create() at IEC61850.Client.IedConnection..ctor() in C:\libiec61850-master\dotnet\IEC61850forCSharp\IEC61850ClientAPI.cs:line 410 at example1.MainClass.Main(String[] args) in C:\libiec61850-master\dotnet\example1\Main.cs:line 13 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

I created C++ library by command: cmake -G "Visual Studio 14" C:\libiec61850-master

Am I doing something wrong? Do I have to configure some platform variable?

Timestamp change and goose publishing

Hello,
I have noticed a strange behaviour during the transmission of goose messages (from a server using libiec61850), when only timestamp changes in the referenced dataset. It happens the following (output printed from the receiving server using libiec61850, but wireshark shows the same):

received GOOSE from gcb: MODULO1/LLN0$GO$gcb_Segnalaz
stNum: 8, sqNum: 0, timeToLive: 1500, timestamp: 1496921282.235
{false,0000000000000,20170608105249.383Z},{false,0000000000000,20170608105249.735Z},{false,0000000000000,20170608105249.696Z},{false,0000000000000,20170608105249.545Z},{true,0000000000000,20170608112758.848Z},{false,0000000000000,20170608105249.795Z},{false,0000000000000,20170608105249.236Z},{false,0000000000000,
19700101000000.000Z},{false,0000000000000,20170608105249.151Z},{false,0000000000000,20170608105249.844Z},{false,0000000000000,2017060
8105249.668Z}}

received GOOSE from gcb: MODULO1/LLN0$GO$gcb_Segnalaz
stNum: 8, sqNum: 1, timeToLive: 1500, timestamp: 1496921282.235
{false,0000000000000,20170608105249.383Z},{false,0000000000000,20170608105249.735Z},{false,0000000000000,20170608105249.696Z},{false,0000000000000,20170608105249.545Z},{true,0000000000000,20170608112802.704Z},{false,0000000000000,20170608105249.795Z},{false,0000000000000,20170608105249.236Z},{false,0000000000000,
19700101000000.000Z},{false,0000000000000,20170608112802.755Z},{false,0000000000000,20170608105249.844Z},{false,0000000000000,2017060
8105249.668Z}}

As you can see the stNum remains the same but there are some value change (timestamp change).
The standard IEC 61850-7-2, part 18.2.3 says: "A GOOSE message shall at least be sent each time when a value from one or more members referenced by the data-set change". It does not mention the fact that the data attribute must have dchg or qchg set to true. In my publisher server CID, in fact, the timestamps don't have any trigger option specified.

BufferedRCBs error

  1. compile with cygwin + arm-mingw32ce-gcc (v0.59.1) for WinCE.
  2. unrecognized command line option "-mno-unaligned-access", so unaligned access on arm(arm926ej-s).
  3. the buffer report on the iedserver is enabled by the client.
  4. error in reporting.c/sendNextReportEntry()/ add data set value elements/ MmsValue_getSizeInMemory()/case MMS_ARRAY case MMS_STRUCTURE /self->value.structure.components[i] and program exit.

Some compiler warnings

libiec61850_1.2.0/src/mms/iso_acse/acse.c: In function 'parseAarePdu':
libiec61850_1.2.0/src/mms/iso_acse/acse.c:229:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (DEBUG_ACSE)
       ^~
libiec61850_1.2.0/src/mms/iso_acse/acse.c:232:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    bufPos += len;
    ^~~~~~
libiec61850_1.2.0/src/mms/iso_mms/common/mms_value.c: In function 'MmsValue_setElement':
libiec61850_1.2.0/src/mms/iso_mms/common/mms_value.c:1905:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
     if ((complexValue->type != MMS_ARRAY) && (complexValue->type != MMS_STRUCTURE))
     ^~
libiec61850_1.2.0/src/mms/iso_mms/common/mms_value.c:1908:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  if ((index < 0) || (index >= complexValue->value.structure.size))
  ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c: In function 'mmsClient_parseDeleteNamedVariableListResponse':
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:132:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (invokeId != NULL)
       ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:135:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
    ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c: In function 'mmsClient_parseGetNamedVariableListAttributesResponse':
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:269:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (invokeId != NULL)
       ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:272:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
    ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c: In function 'mmsClient_parseDefineNamedVariableResponse':
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:439:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (invokeId != NULL)
       ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_named_variable_list.c:442:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
    ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_connection.c: In function 'mmsIsoCallback':
ibiec61850_1.2.0/src/mms/iso_mms/client/mms_client_connection.c:985:25: warning: 'invokeId' may be used uninitialized in this function [-Wmaybe-uninitialized]
                         mmsClient_handleFileOpenRequest(self, buf, bufPos, bufPos + length, invokeId, response);
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_get_var_access.c: In function 'mmsClient_parseGetVariableAccessAttributesResponse':
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_get_var_access.c:144:6: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
      if (invokeId != NULL)
      ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_get_var_access.c:147:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present ==
   ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_read.c: In function 'mmsClient_parseReadResponse':
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_read.c:262:6: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
      if (invokeId != NULL)
      ^~
libiec61850_1.2.0/src/mms/iso_mms/client/mms_client_read.c:265:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   if (mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present == ConfirmedServiceResponse_PR_read) {
   ^~
libiec61850_1.2.0/src/mms/iso_mms/server/mms_get_namelist_service.c: In function 'mmsServer_handleGetNameListRequest':
libiec61850_1.2.0/src/mms/iso_mms/server/mms_get_namelist_service.c:531:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (DEBUG_MMS_SERVER)
       ^~
libiec61850_1.2.0/src/mms/iso_mms/server/mms_get_namelist_service.c:534:4: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
    LinkedList nameList = getNameListDomainSpecific(connection, domainSpecificName);
    ^~~~~~~~~~
libiec61850_1.2.0/src/mms/iso_mms/server/mms_server_connection.c: In function 'MmsServerConnection_parseMessage':
libiec61850_1.2.0/src/mms/iso_mms/server/mms_server_connection.c:555:6: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
      if (DEBUG_MMS_SERVER)
      ^~
libiec61850_1.2.0/src/mms/iso_mms/server/mms_server_connection.c:557:3: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   break;
   ^~~~~
libiec61850_1.2.0/src/iec61850/client/client_control.c: In function 'ControlObjectClient_create':
libiec61850_1.2.0/src/iec61850/client/client_control.c:165:13: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
             if (MmsVariableSpecification_getType(ctlVal) == MMS_STRUCTURE)
             ^~
libiec61850_1.2.0/src/iec61850/client/client_control.c:168:7: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
       MmsVariableSpecification* operTm = MmsVariableSpecification_getNamedVariableRecursive(oper, "operTm");
       ^~~~~~~~~~~~~~~~~~~~~~~~
libiec61850_1.2.0/src/iec61850/client/client_control.c: In function 'ControlObjectClient_operate':
libiec61850_1.2.0/src/iec61850/client/client_control.c:352:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
     if (self->hasCtlNum)
     ^~
libiec61850_1.2.0/src/iec61850/client/client_control.c:355:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  operParameters = MmsValue_createEmptyStructure(operElementCount);
  ^~~~~~~~~~~~~~
libiec61850_1.2.0/src/goose/goose_receiver.c: In function 'GooseReceiver_tick':
libiec61850_1.2.0/src/goose/goose_receiver.c:598:41: warning: 'confRev' may be used uninitialized in this function [-Wmaybe-uninitialized]
             matchingSubscriber->confRev = confRev;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
libiec61850_1.2.0/src/goose/goose_receiver.c:463:14: note: 'confRev' was declared here
     uint32_t confRev;
              ^~~~~~~

Support for R-GOOSE and R-SV (IEC TR 61850-90-5)

IEC TR 61850-90-5 introduces a mechanism for transfer of digital states and time synchronized phasor measurement data over wide-area networks between Phasor Measurement Units (PMUs), Phasor Data Concentrators (PDCs) and WAMPAC applications in the context of IEC 61850.

From: Interpreting and Implementing IEC 61850-90-5 Routed-Sampled Value and Routed-GOOSE Protocols for IEEE C37.118.2 Compliant Wide-Area Synchrophasor Data Transfer

For our research we implemented R-GOOSE in a private fork of libiec61850.
We would like to know if there is interest in merging support for this technical report (TR 61850-90-5) into libiec61850.

Disclaimer: we are not related to the original authors of the above mentioned paper.

2 events happened in a second, only one is reported

Hi here,

i am using the buffer report function. something issue happened.
when two events happened in a second, only one is recorded in the report buffer,
if the two events happen more then a second interval, there are two record in the report buffer.
could you analysis this ?

How to enable keepalive ?

I use libiec61850 in Linux, I wonder how to enable the keepalive,
In stack_config.h , there is a define:
#define CONFIG_ACTIVATE_TCP_KEEPALIVE 1
when TcpServerSocket_create or Socket_connect is called, the above define will be judged, if it is defined activateKeepAlive will be called.
But in socket_linux.c, in the activateKeepAlive function, there are two defines SO_KEEPALIVE and TCP_KEEPCNT,
Do I need to define them by myself?

static void
activateKeepAlive(int sd)
{
#if defined SO_KEEPALIVE
    int optval;
    socklen_t optlen = sizeof(optval);

    optval = 1;
    setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen);

#if defined TCP_KEEPCNT
    optval = CONFIG_TCP_KEEPALIVE_IDLE;
    setsockopt(sd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen);

    optval = CONFIG_TCP_KEEPALIVE_INTERVAL;
    setsockopt(sd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen);

    optval = CONFIG_TCP_KEEPALIVE_CNT;
    setsockopt(sd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen);
#endif /* TCP_KEEPCNT */

#endif /* SO_KEEPALIVE */
}

[C#/C++] BITSTRING Converter

Hi,

I am testing the method (C#): BitStringFromUInt32
It calls (C++) MmsValue_setBitStringFromInteger(valueReference, intValue);

The simple code:

MmsValue value = MmsValue.NewBitString(2);

value.BitStringFromUInt32(0);
Console.WriteLine(value);

value.BitStringFromUInt32(1);
Console.WriteLine(value);

value.BitStringFromUInt32(2);
Console.WriteLine(value);

value.BitStringFromUInt32(3);
Console.WriteLine(value);

Returns:

00 (0)
10 (1)
01 (2)
11 (3)

image

Binary table:

00 (0)
01 (1)
10 (2)
11 (3)

The results should be the same as the binary table. Is this conversion wrong?

How to deal with EntryID of ClientReportControlBlock?

I created a client and wanted to receive reports form an IED(I use IEDSCout as my Simulator).
but everytime i restart my client, I will receviced the whole reports buffered by the server.
I followed the method search from internet which says writing the entryId , but it does not work,
my code is as follows, can you help me?

here are the tissues from http://iec61850.tissue-db.com:
BRCB entryID
EntryID needs clarification

/*
 * client_example1.c
 *
 * This example is intended to be used with server_example3 or server_example_goose.
 */

#include "iec61850_client.h"

#include "stack_config.h"

#include "ied_connection_private.h"

#include "libiec61850_platform_includes.h"
#include <stdlib.h>
#include <stdio.h>

#include "hal_thread.h"
void
ClientReportControlBlock_setEntryId_ex(ClientReportControlBlock self, MmsValue* entryId)
{
    if (self->entryId != NULL) {
        bool r = MmsValue_update(self->entryId, entryId);
        printf("ClientReportControlBlock_setEntryId_ex MmsValue_update:%d\n",r);
    }
    else {
        if (MmsValue_getType(entryId) != MMS_OCTET_STRING) {
            if (DEBUG_IED_CLIENT)
                printf("IED_CLIENT: ClientReportControlBlock_setEntryId invalid argument type\n");
        }
        else
            self->entryId = MmsValue_clone(entryId);
    }
}
void
reportCallbackFunction(void* parameter, ClientReport report)
{
    MmsValue* dataSetValues = ClientReport_getDataSetValues(report);
	char* reportId = ClientReport_getRptId(report);
	uint16_t reportSeqNum = ClientReport_getSeqNum(report);
	printf("reportId %s,reportSeqNum %d\n",reportId,reportSeqNum);
    //printf("received report for %s\n", ClientReport_getRcbReference(report));
	MmsValue * entryId = ClientReport_getEntryId(report);	
	if (entryId) {
		char * buf = (char*)MmsValue_getOctetStringBuffer(entryId);
		printf("Entry ID: %02hhX-%02hhX-%02hhX %02hhX-%02hhX-%02hhX-%02hhX-%02hhX\n", buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
	}
    /*int i;
    for (i = 0; i < 4; i++) {
        ReasonForInclusion reason = ClientReport_getReasonForInclusion(report, i);

        if (reason != IEC61850_REASON_NOT_INCLUDED) {
            printf("  GGIO1.SPCSO%i.stVal: %i (included for reason %i)\n", i,
                    MmsValue_getBoolean(MmsValue_getElement(dataSetValues, i)), reason);
        }
    }*/
}

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

    char* hostname;
    int tcpPort = 102;

    if (argc > 1)
        hostname = argv[1];
    else
        hostname = "192.168.25.25";

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

    IedClientError error;

    IedConnection con = IedConnection_create();

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

    if (error == IED_ERROR_OK) {

        IedConnection_getServerDirectory(con, &error, false);

        /* read an analog measurement value from server */
        MmsValue* value = IedConnection_readObject(con, &error, "TEMPLATELD0/LLN0.ActSG.mag.i", IEC61850_FC_MX);

        if (value != NULL) {
            int32_t fval = MmsValue_toInt32(value);
            printf("read int32 value: %d\n", fval);
            MmsValue_delete(value);
        }

        /* write a variable to the server */
        value = MmsValue_newVisibleString("test");
        IedConnection_writeObject(con, &error, "TEMPLATELD0/LPHD1.PhyNam.vendor", IEC61850_FC_DC, value);

        if (error != IED_ERROR_OK)
            printf("failed to write TEMPLATELD0/LPHD1.PhyName.vendor!\n");
        else
        	printf("succeed to write TEMPLATELD0/LPHD1.PhyName.vendor test!\n");

        MmsValue_delete(value);


        /* read data set */
        ClientDataSet clientDataSet = IedConnection_readDataSetValues(con, &error, "TEMPLATELD0/LLN0.dsWarning", NULL);

        if (clientDataSet == NULL)
            printf("failed to read dataset TEMPLATELD0/LLN0.dsWarning\n");
        else
        	printf("succeed to read dataset TEMPLATELD0/LLN0.dsWarning\n");
		
        /* Read RCB values */
        ClientReportControlBlock rcb =
                IedConnection_getRCBValues(con, &error, "TEMPLATELD0/LLN0.BR.brcbAlarm01", NULL);

        bool rptEna = ClientReportControlBlock_getRptEna(rcb);
        printf("RptEna = %i\n", rptEna);
        
		/* setEntryId */
        char buf[8] = {00,00,00,00,00,00,0x00,0x16};
		MmsValue *entryId = MmsValue_newOctetString(8, 8); 
		MmsValue_setOctetString(entryId, (uint8_t*)buf, 8);
		ClientReportControlBlock_setEntryId_ex(rcb, entryId);
		
        /* Install handler for reports */
        IedConnection_installReportHandler(con, "TEMPLATELD0/LLN0.BR.brcbAlarm01", ClientReportControlBlock_getRptId(rcb), reportCallbackFunction, rcb);
        
		/* Set trigger options and enable report */
        ClientReportControlBlock_setTrgOps(rcb, TRG_OPT_DATA_UPDATE | TRG_OPT_INTEGRITY | TRG_OPT_GI);
        ClientReportControlBlock_setRptEna(rcb, true);
        ClientReportControlBlock_setIntgPd(rcb, 30000);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA | RCB_ELEMENT_TRG_OPS | RCB_ELEMENT_INTG_PD, true);
		
        if (error != IED_ERROR_OK)
            printf("report activation failed (code: %i)\n", error);
        else
        	printf("report activation succeed (code: %i)\n", error);	

        //Thread_sleep(1000);

        /* trigger GI report */
        ClientReportControlBlock_setGI(rcb, true);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_GI, true);

        if (error != IED_ERROR_OK)
            printf("Error triggering a GI report (code: %i)\n", error);

        Thread_sleep(1000000);
		
        /* disable reporting */
        ClientReportControlBlock_setRptEna(rcb, false);
        IedConnection_setRCBValues(con, &error, rcb, RCB_ELEMENT_RPT_ENA, true);

        if (error != IED_ERROR_OK)
            printf("disable reporting failed (code: %i)\n", error);
        else
        	printf("disable reporting succeed (code: %i)\n", error);
		
        ClientDataSet_destroy(clientDataSet);

        ClientReportControlBlock_destroy(rcb);

        close_connection:

        IedConnection_close(con);
    }
    else {
        printf("Failed to connect to %s:%i\n", hostname, tcpPort);
    }

    IedConnection_destroy(con);
}


[C#] [ReportControlBlock] The methods (SetTrgOps / SetOptFlds) throwing System.AccessViolationException

Hi,

I am testing the reports. I used the sample projects on dotnet solution

image

image

System.AccessViolationException was unhandled HResult=-2147467261 Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt. Source=iec61850dotnet StackTrace: at IEC61850.Client.ReportControlBlock.ClientReportControlBlock_setTrgOps(IntPtr self, Int32 trgOps) at IEC61850.Client.ReportControlBlock.SetTrgOps(TriggerOptions trgOps) at Debugger.IEC61850v2.Program.Main(String[] args) in C:\Tests\IEC61850\Program.cs:line 118 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:

I realized that the exception is only thrown if the program executes the method GetRCBValues (Image 1 line 3). If this method is not executed. There is no exception and the command works perfectly.

It does not appear to be an error in communication or protocol. Since the SetRCBValues method is not even executed. I believe the problem is in the ReportControlBlock object.

Problem when generating model configuration file

When I run genconfig.jar, I get the following exception:

parse IED section ...
Exception in thread "main" java.lang.NumberFormatException: For input string: "0,01"
	at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
	at sun.misc.FloatingDecimal.parseFloat(Unknown Source)
	at java.lang.Float.parseFloat(Unknown Source)
	at java.lang.Float.<init>(Unknown Source)
	at com.libiec61850.scl.model.DataModelValue.<init>(DataModelValue.java:113)
	at com.libiec61850.scl.model.LogicalNode.parseDataAttributeNodes(LogicalNode.java:191)
	at com.libiec61850.scl.model.LogicalNode.parseSubDataInstances(LogicalNode.java:220)
	at com.libiec61850.scl.model.LogicalNode.<init>(LogicalNode.java:169)
	at com.libiec61850.scl.model.LogicalDevice.parseLogicalNodes(LogicalDevice.java:65)
	at com.libiec61850.scl.model.LogicalDevice.<init>(LogicalDevice.java:49)
	at com.libiec61850.scl.model.Server.<init>(Server.java:52)
	at com.libiec61850.scl.model.AccessPoint.<init>(AccessPoint.java:48)
	at com.libiec61850.scl.model.IED.<init>(IED.java:50)
	at com.libiec61850.scl.SclParser.parseIedSections(SclParser.java:240)
	at com.libiec61850.scl.SclParser.<init>(SclParser.java:89)
	at com.libiec61850.scl.SclParser.<init>(SclParser.java:102)
	at com.libiec61850.tools.DynamicModelGenerator.<init>(DynamicModelGenerator.java:62)
	at com.libiec61850.tools.DynamicModelGenerator.main(DynamicModelGenerator.java:454)

The problem is that my CID file contains some Vals of float DAIs that are initialized with the comma as a decimal separator, and the constructor of Java Float objects only accepts the dot as decimal separator.
I looked in the standard, and I only found this section in IEC61850-6 that describes the XML schema for the values:

<xs:complexType name="tVal">
   <xs:simpleContent>
      <xs:extension base="xs:normalizedString">
         <xs:attribute name="sGroup" type="xs:unsignedInt" use="optional"/>
      </xs:extension>
   </xs:simpleContent>
</xs:complexType>

It is not clear to me whether the comma separator is accepted or not. Is it possible to make the Java program more robust?

readObjectInternal() hangs occasionally reading mms value

Noticed that in dotnet project readObjectInternal() hangs (doesn't return) sometimes when reading eg. boolean value from IED. Read is executed but nothing related to client reading boolean value is shown in Wireshark. Then it just waits there forever.

iedconnection_readobject

How to utilize control operation for Python (SWIG)?

I've managed to build the lib for Python and now am using it to run a IEC 61850 server.
However SWIG was not able to adopt the control model callback "typedef ControlHandlerResult" in order to utilize the corresponding IedServer_setControlHandler().
The way I see it, there are two options to convert the callback function / typedefs via SWIG:

  1. Modifying the interface-file (*.i) and adding the callback.
  2. Modifying the C source code and rewriting the function.
    Anyway I'm struggling to find the correct solution to make the control operation available in Python, mainly because my skills in C are only very basic. Also my aim is to use the libIEC61850 in Python, since I'm connecting to different APIs via Python.

How can I utilize the control operation with Python?
Does anyone have a description on how to modify the interface file or the source code in order to utilize the control operation with Python?

Regards!

How convert a void *data in python?

I want find the LD name in python like this:

deviceList, error = iec61850.IedConnection_getLogicalDeviceList(con)
assert (error == iec61850.IED_ERROR_OK)
device = iec61850.LinkedList_getNext(deviceList)
while device:
    print device.data
    device = iec61850.LinkedList_getNext(device)

But 'device.data' is a SWIG void * obj, so result is:
<Swig Object of type 'void *' at 0x........>

I don't know how convert it in python, just modify the 'iec61850.i':

%module iec61850
%{
......
char* Prt2Char(void *prt)
{ return (char*)prt;}
%}
......
char* Prt2Char(void *prt);

then I try again like this:

......
while device:
    print iec61850.Prt2Char(device.data)
......

It's work, but I don't think is good way, does anyone have a better idea?

Is that possible to keep the events on buffered report ?

Everyday there are some events generate in my device, only when the client enable the buffered report the device will report events to client. But if power outage all there events will lost due to all the events was buffered in memory. Have any ways to avoid this situation ?

sv_subscriber is not working

hi
I use sv_publisher example and it works well - I can capture packets with wireshark/tcpdump, but sv_subscriber receives nothing - the callback handler is not called

How to associate values with data attribute names?

Is there an easy way to associate the LinkedList of IedConnection_getDataSetDirectory() to the ClientDataSet of IedConnection_readDataSetValues()?

Or even better, is there a way to associate each MMS Structure of MmsConnection_readVariable(Domain, LogicalNode) to the Linked List of MmsConnection_getDomainVariableNames(Domain)?

e.g.

# MmsConnection_getDomainVariableNames("ied1Example")
EVCT
...
EVCT$DC
EVCT$DC$Comm
EVCT$DC$Comm$id
...
EVCT$ST
EVCT$ST$Comm
EVCT$ST$Comm$func

# MmsConnection_readVariable("ied1Example", "EVCT")
{{{Function 1}},{{ID 1}},{{FunctionEvents,false,false,ied1Example/EVCT$FunctionDataset,0,0001000000,0,0,010000,0,false,}}}

The getDomainVariableNames prints the id reference first, but readVariable prints the func value first.

I want to avoid doing several calls for each data attribute and I can't figure out a way to automatically link the values from readVariable to the structure of getDomainVariableNames. Any suggestions?

Thanks!

Reporting behaviour in version 1.1.1

Hi,
I noticed a strange behaviour that was not present in version 1.0.
It occous when I use reporting in the client api, sometimes ( not always ) when the callback is called the :

MmsValue* dataSetValues = ClientReport_getDataSetValues(report);

gave me the previous (N-1) MmsValue, like it has not been correctly updated in memory.
The ClientReport_getSeqNum(report) gave me correct SeqNum, identical to IED Scout sniffer, but the mms values were not updated.
I confirm that everything worked perfectly on version 1.0

I tried to check differences in the libraries, but I have not found anything for now..

Has anybody seen something similar? Thanks a lot!

[Question] [C#] Connection

Hi,

I have doubts about connection.

1 - When the ConnectionClosedHandler method is called. Do I have to call some IedConnection method? Like (Abort, Release, Close and Dispose)

2 - When an IedConnectionException throws with IedClientError like (IED_ERROR_NOT_CONNECTED, IED_ERROR_CONNECTION_LOST, IED_ERROR_CONNECTION_REJECTED). Do I have to call some IedConnection method? Like (Abort, Release, Close and Dispose)

3 - We have 4 methods to close connection (Abort, Release, Close and Dispose). Can I call all methods? Is there a call order? Like (Release, Abort, Close, Dispose)

I read the documentation (http://libiec61850.com/csharp-api/class_i_e_c61850_1_1_client_1_1_ied_connection.html) about each method. However, I did not understand very well.

Control operate not working (ADD_CAUSE_NOT_SUPPORTED)

Hello,

This is a nice project and I am trying to use it.

I have this IED:

image

I am trying to operate a command:

            IedConnection iedConnection = new IedConnection();
            iedConnection.Connect("192.168.0.125", "102");

            switch (controlModel)
            {
                case ControlModel.STATUS_ONLY:
                    Console.WriteLine("Control is status-only!");
                    break;

                case ControlModel.DIRECT_NORMAL:
                case ControlModel.DIRECT_ENHANCED:
                    if (control.Operate(true))
                        Console.WriteLine("operated successfully!");
                    else
                        Console.WriteLine("operate failed!");
                    break;

                case ControlModel.SBO_NORMAL:
                case ControlModel.SBO_ENHANCED:
                    if (control.Operate(false))
                        Console.WriteLine("operated successfully!");
                    else
                        Console.WriteLine("operate failed!");

                    LastApplError error = control.GetLastApplError();

                    break;
            }

            iedConnection.Abort();
            iedConnection.Dispose();

I get error: ADD_CAUSE_NOT_SUPPORTED

What am I doing wrong?

Download a 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 for files in a sub-directory.
How do I pass the full path name to GetFile() method in order to download these files?

MmsVariableSpecification_getName

Hi Michael,

I am not able to get name from MmsVariableSpecification. It is always empty and I cannot find the code in the library where the name is assigned.

MmsVariableSpecification* var = IedConnection_getVariableSpecification(con, &error, dataAttributeReference, fc);
if(error != IED_ERROR_OK)
{
    printf("Failed to read Variable Specification (error code: %i)\n", error);
    return;
}
printf("Variable Name: %s\n", MmsVariableSpecification_getName(var));

Best Regards,
Boris

Reason code and DataSet members parameters missing in buffered report

  • when the "CUrrent index" parameter of dataset changed, the lib will generate an buffered report.
    but the strange is that sometimes client received an buffered report which missing the Reason code and DataSet members parameters.
    My understanding is: if no data changed should no buffered report was received.
    but see below log, there are 3 new report were received by client, the last one lost Reason code and DataSet members parameters, is there something wrong with the lib?

2018-05-04 09:01:12.878] [osgp-tst-03] [Thread-118] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:96 - newReport for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.887Z, sqNum: 0
2018-05-04 09:01:12.878] [osgp-tst-03] [Thread-118] WARN c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:100 - Buffer Overflow reported for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.887Z, sqNum: 0 - entries within the buffer may have been lost.
2018-05-04 09:01:12.878] [osgp-tst-03] [Thread-118] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@logReportDetails:277 - Report details for device KAI-002
RptId: evn_rpn
DataSetRef: SWDeviceGenericIO/LLN0.evn_rpn
ConfRev: null
BufOvfl: true
EntryId: none: [0, 0, 1, 99, 44, -12, 87, -9]
InclusionBitString: [true]
MoreSegmentsFollow: false
SqNum: 0
SubSqNum: null
TimeOfEntry: none: 1083704400887
(2018-05-04T21:00:00.887Z)
ReasonCodes:
0x40 (DataChange)
DataSet: SWDeviceGenericIO/LLN0.evn_rpn
DataSet members: 1
member: SWDeviceGenericIO/CSLC.EvnRpn [ST]
SWDeviceGenericIO/CSLC.EvnRpn.evnType: 2
SWDeviceGenericIO/CSLC.EvnRpn.swNum: 2
SWDeviceGenericIO/CSLC.EvnRpn.trgType: 2
SWDeviceGenericIO/CSLC.EvnRpn.swVal: true
SWDeviceGenericIO/CSLC.EvnRpn.trgTime: Fri May 04 09:01:02 UTC 2018
SWDeviceGenericIO/CSLC.EvnRpn.remark: CUrrent index:4
evnType: 2 = LIGHT_EVENTS_LIGHT_ON
swNum: 2 = get external index for switch 2
trgType: 2 = ad-hoc trigger
swVal: true = ON
trgTime: 2018-05-04T09:01:02.000Z
remark: CUrrent index:4

2018-05-04 09:01:12.879] [osgp-tst-03] [Thread-118] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:121 - Handle member SWDeviceGenericIO/CSLC.EvnRpn for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.887Z, sqNum: 0
2018-05-04 09:01:12.896] [osgp-tst-03] [Thread-120] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:96 - newReport for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.888Z, sqNum: 1
2018-05-04 09:01:12.896] [osgp-tst-03] [Thread-120] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@logReportDetails:277 - Report details for device KAI-002
RptId: evn_rpn
DataSetRef: SWDeviceGenericIO/LLN0.evn_rpn
ConfRev: null
BufOvfl: false
EntryId: none: [0, 0, 1, 99, 44, -12, 87, -8]
InclusionBitString: [true]
MoreSegmentsFollow: false
SqNum: 1
SubSqNum: null
TimeOfEntry: none: 1083704400888
(2018-05-04T21:00:00.888Z)
ReasonCodes:
0x40 (DataChange)
DataSet: SWDeviceGenericIO/LLN0.evn_rpn
DataSet members: 1
member: SWDeviceGenericIO/CSLC.EvnRpn [ST]
SWDeviceGenericIO/CSLC.EvnRpn.evnType: 2
SWDeviceGenericIO/CSLC.EvnRpn.swNum: 3
SWDeviceGenericIO/CSLC.EvnRpn.trgType: 2
SWDeviceGenericIO/CSLC.EvnRpn.swVal: true
SWDeviceGenericIO/CSLC.EvnRpn.trgTime: Fri May 04 09:01:03 UTC 2018
SWDeviceGenericIO/CSLC.EvnRpn.remark: CUrrent index:5
evnType: 2 = LIGHT_EVENTS_LIGHT_ON
swNum: 3 = get external index for switch 3
trgType: 2 = ad-hoc trigger
swVal: true = ON
trgTime: 2018-05-04T09:01:03.000Z
remark: CUrrent index:5

2018-05-04 09:01:12.896] [osgp-tst-03] [Thread-120] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:121 - Handle member SWDeviceGenericIO/CSLC.EvnRpn for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.888Z, sqNum: 1
2018-05-04 09:01:12.960] [osgp-tst-03] [Thread-121] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:96 - newReport for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.889Z, sqNum: 2
2018-05-04 09:01:12.960] [osgp-tst-03] [Thread-121] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@logReportDetails:277 - Report details for device KAI-002
RptId: evn_rpn
DataSetRef: SWDeviceGenericIO/LLN0.evn_rpn
ConfRev: null
BufOvfl: false
EntryId: none: [0, 0, 1, 99, 44, -12, 87, -7]
InclusionBitString: [false]
MoreSegmentsFollow: false
SqNum: 2
SubSqNum: null
TimeOfEntry: none: 1083704400889
(2018-05-04T21:00:00.889Z)
DataSet: SWDeviceGenericIO/LLN0.evn_rpn

2018-05-04 09:01:12.960] [osgp-tst-03] [Thread-121] WARN c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@newReport:111 - No dataSet members available for device: KAI-002, reportId: evn_rpn, timeOfEntry: 2018-05-04T21:00:00.889Z, sqNum: 2
2018-05-04 09:01:27.808] [osgp-tst-03] [Thread-122] INFO c.a.o.a.p.i.i.n.r.Iec61850ClientSSLDEventListener@associationClosed:370 - associationClosed() for device: KAI-002, IOException: Connection reset

client file requests with long name generate invalid encoding

Looks like bug is here in mms_client_files.c mmsclient_createFileDirectoryRequest

uint32_t confirmedRequestPduSize = 1 + 2 + 2 + invokeIdSize + 0; /// This line assumes 
                                                                 /// a fixed length octet for the 
                                                                 /// File dir tagged data
uint32_t parameterSize = 0;

if (fileSpecification)
    parameterSize += encodeFileSpecification(0xa0, fileSpecification, NULL, 0);
if (continueAfter)
    parameterSize += encodeFileSpecification(0xa1, continueAfter, NULL, 0);

This seems to happen elsewhere in this file as well.

IedServer_update*AttributeValue segmentation fault

When I try to update the value of a DataAttribute inside an Oper Object, the library goes into segmentation fault. Probably what I am trying to do is not so widely used, but could you consider not to crash the application?
Just to detail more my problem, let's assume I want to update a boolean ctlVal. The problem is inside IedServer_updateBooleanAttributeValue, when MmsValue_getBoolean is called.

running sampled values examples

Is there anywhere a guide to run the examples concerning the sampled values (publisher/subscriber). It would be great to me.

Since now, I have successfully built the library; I am using Ubuntu 16.04 and I have tried the examples
libiec61850/examples/iec61850_9_2LE_example
libiec61850/examples/iec6185_sv_client_example

These are logs:
log publisher
log subscriber

I presume that subscriber should receive SV, but It seams to stop on some access error.

Thank you in advance,
eng. Stefano Del Prete
research assistan
University of Campania.

SWIG. ClientReport object/InstallHandler

When I get reports using the C code from the client reporting example everything about works fine:

/* Configure the report receiver */
IedConnection_installReportHandler(con, 
                           "TEMPLATELD0/LLN0.BR.brcbMX0101", 
                            ClientReportControlBlock_getRptId(rcb), 
                            reportCallbackFunction,
                            (void*) dataSetDirectory);

But when I try to implement this example in for Python client --> I'm stucking in InstallReportHandler method:

iec61850.IedConnection_installReportHandler(con,
                                                "TEMPLATELD0/LLN0.BR.brcbMX0101",
                                                iec61850.ClientReportControlBlock_getRptId(rcb),
                                                MyCallbackFunction,
                                                dataSetDirectory
                                                )

and as a result of it is "Argument 4 of type ReportCallBackFunction" exception from wrapper.cxx parsing part,
If I use MyCallBackFunction() ---with brackets then It calls each time when IedConnection_installReportHandler calls

Issue.part 2:
as a result of it: In C-code it's easy to create and manipulate with ClientReport objects (from example too):

void reportCallbackFunction(void* parameter, ClientReport report)

but in iec61850.py there is only ClientReport methods that take this object as a parameter

If it not from issue-graded problem:
Can anyone provide any example for this "InstallHandler - Receive by event - Create and Read ClientReport object" chain

Thanks/Ivan

[C# API] CreateControlObject throws System.AccessViolationException on Dispose

Hi,

I realized that I get an error when I use the command IedConnection.Dispose() after ControlObject.CreateControlObject().

The error only occurs when I use ControlObject.CreateControlObject().
However, the command was executed successfully.

image
image

System.AccessViolationException was unhandled
HResult=-2147467261
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=iec61850dotnet
StackTrace:
at IEC61850.Client.ControlObject.ControlObjectClient_destroy(IntPtr self)
at IEC61850.Client.ControlObject.Finalize()
InnerException:

[sample code]

    public enum Dbpos
    {
        INTERMEDIATE_STATE = 0,
        OFF = 1,
        ON = 2,
        BAD_STATE = 3
    }

    public static void Main(string[] args)
    {
        string hostname = "192.168.0.125";
        int port = 102;

        IedConnection iedConnection = new IedConnection();

        try
        {
            iedConnection.Connect(hostname, port);

            Dbpos stVal = (Dbpos)iedConnection.ReadBitStringValue("IED7SJ63CTRL/Q0CSWI1.Pos.stVal", FunctionalConstraint.ST);
            Validity q = iedConnection.ReadQualityValue("IED7SJ63CTRL/Q0CSWI1.Pos.q", FunctionalConstraint.ST).GetValidity();
            DateTimeOffset t = MmsValue.MsTimeToDateTimeOffset(iedConnection.ReadTimestampValue("IED7SJ63CTRL/Q0CSWI1.Pos.t", FunctionalConstraint.ST).TimeInMilliseconds);

            bool ctlVal = false;

            switch (stVal)
            {
                case Dbpos.BAD_STATE:
                case Dbpos.INTERMEDIATE_STATE:
                    break;

                case Dbpos.OFF:
                    ctlVal = false;
                    break;

                case Dbpos.ON:
                    ctlVal = true;
                    break;
            }

            ControlObject control = iedConnection.CreateControlObject("IED7SJ63CTRL/Q0CSWI1.Pos");
            control.SetOrigin("192.168.0.100", OrCat.REMOTE_CONTROL);

            switch (control.GetControlModel())
            {
                case ControlModel.STATUS_ONLY:
                    break;

                case ControlModel.DIRECT_NORMAL:
                case ControlModel.DIRECT_ENHANCED:
                    Console.WriteLine(control.Operate(ctlVal) ? "Operated successfully!" : "Operate failed!");
                    break;

                case ControlModel.SBO_NORMAL:
                case ControlModel.SBO_ENHANCED:
                    if (control.SelectWithValue(ctlVal))
                    {
                        Console.WriteLine(control.Operate(ctlVal) ? "Operated successfully!" : "Operate failed!");
                    }
                    else
                        Console.WriteLine("Select failed!");
                    break;
            }

            LastApplError error = control.GetLastApplError();

            iedConnection.Abort();
        }
        catch (IedConnectionException ex)
        {
            Console.WriteLine("[IED ERROR: ({0}) {1}] {2}", (int)ex.GetIedClientError(), ex.GetIedClientError(), ex.Message);
        }
        finally
        {
            iedConnection.Dispose();
        }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.