Merge branch 'sv'

pull/6/head
Michael Zillgith 10 years ago
commit 365f105af1

@ -10,8 +10,8 @@ endif()
project(libiec61850)
set(LIB_VERSION_MAJOR "0")
set(LIB_VERSION_MINOR "8")
set(LIB_VERSION_PATCH "7")
set(LIB_VERSION_MINOR "9")
set(LIB_VERSION_PATCH "0")
# feature checks
include(CheckLibraryExists)
@ -59,6 +59,7 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}/config
src/common/inc
src/goose
src/sampled_values
src/hal/inc
src/iec61850/inc
src/iec61850/inc_private
@ -96,6 +97,7 @@ set(API_HEADERS
src/mms/inc/asn1_ber_primitive_value.h
src/goose/goose_subscriber.h
src/goose/goose_receiver.h
src/sampled_values/sv_subscriber.h
)
IF(WIN32)

@ -19,6 +19,7 @@ LIB_SOURCE_DIRS += src/mms/iso_mms/asn1c
LIB_SOURCE_DIRS += src/mms/iso_server
ifndef EXCLUDE_ETHERNET_WINDOWS
LIB_SOURCE_DIRS += src/goose
LIB_SOURCE_DIRS += src/sampled_values
endif
LIB_SOURCE_DIRS += src/iec61850/client
LIB_SOURCE_DIRS += src/iec61850/common
@ -52,6 +53,7 @@ LIB_INCLUDE_DIRS += src/mms/inc
LIB_INCLUDE_DIRS += src/mms/inc_private
LIB_INCLUDE_DIRS += src/hal/inc
LIB_INCLUDE_DIRS += src/goose
LIB_INCLUDE_DIRS += src/sampled_values
LIB_INCLUDE_DIRS += src/iec61850/inc
LIB_INCLUDE_DIRS += src/iec61850/inc_private
ifeq ($(HAL_IMPL), WIN32)
@ -92,6 +94,7 @@ LIB_API_HEADER_FILES += src/mms/inc/ber_integer.h
LIB_API_HEADER_FILES += src/mms/inc/asn1_ber_primitive_value.h
LIB_API_HEADER_FILES += src/goose/goose_subscriber.h
LIB_API_HEADER_FILES += src/goose/goose_receiver.h
LIB_API_HEADER_FILES += src/sampled_values/sv_subscriber.h
get_sources_from_directory = $(wildcard $1/*.c)
get_sources = $(foreach dir, $1, $(call get_sources_from_directory,$(dir)))

@ -23,6 +23,8 @@
#define DEBUG_MMS_SERVER 0
#define DEBUG_GOOSE_SUBSCRIBER 0
#define DEBUG_GOOSE_PUBLISHER 0
#define DEBUG_SV_SUBSCRIBER 0
#define DEBUG_HAL_ETHERNET 0
/* Maximum MMS PDU SIZE - default is 65000 */
#define CONFIG_MMS_MAXIMUM_PDU_SIZE 65000
@ -34,7 +36,7 @@
* 0 ==> server runs in multi-threaded mode (one thread for each connection and
* one server background thread )
*/
#define CONFIG_MMS_SINGLE_THREADED 0
#define CONFIG_MMS_SINGLE_THREADED 1
/*
* Optimize stack for threadless operation - don't use semaphores
@ -67,12 +69,14 @@
/* Ethernet interface ID for GOOSE and SV */
#define CONFIG_ETHERNET_INTERFACE_ID "eth0"
//#define CONFIG_ETHERNET_INTERFACE_ID "vboxnet0"
//#define CONFIG_ETHERNET_INTERFACE_ID "eth-f"
//#define CONFIG_ETHERNET_INTERFACE_ID "en0" // OS X uses enX in place of ethX as ethernet NIC names.
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
#define CONFIG_INCLUDE_GOOSE_SUPPORT 1
/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */
#define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 1
#ifdef _WIN32
/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */
@ -98,9 +102,14 @@
/* The number of GOOSE retransmissions after an event */
#define CONFIG_GOOSE_EVENT_RETRANSMISSION_COUNT 2
/* Define if GOOSE control block elements are writable (1) or read-only (0) */
#define CONFIG_GOOSE_GOID_WRITABLE 1
#define CONFIG_GOOSE_DATSET_WRITABLE 1
/* Define if GOOSE control block elements are writable (1) or read-only (0)
*
* WARNING: To be compliant with the IEC 61850-8-1 standard all GoCB elements
* but GoEna have to be read-only!
*
* */
#define CONFIG_GOOSE_GOID_WRITABLE 0
#define CONFIG_GOOSE_DATSET_WRITABLE 0
#define CONFIG_GOOSE_CONFREV_WRITABLE 0
#define CONFIG_GOOSE_NDSCOM_WRITABLE 0
#define CONFIG_GOOSE_DSTADDRESS_WRITABLE 0
@ -129,6 +138,9 @@
/* include support for IEC 61850 reporting services */
#define CONFIG_IEC61850_REPORT_SERVICE 1
/* support buffered report control blocks with ResvTms field */
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
/* The default buffer size of buffered RCBs in bytes */
#define CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE 65536
@ -141,7 +153,7 @@
/* default results for MMS identify service */
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
#define CONFIG_DEFAULT_MMS_MODEL_NAME "LIBIEC61850"
#define CONFIG_DEFAULT_MMS_REVISION "0.8.7"
#define CONFIG_DEFAULT_MMS_REVISION "0.9.0"
/* MMS virtual file store base path - where file services are looking for files */
#define CONFIG_VIRTUAL_FILESTORE_BASEPATH "./vmd-filestore/"

@ -71,6 +71,9 @@
/* Set to 1 to include GOOSE support in the build. Otherwise set to 0 */
#cmakedefine01 CONFIG_INCLUDE_GOOSE_SUPPORT
/* Set to 1 to include Sampled Values support in the build. Otherwise set to 0 */
#cmakedefine01 CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT
#ifdef _WIN32
/* GOOSE will be disabled for Windows if ethernet support (winpcap) is not available */

File diff suppressed because it is too large Load Diff

@ -1224,14 +1224,15 @@ namespace IEC61850
DATA_REFERENCE = 16,
BUFFER_OVERFLOW = 32,
ENTRY_ID = 64,
CONF_REV = 128
CONF_REV = 128,
ALL = 255
}
public enum Validity
{
GOOD = 0,
INVALID = 1,
RESERVED = 2,
RESERVED = 1,
INVALID = 2,
QUESTIONABLE = 3
}
@ -1322,6 +1323,16 @@ namespace IEC61850
EX = 11,
/** Control */
CO = 12,
/** Unicast SV */
US = 13,
/** Multicast SV */
MS = 14,
/** Unbuffered report */
RP = 15,
/** Buffered report */
BR = 16,
/** All FCs - wildcard value */
ALL = 99,
NONE = -1
}

@ -140,6 +140,12 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)]
static extern bool MmsValue_equals(IntPtr self, IntPtr otherValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsValue_newBinaryTime (bool timeOfDay);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsValue_setBinaryTime (IntPtr self, UInt64 timestamp);
internal MmsValue (IntPtr value)
{
@ -229,6 +235,26 @@ namespace IEC61850
return new MmsValue(newValue, true);
}
/// <summary>
/// Create a new MmsValue instance of type MMS_BINARY_TIME
/// </summary>
/// <returns>the new MmsValue instance.</returns>
/// <param name="largeFormat">If set to <c>true</c> large 6 byte format.</param>
public static MmsValue NewBinaryTime(bool largeFormat)
{
IntPtr newValue = MmsValue_newBinaryTime (largeFormat);
return new MmsValue (newValue, true);
}
/// <summary>
/// Sets the binary time.
/// </summary>
/// <param name="timestamp">Timestamp.</param>
public void SetBinaryTime(UInt64 timestamp) {
MmsValue_setBinaryTime (this.valueReference, timestamp);
}
internal IntPtr valueReference;
private bool responsableForDeletion;

@ -372,6 +372,8 @@ namespace IEC61850
IedConnection_setRCBValues (connection, out error, self, parametersMask, singleRequest);
resetSendFlags();
if (error != 0)
throw new IedConnectionException ("setRCBValues service failed", error);
@ -382,8 +384,6 @@ namespace IEC61850
InstallReportHandler(this.reportHandler, this.reportHandlerParameter);
}
}
resetSendFlags();
}
/// <summary>

@ -0,0 +1,28 @@
namespace reporting.Properties {
// This class allows you to handle specific events on the settings class:
// The SettingChanging event is raised before a setting's value is changed.
// The PropertyChanged event is raised after a setting's value is changed.
// The SettingsLoaded event is raised after the setting values are loaded.
// The SettingsSaving event is raised before the setting values are saved.
internal sealed partial class Settings {
public Settings() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
}
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
// Add code to handle the SettingChangingEvent event here.
}
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
// Add code to handle the SettingsSaving event here.
}
}
}

@ -18,8 +18,9 @@ add_subdirectory(iec61850_client_example4)
add_subdirectory(iec61850_client_example5)
add_subdirectory(iec61850_client_example_files)
add_subdirectory(iec61850_client_example_reporting)
add_subdirectory(goose_subscriber)
add_subdirectory(mms_client_example1)
add_subdirectory(mms_client_example2)
add_subdirectory(mms_client_example3)
add_subdirectory(mms_client_example4)
add_subdirectory(goose_subscriber)
add_subdirectory(sv_subscriber)

@ -25,6 +25,7 @@ EXAMPLE_DIRS += server_example_threadless
EXAMPLE_DIRS += server_example_setting_groups
EXAMPLE_DIRS += goose_subscriber
EXAMPLE_DIRS += goose_publisher
EXAMPLE_DIRS += sv_subscriber
EXAMPLE_DIRS += mms_utility
MODEL_DIRS += server_example1

@ -5,8 +5,6 @@ set(goose_subscriber_example_SRCS
IF(WIN32)
IF(WITH_WPCAP)
set_source_files_properties(${goose_subscriber_example_SRCS}
PROPERTIES LANGUAGE CXX)
add_executable(goose_subscriber_example
@ -17,8 +15,6 @@ target_link_libraries(goose_subscriber_example
iec61850
)
ENDIF(WITH_WPCAP)
ELSE(WIN32)
add_executable(goose_subscriber_example

@ -0,0 +1,21 @@
include_directories(
.
)
set(server_example2_SRCS
server_example2.c
static_model.c
)
IF(WIN32)
set_source_files_properties(${server_example2_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
add_executable(server_example2
${server_example2_SRCS}
)
target_link_libraries(server_example2
iec61850
)

@ -0,0 +1,24 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = server_example2
PROJECT_SOURCES = server_example2.c
PROJECT_SOURCES += static_model.c
PROJECT_ICD_FILE = complexModel.icd
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
model: $(PROJECT_ICD_FILE)
java -jar $(LIBIEC_HOME)/tools/model_generator/genmodel.jar $(PROJECT_ICD_FILE)
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDFLAGS) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,86 @@
/*
* server_example2.c
*
* Copyright 2013 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "iec61850_server.h"
#include "hal_thread.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
/* Include the generated header with the model access handles */
#include "static_model.h"
/* import IEC 61850 device model created from SCL-File */
extern IedModel iedModel;
static int running = 0;
void sigint_handler(int signalId)
{
running = 0;
}
int
main(int argc, char** argv)
{
IedServer iedServer = IedServer_create(&iedModel);
// TODO get stored values from persistent storage
// TODO set initial measurement and status values from process
/* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, 102);
if (!IedServer_isRunning(iedServer)) {
printf("Starting server failed! Exit.\n");
IedServer_destroy(iedServer);
exit(-1);
}
running = 1;
signal(SIGINT, sigint_handler);
float power = 500.f;
while (running) {
uint64_t timeval = Hal_getTimeInMs();
IedServer_unlockDataModel(iedServer);
power += 0.1f;
Thread_sleep(500);
}
/* stop MMS server - close TCP server socket and all client sockets */
IedServer_stop(iedServer);
/* Cleanup - free all resources */
IedServer_destroy(iedServer);
return 0;
} /* main() */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,161 @@
/*
* static_model.h
*
* automatically generated from sv.icd
*/
#ifndef STATIC_MODEL_H_
#define STATIC_MODEL_H_
#include <stdlib.h>
#include "iec61850_model.h"
extern IedModel iedModel;
extern LogicalDevice iedModel_MUnn;
extern LogicalNode iedModel_MUnn_LLN0;
extern DataObject iedModel_MUnn_LLN0_Mod;
extern DataAttribute iedModel_MUnn_LLN0_Mod_ctlVal;
extern DataAttribute iedModel_MUnn_LLN0_Mod_stVal;
extern DataAttribute iedModel_MUnn_LLN0_Mod_q;
extern DataAttribute iedModel_MUnn_LLN0_Mod_t;
extern LogicalNode iedModel_MUnn_TCTR1;
extern DataObject iedModel_MUnn_TCTR1_Amp;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR1_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR2;
extern DataObject iedModel_MUnn_TCTR2_Amp;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR2_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR3;
extern DataObject iedModel_MUnn_TCTR3_Amp;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR3_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TCTR4;
extern DataObject iedModel_MUnn_TCTR4_Amp;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_instMag_i;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_q;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TCTR4_Amp_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR1;
extern DataObject iedModel_MUnn_TVTR1_Vol;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR1_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR2;
extern DataObject iedModel_MUnn_TVTR2_Vol;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR2_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR3;
extern DataObject iedModel_MUnn_TVTR3_Vol;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR3_Vol_sVC_offset;
extern LogicalNode iedModel_MUnn_TVTR4;
extern DataObject iedModel_MUnn_TVTR4_Vol;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_instMag_i;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_q;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor;
extern DataAttribute iedModel_MUnn_TVTR4_Vol_sVC_offset;
#define IEDMODEL_MUnn (&iedModel_MUnn)
#define IEDMODEL_MUnn_LLN0 (&iedModel_MUnn_LLN0)
#define IEDMODEL_MUnn_LLN0_Mod (&iedModel_MUnn_LLN0_Mod)
#define IEDMODEL_MUnn_LLN0_Mod_ctlVal (&iedModel_MUnn_LLN0_Mod_ctlVal)
#define IEDMODEL_MUnn_LLN0_Mod_stVal (&iedModel_MUnn_LLN0_Mod_stVal)
#define IEDMODEL_MUnn_LLN0_Mod_q (&iedModel_MUnn_LLN0_Mod_q)
#define IEDMODEL_MUnn_LLN0_Mod_t (&iedModel_MUnn_LLN0_Mod_t)
#define IEDMODEL_MUnn_TCTR1 (&iedModel_MUnn_TCTR1)
#define IEDMODEL_MUnn_TCTR1_Amp (&iedModel_MUnn_TCTR1_Amp)
#define IEDMODEL_MUnn_TCTR1_Amp_instMag (&iedModel_MUnn_TCTR1_Amp_instMag)
#define IEDMODEL_MUnn_TCTR1_Amp_instMag_i (&iedModel_MUnn_TCTR1_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR1_Amp_q (&iedModel_MUnn_TCTR1_Amp_q)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC (&iedModel_MUnn_TCTR1_Amp_sVC)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR1_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR1_Amp_sVC_offset (&iedModel_MUnn_TCTR1_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR2 (&iedModel_MUnn_TCTR2)
#define IEDMODEL_MUnn_TCTR2_Amp (&iedModel_MUnn_TCTR2_Amp)
#define IEDMODEL_MUnn_TCTR2_Amp_instMag (&iedModel_MUnn_TCTR2_Amp_instMag)
#define IEDMODEL_MUnn_TCTR2_Amp_instMag_i (&iedModel_MUnn_TCTR2_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR2_Amp_q (&iedModel_MUnn_TCTR2_Amp_q)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC (&iedModel_MUnn_TCTR2_Amp_sVC)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR2_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR2_Amp_sVC_offset (&iedModel_MUnn_TCTR2_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR3 (&iedModel_MUnn_TCTR3)
#define IEDMODEL_MUnn_TCTR3_Amp (&iedModel_MUnn_TCTR3_Amp)
#define IEDMODEL_MUnn_TCTR3_Amp_instMag (&iedModel_MUnn_TCTR3_Amp_instMag)
#define IEDMODEL_MUnn_TCTR3_Amp_instMag_i (&iedModel_MUnn_TCTR3_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR3_Amp_q (&iedModel_MUnn_TCTR3_Amp_q)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC (&iedModel_MUnn_TCTR3_Amp_sVC)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR3_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR3_Amp_sVC_offset (&iedModel_MUnn_TCTR3_Amp_sVC_offset)
#define IEDMODEL_MUnn_TCTR4 (&iedModel_MUnn_TCTR4)
#define IEDMODEL_MUnn_TCTR4_Amp (&iedModel_MUnn_TCTR4_Amp)
#define IEDMODEL_MUnn_TCTR4_Amp_instMag (&iedModel_MUnn_TCTR4_Amp_instMag)
#define IEDMODEL_MUnn_TCTR4_Amp_instMag_i (&iedModel_MUnn_TCTR4_Amp_instMag_i)
#define IEDMODEL_MUnn_TCTR4_Amp_q (&iedModel_MUnn_TCTR4_Amp_q)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC (&iedModel_MUnn_TCTR4_Amp_sVC)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC_scaleFactor (&iedModel_MUnn_TCTR4_Amp_sVC_scaleFactor)
#define IEDMODEL_MUnn_TCTR4_Amp_sVC_offset (&iedModel_MUnn_TCTR4_Amp_sVC_offset)
#define IEDMODEL_MUnn_TVTR1 (&iedModel_MUnn_TVTR1)
#define IEDMODEL_MUnn_TVTR1_Vol (&iedModel_MUnn_TVTR1_Vol)
#define IEDMODEL_MUnn_TVTR1_Vol_instMag (&iedModel_MUnn_TVTR1_Vol_instMag)
#define IEDMODEL_MUnn_TVTR1_Vol_instMag_i (&iedModel_MUnn_TVTR1_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR1_Vol_q (&iedModel_MUnn_TVTR1_Vol_q)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC (&iedModel_MUnn_TVTR1_Vol_sVC)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR1_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR1_Vol_sVC_offset (&iedModel_MUnn_TVTR1_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR2 (&iedModel_MUnn_TVTR2)
#define IEDMODEL_MUnn_TVTR2_Vol (&iedModel_MUnn_TVTR2_Vol)
#define IEDMODEL_MUnn_TVTR2_Vol_instMag (&iedModel_MUnn_TVTR2_Vol_instMag)
#define IEDMODEL_MUnn_TVTR2_Vol_instMag_i (&iedModel_MUnn_TVTR2_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR2_Vol_q (&iedModel_MUnn_TVTR2_Vol_q)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC (&iedModel_MUnn_TVTR2_Vol_sVC)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR2_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR2_Vol_sVC_offset (&iedModel_MUnn_TVTR2_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR3 (&iedModel_MUnn_TVTR3)
#define IEDMODEL_MUnn_TVTR3_Vol (&iedModel_MUnn_TVTR3_Vol)
#define IEDMODEL_MUnn_TVTR3_Vol_instMag (&iedModel_MUnn_TVTR3_Vol_instMag)
#define IEDMODEL_MUnn_TVTR3_Vol_instMag_i (&iedModel_MUnn_TVTR3_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR3_Vol_q (&iedModel_MUnn_TVTR3_Vol_q)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC (&iedModel_MUnn_TVTR3_Vol_sVC)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR3_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR3_Vol_sVC_offset (&iedModel_MUnn_TVTR3_Vol_sVC_offset)
#define IEDMODEL_MUnn_TVTR4 (&iedModel_MUnn_TVTR4)
#define IEDMODEL_MUnn_TVTR4_Vol (&iedModel_MUnn_TVTR4_Vol)
#define IEDMODEL_MUnn_TVTR4_Vol_instMag (&iedModel_MUnn_TVTR4_Vol_instMag)
#define IEDMODEL_MUnn_TVTR4_Vol_instMag_i (&iedModel_MUnn_TVTR4_Vol_instMag_i)
#define IEDMODEL_MUnn_TVTR4_Vol_q (&iedModel_MUnn_TVTR4_Vol_q)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC (&iedModel_MUnn_TVTR4_Vol_sVC)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC_scaleFactor (&iedModel_MUnn_TVTR4_Vol_sVC_scaleFactor)
#define IEDMODEL_MUnn_TVTR4_Vol_sVC_offset (&iedModel_MUnn_TVTR4_Vol_sVC_offset)
#endif /* STATIC_MODEL_H_ */

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSPY v5 rel. 4 U (http://www.xmlspy.com) by Christoph Brunner (ABB Switzerland Ltd) -->
<SCL xmlns="http://www.iec.ch/61850/2003/SCL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.iec.ch/61850/2003/SCL
SCL.xsd">
<Header id="9-2LE-Spec" nameStructure="FuncName" version="0.7" revision="1"/>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="TEMPLATE" apName="accessPoint1">
<Address>
<P type="IP">10.0.0.2</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">10.0.0.1</P>
<P type="OSI-TSEL">0001</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</P>
</Address>
<SMV ldInst="MUnn" cbName="MSVCB01">
<Address>
<P type="VLAN-ID">1</P>
<P type="VLAN-PRIORITY">4</P>
<P type="MAC-Address">01-0c-cd-04-00-01</P>
<P type="APPID">1001</P>
</Address>
</SMV>
</ConnectedAP>
</SubNetwork>
</Communication>
<Substation name="">
<VoltageLevel name="">
<Bay name="">
<ConductingEquipment name="Inn" type="CTR">
<SubEquipment name="A" phase="A">
<LNode lnClass="TCTR" lnInst="1"/>
</SubEquipment>
<SubEquipment name="B" phase="B">
<LNode lnClass="TCTR" lnInst="2"/>
</SubEquipment>
<SubEquipment name="C" phase="C">
<LNode lnClass="TCTR" lnInst="3"/>
</SubEquipment>
<SubEquipment name="N" phase="N">
<LNode lnClass="TCTR" lnInst="4"/>
</SubEquipment>
</ConductingEquipment>
<ConductingEquipment name="Unn" type="VTR">
<SubEquipment name="A" phase="A">
<LNode lnClass="TVTR" lnInst="1"/>
</SubEquipment>
<SubEquipment name="B" phase="B">
<LNode lnClass="TVTR" lnInst="2"/>
</SubEquipment>
<SubEquipment name="C" phase="C">
<LNode lnClass="TVTR" lnInst="3"/>
</SubEquipment>
<SubEquipment name="N" phase="N">
<LNode lnClass="TVTR" lnInst="4"/>
</SubEquipment>
</ConductingEquipment>
</Bay>
</VoltageLevel>
</Substation>
<IED name="TEMPLATE">
<AccessPoint name="accessPoint1">
<Server>
<Authentication/>
<LDevice inst="MUnn">
<LN0 lnType="9-2LELLN0" lnClass="LLN0" inst="">
<DataSet name="PhsMeas1">
<FCDA lnClass="TCTR" ldInst="1" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="2" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="3" fc="MX" doName="Amp"/>
<FCDA lnClass="TCTR" ldInst="4" fc="MX" doName="Amp"/>
<FCDA lnClass="TVTR" ldInst="1" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="2" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="3" fc="MX" doName="Vol"/>
<FCDA lnClass="TVTR" ldInst="4" fc="MX" doName="Vol"/>
</DataSet>
<SampledValueControl name="MSVCB01" datSet="PhsMeas1" smvID="xxxxMUnn01"
smpRate="80" nofASDU="1" confRev="1">
<SmvOpts refreshTime="false" sampleSynchronized="true"
security="false" dataRef="false"/>
</SampledValueControl>
</LN0>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="1"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="2"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="3"/>
<LN lnType="9-2LETCTR" lnClass="TCTR" inst="4"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="1"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="2"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="3"/>
<LN lnType="9-2LETVTR" lnClass="TVTR" inst="4"/>
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="9-2LELLN0" lnClass="LLN0">
<DO name="Mod" type="9-2LEINC"/>
</LNodeType>
<LNodeType id="9-2LETCTR" lnClass="TCTR">
<DO name="Amp" type="9-2LESAVAmp"/>
</LNodeType>
<LNodeType id="9-2LETVTR" lnClass="TVTR">
<DO name="Vol" type="9-2LESAVVol"/>
</LNodeType>
<DOType id="9-2LESAVAmp" cdc="SAV">
<DA name="instMag" bType="Struct" type="9-2LEAV" fc="MX"/>
<DA name="q" bType="Quality" fc="MX"/>
<DA name="sVC" bType="Struct" type="9-2LEsVCAmp" fc="CF"/>
</DOType>
<DOType id="9-2LESAVVol" cdc="SAV">
<DA name="instMag" bType="Struct" type="9-2LEAV" fc="MX"/>
<DA name="q" bType="Quality" fc="MX"/>
<DA name="sVC" bType="Struct" type="9-2LEsVCVol" fc="CF"/>
</DOType>
<DOType id="9-2LEINC" cdc="INC">
<DA name="ctlVal" fc="CO" bType="INT32"/>
<DA name="stVal" fc="ST" bType="INT32" dchg="true"/>
<DA name="q" fc="ST" bType="Quality" dchg="true"/>
<DA name="t" fc="ST" bType="Timestamp" dchg="true"/>
</DOType>
<DAType id="9-2LEAV">
<BDA name="i" bType="INT32"/>
</DAType>
<DAType id="9-2LEsVCAmp">
<BDA name="scaleFactor" bType="FLOAT32">
<Val>0.001</Val>
</BDA>
<BDA name="offset" bType="FLOAT32">
<Val>0</Val>
</BDA>
</DAType>
<DAType id="9-2LEsVCVol">
<BDA name="scaleFactor" bType="FLOAT32">
<Val>0.01</Val>
</BDA>
<BDA name="offset" bType="FLOAT32">
<Val>0</Val>
</BDA>
</DAType>
</DataTypeTemplates>
</SCL>

@ -0,0 +1,17 @@
set(iec61850_sv_client_example_SRCS
sv_client_example.c
)
IF(WIN32)
set_source_files_properties(${iec61850_sv_client_example_SRCS}
PROPERTIES LANGUAGE CXX)
ENDIF(WIN32)
add_executable(iec61850_sv_client_example
${iec61850_sv_client_example_SRCS}
)
target_link_libraries(iec61850_sv_client_example
iec61850
)

@ -0,0 +1,17 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = sv_client_example
PROJECT_SOURCES = sv_client_example.c
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,119 @@
/*
* sv_client_example.c
*
* This example is intended to show how SV control blocks are accessed
*/
#include "iec61850_client.h"
#include <stdlib.h>
#include <stdio.h>
#include "hal_thread.h"
static void
printDstAddr(PhyComAddress dstAddress)
{
printf(" addr: ");
int i;
for (i = 0; i < 6; i++)
printf("%02x", dstAddress.dstAddress[i]);
printf("\n prio: %u\n", dstAddress.vlanPriority);
printf(" vid: %u\n", dstAddress.vlanId);
printf(" appID: %u\n", dstAddress.appId);
}
int main(int argc, char** argv) {
char* hostname;
int tcpPort = 102;
if (argc > 1)
hostname = argv[1];
else
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) {
char* svcbRef = "simpleIOGenericIO/LLN0.Volt";
ClientSVControlBlock svcb = ClientSVControlBlock_create(con, svcbRef);
if (svcb != NULL) {
if (ClientSVControlBlock_isMulticast(svcb))
printf("SVCB is multicast\n");
else
printf("SVCB is unicast\n");
if (ClientSVControlBlock_setSvEna(svcb, true))
printf("SVCB enabled\n");
else
printf("Failed to enable SVCB\n");
printf("SvEna state: %i\n", ClientSVControlBlock_getSvEna(svcb));
char* msvID = ClientSVControlBlock_getMsvID(svcb);
if (msvID != NULL) {
printf("MsvID: %s\n", msvID);
free(msvID);
}
char* datSetName = ClientSVControlBlock_getDatSet(svcb);
if (datSetName != NULL) {
printf("DatSet: %s\n", datSetName);
free(datSetName);
}
printf("ConfRev: %i\n", ClientSVControlBlock_getConfRev(svcb));
printf("SmpRate: %i\n", ClientSVControlBlock_getSmpRate(svcb));
printf("SmpMod: %i\n", ClientSVControlBlock_getSmpMod(svcb));
int optFlds = ClientSVControlBlock_getOptFlds(svcb);
printf("OptFlds: ");
if (optFlds & IEC61850_SV_OPT_REFRESH_TIME)
printf("refresh-time ");
if (optFlds & IEC61850_SV_OPT_SAMPLE_SYNC)
printf("sample-synch ");
if (optFlds & IEC61850_SV_OPT_SAMPLE_RATE)
printf("sample-rate ");
if (optFlds & IEC61850_SV_OPT_DATA_SET)
printf("date-set ");
if (optFlds & IEC61850_SV_OPT_SECURITY)
printf("security ");
printf("\n");
printf("noASDU: %i\n", ClientSVControlBlock_getNoASDU(svcb));
PhyComAddress dstAddress = ClientSVControlBlock_getDstAddress(svcb);
printDstAddr(dstAddress);
}
else {
printf("SVCB %s does not exist on server!\n", svcbRef);
}
IedConnection_close(con);
}
else {
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
IedConnection_destroy(con);
}

@ -8,13 +8,27 @@
static void
print_help()
{
printf("MMS utility (libiec61850 v0.5) options:\n");
printf("MMS utility (libiec61850 " LIBIEC61850_VERSION ") options:\n");
printf("-h <hostname> specify hostname\n");
printf("-p <port> specify port\n");
printf("-l <max_pdu_size> specify maximum PDU size\n");
printf("-d show list of MMS domains\n");
printf("-i show server identity\n");
printf("-t <domain_name> show domain directory\n");
printf("-r <variable_name> read domain variable\n");
printf("-a <domain_name> specify domain for read or write command\n");
printf("-f show file list\n");
}
static void
mmsFileDirectoryHandler (void* parameter, char* filename, uint32_t size, uint64_t lastModified)
{
char* lastName = (char*) parameter;
strcpy (lastName, filename);
printf("%s\n", filename);
}
int main(int argc, char** argv) {
@ -24,14 +38,19 @@ int main(int argc, char** argv) {
int maxPduSize = 65000;
char* domainName = NULL;
char* variableName = NULL;
int readDeviceList = 0;
int getDeviceDirectory = 0;
int identifyDevice = 0;
int readWriteHasDomain = 0;
int readVariable = 0;
int showFileList = 0;
int c;
while ((c = getopt(argc, argv, "idh:p:l:t:")) != -1)
while ((c = getopt(argc, argv, "ifdh:p:l:t:a:r:")) != -1)
switch (c) {
case 'h':
hostname = copyString(optarg);
@ -52,6 +71,18 @@ int main(int argc, char** argv) {
getDeviceDirectory = 1;
domainName = copyString(optarg);
break;
case 'a':
readWriteHasDomain = 1;
domainName = copyString(optarg);
break;
case 'r':
readVariable = 1;
variableName = copyString(optarg);
break;
case 'f':
showFileList = 1;
break;
default:
print_help();
return 0;
@ -103,12 +134,49 @@ int main(int argc, char** argv) {
while ((element = LinkedList_getNext(element)) != NULL) {
char* name = (char*) element->data;
if (strchr(name, '$') == NULL)
printf(" %s\n", name);
}
}
if (readVariable) {
if (readWriteHasDomain) {
MmsValue* result = MmsConnection_readVariable(con, &error, domainName, variableName);
if (error != MMS_ERROR_NONE) {
printf("Reading variable failed: (ERROR %i)\n", error);
}
else {
printf("Read SUCCESS\n");
if (result != NULL) {
char outbuf[1024];
MmsValue_printToBuffer(result, outbuf, 1024);
printf("%s\n", outbuf);
}
else
printf("result: NULL\n");
}
}
else
printf("Reading VMD scope variable not yet supported!\n");
}
if (showFileList) {
char lastName[300];
lastName[0] = 0;
char* continueAfter = NULL;
while (MmsConnection_getFileDirectory(con, &error, "", continueAfter, mmsFileDirectoryHandler, lastName)) {
continueAfter = lastName;
}
}
exit:
MmsConnection_destroy(con);
}

@ -3,171 +3,38 @@
*
* automatically generated from sampleModel_with_dataset.icd
*/
#include <stdlib.h>
#include "iec61850_model.h"
#include "static_model.h"
extern IedModel iedModel;
static void initializeValues();
extern LogicalDevice iedModel_Device1;
extern LogicalNode iedModel_Device1_LLN0;
extern DataObject iedModel_Device1_LLN0_Mod;
extern DataAttribute iedModel_Device1_LLN0_Mod_q;
extern DataAttribute iedModel_Device1_LLN0_Mod_t;
extern DataAttribute iedModel_Device1_LLN0_Mod_ctlModel;
extern DataObject iedModel_Device1_LLN0_Beh;
extern DataAttribute iedModel_Device1_LLN0_Beh_stVal;
extern DataAttribute iedModel_Device1_LLN0_Beh_q;
extern DataAttribute iedModel_Device1_LLN0_Beh_t;
extern DataObject iedModel_Device1_LLN0_Health;
extern DataAttribute iedModel_Device1_LLN0_Health_stVal;
extern DataAttribute iedModel_Device1_LLN0_Health_q;
extern DataAttribute iedModel_Device1_LLN0_Health_t;
extern DataObject iedModel_Device1_LLN0_NamPlt;
extern DataAttribute iedModel_Device1_LLN0_NamPlt_vendor;
extern DataAttribute iedModel_Device1_LLN0_NamPlt_swRev;
extern DataAttribute iedModel_Device1_LLN0_NamPlt_d;
extern DataAttribute iedModel_Device1_LLN0_NamPlt_configRev;
extern DataAttribute iedModel_Device1_LLN0_NamPlt_ldNs;
extern LogicalNode iedModel_Device1_LPHD1;
extern DataObject iedModel_Device1_LPHD1_PhyNam;
extern DataAttribute iedModel_Device1_LPHD1_PhyNam_vendor;
extern DataObject iedModel_Device1_LPHD1_PhyHealth;
extern DataAttribute iedModel_Device1_LPHD1_PhyHealth_stVal;
extern DataAttribute iedModel_Device1_LPHD1_PhyHealth_q;
extern DataAttribute iedModel_Device1_LPHD1_PhyHealth_t;
extern DataObject iedModel_Device1_LPHD1_Proxy;
extern DataAttribute iedModel_Device1_LPHD1_Proxy_stVal;
extern DataAttribute iedModel_Device1_LPHD1_Proxy_q;
extern DataAttribute iedModel_Device1_LPHD1_Proxy_t;
extern LogicalNode iedModel_Device1_DGEN1;
extern DataObject iedModel_Device1_DGEN1_Mod;
extern DataAttribute iedModel_Device1_DGEN1_Mod_q;
extern DataAttribute iedModel_Device1_DGEN1_Mod_t;
extern DataAttribute iedModel_Device1_DGEN1_Mod_ctlModel;
extern DataObject iedModel_Device1_DGEN1_Beh;
extern DataAttribute iedModel_Device1_DGEN1_Beh_stVal;
extern DataAttribute iedModel_Device1_DGEN1_Beh_q;
extern DataAttribute iedModel_Device1_DGEN1_Beh_t;
extern DataObject iedModel_Device1_DGEN1_Health;
extern DataAttribute iedModel_Device1_DGEN1_Health_stVal;
extern DataAttribute iedModel_Device1_DGEN1_Health_q;
extern DataAttribute iedModel_Device1_DGEN1_Health_t;
extern DataObject iedModel_Device1_DGEN1_NamPlt;
extern DataAttribute iedModel_Device1_DGEN1_NamPlt_vendor;
extern DataAttribute iedModel_Device1_DGEN1_NamPlt_swRev;
extern DataAttribute iedModel_Device1_DGEN1_NamPlt_d;
extern DataObject iedModel_Device1_DGEN1_OpTmh;
extern DataAttribute iedModel_Device1_DGEN1_OpTmh_stVal;
extern DataAttribute iedModel_Device1_DGEN1_OpTmh_q;
extern DataAttribute iedModel_Device1_DGEN1_OpTmh_t;
extern DataObject iedModel_Device1_DGEN1_GnOpSt;
extern DataAttribute iedModel_Device1_DGEN1_GnOpSt_stVal;
extern DataAttribute iedModel_Device1_DGEN1_GnOpSt_q;
extern DataAttribute iedModel_Device1_DGEN1_GnOpSt_t;
extern DataObject iedModel_Device1_DGEN1_OpTmsRs;
extern DataAttribute iedModel_Device1_DGEN1_OpTmsRs_stVal;
extern DataAttribute iedModel_Device1_DGEN1_OpTmsRs_q;
extern DataAttribute iedModel_Device1_DGEN1_OpTmsRs_t;
extern DataObject iedModel_Device1_DGEN1_TotWh;
extern DataAttribute iedModel_Device1_DGEN1_TotWh_mag;
extern DataAttribute iedModel_Device1_DGEN1_TotWh_mag_f;
extern DataAttribute iedModel_Device1_DGEN1_TotWh_q;
extern DataAttribute iedModel_Device1_DGEN1_TotWh_t;
extern LogicalNode iedModel_Device1_DSCH1;
extern DataObject iedModel_Device1_DSCH1_Mod;
extern DataAttribute iedModel_Device1_DSCH1_Mod_q;
extern DataAttribute iedModel_Device1_DSCH1_Mod_t;
extern DataAttribute iedModel_Device1_DSCH1_Mod_ctlModel;
extern DataObject iedModel_Device1_DSCH1_Beh;
extern DataAttribute iedModel_Device1_DSCH1_Beh_stVal;
extern DataAttribute iedModel_Device1_DSCH1_Beh_q;
extern DataAttribute iedModel_Device1_DSCH1_Beh_t;
extern DataObject iedModel_Device1_DSCH1_Health;
extern DataAttribute iedModel_Device1_DSCH1_Health_stVal;
extern DataAttribute iedModel_Device1_DSCH1_Health_q;
extern DataAttribute iedModel_Device1_DSCH1_Health_t;
extern DataObject iedModel_Device1_DSCH1_NamPlt;
extern DataAttribute iedModel_Device1_DSCH1_NamPlt_vendor;
extern DataAttribute iedModel_Device1_DSCH1_NamPlt_swRev;
extern DataAttribute iedModel_Device1_DSCH1_NamPlt_d;
extern DataObject iedModel_Device1_DSCH1_SchdSt;
extern DataAttribute iedModel_Device1_DSCH1_SchdSt_stVal;
extern DataAttribute iedModel_Device1_DSCH1_SchdSt_q;
extern DataAttribute iedModel_Device1_DSCH1_SchdSt_t;
extern DataObject iedModel_Device1_DSCH1_SchdId;
extern DataObject iedModel_Device1_DSCH1_SchdCat;
extern DataObject iedModel_Device1_DSCH1_SchdTyp;
extern DataObject iedModel_Device1_DSCH1_SchdAbsTm;
extern DataAttribute iedModel_Device1_DSCH1_SchdAbsTm_val;
extern DataAttribute iedModel_Device1_DSCH1_SchdAbsTm_time;
extern LogicalNode iedModel_Device1_MMXU1;
extern DataObject iedModel_Device1_MMXU1_Mod;
extern DataAttribute iedModel_Device1_MMXU1_Mod_q;
extern DataAttribute iedModel_Device1_MMXU1_Mod_t;
extern DataAttribute iedModel_Device1_MMXU1_Mod_ctlModel;
extern DataObject iedModel_Device1_MMXU1_Beh;
extern DataAttribute iedModel_Device1_MMXU1_Beh_stVal;
extern DataAttribute iedModel_Device1_MMXU1_Beh_q;
extern DataAttribute iedModel_Device1_MMXU1_Beh_t;
extern DataObject iedModel_Device1_MMXU1_Health;
extern DataAttribute iedModel_Device1_MMXU1_Health_stVal;
extern DataAttribute iedModel_Device1_MMXU1_Health_q;
extern DataAttribute iedModel_Device1_MMXU1_Health_t;
extern DataObject iedModel_Device1_MMXU1_NamPlt;
extern DataAttribute iedModel_Device1_MMXU1_NamPlt_vendor;
extern DataAttribute iedModel_Device1_MMXU1_NamPlt_swRev;
extern DataAttribute iedModel_Device1_MMXU1_NamPlt_d;
extern LogicalNode iedModel_Device1_MMXU2;
extern DataObject iedModel_Device1_MMXU2_Mod;
extern DataAttribute iedModel_Device1_MMXU2_Mod_q;
extern DataAttribute iedModel_Device1_MMXU2_Mod_t;
extern DataAttribute iedModel_Device1_MMXU2_Mod_ctlModel;
extern DataObject iedModel_Device1_MMXU2_Beh;
extern DataAttribute iedModel_Device1_MMXU2_Beh_stVal;
extern DataAttribute iedModel_Device1_MMXU2_Beh_q;
extern DataAttribute iedModel_Device1_MMXU2_Beh_t;
extern DataObject iedModel_Device1_MMXU2_Health;
extern DataAttribute iedModel_Device1_MMXU2_Health_stVal;
extern DataAttribute iedModel_Device1_MMXU2_Health_q;
extern DataAttribute iedModel_Device1_MMXU2_Health_t;
extern DataObject iedModel_Device1_MMXU2_NamPlt;
extern DataAttribute iedModel_Device1_MMXU2_NamPlt_vendor;
extern DataAttribute iedModel_Device1_MMXU2_NamPlt_swRev;
extern DataAttribute iedModel_Device1_MMXU2_NamPlt_d;
extern DataObject iedModel_Device1_MMXU2_TotW;
extern DataAttribute iedModel_Device1_MMXU2_TotW_mag;
extern DataAttribute iedModel_Device1_MMXU2_TotW_mag_f;
extern DataAttribute iedModel_Device1_MMXU2_TotW_q;
extern DataAttribute iedModel_Device1_MMXU2_TotW_t;
extern DataSet ds_Device1_LLN0_dataset1;
extern DataSetEntry ds_Device1_LLN0_dataset1_fcda0;
extern DataSetEntry ds_Device1_LLN0_dataset1_fcda1;
extern DataSetEntry ds_Device1_LLN0_dataset1_fcda2;
DataSetEntry ds_Device1_LLN0_dataset1_fcda0 = {
extern DataSet iedModelds_Device1_LLN0_dataset1;
extern DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda0;
extern DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda1;
extern DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda2;
DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda0 = {
"Device1",
false,
"LLN0$ST$Mod$q",
-1,
NULL,
NULL,
&ds_Device1_LLN0_dataset1_fcda1
&iedModelds_Device1_LLN0_dataset1_fcda1
};
DataSetEntry ds_Device1_LLN0_dataset1_fcda1 = {
DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda1 = {
"Device1",
false,
"MMXU1$ST$Mod$q",
-1,
NULL,
NULL,
&ds_Device1_LLN0_dataset1_fcda2
&iedModelds_Device1_LLN0_dataset1_fcda2
};
DataSetEntry ds_Device1_LLN0_dataset1_fcda2 = {
DataSetEntry iedModelds_Device1_LLN0_dataset1_fcda2 = {
"Device1",
false,
"MMXU1$CF$Mod$ctlModel",
@ -177,11 +44,11 @@ DataSetEntry ds_Device1_LLN0_dataset1_fcda2 = {
NULL
};
DataSet ds_Device1_LLN0_dataset1 = {
DataSet iedModelds_Device1_LLN0_dataset1 = {
"Device1",
"LLN0$dataset1",
3,
&ds_Device1_LLN0_dataset1_fcda0,
&iedModelds_Device1_LLN0_dataset1_fcda0,
NULL
};
@ -218,7 +85,7 @@ DataAttribute iedModel_Device1_LLN0_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -231,7 +98,7 @@ DataAttribute iedModel_Device1_LLN0_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -244,7 +111,7 @@ DataAttribute iedModel_Device1_LLN0_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -266,7 +133,7 @@ DataAttribute iedModel_Device1_LLN0_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -279,7 +146,7 @@ DataAttribute iedModel_Device1_LLN0_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -292,7 +159,7 @@ DataAttribute iedModel_Device1_LLN0_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -314,7 +181,7 @@ DataAttribute iedModel_Device1_LLN0_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -327,7 +194,7 @@ DataAttribute iedModel_Device1_LLN0_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -340,7 +207,7 @@ DataAttribute iedModel_Device1_LLN0_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -362,7 +229,7 @@ DataAttribute iedModel_Device1_LLN0_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -375,7 +242,7 @@ DataAttribute iedModel_Device1_LLN0_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -388,7 +255,7 @@ DataAttribute iedModel_Device1_LLN0_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -401,7 +268,7 @@ DataAttribute iedModel_Device1_LLN0_NamPlt_configRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -414,7 +281,7 @@ DataAttribute iedModel_Device1_LLN0_NamPlt_ldNs = {
NULL,
0,
IEC61850_FC_EX,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -444,7 +311,7 @@ DataAttribute iedModel_Device1_LPHD1_PhyNam_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -466,7 +333,7 @@ DataAttribute iedModel_Device1_LPHD1_PhyHealth_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -479,7 +346,7 @@ DataAttribute iedModel_Device1_LPHD1_PhyHealth_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -492,7 +359,7 @@ DataAttribute iedModel_Device1_LPHD1_PhyHealth_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -514,7 +381,7 @@ DataAttribute iedModel_Device1_LPHD1_Proxy_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -527,7 +394,7 @@ DataAttribute iedModel_Device1_LPHD1_Proxy_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -540,7 +407,7 @@ DataAttribute iedModel_Device1_LPHD1_Proxy_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -570,7 +437,7 @@ DataAttribute iedModel_Device1_DGEN1_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -583,7 +450,7 @@ DataAttribute iedModel_Device1_DGEN1_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -596,7 +463,7 @@ DataAttribute iedModel_Device1_DGEN1_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -618,7 +485,7 @@ DataAttribute iedModel_Device1_DGEN1_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -631,7 +498,7 @@ DataAttribute iedModel_Device1_DGEN1_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -644,7 +511,7 @@ DataAttribute iedModel_Device1_DGEN1_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -666,7 +533,7 @@ DataAttribute iedModel_Device1_DGEN1_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -679,7 +546,7 @@ DataAttribute iedModel_Device1_DGEN1_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -692,7 +559,7 @@ DataAttribute iedModel_Device1_DGEN1_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -714,7 +581,7 @@ DataAttribute iedModel_Device1_DGEN1_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -727,7 +594,7 @@ DataAttribute iedModel_Device1_DGEN1_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -740,7 +607,7 @@ DataAttribute iedModel_Device1_DGEN1_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -762,7 +629,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -775,7 +642,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -788,7 +655,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -810,7 +677,7 @@ DataAttribute iedModel_Device1_DGEN1_GnOpSt_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -823,7 +690,7 @@ DataAttribute iedModel_Device1_DGEN1_GnOpSt_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -836,7 +703,7 @@ DataAttribute iedModel_Device1_DGEN1_GnOpSt_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -858,7 +725,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmsRs_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -871,7 +738,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmsRs_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -884,7 +751,7 @@ DataAttribute iedModel_Device1_DGEN1_OpTmsRs_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -906,7 +773,7 @@ DataAttribute iedModel_Device1_DGEN1_TotWh_mag = {
(ModelNode*) &iedModel_Device1_DGEN1_TotWh_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -919,7 +786,7 @@ DataAttribute iedModel_Device1_DGEN1_TotWh_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -932,7 +799,7 @@ DataAttribute iedModel_Device1_DGEN1_TotWh_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -945,7 +812,7 @@ DataAttribute iedModel_Device1_DGEN1_TotWh_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -975,7 +842,7 @@ DataAttribute iedModel_Device1_DSCH1_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -988,7 +855,7 @@ DataAttribute iedModel_Device1_DSCH1_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1001,7 +868,7 @@ DataAttribute iedModel_Device1_DSCH1_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1023,7 +890,7 @@ DataAttribute iedModel_Device1_DSCH1_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1036,7 +903,7 @@ DataAttribute iedModel_Device1_DSCH1_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1049,7 +916,7 @@ DataAttribute iedModel_Device1_DSCH1_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1071,7 +938,7 @@ DataAttribute iedModel_Device1_DSCH1_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1084,7 +951,7 @@ DataAttribute iedModel_Device1_DSCH1_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1097,7 +964,7 @@ DataAttribute iedModel_Device1_DSCH1_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1119,7 +986,7 @@ DataAttribute iedModel_Device1_DSCH1_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1132,7 +999,7 @@ DataAttribute iedModel_Device1_DSCH1_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1145,7 +1012,7 @@ DataAttribute iedModel_Device1_DSCH1_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1167,7 +1034,7 @@ DataAttribute iedModel_Device1_DSCH1_SchdSt_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1180,7 +1047,7 @@ DataAttribute iedModel_Device1_DSCH1_SchdSt_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1193,7 +1060,7 @@ DataAttribute iedModel_Device1_DSCH1_SchdSt_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1242,7 +1109,7 @@ DataAttribute iedModel_Device1_DSCH1_SchdAbsTm_val = {
NULL,
255,
IEC61850_FC_SP,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1255,7 +1122,7 @@ DataAttribute iedModel_Device1_DSCH1_SchdAbsTm_time = {
NULL,
255,
IEC61850_FC_SP,
TIMESTAMP,
IEC61850_TIMESTAMP,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1285,7 +1152,7 @@ DataAttribute iedModel_Device1_MMXU1_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1298,7 +1165,7 @@ DataAttribute iedModel_Device1_MMXU1_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1311,7 +1178,7 @@ DataAttribute iedModel_Device1_MMXU1_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1333,7 +1200,7 @@ DataAttribute iedModel_Device1_MMXU1_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1346,7 +1213,7 @@ DataAttribute iedModel_Device1_MMXU1_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1359,7 +1226,7 @@ DataAttribute iedModel_Device1_MMXU1_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1381,7 +1248,7 @@ DataAttribute iedModel_Device1_MMXU1_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1394,7 +1261,7 @@ DataAttribute iedModel_Device1_MMXU1_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1407,7 +1274,7 @@ DataAttribute iedModel_Device1_MMXU1_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1429,7 +1296,7 @@ DataAttribute iedModel_Device1_MMXU1_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1442,7 +1309,7 @@ DataAttribute iedModel_Device1_MMXU1_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1455,7 +1322,7 @@ DataAttribute iedModel_Device1_MMXU1_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1485,7 +1352,7 @@ DataAttribute iedModel_Device1_MMXU2_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1498,7 +1365,7 @@ DataAttribute iedModel_Device1_MMXU2_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1511,7 +1378,7 @@ DataAttribute iedModel_Device1_MMXU2_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1533,7 +1400,7 @@ DataAttribute iedModel_Device1_MMXU2_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1546,7 +1413,7 @@ DataAttribute iedModel_Device1_MMXU2_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1559,7 +1426,7 @@ DataAttribute iedModel_Device1_MMXU2_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1581,7 +1448,7 @@ DataAttribute iedModel_Device1_MMXU2_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1594,7 +1461,7 @@ DataAttribute iedModel_Device1_MMXU2_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1607,7 +1474,7 @@ DataAttribute iedModel_Device1_MMXU2_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1629,7 +1496,7 @@ DataAttribute iedModel_Device1_MMXU2_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1642,7 +1509,7 @@ DataAttribute iedModel_Device1_MMXU2_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1655,7 +1522,7 @@ DataAttribute iedModel_Device1_MMXU2_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -1677,7 +1544,7 @@ DataAttribute iedModel_Device1_MMXU2_TotW_mag = {
(ModelNode*) &iedModel_Device1_MMXU2_TotW_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1690,7 +1557,7 @@ DataAttribute iedModel_Device1_MMXU2_TotW_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1703,7 +1570,7 @@ DataAttribute iedModel_Device1_MMXU2_TotW_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1716,14 +1583,15 @@ DataAttribute iedModel_Device1_MMXU2_TotW_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
extern ReportControlBlock iedModel_Device1_LLN0_report0;
ReportControlBlock iedModel_Device1_LLN0_report0 = {&iedModel_Device1_LLN0, "LLN0_Events_BuffRep01", "LLN0$RP$brcbEV1", true, "dataset1", 1, 9, 239, 50, 900000, NULL};
ReportControlBlock iedModel_Device1_LLN0_report0 = {&iedModel_Device1_LLN0, "LLN0_Events_BuffRep01", "LLN0$RP$brcbEV1", true, "dataset1", 1, 25, 239, 50, 900000, NULL};
@ -1731,10 +1599,11 @@ ReportControlBlock iedModel_Device1_LLN0_report0 = {&iedModel_Device1_LLN0, "LLN
IedModel iedModel = {
"SampleIED",
&iedModel_Device1,
&ds_Device1_LLN0_dataset1,
&iedModelds_Device1_LLN0_dataset1,
&iedModel_Device1_LLN0_report0,
NULL,
NULL,
NULL,
initializeValues
};

File diff suppressed because it is too large Load Diff

@ -248,7 +248,7 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -261,7 +261,7 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -274,7 +274,7 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -287,7 +287,7 @@ DataAttribute iedModel_GenericIO_LLN0_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -309,7 +309,7 @@ DataAttribute iedModel_GenericIO_LLN0_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -322,7 +322,7 @@ DataAttribute iedModel_GenericIO_LLN0_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -335,7 +335,7 @@ DataAttribute iedModel_GenericIO_LLN0_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -357,7 +357,7 @@ DataAttribute iedModel_GenericIO_LLN0_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -370,7 +370,7 @@ DataAttribute iedModel_GenericIO_LLN0_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -383,7 +383,7 @@ DataAttribute iedModel_GenericIO_LLN0_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -405,7 +405,7 @@ DataAttribute iedModel_GenericIO_LLN0_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -418,7 +418,7 @@ DataAttribute iedModel_GenericIO_LLN0_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -431,7 +431,7 @@ DataAttribute iedModel_GenericIO_LLN0_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -444,7 +444,7 @@ DataAttribute iedModel_GenericIO_LLN0_NamPlt_configRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -457,7 +457,7 @@ DataAttribute iedModel_GenericIO_LLN0_NamPlt_ldNs = {
NULL,
0,
IEC61850_FC_EX,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -487,7 +487,7 @@ DataAttribute iedModel_GenericIO_LPHD1_PhyNam_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -509,7 +509,7 @@ DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -522,7 +522,7 @@ DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -535,7 +535,7 @@ DataAttribute iedModel_GenericIO_LPHD1_PhyHealth_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -557,7 +557,7 @@ DataAttribute iedModel_GenericIO_LPHD1_Proxy_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -570,7 +570,7 @@ DataAttribute iedModel_GenericIO_LPHD1_Proxy_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -583,7 +583,7 @@ DataAttribute iedModel_GenericIO_LPHD1_Proxy_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -613,7 +613,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -626,7 +626,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -639,7 +639,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -661,7 +661,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -674,7 +674,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -687,7 +687,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -709,7 +709,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -722,7 +722,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -735,7 +735,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -757,7 +757,7 @@ DataAttribute iedModel_GenericIO_GGIO1_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -770,7 +770,7 @@ DataAttribute iedModel_GenericIO_GGIO1_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -783,7 +783,7 @@ DataAttribute iedModel_GenericIO_GGIO1_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -805,7 +805,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag = {
(ModelNode*) &iedModel_GenericIO_GGIO1_AnIn1_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -818,7 +818,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn1_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -831,7 +831,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn1_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -844,7 +844,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn1_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -866,7 +866,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag = {
(ModelNode*) &iedModel_GenericIO_GGIO1_AnIn2_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -879,7 +879,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn2_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -892,7 +892,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn2_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -905,7 +905,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn2_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -927,7 +927,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag = {
(ModelNode*) &iedModel_GenericIO_GGIO1_AnIn3_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -940,7 +940,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn3_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -953,7 +953,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn3_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -966,7 +966,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn3_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -988,7 +988,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag = {
(ModelNode*) &iedModel_GenericIO_GGIO1_AnIn4_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1001,7 +1001,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn4_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1014,7 +1014,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn4_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1027,7 +1027,7 @@ DataAttribute iedModel_GenericIO_GGIO1_AnIn4_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1049,7 +1049,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1062,7 +1062,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1075,7 +1075,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1088,7 +1088,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1101,7 +1101,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1114,7 +1114,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1127,7 +1127,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -1140,7 +1140,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -1153,7 +1153,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1166,7 +1166,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1179,7 +1179,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -1192,7 +1192,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1205,7 +1205,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO1_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1227,7 +1227,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1240,7 +1240,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1253,7 +1253,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1266,7 +1266,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1279,7 +1279,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1292,7 +1292,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1305,7 +1305,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -1318,7 +1318,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -1331,7 +1331,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1344,7 +1344,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1357,7 +1357,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -1370,7 +1370,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1383,7 +1383,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO2_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1405,7 +1405,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1418,7 +1418,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1431,7 +1431,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1444,7 +1444,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1457,7 +1457,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1470,7 +1470,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1483,7 +1483,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -1496,7 +1496,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -1509,7 +1509,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1522,7 +1522,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1535,7 +1535,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -1548,7 +1548,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1561,7 +1561,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO3_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1583,7 +1583,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1596,7 +1596,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1609,7 +1609,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1622,7 +1622,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1635,7 +1635,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin = {
(ModelNode*) &iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1648,7 +1648,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1661,7 +1661,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -1674,7 +1674,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -1687,7 +1687,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1700,7 +1700,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -1713,7 +1713,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -1726,7 +1726,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -1739,7 +1739,7 @@ DataAttribute iedModel_GenericIO_GGIO1_SPCSO4_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1761,7 +1761,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind1_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1774,7 +1774,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind1_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1787,7 +1787,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind1_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1809,7 +1809,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind2_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1822,7 +1822,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind2_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1835,7 +1835,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind2_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1857,7 +1857,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind3_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1870,7 +1870,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind3_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1883,7 +1883,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind3_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1905,7 +1905,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1918,7 +1918,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1931,7 +1931,7 @@ DataAttribute iedModel_GenericIO_GGIO1_Ind4_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1944,13 +1944,14 @@ extern ReportControlBlock iedModel_GenericIO_LLN0_report4;
extern ReportControlBlock iedModel_GenericIO_LLN0_report5;
extern ReportControlBlock iedModel_GenericIO_LLN0_report6;
ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 4294967295, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report1};
ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsIndexed01", "Events2", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report2};
ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsIndexed02", "Events2", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report3};
ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsIndexed03", "Events2", false, "Events", 1, 8, 111, 50, 1000, &iedModel_GenericIO_LLN0_report4};
ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "Measurements01", "Measurements", true, "Measurements", 1, 0, 111, 50, 1000, &iedModel_GenericIO_LLN0_report5};
ReportControlBlock iedModel_GenericIO_LLN0_report5 = {&iedModel_GenericIO_LLN0, "Measurements02", "Measurements", true, "Measurements", 1, 0, 111, 50, 1000, &iedModel_GenericIO_LLN0_report6};
ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0, "Measurements03", "Measurements", true, "Measurements", 1, 0, 111, 50, 1000, NULL};
ReportControlBlock iedModel_GenericIO_LLN0_report0 = {&iedModel_GenericIO_LLN0, "EventsRCB01", "Events1", false, "Events", 4294967295, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report1};
ReportControlBlock iedModel_GenericIO_LLN0_report1 = {&iedModel_GenericIO_LLN0, "EventsIndexed01", "Events2", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report2};
ReportControlBlock iedModel_GenericIO_LLN0_report2 = {&iedModel_GenericIO_LLN0, "EventsIndexed02", "Events2", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report3};
ReportControlBlock iedModel_GenericIO_LLN0_report3 = {&iedModel_GenericIO_LLN0, "EventsIndexed03", "Events2", false, "Events", 1, 24, 111, 50, 1000, &iedModel_GenericIO_LLN0_report4};
ReportControlBlock iedModel_GenericIO_LLN0_report4 = {&iedModel_GenericIO_LLN0, "Measurements01", "Measurements", true, "Measurements", 1, 16, 111, 50, 1000, &iedModel_GenericIO_LLN0_report5};
ReportControlBlock iedModel_GenericIO_LLN0_report5 = {&iedModel_GenericIO_LLN0, "Measurements02", "Measurements", true, "Measurements", 1, 16, 111, 50, 1000, &iedModel_GenericIO_LLN0_report6};
ReportControlBlock iedModel_GenericIO_LLN0_report6 = {&iedModel_GenericIO_LLN0, "Measurements03", "Measurements", true, "Measurements", 1, 16, 111, 50, 1000, NULL};
@ -1962,6 +1963,7 @@ IedModel iedModel = {
&iedModel_GenericIO_LLN0_report0,
NULL,
NULL,
NULL,
initializeValues
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -3,56 +3,9 @@
*
* automatically generated from mhai_array.icd
*/
#include <stdlib.h>
#include "iec61850_model.h"
#include "static_model.h"
extern IedModel iedModel;
static void initializeValues();
extern LogicalDevice iedModel_ComplexArray;
extern LogicalNode iedModel_ComplexArray_LLN0;
extern DataObject iedModel_ComplexArray_LLN0_Mod;
extern DataAttribute iedModel_ComplexArray_LLN0_Mod_q;
extern DataAttribute iedModel_ComplexArray_LLN0_Mod_t;
extern DataAttribute iedModel_ComplexArray_LLN0_Mod_ctlModel;
extern DataObject iedModel_ComplexArray_LLN0_Beh;
extern DataAttribute iedModel_ComplexArray_LLN0_Beh_stVal;
extern DataAttribute iedModel_ComplexArray_LLN0_Beh_q;
extern DataAttribute iedModel_ComplexArray_LLN0_Beh_t;
extern DataObject iedModel_ComplexArray_LLN0_Health;
extern DataAttribute iedModel_ComplexArray_LLN0_Health_stVal;
extern DataAttribute iedModel_ComplexArray_LLN0_Health_q;
extern DataAttribute iedModel_ComplexArray_LLN0_Health_t;
extern DataObject iedModel_ComplexArray_LLN0_NamPlt;
extern DataAttribute iedModel_ComplexArray_LLN0_NamPlt_vendor;
extern DataAttribute iedModel_ComplexArray_LLN0_NamPlt_swRev;
extern DataAttribute iedModel_ComplexArray_LLN0_NamPlt_d;
extern DataAttribute iedModel_ComplexArray_LLN0_NamPlt_configRev;
extern DataAttribute iedModel_ComplexArray_LLN0_NamPlt_ldNs;
extern LogicalNode iedModel_ComplexArray_LPHD1;
extern DataObject iedModel_ComplexArray_LPHD1_PhyNam;
extern DataAttribute iedModel_ComplexArray_LPHD1_PhyNam_vendor;
extern DataObject iedModel_ComplexArray_LPHD1_PhyHealth;
extern DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_stVal;
extern DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_q;
extern DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_t;
extern DataObject iedModel_ComplexArray_LPHD1_Proxy;
extern DataAttribute iedModel_ComplexArray_LPHD1_Proxy_stVal;
extern DataAttribute iedModel_ComplexArray_LPHD1_Proxy_q;
extern DataAttribute iedModel_ComplexArray_LPHD1_Proxy_t;
extern LogicalNode iedModel_ComplexArray_MHAI1;
extern DataObject iedModel_ComplexArray_MHAI1_HA;
extern DataObject iedModel_ComplexArray_MHAI1_HA_phsAHar;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag_f;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_ang;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_ang_f;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_q;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_t;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_numHar;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_numCyc;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_evalTm;
extern DataAttribute iedModel_ComplexArray_MHAI1_HA_frequency;
@ -89,7 +42,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -102,7 +55,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -115,7 +68,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -137,7 +90,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -150,7 +103,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -163,7 +116,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -185,7 +138,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -198,7 +151,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -211,7 +164,7 @@ DataAttribute iedModel_ComplexArray_LLN0_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -233,7 +186,7 @@ DataAttribute iedModel_ComplexArray_LLN0_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -246,7 +199,7 @@ DataAttribute iedModel_ComplexArray_LLN0_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -259,7 +212,7 @@ DataAttribute iedModel_ComplexArray_LLN0_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -272,7 +225,7 @@ DataAttribute iedModel_ComplexArray_LLN0_NamPlt_configRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -285,7 +238,7 @@ DataAttribute iedModel_ComplexArray_LLN0_NamPlt_ldNs = {
NULL,
0,
IEC61850_FC_EX,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -315,7 +268,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_PhyNam_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -337,7 +290,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_stVal = {
NULL,
0,
IEC61850_FC_ST,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -350,7 +303,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -363,7 +316,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_PhyHealth_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -385,7 +338,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_Proxy_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -398,7 +351,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_Proxy_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -411,7 +364,7 @@ DataAttribute iedModel_ComplexArray_LPHD1_Proxy_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -450,7 +403,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal = {
(ModelNode*) &iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED + TRG_OPT_DATA_UPDATE,
NULL,
0};
@ -463,7 +416,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag = {
(ModelNode*) &iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED + TRG_OPT_DATA_UPDATE,
NULL,
0};
@ -476,7 +429,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_mag_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED + TRG_OPT_DATA_UPDATE,
NULL,
0};
@ -489,7 +442,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_ang = {
(ModelNode*) &iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_ang_f,
0,
IEC61850_FC_MX,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0 + TRG_OPT_DATA_CHANGED + TRG_OPT_DATA_UPDATE,
NULL,
0};
@ -502,7 +455,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_cVal_ang_f = {
NULL,
0,
IEC61850_FC_MX,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED + TRG_OPT_DATA_UPDATE,
NULL,
0};
@ -515,7 +468,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_q = {
NULL,
0,
IEC61850_FC_MX,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -528,7 +481,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_phsAHar_t = {
NULL,
0,
IEC61850_FC_MX,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -541,7 +494,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_numHar = {
NULL,
0,
IEC61850_FC_CF,
INT16U,
IEC61850_INT16U,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -554,7 +507,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_numCyc = {
NULL,
0,
IEC61850_FC_CF,
INT16U,
IEC61850_INT16U,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -567,7 +520,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_evalTm = {
NULL,
0,
IEC61850_FC_CF,
INT16U,
IEC61850_INT16U,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -580,7 +533,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_frequency = {
NULL,
0,
IEC61850_FC_CF,
FLOAT32,
IEC61850_FLOAT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -590,6 +543,7 @@ DataAttribute iedModel_ComplexArray_MHAI1_HA_frequency = {
IedModel iedModel = {
"test",
&iedModel_ComplexArray,
@ -597,6 +551,7 @@ IedModel iedModel = {
NULL,
NULL,
NULL,
NULL,
initializeValues
};

@ -40,13 +40,13 @@ DE(GGIO1$MX$AnIn2);
DE(GGIO1$MX$AnIn3);
DE(GGIO1$MX$AnIn4);
}
RC(EventsRCB01 Events 0 Events 1 8 111 50 1000);
RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 8 111 50 1000);
RC(EventsRCB01 Events 0 Events 1 24 111 50 1000);
RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 111 50 1000);
GC(gcbEvents events Events 2 0 -1 -1 ){
PA(4 111 1000 010ccd010001);
PA(4 273 4096 010ccd010001);
}
GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){
PA(4 111 1000 010ccd010001);
PA(4 273 4096 010ccd010001);
}
}
LN(LPHD1){

File diff suppressed because it is too large Load Diff

@ -57,6 +57,8 @@ int main(int argc, char** argv) {
ReportControlBlock_create("events01", lln0, "events01", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions, 50, 0);
ReportControlBlock_create("events02", lln0, "events02", false, NULL, 1, TRG_OPT_DATA_CHANGED, rptOptions, 50, 0);
GSEControlBlock_create("gse01", lln0, "events01", "events", 1, false, 200, 3000);
/*********************
* run server
********************/
@ -81,9 +83,8 @@ int main(int argc, char** argv) {
while (running) {
IedServer_lockDataModel(iedServer);
MmsValue_setFloat(temperatureValue->mmsValue, val);
MmsValue_setUtcTimeMs(temperatureTimestamp->mmsValue, Hal_getTimeInMs());
IedServer_updateAttributeValue(iedServer, temperatureValue, temperatureValue->mmsValue);
IedServer_updateUTCTimeAttributeValue(iedServer, temperatureTimestamp, Hal_getTimeInMs())
IedServer_updateFloatAttributeValue(iedServer, temperatureValue, val);
IedServer_unlockDataModel(iedServer);

File diff suppressed because it is too large Load Diff

@ -122,7 +122,6 @@
</DOType>
<DOType cdc="ASG" id="ASG_SE">
<DA bType="Struct" fc="SG" name="setMag" type="AnalogueValue_1"/>
<DA bType="Struct" fc="SE" name="setMag" type="AnalogueValue_1"/>
</DOType>
@ -151,7 +150,6 @@
</DOType>
<DOType id="ING_SE" cdc="ING">
<DA name="setVal" bType="INT32" fc="SG" dchg="true" />
<DA name="setVal" bType="INT32" fc="SE" dchg="true" />
</DOType>

@ -3,101 +3,9 @@
*
* automatically generated from sg_demo.icd
*/
#include <stdlib.h>
#include "iec61850_model.h"
#include "static_model.h"
extern IedModel iedModel;
static void initializeValues();
extern LogicalDevice iedModel_PROT;
extern LogicalNode iedModel_PROT_LLN0;
extern DataObject iedModel_PROT_LLN0_Mod;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_ctlVal;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_operTm;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin_orCat;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin_orIdent;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_ctlNum;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_T;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_Test;
extern DataAttribute iedModel_PROT_LLN0_Mod_Oper_Check;
extern DataAttribute iedModel_PROT_LLN0_Mod_stVal;
extern DataAttribute iedModel_PROT_LLN0_Mod_q;
extern DataAttribute iedModel_PROT_LLN0_Mod_t;
extern DataAttribute iedModel_PROT_LLN0_Mod_ctlModel;
extern DataObject iedModel_PROT_LLN0_Beh;
extern DataAttribute iedModel_PROT_LLN0_Beh_stVal;
extern DataAttribute iedModel_PROT_LLN0_Beh_q;
extern DataAttribute iedModel_PROT_LLN0_Beh_t;
extern DataObject iedModel_PROT_LLN0_Health;
extern DataAttribute iedModel_PROT_LLN0_Health_stVal;
extern DataAttribute iedModel_PROT_LLN0_Health_q;
extern DataAttribute iedModel_PROT_LLN0_Health_t;
extern DataObject iedModel_PROT_LLN0_NamPlt;
extern DataAttribute iedModel_PROT_LLN0_NamPlt_vendor;
extern DataAttribute iedModel_PROT_LLN0_NamPlt_swRev;
extern DataAttribute iedModel_PROT_LLN0_NamPlt_d;
extern DataAttribute iedModel_PROT_LLN0_NamPlt_configRev;
extern DataAttribute iedModel_PROT_LLN0_NamPlt_ldNs;
extern LogicalNode iedModel_PROT_LPHD1;
extern DataObject iedModel_PROT_LPHD1_PhyNam;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_vendor;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_hwRev;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_swRev;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_serNum;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_model;
extern DataAttribute iedModel_PROT_LPHD1_PhyNam_location;
extern DataObject iedModel_PROT_LPHD1_PhyHealth;
extern DataAttribute iedModel_PROT_LPHD1_PhyHealth_stVal;
extern DataAttribute iedModel_PROT_LPHD1_PhyHealth_q;
extern DataAttribute iedModel_PROT_LPHD1_PhyHealth_t;
extern DataObject iedModel_PROT_LPHD1_Proxy;
extern DataAttribute iedModel_PROT_LPHD1_Proxy_stVal;
extern DataAttribute iedModel_PROT_LPHD1_Proxy_q;
extern DataAttribute iedModel_PROT_LPHD1_Proxy_t;
extern LogicalNode iedModel_PROT_PTOC1;
extern DataObject iedModel_PROT_PTOC1_Beh;
extern DataAttribute iedModel_PROT_PTOC1_Beh_stVal;
extern DataAttribute iedModel_PROT_PTOC1_Beh_q;
extern DataAttribute iedModel_PROT_PTOC1_Beh_t;
extern DataObject iedModel_PROT_PTOC1_Mod;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_ctlVal;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_operTm;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin_orCat;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin_orIdent;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_ctlNum;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_T;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_Test;
extern DataAttribute iedModel_PROT_PTOC1_Mod_Oper_Check;
extern DataAttribute iedModel_PROT_PTOC1_Mod_stVal;
extern DataAttribute iedModel_PROT_PTOC1_Mod_q;
extern DataAttribute iedModel_PROT_PTOC1_Mod_t;
extern DataAttribute iedModel_PROT_PTOC1_Mod_ctlModel;
extern DataObject iedModel_PROT_PTOC1_Str;
extern DataAttribute iedModel_PROT_PTOC1_Str_general;
extern DataAttribute iedModel_PROT_PTOC1_Str_dirGeneral;
extern DataAttribute iedModel_PROT_PTOC1_Str_q;
extern DataAttribute iedModel_PROT_PTOC1_Str_t;
extern DataObject iedModel_PROT_PTOC1_Op;
extern DataAttribute iedModel_PROT_PTOC1_Op_general;
extern DataAttribute iedModel_PROT_PTOC1_Op_q;
extern DataAttribute iedModel_PROT_PTOC1_Op_t;
extern DataObject iedModel_PROT_PTOC1_StrVal;
extern DataAttribute iedModel_PROT_PTOC1_StrVal_setMag;
extern DataAttribute iedModel_PROT_PTOC1_StrVal_setMag_f;
extern DataAttribute iedModel_SE_PROT_PTOC1_StrVal_setMag;
extern DataAttribute iedModel_SE_PROT_PTOC1_StrVal_setMag_f;
extern DataObject iedModel_PROT_PTOC1_OpDlTmms;
extern DataAttribute iedModel_PROT_PTOC1_OpDlTmms_setVal;
extern DataAttribute iedModel_SE_PROT_PTOC1_OpDlTmms_setVal;
extern DataObject iedModel_PROT_PTOC1_RsDlTmms;
extern DataAttribute iedModel_PROT_PTOC1_RsDlTmms_setVal;
extern DataAttribute iedModel_SE_PROT_PTOC1_RsDlTmms_setVal;
extern DataObject iedModel_PROT_PTOC1_RstTms;
extern DataAttribute iedModel_PROT_PTOC1_RstTms_setVal;
extern DataAttribute iedModel_SE_PROT_PTOC1_RstTms_setVal;
@ -134,7 +42,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper = {
(ModelNode*) &iedModel_PROT_LLN0_Mod_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -147,7 +55,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -160,7 +68,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_operTm = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -173,7 +81,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin = {
(ModelNode*) &iedModel_PROT_LLN0_Mod_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -186,7 +94,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -199,7 +107,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -212,7 +120,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -225,7 +133,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -238,7 +146,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -251,7 +159,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -264,7 +172,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -277,7 +185,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -290,7 +198,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -303,7 +211,7 @@ DataAttribute iedModel_PROT_LLN0_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -325,7 +233,7 @@ DataAttribute iedModel_PROT_LLN0_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -338,7 +246,7 @@ DataAttribute iedModel_PROT_LLN0_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -351,7 +259,7 @@ DataAttribute iedModel_PROT_LLN0_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -373,7 +281,7 @@ DataAttribute iedModel_PROT_LLN0_Health_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -386,7 +294,7 @@ DataAttribute iedModel_PROT_LLN0_Health_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -399,7 +307,7 @@ DataAttribute iedModel_PROT_LLN0_Health_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -421,7 +329,7 @@ DataAttribute iedModel_PROT_LLN0_NamPlt_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -434,7 +342,7 @@ DataAttribute iedModel_PROT_LLN0_NamPlt_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -447,7 +355,7 @@ DataAttribute iedModel_PROT_LLN0_NamPlt_d = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -460,7 +368,7 @@ DataAttribute iedModel_PROT_LLN0_NamPlt_configRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -473,7 +381,7 @@ DataAttribute iedModel_PROT_LLN0_NamPlt_ldNs = {
NULL,
0,
IEC61850_FC_EX,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -503,7 +411,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_vendor = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -516,7 +424,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_hwRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -529,7 +437,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_swRev = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -542,7 +450,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_serNum = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -555,7 +463,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_model = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -568,7 +476,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyNam_location = {
NULL,
0,
IEC61850_FC_DC,
VISIBLE_STRING_255,
IEC61850_VISIBLE_STRING_255,
0,
NULL,
0};
@ -590,7 +498,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyHealth_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -603,7 +511,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyHealth_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -616,7 +524,7 @@ DataAttribute iedModel_PROT_LPHD1_PhyHealth_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -638,7 +546,7 @@ DataAttribute iedModel_PROT_LPHD1_Proxy_stVal = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -651,7 +559,7 @@ DataAttribute iedModel_PROT_LPHD1_Proxy_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -664,7 +572,7 @@ DataAttribute iedModel_PROT_LPHD1_Proxy_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -694,7 +602,7 @@ DataAttribute iedModel_PROT_PTOC1_Beh_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -707,7 +615,7 @@ DataAttribute iedModel_PROT_PTOC1_Beh_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -720,7 +628,7 @@ DataAttribute iedModel_PROT_PTOC1_Beh_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -742,7 +650,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper = {
(ModelNode*) &iedModel_PROT_PTOC1_Mod_Oper_ctlVal,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -755,7 +663,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_ctlVal = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -768,7 +676,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_operTm = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -781,7 +689,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin = {
(ModelNode*) &iedModel_PROT_PTOC1_Mod_Oper_origin_orCat,
0,
IEC61850_FC_CO,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -794,7 +702,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin_orCat = {
NULL,
0,
IEC61850_FC_CO,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -807,7 +715,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_origin_orIdent = {
NULL,
0,
IEC61850_FC_CO,
OCTET_STRING_64,
IEC61850_OCTET_STRING_64,
0,
NULL,
0};
@ -820,7 +728,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_ctlNum = {
NULL,
0,
IEC61850_FC_CO,
INT8U,
IEC61850_INT8U,
0,
NULL,
0};
@ -833,7 +741,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_T = {
NULL,
0,
IEC61850_FC_CO,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -846,7 +754,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_Test = {
NULL,
0,
IEC61850_FC_CO,
BOOLEAN,
IEC61850_BOOLEAN,
0,
NULL,
0};
@ -859,7 +767,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_Oper_Check = {
NULL,
0,
IEC61850_FC_CO,
CHECK,
IEC61850_CHECK,
0,
NULL,
0};
@ -872,7 +780,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_stVal = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -885,7 +793,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -898,7 +806,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -911,7 +819,7 @@ DataAttribute iedModel_PROT_PTOC1_Mod_ctlModel = {
NULL,
0,
IEC61850_FC_CF,
ENUMERATED,
IEC61850_ENUMERATED,
0,
NULL,
0};
@ -933,7 +841,7 @@ DataAttribute iedModel_PROT_PTOC1_Str_general = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -946,7 +854,7 @@ DataAttribute iedModel_PROT_PTOC1_Str_dirGeneral = {
NULL,
0,
IEC61850_FC_ST,
ENUMERATED,
IEC61850_ENUMERATED,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -959,7 +867,7 @@ DataAttribute iedModel_PROT_PTOC1_Str_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -972,7 +880,7 @@ DataAttribute iedModel_PROT_PTOC1_Str_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -994,7 +902,7 @@ DataAttribute iedModel_PROT_PTOC1_Op_general = {
NULL,
0,
IEC61850_FC_ST,
BOOLEAN,
IEC61850_BOOLEAN,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1007,7 +915,7 @@ DataAttribute iedModel_PROT_PTOC1_Op_q = {
NULL,
0,
IEC61850_FC_ST,
QUALITY,
IEC61850_QUALITY,
0 + TRG_OPT_QUALITY_CHANGED,
NULL,
0};
@ -1020,7 +928,7 @@ DataAttribute iedModel_PROT_PTOC1_Op_t = {
NULL,
0,
IEC61850_FC_ST,
TIMESTAMP,
IEC61850_TIMESTAMP,
0,
NULL,
0};
@ -1042,7 +950,7 @@ DataAttribute iedModel_PROT_PTOC1_StrVal_setMag = {
(ModelNode*) &iedModel_PROT_PTOC1_StrVal_setMag_f,
0,
IEC61850_FC_SG,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1055,7 +963,7 @@ DataAttribute iedModel_PROT_PTOC1_StrVal_setMag_f = {
NULL,
0,
IEC61850_FC_SG,
FLOAT32,
IEC61850_FLOAT32,
0,
NULL,
0};
@ -1068,7 +976,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_StrVal_setMag = {
(ModelNode*) &iedModel_SE_PROT_PTOC1_StrVal_setMag_f,
0,
IEC61850_FC_SE,
CONSTRUCTED,
IEC61850_CONSTRUCTED,
0,
NULL,
0};
@ -1081,7 +989,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_StrVal_setMag_f = {
NULL,
0,
IEC61850_FC_SE,
FLOAT32,
IEC61850_FLOAT32,
0,
NULL,
0};
@ -1103,7 +1011,7 @@ DataAttribute iedModel_PROT_PTOC1_OpDlTmms_setVal = {
NULL,
0,
IEC61850_FC_SG,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1116,7 +1024,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_OpDlTmms_setVal = {
NULL,
0,
IEC61850_FC_SE,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1138,7 +1046,7 @@ DataAttribute iedModel_PROT_PTOC1_RsDlTmms_setVal = {
NULL,
0,
IEC61850_FC_SG,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1151,7 +1059,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_RsDlTmms_setVal = {
NULL,
0,
IEC61850_FC_SE,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1173,7 +1081,7 @@ DataAttribute iedModel_PROT_PTOC1_RstTms_setVal = {
NULL,
0,
IEC61850_FC_SG,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1186,7 +1094,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_RstTms_setVal = {
NULL,
0,
IEC61850_FC_SE,
INT32,
IEC61850_INT32,
0 + TRG_OPT_DATA_CHANGED,
NULL,
0};
@ -1194,6 +1102,7 @@ DataAttribute iedModel_SE_PROT_PTOC1_RstTms_setVal = {
extern SettingGroupControlBlock iedModel_PROT_LLN0_sgcb;
SettingGroupControlBlock iedModel_PROT_LLN0_sgcb = {&iedModel_PROT_LLN0, 1, 5, 0, false, 0, 0, NULL};
@ -1205,6 +1114,7 @@ IedModel iedModel = {
NULL,
NULL,
NULL,
NULL,
&iedModel_PROT_LLN0_sgcb,
initializeValues
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,30 @@
set(sv_subscriber_example_SRCS
sv_subscriber_example.c
)
IF(WIN32)
set_source_files_properties(${sv_subscriber_example_SRCS}
PROPERTIES LANGUAGE CXX)
add_executable(sv_subscriber_example
${sv_subscriber_example_SRCS}
)
target_link_libraries(sv_subscriber_example
iec61850
)
ELSE(WIN32)
add_executable(sv_subscriber_example
${sv_subscriber_example_SRCS}
)
target_link_libraries(sv_subscriber_example
iec61850
)
ENDIF(WIN32)

@ -0,0 +1,21 @@
LIBIEC_HOME=../..
PROJECT_BINARY_NAME = sv_subscriber
PROJECT_SOURCES += sv_subscriber_example.c
INCLUDES += -I.
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,88 @@
/*
* sv_subscriber_example.c
*
* Example program for Sampled Values (SV) subscriber
*
*/
#include "hal_thread.h"
#include <signal.h>
#include <stdio.h>
#include "sv_subscriber.h"
static bool running = true;
void sigint_handler(int signalId)
{
running = 0;
}
/* Callback handler for received SV messages */
static void
svUpdateListener (SVSubscriber subscriber, void* parameter, SVClientASDU asdu)
{
printf("svUpdateListener called\n");
const char* svID = SVClientASDU_getSvId(asdu);
if (svID != NULL)
printf(" svID=(%s)\n", svID);
printf(" smpCnt: %i\n", SVClientASDU_getSmpCnt(asdu));
printf(" confRev: %u\n", SVClientASDU_getConfRev(asdu));
/*
* Access to the data requires a priori knowledge of the data set.
* For this example we assume a data set consisting of FLOAT32 values.
* A FLOAT32 value is encoded as 4 bytes. You can find the first FLOAT32
* value at byte position 0, the second value at byte position 4, the third
* value at byte position 8, and so on.
*
* To prevent damages due configuration, please check the length of the
* data block of the SV message before accessing the data.
*/
if (SVClientASDU_getDataSize(asdu) >= 8) {
printf(" DATA[0]: %f\n", SVClientASDU_getFLOAT32(asdu, 0));
printf(" DATA[1]: %f\n", SVClientASDU_getFLOAT32(asdu, 4));
}
}
int
main(int argc, char** argv)
{
SVReceiver receiver = SVReceiver_create();
if (argc > 1) {
SVReceiver_setInterfaceId(receiver, argv[1]);
printf("Set interface id: %s\n", argv[1]);
}
else {
printf("Using interface eth0\n");
SVReceiver_setInterfaceId(receiver, "eth0");
}
/* Create a subscriber listening to SV messages with APPID 4000h */
SVSubscriber subscriber = SVSubscriber_create(NULL, 0x4000);
/* Install a callback handler for the subscriber */
SVSubscriber_setListener(subscriber, svUpdateListener, NULL);
/* Connect the subscriber to the receiver */
SVReceiver_addSubscriber(receiver, subscriber);
/* Start listening to SV messages - starts a new receiver background thread */
SVReceiver_start(receiver);
signal(SIGINT, sigint_handler);
while (running)
Thread_sleep(1);
/* Stop listening to SV messages */
SVReceiver_stop(receiver);
/* Cleanup and free resources */
SVReceiver_destroy(receiver);
}

@ -0,0 +1,22 @@
LIBIEC_HOME=../../../
PROJECT_BINARY_NAME = sv_test_publisher
PROJECT_SOURCES = sv_publisher.c
# PROJECT_SOURCES += remote_control.c
INCLUDES += -I.
include $(LIBIEC_HOME)/make/target_system.mk
include $(LIBIEC_HOME)/make/stack_includes.mk
all: $(PROJECT_BINARY_NAME)
include $(LIBIEC_HOME)/make/common_targets.mk
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
clean:
rm -f $(PROJECT_BINARY_NAME)

@ -0,0 +1,571 @@
/*
* sv_publisher.c
*
* Copyright 2013 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "stack_config.h"
#include "libiec61850_platform_includes.h"
#include "hal_ethernet.h"
#define DEBUG_SV_PUBLISHER 1
#define CONFIG_SV_DEFAULT_DST_ADDRESS CONFIG_GOOSE_DEFAULT_DST_ADDRESS
#define CONFIG_SV_DEFAULT_PRIORITY 4
#define CONFIG_SV_DEFAULT_VLAN_ID 0
#define CONFIG_SV_DEFAULT_APPID 0x4000
#define SV_MAX_MESSAGE_SIZE 1518
#define IEC61850_SV_SMPSYNC_NOT_SYNCHRONIZED 0
#define IEC61850_SV_SMPSYNC_SYNCED_UNSPEC_LOCAL_CLOCK 1
#define IEC61850_SV_SMPSYNC_SYNCED_GLOBAL_CLOCK 2
#define IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD 0
#define IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND 1
#define IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE 2
typedef struct sCommParameters {
uint8_t vlanPriority;
uint16_t vlanId;
uint16_t appId;
uint8_t dstAddress[6];
} CommParameters;
typedef struct sSV_ASDU* SV_ASDU;
struct sSV_ASDU {
char* svID;
char* datset;
int dataSize;
bool hasRefrTm;
bool hasSmpRate;
bool hasSmpMod;
uint8_t* _dataBuffer;
uint8_t smpSynch;
uint16_t smpCnt;
uint32_t confRev;
uint8_t* smpCntBuf;
SV_ASDU _next;
};
typedef struct sSampledValuesPublisher* SampledValuesPublisher;
struct sSampledValuesPublisher {
uint8_t* buffer;
uint16_t appId;
EthernetSocket ethernetSocket;
int lengthField; /* can probably be removed since packets have fixed size! */
int payloadStart;
int payloadLength; /* length of payload buffer */
int asduCount; /* number of ASDUs in the APDU */
SV_ASDU asduLIst;
};
static void
preparePacketBuffer(SampledValuesPublisher self, CommParameters* parameters, char* interfaceID)
{
uint8_t srcAddr[6];
if (interfaceID != NULL)
Ethernet_getInterfaceMACAddress(interfaceID, srcAddr);
else
Ethernet_getInterfaceMACAddress(CONFIG_ETHERNET_INTERFACE_ID, srcAddr);
uint8_t defaultDstAddr[] = CONFIG_SV_DEFAULT_DST_ADDRESS;
uint8_t* dstAddr;
uint8_t priority;
uint16_t vlanId;
uint16_t appId;
if (parameters == NULL) {
dstAddr = defaultDstAddr;
priority = CONFIG_SV_DEFAULT_PRIORITY;
vlanId = CONFIG_SV_DEFAULT_VLAN_ID;
appId = CONFIG_SV_DEFAULT_APPID;
}
else {
dstAddr = parameters->dstAddress;
priority = parameters->vlanPriority;
vlanId = parameters->vlanId;
appId = parameters->appId;
}
if (interfaceID != NULL)
self->ethernetSocket = Ethernet_createSocket(interfaceID, dstAddr);
else
self->ethernetSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, dstAddr);
self->buffer = (uint8_t*) GLOBAL_MALLOC(SV_MAX_MESSAGE_SIZE);
memcpy(self->buffer, dstAddr, 6);
memcpy(self->buffer + 6, srcAddr, 6);
int bufPos = 12;
/* Priority tag - IEEE 802.1Q */
self->buffer[bufPos++] = 0x81;
self->buffer[bufPos++] = 0x00;
uint8_t tci1 = priority << 5;
tci1 += vlanId / 256;
uint8_t tci2 = vlanId % 256;
self->buffer[bufPos++] = tci1; /* Priority + VLAN-ID */
self->buffer[bufPos++] = tci2; /* VLAN-ID */
/* EtherType Sampled Values */
self->buffer[bufPos++] = 0x88;
self->buffer[bufPos++] = 0xBa;
/* APPID */
self->buffer[bufPos++] = appId / 256;
self->buffer[bufPos++] = appId % 256;
self->lengthField = bufPos;
/* Length */
self->buffer[bufPos++] = 0x00;
self->buffer[bufPos++] = 0x08;
/* Reserved1 */
self->buffer[bufPos++] = 0x00;
self->buffer[bufPos++] = 0x00;
/* Reserved2 */
self->buffer[bufPos++] = 0x00;
self->buffer[bufPos++] = 0x00;
self->payloadStart = bufPos;
}
static int
encodeUInt16FixedSize(uint16_t value, uint8_t* buffer, int bufPos)
{
uint8_t* valueArray = (uint8_t*) &value;
#if (ORDER_LITTLE_ENDIAN == 1)
buffer[bufPos++] = valueArray[1];
buffer[bufPos++] = valueArray[0];
#else
buffer[bufPos++] = valueArray[0];
buffer[bufPos++] = valueArray[1];
#endif
return bufPos;
}
static int
encodeUInt32FixedSize(uint32_t value, uint8_t* buffer, int bufPos)
{
uint8_t* valueArray = (uint8_t*) &value;
#if (ORDER_LITTLE_ENDIAN == 1)
buffer[bufPos++] = valueArray[3];
buffer[bufPos++] = valueArray[2];
buffer[bufPos++] = valueArray[1];
buffer[bufPos++] = valueArray[0];
#else
buffer[bufPos++] = valueArray[0];
buffer[bufPos++] = valueArray[1];
buffer[bufPos++] = valueArray[2];
buffer[bufPos++] = valueArray[3];
#endif
return bufPos;
}
SampledValuesPublisher
SampledValuesPublisher_create()
{
SampledValuesPublisher self = GLOBAL_CALLOC(1, sizeof(struct sSampledValuesPublisher));
self->asduLIst = NULL;
preparePacketBuffer(self, NULL, "eth0");
return self;
}
SV_ASDU
SampledValuesPublisher_addASDU(SampledValuesPublisher self, char* svID, char* datset, uint32_t confRev)
{
SV_ASDU newAsdu = GLOBAL_CALLOC(1, sizeof(struct sSV_ASDU));
newAsdu->svID = svID;
newAsdu->datset = datset;
newAsdu->confRev = confRev;
newAsdu->_next = NULL;
/* append new ASDU to list */
if (self->asduLIst == NULL)
self->asduLIst = newAsdu;
else {
SV_ASDU lastAsdu = self->asduLIst;
while (lastAsdu->_next != NULL)
lastAsdu = lastAsdu->_next;
lastAsdu->_next = newAsdu;
}
return newAsdu;
}
static int
SV_ASDU_getEncodedSize(SV_ASDU self)
{
int encodedSize = 0;
/* svID */
encodedSize += ( 2 + strlen(self->svID) );
/* datset */
if (self->datset != NULL)
encodedSize += ( 2 + strlen(self->datset) );
/* smpCnt */
encodedSize += 4;
/* confRef */
encodedSize += 6;
/* refrTm */
if (self->hasRefrTm)
encodedSize += 10; /* ??? */
/* smpSynch */
encodedSize += 3;
/* smpRate */
if (self->hasSmpRate)
encodedSize += 4;
/* sample */
encodedSize += 2;
encodedSize += self->dataSize;
/* smpMod */
if (self->hasSmpMod)
encodedSize += 4;
return encodedSize;
}
static int
SV_ASDU_encodeToBuffer(SV_ASDU self, uint8_t* buffer, int bufPos)
{
int encodedSize = SV_ASDU_getEncodedSize(self);
/* tag and length field */
bufPos = BerEncoder_encodeTL(0x30, encodedSize, buffer, bufPos);
/* svID */
bufPos = BerEncoder_encodeStringWithTag(0x80, self->svID, buffer, bufPos);
/* DatSet */
if (self->datset != NULL)
bufPos = BerEncoder_encodeStringWithTag(0x81, self->datset, buffer, bufPos);
uint8_t octetString[4];
/* SmpCnt */
bufPos = BerEncoder_encodeTL(0x82, 2, buffer, bufPos);
self->smpCntBuf = buffer + bufPos;
bufPos = encodeUInt16FixedSize(self->smpCnt, buffer, bufPos);
/* ConfRev */
bufPos = BerEncoder_encodeTL(0x83, 4, buffer, bufPos);
bufPos = encodeUInt32FixedSize(self->confRev, buffer, bufPos);
/* RefrTm */
//TODO implement me
/* SmpSynch */
bufPos = BerEncoder_encodeTL(0x85, 1, buffer, bufPos);
buffer[bufPos++] = self->smpSynch;
/* SmpRate */
//TODO implement me
/* Sample */
bufPos = BerEncoder_encodeTL(0x87, self->dataSize, buffer, bufPos);
self->_dataBuffer = buffer + bufPos;
bufPos += self->dataSize; /* data has to inserted by user before sending message */
/* SmpMod */
//TODO implement me
return bufPos;
}
void
SampledValuesPublisher_setupComplete(SampledValuesPublisher self)
{
int numberOfAsdu = 0;
/* determine number of ASDUs and length of all ASDUs */
SV_ASDU nextAsdu = self->asduLIst;
int totalASDULength = 0;
while (nextAsdu != NULL) {
numberOfAsdu++;
int asduLength = SV_ASDU_getEncodedSize(nextAsdu);
/* tag and length field */
asduLength += BerEncoder_determineLengthSize(asduLength);
asduLength++;
totalASDULength += asduLength;
nextAsdu = nextAsdu->_next;
}
/* encode frame to buffer */
int sequenceSize = 1 + BerEncoder_determineLengthSize(totalASDULength) + totalASDULength;
int innerSize = 2 + BerEncoder_UInt32determineEncodedSize(numberOfAsdu) + sequenceSize;
uint8_t* buffer = self->buffer + self->payloadStart;
int bufPos = BerEncoder_encodeTL(0x60, innerSize, buffer, 0);
/* noASDU */
bufPos = BerEncoder_encodeUInt32WithTL(0x80, numberOfAsdu, buffer, bufPos);
/* seqASDU */
bufPos = BerEncoder_encodeTL(0xa2, totalASDULength, buffer, bufPos);
nextAsdu = self->asduLIst;
while (nextAsdu != NULL) {
bufPos = SV_ASDU_encodeToBuffer(nextAsdu, buffer, bufPos);
nextAsdu = nextAsdu->_next;
}
/* Update length field */
int payloadLength = bufPos;
size_t msgLength = payloadLength + 8;
int lengthIndex = self->lengthField;
self->buffer[lengthIndex] = msgLength / 256;
self->buffer[lengthIndex + 1] = msgLength & 0xff;
self->payloadLength = payloadLength;
}
void
SampledValuesPublisher_publish(SampledValuesPublisher self)
{
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: send SV message\n");
Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + self->payloadLength);
}
void
SampledValuesPublisher_destroy(SampledValuesPublisher self)
{
GLOBAL_FREEMEM(self->buffer);
}
void
SV_ASDU_resetBuffer(SV_ASDU self)
{
self->dataSize = 0;
}
int
SV_ASDU_addINT8(SV_ASDU self)
{
int index = self->dataSize;
self->dataSize += 1;
return index;
}
void
SV_ASDU_setINT8(SV_ASDU self, int index, int8_t value)
{
self->_dataBuffer[index] = value;
}
int
SV_ASDU_addINT32(SV_ASDU self)
{
int index = self->dataSize;
self->dataSize += 4;
return index;
}
int
SV_ASDU_addFLOAT(SV_ASDU self)
{
int index = self->dataSize;
self->dataSize += 4;
return index;
}
void
SV_ASDU_setFLOAT(SV_ASDU self, int index, float value)
{
uint8_t* buf = (uint8_t*) &value;
#if (ORDER_LITTLE_ENDIAN == 1)
BerEncoder_revertByteOrder(buf, 4);
#endif
int i;
uint8_t* buffer = self->_dataBuffer + index;
for (i = 0; i < 4; i++) {
buffer[i] = buf[i];
}
}
void
SV_ASDU_setSmpCnt(SV_ASDU self, uint16_t value)
{
//TODO write value to correct field in buffer
}
void
SV_ASDU_increaseSmpCnt(SV_ASDU self)
{
self->smpCnt++;
encodeUInt16FixedSize(self->smpCnt, self->smpCntBuf, 0);
}
#if 0
void
SV_ASDU_setRefrTm(SV_ASDU self, Timestamp refrTm)
{
}
#endif
int
main(int argc, char** argv)
{
SampledValuesPublisher svPublisher = SampledValuesPublisher_create();
SV_ASDU asdu1 = SampledValuesPublisher_addASDU(svPublisher, "svpub1", NULL, 1);
int float1 = SV_ASDU_addFLOAT(asdu1);
int float2 = SV_ASDU_addFLOAT(asdu1);
SV_ASDU asdu2 = SampledValuesPublisher_addASDU(svPublisher, "svpub2", NULL, 1);
int float3 = SV_ASDU_addFLOAT(asdu2);
int float4 = SV_ASDU_addFLOAT(asdu2);
SampledValuesPublisher_setupComplete(svPublisher);
float fVal1 = 1234.5678f;
float fVal2 = 0.12345f;
int i;
for (i = 0; i < 10; i++) {
SV_ASDU_setFLOAT(asdu1, float1, fVal1);
SV_ASDU_setFLOAT(asdu1, float2, fVal2);
SV_ASDU_increaseSmpCnt(asdu1);
SV_ASDU_increaseSmpCnt(asdu2);
fVal1 += 1.1f;
fVal2 += 0.1f;
SampledValuesPublisher_publish(svPublisher);
}
SampledValuesPublisher_destroy(svPublisher);
}
int
main1(int argc, char** argv)
{
SampledValuesPublisher svPublisher = SampledValuesPublisher_create();
SV_ASDU asdu = SampledValuesPublisher_addASDU(svPublisher, "svpub1", NULL, 1);
int float1 = SV_ASDU_addFLOAT(asdu);
int float2 = SV_ASDU_addFLOAT(asdu);
SampledValuesPublisher_setupComplete(svPublisher);
float fVal1 = 1234.5678f;
float fVal2 = 0.12345f;
int i;
for (i = 0; i < 10; i++) {
SV_ASDU_setFLOAT(asdu, float1, fVal1);
SV_ASDU_setFLOAT(asdu, float2, fVal2);
SV_ASDU_increaseSmpCnt(asdu);
fVal1 += 1.1f;
fVal2 += 0.1f;
SampledValuesPublisher_publish(svPublisher);
}
SampledValuesPublisher_destroy(svPublisher);
}

@ -7,3 +7,4 @@ INCLUDES += -I$(LIBIEC_HOME)/src/iec61850/inc
INCLUDES += -I$(LIBIEC_HOME)/src/iec61850/inc_private
INCLUDES += -I$(LIBIEC_HOME)/src/hal/inc
INCLUDES += -I$(LIBIEC_HOME)/src/goose
INCLUDES += -I$(LIBIEC_HOME)/src/sampled_values

@ -58,6 +58,7 @@ set (lib_common_SRCS
./iec61850/client/client_control.c
./iec61850/client/client_report_control.c
./iec61850/client/client_goose_control.c
./iec61850/client/client_sv_control.c
./iec61850/client/client_report.c
./iec61850/client/ied_connection.c
./iec61850/common/iec61850_common.c
@ -71,7 +72,7 @@ set (lib_common_SRCS
./iec61850/server/mms_mapping/mms_mapping.c
./iec61850/server/mms_mapping/reporting.c
./iec61850/server/mms_mapping/mms_goose.c
./iec61850/server/mms_mapping/mms_sv.c
)
set (lib_asn1c_SRCS
@ -173,6 +174,10 @@ set (lib_goose_SRCS
./goose/goose_publisher.c
)
set (lib_sv_SRCS
./sampled_values/sv_subscriber.c
)
set (lib_linux_SRCS
./hal/socket/linux/socket_linux.c
./hal/ethernet/linux/ethernet_linux.c
@ -213,6 +218,8 @@ set_source_files_properties(${lib_common_SRCS} ${lib_windows_SRCS}
IF(WITH_WPCAP)
set_source_files_properties(${lib_goose_SRCS}
PROPERTIES LANGUAGE CXX)
set_source_files_properties(${lib_sv_SRCS}
PROPERTIES LANGUAGE CXX)
ELSE()
add_definitions(-DEXCLUDE_ETHERNET_WINDOWS)
ENDIF()
@ -228,6 +235,7 @@ set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
${lib_goose_SRCS}
${lib_sv_SRCS}
${lib_windows_SRCS}
)
@ -246,6 +254,7 @@ set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
${lib_goose_SRCS}
${lib_sv_SRCS}
${lib_bsd_SRCS}
)
ELSEIF(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
@ -253,6 +262,7 @@ set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
${lib_goose_SRCS}
${lib_sv_SRCS}
${lib_bsd_SRCS}
)
ELSE()
@ -260,6 +270,7 @@ set (library_SRCS
${lib_common_SRCS}
${lib_asn1c_SRCS}
${lib_goose_SRCS}
${lib_sv_SRCS}
${lib_linux_SRCS}
)
ENDIF(APPLE)

@ -15,7 +15,7 @@
#include "platform_endian.h"
#define LIBIEC61850_VERSION "0.8.7"
#define LIBIEC61850_VERSION "0.9.0"
#ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"
@ -29,6 +29,10 @@
#define CONFIG_DEFAULT_MMS_REVISION LIBIEC61850_VERSION
#endif
#ifndef CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT
#define CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT 0
#endif
#if (DEBUG != 1)
#define NDEBUG 1
#endif

@ -18,7 +18,7 @@ DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "libIEC61850"
PROJECT_NUMBER = 0.8.7
PROJECT_NUMBER = 0.9.0
PROJECT_BRIEF = "Open-source IEC 61850 MMS/GOOSE server and client library"
@ -219,6 +219,7 @@ INPUT += "iec61850/inc/iec61850_config_file_parser.h"
INPUT += "iec61850/inc/iec61850_cdc.h"
INPUT += "goose/goose_subscriber.h"
INPUT += "goose/goose_receiver.h"
INPUT += "sampled_values/sv_subscriber.h"
INPUT += "mms/inc/mms_device_model.h"
INPUT += "mms/inc/mms_types.h"
INPUT += "mms/inc/mms_common.h"

@ -109,6 +109,12 @@ GooseSubscriber_isTest(GooseSubscriber self)
return self->simulation;
}
uint32_t
GooseSubscriber_getConfRev(GooseSubscriber self)
{
return self->confRev;
}
bool
GooseSubscriber_needsCommission(GooseSubscriber self)
{

@ -125,6 +125,17 @@ GooseSubscriber_getSqNum(GooseSubscriber self);
bool
GooseSubscriber_isTest(GooseSubscriber self);
/**
* \brief returns the confRev value of the last received GOOSE message
*
* \param self GooseSubscriber instance to operate on.
*
* \return the confRev value of the last received GOOSE message. If the message does not contain such
* a value the result is always 0
*/
uint32_t
GooseSubscriber_getConfRev(GooseSubscriber self);
bool
GooseSubscriber_needsCommission(GooseSubscriber self);

@ -29,6 +29,10 @@
#include "libiec61850_platform_includes.h"
#ifndef DEBUG_HAL_ETHERNET
#define DEBUG_HAL_ETHERNET 1
#endif
#if (CONFIG_INCLUDE_ETHERNET_WINDOWS == 1)
@ -95,11 +99,11 @@ loadDLLs(void)
HINSTANCE hDll = LoadLibrary("iphlpapi.dll");
if (hDll == NULL) {
if (DEBUG_HAL_ETHERNET)
printf("Error loading iphlpapi.dll!\n");
return;
}
GetAdaptersAddresses = (pgetadaptersaddresses) GetProcAddress(hDll,
"GetAdaptersAddresses");
@ -111,7 +115,6 @@ loadDLLs(void)
#endif /* __GNUC__ */
static char*
getInterfaceName(int interfaceIndex)
{
@ -137,6 +140,7 @@ getInterfaceName(int interfaceIndex)
if (i == interfaceIndex) {
interfaceName = (char*) malloc(strlen(device->name) + 1);
strcpy(interfaceName, device->name);
if (DEBUG_HAL_ETHERNET)
printf("Use interface (%s)\n", interfaceName);
ifaceFound = true;
break;
@ -147,6 +151,7 @@ getInterfaceName(int interfaceIndex)
if (!ifaceFound)
{
if (DEBUG_HAL_ETHERNET)
printf("No ethernet interfaces found! Make sure WinPcap is installed.\n");
return NULL;
}
@ -180,13 +185,16 @@ getAdapterMacAddress(char* pcapAdapterName, uint8_t* macAddress)
int i;
if (DEBUG_HAL_ETHERNET) {
printf("Adapter %s: ", pAddress->AdapterName);
for (i = 0; i < (int) addressLength; i++) {
printf("%02x ", pAddress->PhysicalAddress[i]);
}
}
if (strstr(pcapAdapterName, pAddress->AdapterName) != 0) {
if (DEBUG_HAL_ETHERNET)
printf(" requested found!");
for (i = 0; i < (int) addressLength; i++) {

@ -316,7 +316,7 @@ Socket_connect(Socket self, const char* address, int port)
activateTcpNoDelay(self);
#if CONFIG_ACTIVATE_TCP_KEEPALIVE == 1
#if (CONFIG_ACTIVATE_TCP_KEEPALIVE == 1)
activateKeepAlive(self->fd);
#endif

@ -397,11 +397,15 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
/* has report-timestamp */
if (MmsValue_getBitStringBit(optFlds, 2) == true) {
MmsValue* timeStampValue = MmsValue_getElement(value, inclusionIndex);
if (MmsValue_getType(timeStampValue) == MMS_BINARY_TIME) {
matchingReport->hasTimestamp = true;
matchingReport->timestamp = MmsValue_getBinaryTimeAsUtcMs(timeStampValue);
if (DEBUG_IED_CLIENT)
printf("DEBUG_IED_CLIENT: report has timestamp %llu\n", matchingReport->timestamp);
}
inclusionIndex++;

@ -637,7 +637,7 @@ IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientRepo
MmsValue* dataAccessError = (MmsValue*) accessResult->data;
if (MmsValue_getDataAccessError(dataAccessError) != DATA_ACCESS_ERROR_SUCCESS) {
*error = IED_ERROR_UNKNOWN;
*error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(dataAccessError));
break;
}

@ -0,0 +1,358 @@
/*
* client_sv_control.c
*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "iec61850_client.h"
#include "stack_config.h"
#include "ied_connection_private.h"
#include "libiec61850_platform_includes.h"
struct sClientSVControlBlock {
IedConnection connection;
bool isMulticast;
char* reference;
IedClientError lastError;
};
ClientSVControlBlock
ClientSVControlBlock_create(IedConnection connection, const char* reference)
{
bool isMulticast = false;
/* Check if CB exists and if it is a unicast or mulitcast CB */
IedClientError error;
MmsValue* value = IedConnection_readObject(connection, &error, reference, IEC61850_FC_MS);
if (value != NULL) {
isMulticast = true;
MmsValue_delete(value);
}
else {
value = IedConnection_readObject(connection, &error, reference, IEC61850_FC_US);
if (value == NULL)
return NULL;
MmsValue_delete(value);
}
ClientSVControlBlock self = (ClientSVControlBlock) GLOBAL_CALLOC(1, sizeof(struct sClientSVControlBlock));
if (self) {
self->connection = connection;
self->reference = copyString(reference);
self->isMulticast = isMulticast;
}
return self;
}
void
ClientSVControlBlock_destroy(ClientSVControlBlock self)
{
if (self) {
GLOBAL_FREEMEM(self->reference);
GLOBAL_FREEMEM(self);
}
}
IedClientError
ClientSVControlBlock_getLastComError(ClientSVControlBlock self)
{
return self->lastError;
}
bool
ClientSVControlBlock_isMulticast(ClientSVControlBlock self)
{
return self->isMulticast;
}
static bool
setBooleanVariable(ClientSVControlBlock self, const char* varName, bool value)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, varName);
self->lastError = IED_ERROR_OK;
if (self->isMulticast)
IedConnection_writeBooleanValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS, value);
else
IedConnection_writeBooleanValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_US, value);
if (self->lastError == IED_ERROR_OK)
return true;
else
return false;
}
bool
ClientSVControlBlock_setSvEna(ClientSVControlBlock self, bool svEna)
{
return setBooleanVariable(self, "SvEna", svEna);
}
bool
ClientSVControlBlock_setResv(ClientSVControlBlock self, bool svEna)
{
if (self->isMulticast == false)
return setBooleanVariable(self, "SvEna", svEna);
else
return false;
}
static bool
readBooleanVariable(ClientSVControlBlock self, const char* varName)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, varName);
self->lastError = IED_ERROR_OK;
bool retVal;
if (self->isMulticast)
retVal = IedConnection_readBooleanValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS);
else
retVal = IedConnection_readBooleanValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_US);
return retVal;
}
bool
ClientSVControlBlock_getSvEna(ClientSVControlBlock self)
{
return readBooleanVariable(self, "SvEna");
}
bool
ClientSVControlBlock_getResv(ClientSVControlBlock self)
{
return readBooleanVariable(self, "Resv");
}
static char*
readStringVariable(ClientSVControlBlock self, const char* varName)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, varName);
self->lastError = IED_ERROR_OK;
char* retVal;
if (self->isMulticast)
retVal = IedConnection_readStringValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS);
else
retVal = IedConnection_readStringValue(self->connection, &(self->lastError), refBuf, IEC61850_FC_US);
return retVal;
}
char*
ClientSVControlBlock_getMsvID(ClientSVControlBlock self)
{
return readStringVariable(self, "MsvID");
}
char*
ClientSVControlBlock_getDatSet(ClientSVControlBlock self)
{
return readStringVariable(self, "DatSet");
}
static uint32_t
readUIntVariable(ClientSVControlBlock self, const char* varName)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, varName);
self->lastError = IED_ERROR_OK;
uint32_t retVal;
if (self->isMulticast)
retVal = IedConnection_readUnsigned32Value(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS);
else
retVal = IedConnection_readUnsigned32Value(self->connection, &(self->lastError), refBuf, IEC61850_FC_US);
return retVal;
}
uint32_t
ClientSVControlBlock_getConfRev(ClientSVControlBlock self)
{
return readUIntVariable(self, "ConfRev");
}
uint16_t
ClientSVControlBlock_getSmpRate(ClientSVControlBlock self)
{
return readUIntVariable(self, "SmpRate");
}
int
ClientSVControlBlock_getOptFlds(ClientSVControlBlock self)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, "OptFlds");
self->lastError = IED_ERROR_OK;
MmsValue* optFlds;
if (self->isMulticast)
optFlds = IedConnection_readObject(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS);
else
optFlds = IedConnection_readObject(self->connection, &(self->lastError), refBuf, IEC61850_FC_US);
if (optFlds == NULL)
return 0;
int retVal = 0;
if (MmsValue_getType(optFlds) == MMS_BIT_STRING)
retVal = MmsValue_getBitStringAsInteger(optFlds);
MmsValue_delete(optFlds);
return retVal;
}
uint8_t
ClientSVControlBlock_getSmpMod(ClientSVControlBlock self)
{
return readUIntVariable(self, "SmpMod");
}
int
ClientSVControlBlock_getNoASDU(ClientSVControlBlock self)
{
return readUIntVariable(self, "noASDU");
}
PhyComAddress
ClientSVControlBlock_getDstAddress(ClientSVControlBlock self)
{
char refBuf[130];
strcpy(refBuf, self->reference);
strcat(refBuf, ".");
strcat(refBuf, "DstAddress");
self->lastError = IED_ERROR_OK;
MmsValue* dstAddrValue;
if (self->isMulticast)
dstAddrValue = IedConnection_readObject(self->connection, &(self->lastError), refBuf, IEC61850_FC_MS);
else
dstAddrValue = IedConnection_readObject(self->connection, &(self->lastError), refBuf, IEC61850_FC_US);
PhyComAddress retVal;
memset(&retVal, 0, sizeof(retVal));
if (dstAddrValue == NULL) goto exit_error;
if (MmsValue_getType(dstAddrValue) != MMS_STRUCTURE) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
if (MmsValue_getArraySize(dstAddrValue) != 4) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
MmsValue* addr = MmsValue_getElement(dstAddrValue, 0);
if (MmsValue_getType(addr) != MMS_OCTET_STRING) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong type\n");
goto exit_cleanup;
}
if (MmsValue_getOctetStringSize(addr) != 6) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - addr has wrong size\n");
goto exit_cleanup;
}
uint8_t* addrBuf = MmsValue_getOctetStringBuffer(addr);
memcpy(&(retVal.dstAddress), addrBuf, 6);
MmsValue* prio = MmsValue_getElement(dstAddrValue, 1);
if (MmsValue_getType(prio) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - prio has wrong type\n");
goto exit_cleanup;
}
retVal.vlanPriority = MmsValue_toUint32(prio);
MmsValue* vid = MmsValue_getElement(dstAddrValue, 2);
if (MmsValue_getType(vid) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - vid has wrong type\n");
goto exit_cleanup;
}
retVal.vlanId = MmsValue_toUint32(vid);
MmsValue* appID = MmsValue_getElement(dstAddrValue, 3);
if (MmsValue_getType(appID) != MMS_UNSIGNED) {
if (DEBUG_IED_CLIENT) printf("IED_CLIENT: SVCB - appID has wrong type\n");
goto exit_cleanup;
}
retVal.appId = MmsValue_toUint32(appID);
exit_cleanup:
MmsValue_delete(dstAddrValue);
exit_error:
return retVal;
}

@ -1901,6 +1901,16 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
bool isAssociationSpecific = false;
if (dataSetReference[0] != '@') {
if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
domainId = NULL;
if (dataSetReference[0] == '/')
itemId = dataSetReference + 1;
else
itemId = dataSetReference;
}
else {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
if (domainId == NULL) {
@ -1919,6 +1929,7 @@ IedConnection_createDataSet(IedConnection self, IedClientError* error, const cha
StringUtils_replace(itemIdRef, '.', '$');
itemId = itemIdRef;
}
}
else {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
@ -1965,13 +1976,24 @@ exit_function:
void
IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const char* dataSetReference)
{
char domainId[65];
char domainIdBuf[65];
char* domainId = domainIdBuf;
char itemId[DATA_SET_MAX_NAME_LENGTH + 1];
bool isAssociationSpecific = false;
int dataSetReferenceLength = strlen(dataSetReference);
if (dataSetReference[0] != '@') {
if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
domainId = NULL;
if (dataSetReference[0] == '/')
strcpy(itemId, dataSetReference + 1);
else
strcpy(itemId, dataSetReference);
}
else {
if (MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainId) == NULL) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
goto exit_function;
@ -1988,6 +2010,7 @@ IedConnection_deleteDataSet(IedConnection self, IedClientError* error, const cha
StringUtils_replace(itemId, '.', '$');
}
}
else {
if (dataSetReferenceLength > 33) {
*error = IED_ERROR_OBJECT_REFERENCE_INVALID;
@ -2028,6 +2051,15 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
bool isAssociationSpecific = false;
if (dataSetReference[0] != '@') {
if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
domainId = NULL;
if (dataSetReference[0] == '/')
itemId = dataSetReference + 1;
else
itemId = dataSetReference;
}
else {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
if (domainId == NULL) {
@ -2046,6 +2078,7 @@ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, con
StringUtils_replace(itemIdRefInBuffer, '.', '$');
itemId = itemIdRefInBuffer;
}
}
else {
itemId = dataSetReference + 1;
isAssociationSpecific = true;
@ -2103,6 +2136,16 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
bool isAssociationSpecific = false;
if (dataSetReference[0] != '@') {
if ((dataSetReference[0] == '/') || (strchr(dataSetReference, '/') == NULL)) {
domainId = NULL;
if (dataSetReference[0] == '/')
itemId = dataSetReference + 1;
else
itemId = dataSetReference;
}
else {
domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer);
if (domainId == NULL) {
@ -2122,6 +2165,7 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
StringUtils_replace(itemIdRef, '.', '$');
itemId = itemIdRef;
}
}
else {
itemId = dataSetReference + 1;
isAssociationSpecific = true;

@ -125,6 +125,14 @@ FunctionalConstraint_toString(FunctionalConstraint fc) {
return "EX";
case IEC61850_FC_CO:
return "CO";
case IEC61850_FC_US:
return "US";
case IEC61850_FC_MS:
return "MS";
case IEC61850_FC_RP:
return "RP";
case IEC61850_FC_BR:
return "BR";
default:
return NULL;
}
@ -153,6 +161,8 @@ FunctionalConstraint_fromString(const char* fcString)
if (fcString[0] == 'M') {
if (fcString[1] == 'X')
return IEC61850_FC_MX;
if (fcString[1] == 'S')
return IEC61850_FC_MS;
return IEC61850_FC_NONE;
}
@ -179,6 +189,8 @@ FunctionalConstraint_fromString(const char* fcString)
if (fcString[0] == 'B') {
if (fcString[1] == 'L')
return IEC61850_FC_BL;
if (fcString[1] == 'R')
return IEC61850_FC_BR;
return IEC61850_FC_NONE;
}
@ -188,6 +200,18 @@ FunctionalConstraint_fromString(const char* fcString)
return IEC61850_FC_NONE;
}
if (fcString[0] == 'U') {
if (fcString[1] == 'S')
return IEC61850_FC_US;
return IEC61850_FC_NONE;
}
if (fcString[0] == 'R') {
if (fcString[1] == 'P')
return IEC61850_FC_RP;
return IEC61850_FC_NONE;
}
return IEC61850_FC_NONE;
}
@ -288,7 +312,7 @@ Timestamp_setTimeInSeconds(Timestamp* self, uint32_t secondsSinceEpoch)
void
Timestamp_setTimeInMilliseconds(Timestamp* self, uint64_t millisSinceEpoch)
{
uint32_t timeval32 = (millisSinceEpoch / 1000LL);
uint32_t timeval32 = (uint32_t) (millisSinceEpoch / 1000LL);
uint8_t* timeArray = (uint8_t*) &timeval32;
uint8_t* valueArray = self->val;

@ -1,7 +1,7 @@
/*
* iec61850_client.h
*
* Copyright 2013, 2014 Michael Zillgith
* Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -304,6 +304,138 @@ IedConnection_installConnectionClosedHandler(IedConnection self, IedConnectionCl
MmsConnection
IedConnection_getMmsConnection(IedConnection self);
/** @} */
/**
* @defgroup IEC61850_CLIENT_SV Client side SV control block handling functions
*
* @{
*/
/** SV ASDU contains attribute RefrTm */
#define IEC61850_SV_OPT_REFRESH_TIME 1
/** SV ASDU contains attribute SmpSynch */
#define IEC61850_SV_OPT_SAMPLE_SYNC 2
/** SV ASDU contains attribute SmpRate */
#define IEC61850_SV_OPT_SAMPLE_RATE 4
/** SV ASDU contains attribute DatSet */
#define IEC61850_SV_OPT_DATA_SET 8
/** SV ASDU contains attribute Security */
#define IEC61850_SV_OPT_SECURITY 16
/** an opaque handle to the instance data of a ClientSVControlBlock object */
typedef struct sClientSVControlBlock* ClientSVControlBlock;
/**
* \brief Create a new ClientSVControlBlock instance
*
* This function simplifies client side access to server MSV/USV control blocks
* NOTE: Do not use the functions after the IedConnection object is invalidated!
*
* \param connection the IedConnection object with a valid connection to the server.
* \param reference the object reference of the control block
*
* \return the new instance
*/
ClientSVControlBlock
ClientSVControlBlock_create(IedConnection connection, const char* reference);
/**
* \brief Free all resources related to the ClientSVControlBlock instance.
*
* \param self the ClientSVControlBlock instance to operate on
*/
void
ClientSVControlBlock_destroy(ClientSVControlBlock self);
bool
ClientSVControlBlock_isMulticast(ClientSVControlBlock self);
/**
* \brief Return the error code of the last write or write acccess to the SVCB
*
* \param self the ClientSVControlBlock instance to operate on
*
* \return the error code of the last read or write access
*/
IedClientError
ClientSVControlBlock_getLastComError(ClientSVControlBlock self);
bool
ClientSVControlBlock_setSvEna(ClientSVControlBlock self, bool svEna);
bool
ClientSVControlBlock_getSvEna(ClientSVControlBlock self);
bool
ClientSVControlBlock_setResv(ClientSVControlBlock self, bool svEna);
bool
ClientSVControlBlock_getResv(ClientSVControlBlock self);
char*
ClientSVControlBlock_getMsvID(ClientSVControlBlock self);
/**
* \brief Get the (MMS) reference to the data set
*
* NOTE: the returned string is dynamically allocated with the
* GLOBAL_MALLOC macro. The application is responsible to release
* the memory when the string is no longer needed.
*
* \param self the ClientSVControlBlock instance to operate on
*
* \return the data set reference as a NULL terminated string
*/
char*
ClientSVControlBlock_getDatSet(ClientSVControlBlock self);
uint32_t
ClientSVControlBlock_getConfRev(ClientSVControlBlock self);
uint16_t
ClientSVControlBlock_getSmpRate(ClientSVControlBlock self);
/**
* \brief returns the destination address of the SV publisher
*
* \param self the ClientSVControlBlock instance to operate on
*/
PhyComAddress
ClientSVControlBlock_getDstAddress(ClientSVControlBlock self);
/**
* \brief returns the OptFlds bit string as integer
*
* \param self the ClientSVControlBlock instance to operate on
*/
int
ClientSVControlBlock_getOptFlds(ClientSVControlBlock self);
/**
* \brief returns number of sample mode of the SV publisher
*
* \param self the ClientSVControlBlock instance to operate on
*/
uint8_t
ClientSVControlBlock_getSmpMod(ClientSVControlBlock self);
/**
* \brief returns number of ASDUs included in the SV message
*
* \param self the ClientSVControlBlock instance to operate on
*/
int
ClientSVControlBlock_getNoASDU(ClientSVControlBlock self);
/** @} */
/**
@ -1178,7 +1310,9 @@ IedConnection_readDataSetValues(IedConnection self, IedClientError* error, const
* \brief create a new data set at the connected server device
*
* This function creates a new data set at the server. The parameter dataSetReference is the name of the new data set
* to create. It is either in the form LDName/LNodeName.dataSetName or @dataSetName for an association specific data set.
* to create. It is either in the form LDName/LNodeName.dataSetName for permanent domain or VMD scope data sets or
* @dataSetName for an association specific data set. If the LDName part of the reference is missing the resulting
* data set will be of VMD scope.
*
* The dataSetElements parameter contains a linked list containing the object references of FCDs or FCDAs. The format of
* this object references is LDName/LNodeName.item(arrayIndex)component[FC].

@ -36,6 +36,14 @@ extern "C" {
*/
/**@{*/
/** PhyComAddress type contains Ethernet address and VLAN attributes */
typedef struct {
uint8_t vlanPriority;
uint16_t vlanId;
uint16_t appId;
uint8_t dstAddress[6];
} PhyComAddress;
/**
* @defgroup TRIGGER_OPTIONS Trigger options (bit values combinable)
*
@ -217,6 +225,16 @@ typedef enum eFunctionalConstraint {
IEC61850_FC_EX = 11,
/** Control */
IEC61850_FC_CO = 12,
/** Unicast SV */
IEC61850_FC_US = 13,
/** Multicast SV */
IEC61850_FC_MS = 14,
/** Unbuffered report */
IEC61850_FC_RP = 15,
/** Buffered report */
IEC61850_FC_BR = 16,
/** All FCs - wildcard value */
IEC61850_FC_ALL = 99,
IEC61850_FC_NONE = -1
} FunctionalConstraint;

@ -183,7 +183,7 @@ SettingGroupControlBlock_create(LogicalNode* parent, uint8_t actSG, uint8_t numO
* \param parent the parent LN
* \param appId the application ID of the GoCB
* \param dataSet the data set reference to be used by the GoCB
* \param confRef the configuration revision
* \param confRev the configuration revision
* \param fixedOffs indicates if GOOSE publisher shall use fixed offsets (NOT YET SUPPORTED)
* \param minTime minimum GOOSE retransmission time (-1 if not specified - uses stack default then)
* \param maxTime GOOSE retransmission time in stable state (-1 if not specified - uses stack default then)
@ -191,15 +191,40 @@ SettingGroupControlBlock_create(LogicalNode* parent, uint8_t actSG, uint8_t numO
* \return the new GoCB instance
*/
GSEControlBlock*
GSEControlBlock_create(const char* name, LogicalNode* parent, char* appId, char* dataSet, uint32_t confRef,
GSEControlBlock_create(const char* name, LogicalNode* parent, char* appId, char* dataSet, uint32_t confRev,
bool fixedOffs, int minTime, int maxTime);
/**
* \brief create a PhyComAddress object and add it to a GoCB
* \brief create a new Multicast/Unicast Sampled Value (SV) control block (SvCB)
*
* Create a new Sampled Value control block (SvCB) and add it to the given logical node (LN)
*
* \param name name of the SvCB relative to the parent LN
* \param parent the parent LN
* \param svID the application ID of the SvCB
* \param dataSet the data set reference to be used by the SVCB
* \param confRev the configuration revision
* \param smpMod the sampling mode used
* \param smpRate the sampling rate used
* \param optFlds the optional element configuration
*
* \return the new SvCB instance
*/
SVControlBlock*
SVControlBlock_create(const char* name, LogicalNode* parent, char* svID, char* dataSet, uint32_t confRev, uint8_t smpMod,
uint16_t smpRate, uint8_t optFlds, bool isUnicast);
void
SVControlBlock_addPhyComAddress(SVControlBlock* self, PhyComAddress* phyComAddress);
void
GSEControlBlock_addPhyComAddress(GSEControlBlock* self, PhyComAddress* phyComAddress);
/**
* \brief create a PhyComAddress object
*
* A PhyComAddress object contains all required addressing informations for a GOOSE publisher.
* A PhyComAddress object contains all required addressing information for a GOOSE publisher.
*
* \param parent the parent GSEControlBlock object
* \param vlanPriority the priority field of the VLAN tag
* \param vlanId the ID field of the VLAN tag
* \param appId the application identifier
@ -208,7 +233,7 @@ GSEControlBlock_create(const char* name, LogicalNode* parent, char* appId, char*
* \return the new PhyComAddress object
*/
PhyComAddress*
PhyComAddress_create(GSEControlBlock* parent, uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint8_t dstAddress[]);
PhyComAddress_create(uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint8_t dstAddress[]);
/**
* \brief create a new data set

@ -1,7 +1,7 @@
/*
* model.h
*
* Copyright 2013, 2014 Michael Zillgith
* Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -80,8 +80,44 @@ typedef struct sSettingGroupControlBlock SettingGroupControlBlock;
typedef struct sGSEControlBlock GSEControlBlock;
typedef struct sSVControlBlock SVControlBlock;
typedef enum {
IEC61850_BOOLEAN = 0,/* int */
IEC61850_INT8 = 1, /* int8_t */
IEC61850_INT16 = 2, /* int16_t */
IEC61850_INT32 = 3, /* int32_t */
IEC61850_INT64 = 4, /* int64_t */
IEC61850_INT128 = 5, /* no native mapping! */
IEC61850_INT8U = 6, /* uint8_t */
IEC61850_INT16U = 7, /* uint16_t */
IEC61850_INT24U = 8, /* uint32_t */
IEC61850_INT32U = 9, /* uint32_t */
IEC61850_FLOAT32 = 10, /* float */
IEC61850_FLOAT64 = 11, /* double */
IEC61850_ENUMERATED = 12,
IEC61850_OCTET_STRING_64 = 13,
IEC61850_OCTET_STRING_6 = 14,
IEC61850_OCTET_STRING_8 = 15,
IEC61850_VISIBLE_STRING_32 = 16,
IEC61850_VISIBLE_STRING_64 = 17,
IEC61850_VISIBLE_STRING_65 = 18,
IEC61850_VISIBLE_STRING_129 = 19,
IEC61850_VISIBLE_STRING_255 = 20,
IEC61850_UNICODE_STRING_255 = 21,
IEC61850_TIMESTAMP = 22,
IEC61850_QUALITY = 23,
IEC61850_CHECK = 24,
IEC61850_CODEDENUM = 25,
IEC61850_GENERIC_BITSTRING = 26,
IEC61850_CONSTRUCTED = 27,
IEC61850_ENTRY_TIME = 28,
IEC61850_PHYCOMADDR = 29
#if (CONFIG_IEC61850_USE_COMPAT_TYPE_DECLARATIONS == 1)
,
BOOLEAN = 0,/* int */
INT8 = 1, /* int8_t */
INT16 = 2, /* int16_t */
@ -112,6 +148,7 @@ typedef enum {
CONSTRUCTED = 27,
ENTRY_TIME = 28,
PHYCOMADDR = 29
#endif
} DataAttributeType;
typedef enum {
@ -127,6 +164,7 @@ struct sIedModel {
DataSet* dataSets;
ReportControlBlock* rcbs;
GSEControlBlock* gseCBs;
SVControlBlock* svCBs;
SettingGroupControlBlock* sgcbs;
void (*initializer) (void);
};
@ -232,19 +270,12 @@ struct sSettingGroupControlBlock {
SettingGroupControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
};
typedef struct {
uint8_t vlanPriority;
uint16_t vlanId;
uint16_t appId;
uint8_t dstAddress[6];
} PhyComAddress;
struct sGSEControlBlock {
LogicalNode* parent;
char* name;
char* appId;
char* dataSetName; /* pre loaded with relative name in logical node */
uint32_t confRef; /* ConfRef - configuration revision */
uint32_t confRev; /* ConfRev - configuration revision */
bool fixedOffs; /* fixed offsets */
PhyComAddress* address; /* GSE communication parameters */
int minTime; /* optional minTime parameter --> -1 if not present */
@ -252,6 +283,29 @@ struct sGSEControlBlock {
GSEControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
};
struct sSVControlBlock {
LogicalNode* parent;
char* name;
char* svId; /* MsvUD/UsvID */
char* dataSetName; /* pre loaded with relative name in logical node */
uint8_t optFlds;
uint8_t smpMod;
uint16_t smpRate;
uint32_t confRev; /* ConfRev - configuration revision */
PhyComAddress* dstAddress; /* SV communication parameters */
bool isUnicast;
int noASDU;
SVControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
};
/**
* \brief get the number of direct children of a model node
*

@ -40,6 +40,11 @@ struct sMmsMapping {
const char* gooseInterfaceId;
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
LinkedList svControls;
const char* svInterfaceId;
#endif
LinkedList controlObjects;
LinkedList observedObjects;
LinkedList attributeAccessHandlers;

@ -0,0 +1,47 @@
/*
* mms_sv.h
*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#ifndef LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
#define LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_
typedef struct sMmsSampledValueControlBlock* MmsSampledValueControlBlock;
MmsSampledValueControlBlock
MmsSampledValueControlBlock_create(void);
void
MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self);
MmsVariableSpecification*
LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int svCount, bool unicast);
MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig);
MmsDataAccessError
LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
MmsValue* value, MmsServerConnection connection);
#endif /* LIBIEC61850_SRC_IEC61850_INC_PRIVATE_MMS_SV_H_ */

@ -63,7 +63,7 @@ typedef struct {
MmsValue** valueReferences; /* array to store value references for fast access */
bool gi;
bool gi; /* flag to indicate that a GI report is triggered */
uint16_t sqNum;
uint32_t intgPd;
@ -84,9 +84,14 @@ typedef struct {
bool triggered; /* { covered by mutex } */
uint64_t reportTime; /* { covered by mutex } */
/* the following members are only required for buffered RCBs */
/*
* the following members are only required for buffered RCBs *
* TODO move to ReportBuffer structure!
*/
bool isBuffering; /* true if buffered RCB is buffering (datSet is set to a valid value) */
bool isResync; /* true if buffered RCB is in resync state */
ReportBuffer* reportBuffer;
MmsValue* timeOfEntry;
} ReportControl;

@ -188,7 +188,16 @@ createMmsServerCache(IedServer self)
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
if ((strcmp(fcName, "BR") != 0) && (strcmp(fcName, "RP") != 0)
&& (strcmp(fcName, "GO") != 0))
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
&& (strcmp(fcName, "GO") != 0)
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
&& (strcmp(fcName, "MS") != 0) && (strcmp(fcName, "US") != 0)
#endif
)
{
char* variableName = createString(3, lnName, "$", fcName);

@ -305,24 +305,20 @@ MmsGooseControlBlock_checkAndPublish(MmsGooseControlBlock self, uint64_t current
GoosePublisher_publish(self->publisher, self->dataSetValues);
if (self->retransmissionsLeft > 0) {
self->nextPublishTime = currentTime + CONFIG_GOOSE_EVENT_RETRANSMISSION_INTERVAL;
self->nextPublishTime = currentTime + self->minTime;
if (self->retransmissionsLeft > 1)
GoosePublisher_setTimeAllowedToLive(self->publisher,
CONFIG_GOOSE_EVENT_RETRANSMISSION_INTERVAL * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->minTime * 3);
else
GoosePublisher_setTimeAllowedToLive(self->publisher,
CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->maxTime * 3);
self->retransmissionsLeft--;
}
else {
GoosePublisher_setTimeAllowedToLive(self->publisher,
CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->maxTime * 3);
self->nextPublishTime = currentTime +
CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL;
self->nextPublishTime = currentTime + self->maxTime;
}
#if (CONFIG_MMS_THREADLESS_STACK != 1)
@ -343,18 +339,14 @@ MmsGooseControlBlock_observedObjectChanged(MmsGooseControlBlock self)
self->retransmissionsLeft = CONFIG_GOOSE_EVENT_RETRANSMISSION_COUNT;
if (self->retransmissionsLeft > 0) {
self->nextPublishTime = currentTime +
CONFIG_GOOSE_EVENT_RETRANSMISSION_INTERVAL;
self->nextPublishTime = currentTime + self->minTime;
GoosePublisher_setTimeAllowedToLive(self->publisher,
CONFIG_GOOSE_EVENT_RETRANSMISSION_INTERVAL * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->minTime * 3);
}
else {
self->nextPublishTime = currentTime +
CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL;
self->nextPublishTime = currentTime + self->maxTime;
GoosePublisher_setTimeAllowedToLive(self->publisher,
CONFIG_GOOSE_STABLE_STATE_TRANSMISSION_INTERVAL * 3);
GoosePublisher_setTimeAllowedToLive(self->publisher, self->maxTime * 3);
}
GoosePublisher_publish(self->publisher, self->dataSetValues);
@ -550,7 +542,7 @@ GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
MmsValue* confRef = MmsValue_getElement(gseValues, 3);
MmsValue_setUint32(confRef, gooseControlBlock->confRef);
MmsValue_setUint32(confRef, gooseControlBlock->confRev);
mmsGCB->dataSet = NULL;
@ -587,5 +579,5 @@ GOOSE_createGOOSEControlBlocks(MmsMapping* self, MmsDomain* domain,
return namedVariable;
}
#endif
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */

@ -1,7 +1,7 @@
/*
* mms_mapping.c
*
* Copyright 2013, 2014 Michael Zillgith
* Copyright 2013, 2014, 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -28,6 +28,7 @@
#include "stack_config.h"
#include "mms_goose.h"
#include "mms_sv.h"
#include "reporting.h"
#include "control.h"
#include "ied_server_private.h"
@ -154,118 +155,118 @@ createNamedVariableFromDataAttribute(DataAttribute* attribute)
}
else {
switch (attribute->type) {
case BOOLEAN:
case IEC61850_BOOLEAN:
namedVariable->type = MMS_BOOLEAN;
break;
case INT8:
case IEC61850_INT8:
namedVariable->typeSpec.integer = 8;
namedVariable->type = MMS_INTEGER;
break;
case INT16:
case IEC61850_INT16:
namedVariable->typeSpec.integer = 16;
namedVariable->type = MMS_INTEGER;
break;
case INT32:
case IEC61850_INT32:
namedVariable->typeSpec.integer = 32;
namedVariable->type = MMS_INTEGER;
break;
case INT64:
case IEC61850_INT64:
namedVariable->typeSpec.integer = 64;
namedVariable->type = MMS_INTEGER;
break;
case INT128:
case IEC61850_INT128:
namedVariable->typeSpec.integer = 128;
namedVariable->type = MMS_INTEGER;
break;
case INT8U:
case IEC61850_INT8U:
namedVariable->typeSpec.unsignedInteger = 8;
namedVariable->type = MMS_UNSIGNED;
break;
case INT16U:
case IEC61850_INT16U:
namedVariable->typeSpec.unsignedInteger = 16;
namedVariable->type = MMS_UNSIGNED;
break;
case INT24U:
case IEC61850_INT24U:
namedVariable->typeSpec.unsignedInteger = 24;
namedVariable->type = MMS_UNSIGNED;
break;
case INT32U:
case IEC61850_INT32U:
namedVariable->typeSpec.unsignedInteger = 32;
namedVariable->type = MMS_UNSIGNED;
break;
case FLOAT32:
case IEC61850_FLOAT32:
namedVariable->typeSpec.floatingpoint.formatWidth = 32;
namedVariable->typeSpec.floatingpoint.exponentWidth = 8;
namedVariable->type = MMS_FLOAT;
break;
case FLOAT64:
case IEC61850_FLOAT64:
namedVariable->typeSpec.floatingpoint.formatWidth = 64;
namedVariable->typeSpec.floatingpoint.exponentWidth = 11;
namedVariable->type = MMS_FLOAT;
break;
case ENUMERATED:
case IEC61850_ENUMERATED:
namedVariable->typeSpec.integer = 8; /* 8 bit integer should be enough for all enumerations */
namedVariable->type = MMS_INTEGER;
break;
case CHECK:
case IEC61850_CHECK:
namedVariable->typeSpec.bitString = -2;
namedVariable->type = MMS_BIT_STRING;
break;
case CODEDENUM:
case IEC61850_CODEDENUM:
namedVariable->typeSpec.bitString = 2;
namedVariable->type = MMS_BIT_STRING;
break;
case OCTET_STRING_6:
case IEC61850_OCTET_STRING_6:
namedVariable->typeSpec.octetString = -6;
namedVariable->type = MMS_OCTET_STRING;
break;
case OCTET_STRING_8:
case IEC61850_OCTET_STRING_8:
namedVariable->typeSpec.octetString = 8;
namedVariable->type = MMS_OCTET_STRING;
break;
case OCTET_STRING_64:
case IEC61850_OCTET_STRING_64:
namedVariable->typeSpec.octetString = -64;
namedVariable->type = MMS_OCTET_STRING;
break;
case VISIBLE_STRING_32:
case IEC61850_VISIBLE_STRING_32:
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
break;
case VISIBLE_STRING_64:
case IEC61850_VISIBLE_STRING_64:
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
break;
case VISIBLE_STRING_65:
case IEC61850_VISIBLE_STRING_65:
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
break;
case VISIBLE_STRING_129:
case IEC61850_VISIBLE_STRING_129:
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
break;
case VISIBLE_STRING_255:
case IEC61850_VISIBLE_STRING_255:
namedVariable->typeSpec.visibleString = -255;
namedVariable->type = MMS_VISIBLE_STRING;
break;
case UNICODE_STRING_255:
case IEC61850_UNICODE_STRING_255:
namedVariable->typeSpec.mmsString = -255;
namedVariable->type = MMS_STRING;
break;
case GENERIC_BITSTRING:
case IEC61850_GENERIC_BITSTRING:
namedVariable->type = MMS_BIT_STRING;
break;
case TIMESTAMP:
case IEC61850_TIMESTAMP:
namedVariable->type = MMS_UTC_TIME;
break;
case QUALITY:
case IEC61850_QUALITY:
namedVariable->typeSpec.bitString = -13; // -13 = up to 13 bits
namedVariable->type = MMS_BIT_STRING;
break;
case ENTRY_TIME:
case IEC61850_ENTRY_TIME:
namedVariable->type = MMS_BINARY_TIME;
namedVariable->typeSpec.binaryTime = 6;
break;
case PHYCOMADDR:
case IEC61850_PHYCOMADDR:
MmsMapping_createPhyComAddrStructure(namedVariable);
break;
default:
@ -766,9 +767,8 @@ countGSEControlBlocksForLogicalNode(MmsMapping* self, LogicalNode* logicalNode)
GSEControlBlock* gcb = self->model->gseCBs;
while (gcb != NULL) {
if (gcb->parent == logicalNode) {
if (gcb->parent == logicalNode)
gseCount++;
}
gcb = gcb->sibling;
}
@ -778,6 +778,27 @@ countGSEControlBlocksForLogicalNode(MmsMapping* self, LogicalNode* logicalNode)
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
static int
countSVControlBlocksForLogicalNode(MmsMapping* self, LogicalNode* logicalNode, bool unicast)
{
int svCount = 0;
SVControlBlock* svCb = self->model->svCBs;
while (svCb != NULL) {
if ((svCb->parent == logicalNode) && (svCb->isUnicast == unicast))
svCount++;
svCb = svCb->sibling;
}
return svCount;
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
static SettingGroupControlBlock*
checkForSgcb(MmsMapping* self, LogicalNode* logicalNode)
{
@ -862,6 +883,28 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
int msvcbCount = countSVControlBlocksForLogicalNode(self, logicalNode, false);
if (msvcbCount > 0) {
if (DEBUG_IED_SERVER)
printf(" and %i MSV control blocks\n", msvcbCount);
componentCount++;
}
int usvcbCount = countSVControlBlocksForLogicalNode(self, logicalNode, true);
if (usvcbCount > 0) {
if (DEBUG_IED_SERVER)
printf(" and %i USV control blocks\n", usvcbCount);
componentCount++;
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
namedVariable->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(componentCount,
sizeof(MmsVariableSpecification*));
@ -961,6 +1004,24 @@ createNamedVariableFromLogicalNode(MmsMapping* self, MmsDomain* domain,
currentComponent++;
}
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Add MS and US named variables */
if (msvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] =
LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, false);
currentComponent++;
}
if (usvcbCount > 0) {
namedVariable->typeSpec.structure.elements[currentComponent] =
LIBIEC61850_SV_createSVControlBlocks(self, domain, logicalNode, msvcbCount, true);
currentComponent++;
}
#endif
if (LogicalNode_hasFCData(logicalNode, IEC61850_FC_EX)) {
namedVariable->typeSpec.structure.elements[currentComponent] =
createFCNamedVariable(logicalNode, IEC61850_FC_EX);
@ -1138,6 +1199,11 @@ MmsMapping_create(IedModel* model)
self->gooseInterfaceId = NULL;
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
self->svControls = LinkedList_create();
self->svInterfaceId = NULL;
#endif
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
self->controlObjects = LinkedList_create();
#endif
@ -1177,6 +1243,10 @@ MmsMapping_destroy(MmsMapping* self)
LinkedList_destroyDeep(self->gseControls, (LinkedListValueDeleteFunction) MmsGooseControlBlock_destroy);
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
LinkedList_destroyDeep(self->svControls, (LinkedListValueDeleteFunction) MmsSampledValueControlBlock_destroy);
#endif
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
LinkedList_destroyDeep(self->controlObjects, (LinkedListValueDeleteFunction) ControlObject_destroy);
#endif
@ -1284,6 +1354,23 @@ isGooseControlBlock(char* separator)
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
static bool
isSampledValueControlBlock(char* separator)
{
if (strncmp(separator + 1, "MS", 2) == 0)
return true;
if (strncmp(separator + 1, "US", 2) == 0)
return true;
return false;
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
char*
MmsMapping_getNextNameElement(char* name)
{
@ -1604,12 +1691,22 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* Goose control block - GO */
if (isGooseControlBlock(separator)) {
if (isGooseControlBlock(separator))
return writeAccessGooseControlBlock(self, domain, variableId, value);
}
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Sampled Value control block - MS/US */
if (isSampledValueControlBlock(separator))
return LIBIEC61850_SV_writeAccessSVControlBlock(self, domain, variableId, value, connection);
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) {
@ -2006,6 +2103,7 @@ readAccessGooseControlBlock(MmsMapping* self, MmsDomain* domain, char* variableI
#endif /* (CONFIG_INCLUDE_GOOSE_SUPPORT == 1) */
static MmsValue*
mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerConnection connection)
{
@ -2031,14 +2129,23 @@ mmsReadHandler(void* parameter, MmsDomain* domain, char* variableId, MmsServerCo
}
#endif
/* GOOSE control blocks - GO */
#if (CONFIG_INCLUDE_GOOSE_SUPPORT == 1)
/* GOOSE control blocks - GO */
if (isGooseControlBlock(separator)) {
retValue = readAccessGooseControlBlock(self, domain, variableId);
goto exit_function;
}
#endif
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
/* Sampled Value control blocks - MS/US */
if (isSampledValueControlBlock(separator)) {
retValue = LIBIEC61850_SV_readAccessSampledValueControlBlock(self, domain, variableId);
goto exit_function;
}
#endif
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
/* Report control blocks - BR, RP */
if (isReportControlBlock(separator)) {

@ -0,0 +1,493 @@
/*
* mms_sv.c
*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "stack_config.h"
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)
#include "libiec61850_platform_includes.h"
#include "mms_mapping.h"
#include "linked_list.h"
#include "array_list.h"
#include "mms_sv.h"
#include "mms_mapping_internal.h"
struct sMmsSampledValueControlBlock {
char* name;
bool svEna;
MmsServerConnection reservedByClient;
char* dstAddress;
MmsDomain* domain;
LogicalNode* logicalNode;
MmsVariableSpecification* mmsType;
MmsValue* mmsValue;
MmsValue* svEnaValue;
MmsValue* resvValue;
};
MmsSampledValueControlBlock
MmsSampledValueControlBlock_create()
{
MmsSampledValueControlBlock self = (MmsSampledValueControlBlock) GLOBAL_CALLOC(1, sizeof(struct sMmsSampledValueControlBlock));
return self;
}
void
MmsSampledValueControlBlock_destroy(MmsSampledValueControlBlock self)
{
MmsValue_delete(self->mmsValue);
GLOBAL_FREEMEM(self);
}
static MmsSampledValueControlBlock
lookupSVCB(MmsMapping* self, MmsDomain* domain, char* lnName, char* objectName)
{
LinkedList element = LinkedList_getNext(self->svControls);
while (element != NULL) {
MmsSampledValueControlBlock mmsSVCB = (MmsSampledValueControlBlock) element->data;
if (mmsSVCB->domain == domain) {
if (strcmp(mmsSVCB->logicalNode->name, lnName) == 0) {
if (strcmp(mmsSVCB->name, objectName) == 0) {
return mmsSVCB;
}
}
}
element = LinkedList_getNext(element);
}
return NULL;
}
static void
MmsSampledValueControlBlock_enable(MmsSampledValueControlBlock self)
{
//TODO call application callback handler
self->svEna = true;
MmsValue_setBoolean(self->svEnaValue, true);
}
static void
MmsSampledValueControlBlock_disable(MmsSampledValueControlBlock self)
{
//TODO call application callback handler
self->svEna = false;
MmsValue_setBoolean(self->svEnaValue, false);
}
static bool
MmsSampledValueControlBlock_isEnabled(MmsSampledValueControlBlock self)
{
return self->svEna;
}
MmsDataAccessError
LIBIEC61850_SV_writeAccessSVControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig,
MmsValue* value, MmsServerConnection connection)
{
char variableId[130];
strncpy(variableId, variableIdOrig, 129);
char* separator = strchr(variableId, '$');
*separator = 0;
char* lnName = variableId;
if (lnName == NULL)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
char* objectName = MmsMapping_getNextNameElement(separator + 1);
if (objectName == NULL)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
*(varName - 1) = 0;
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
MmsSampledValueControlBlock mmsSVCB = lookupSVCB(self, domain, lnName, objectName);
if (mmsSVCB == NULL)
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
if (mmsSVCB->reservedByClient != NULL) {
if (mmsSVCB->reservedByClient != connection)
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
}
if (strcmp(varName, "Resv") == 0) {
if (MmsValue_getType(value) != MMS_BOOLEAN)
return DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
if (MmsValue_getBoolean(value)) {
mmsSVCB->reservedByClient = connection;
MmsValue_setBoolean(mmsSVCB->resvValue, true);
}
else {
mmsSVCB->reservedByClient = NULL;
MmsValue_setBoolean(mmsSVCB->resvValue, false);
}
return DATA_ACCESS_ERROR_SUCCESS;
}
else if (strcmp(varName, "SvEna") == 0) {
if (MmsValue_getType(value) != MMS_BOOLEAN)
return DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
if (MmsValue_getBoolean(value))
MmsSampledValueControlBlock_enable(mmsSVCB);
else
MmsSampledValueControlBlock_disable(mmsSVCB);
return DATA_ACCESS_ERROR_SUCCESS;
}
else {
if (MmsSampledValueControlBlock_isEnabled(mmsSVCB))
return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE;
else {
bool allowAccess = false;
// In 61850-9-2 mapping only Resv and SvEna are writable!
if (allowAccess)
return DATA_ACCESS_ERROR_SUCCESS;
else
return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
}
}
}
MmsValue*
LIBIEC61850_SV_readAccessSampledValueControlBlock(MmsMapping* self, MmsDomain* domain, char* variableIdOrig)
{
MmsValue* value = NULL;
char variableId[130];
strncpy(variableId, variableIdOrig, 129);
char* separator = strchr(variableId, '$');
*separator = 0;
char* lnName = variableId;
if (lnName == NULL)
return NULL;
char* objectName = MmsMapping_getNextNameElement(separator + 1);
if (objectName == NULL)
return NULL;
char* varName = MmsMapping_getNextNameElement(objectName);
if (varName != NULL)
*(varName - 1) = 0;
MmsSampledValueControlBlock mmsSVCB = lookupSVCB(self, domain, lnName, objectName);
if (mmsSVCB != NULL) {
if (varName != NULL) {
value = MmsValue_getSubElement(mmsSVCB->mmsValue, mmsSVCB->mmsType, varName);
}
else {
value = mmsSVCB->mmsValue;
}
}
return value;
}
static SVControlBlock*
getSVCBForLogicalNodeWithIndex(MmsMapping* self, LogicalNode* logicalNode, int index, bool isUnicast)
{
int svCount = 0;
SVControlBlock* svcb = self->model->svCBs;
/* Iterate list of SvCBs */
while (svcb != NULL ) {
if ((svcb->parent == logicalNode) && (svcb->isUnicast == isUnicast)) {
if (svCount == index)
return svcb;
svCount++;
}
svcb = svcb->sibling;
}
return NULL ;
}
static MmsVariableSpecification*
createSVControlBlockMmsStructure(char* gcbName, bool isUnicast)
{
MmsVariableSpecification* gcb = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
gcb->name = copyString(gcbName);
gcb->type = MMS_STRUCTURE;
int elementCount;
if (isUnicast)
elementCount = 10;
else
elementCount = 9;
gcb->typeSpec.structure.elementCount = elementCount;
gcb->typeSpec.structure.elements = (MmsVariableSpecification**)
GLOBAL_CALLOC(elementCount, sizeof(MmsVariableSpecification*));
int currentElement = 0;
MmsVariableSpecification* namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("SvEna");
namedVariable->type = MMS_BOOLEAN;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
if (isUnicast) {
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("Resv");
namedVariable->type = MMS_BOOLEAN;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
}
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
if (isUnicast)
namedVariable->name = copyString("UsvID");
else
namedVariable->name = copyString("MsvID");
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("DatSet");
namedVariable->typeSpec.visibleString = -129;
namedVariable->type = MMS_VISIBLE_STRING;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("ConfRev");
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.integer = 32;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("SmpRate");
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.unsignedInteger = 32;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("OptFlds");
namedVariable->type = MMS_BIT_STRING;
namedVariable->typeSpec.bitString = 5;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("SmpMod");
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.integer = 8;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("DstAddress");
MmsMapping_createPhyComAddrStructure(namedVariable);
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("noASDU");
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.integer = 32;
gcb->typeSpec.structure.elements[currentElement++] = namedVariable;
return gcb;
}
static void
createDataSetReference(char* buffer, char* domainName, char* lnName, char* dataSetName)
{
StringUtils_createStringInBuffer(buffer, 5, domainName, "/", lnName, "$", dataSetName);
}
MmsVariableSpecification*
LIBIEC61850_SV_createSVControlBlocks(MmsMapping* self, MmsDomain* domain,
LogicalNode* logicalNode, int svCount, bool unicast)
{
MmsVariableSpecification* namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1,
sizeof(MmsVariableSpecification));
if (unicast)
namedVariable->name = copyString("US");
else
namedVariable->name = copyString("MS");
namedVariable->type = MMS_STRUCTURE;
namedVariable->typeSpec.structure.elementCount = svCount;
namedVariable->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(svCount,
sizeof(MmsVariableSpecification*));
int currentSVCB = 0;
char dataRefBuffer[130];
while (currentSVCB < svCount) {
SVControlBlock* svControlBlock = getSVCBForLogicalNodeWithIndex(
self, logicalNode, currentSVCB, unicast);
MmsVariableSpecification* svTypeSpec = createSVControlBlockMmsStructure(svControlBlock->name, unicast);
MmsValue* svValues = MmsValue_newStructure(svTypeSpec);
namedVariable->typeSpec.structure.elements[currentSVCB] = svTypeSpec;
int currentIndex = 0;
/* SvEna */
MmsValue* svEna = MmsValue_getElement(svValues, currentIndex++);
MmsValue* resv = NULL;
if (unicast) {
/* Resv */
resv = MmsValue_getElement(svValues, currentIndex++);
}
/* SvID */
MmsValue* svID = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setVisibleString(svID, svControlBlock->svId);
/* DatSet */
MmsValue* dataSetRef = MmsValue_getElement(svValues, currentIndex++);
createDataSetReference(dataRefBuffer, MmsDomain_getName(domain),
logicalNode->name, svControlBlock->dataSetName);
MmsValue_setVisibleString(dataSetRef, dataRefBuffer);
/* ConfRev */
MmsValue* confRev = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(confRev, svControlBlock->confRev);
/* SmpRate */
MmsValue* smpRate = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(smpRate, svControlBlock->smpRate);
/* OptFlds */
MmsValue* optFlds = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setBitStringFromInteger(optFlds, svControlBlock->optFlds);
/* SmpMod */
MmsValue* smpMod = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(smpMod, svControlBlock->smpMod);
/* Set communication parameters - DstAddress */
uint8_t priority = CONFIG_GOOSE_DEFAULT_PRIORITY;
uint8_t dstAddr[] = CONFIG_GOOSE_DEFAULT_DST_ADDRESS;
uint16_t vid = CONFIG_GOOSE_DEFAULT_VLAN_ID;
uint16_t appId = CONFIG_GOOSE_DEFAULT_APPID;
if (svControlBlock->dstAddress != NULL) {
priority = svControlBlock->dstAddress->vlanPriority;
vid = svControlBlock->dstAddress->vlanId;
appId = svControlBlock->dstAddress->appId;
int i;
for (i = 0; i < 6; i++) {
dstAddr[i] = svControlBlock->dstAddress->dstAddress[i];
}
}
MmsValue* dstAddress = MmsValue_getElement(svValues, currentIndex++);
MmsValue* addr = MmsValue_getElement(dstAddress, 0);
MmsValue_setOctetString(addr, dstAddr, 6);
MmsValue* prio = MmsValue_getElement(dstAddress, 1);
MmsValue_setUint8(prio, priority);
MmsValue* vlanId = MmsValue_getElement(dstAddress, 2);
MmsValue_setUint16(vlanId, vid);
MmsValue* appIdVal = MmsValue_getElement(dstAddress, 3);
MmsValue_setUint16(appIdVal, appId);
/* noASDU */
MmsValue* noASDU = MmsValue_getElement(svValues, currentIndex++);
MmsValue_setInt32(noASDU, svControlBlock->noASDU);
MmsSampledValueControlBlock mmsSvCb = MmsSampledValueControlBlock_create();
mmsSvCb->mmsValue = svValues;
mmsSvCb->svEnaValue = svEna;
mmsSvCb->resvValue = resv;
mmsSvCb->mmsType = svTypeSpec;
mmsSvCb->domain = domain;
mmsSvCb->logicalNode = logicalNode;
mmsSvCb->name = svControlBlock->name;
LinkedList_add(self->svControls, (void*) mmsSvCb);
currentSVCB++;
}
return namedVariable;
}
#endif /* (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1) */

@ -43,6 +43,10 @@
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
#ifndef CONFIG_IEC61850_BRCB_WITH_RESVTMS
#define CONFIG_IEC61850_BRCB_WITH_RESVTMS 0
#endif
static ReportBuffer*
ReportBuffer_create(void)
{
@ -53,7 +57,7 @@ ReportBuffer_create(void)
self->memoryBlockSize = CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE;
self->memoryBlock = (uint8_t*) GLOBAL_MALLOC(self->memoryBlockSize);
self->reportsCount = 0;
self->isOverflow = false;
self->isOverflow = true;
return self;
}
@ -216,10 +220,15 @@ ReportControl_getRCBValue(ReportControl* rc, char* elementName)
return MmsValue_getElement(rc->rcbValues, 11);
else if (strcmp(elementName, "TimeofEntry") == 0)
return MmsValue_getElement(rc->rcbValues, 12);
#if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
else if (strcmp(elementName, "ResvTms") == 0)
return MmsValue_getElement(rc->rcbValues, 13);
else if (strcmp(elementName, "Owner") == 0)
return MmsValue_getElement(rc->rcbValues, 14);
#else
else if (strcmp(elementName, "Owner") == 0)
return MmsValue_getElement(rc->rcbValues, 13);
#endif
} else {
if (strcmp(elementName, "RptID") == 0)
return MmsValue_getElement(rc->rcbValues, 0);
@ -499,8 +508,13 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
if (dataSet == NULL) {
/* check if association specific data set is requested */
if (dataSetName[0] == '@') {
if (rc->buffered == false) { /* for buffered report non-permanent datasets are not allowed */
if (connection != NULL) {
MmsNamedVariableList mmsVariableList
= MmsServerConnection_getNamedVariableList(connection, dataSetName + 1);
@ -509,6 +523,16 @@ updateReportDataset(MmsMapping* mapping, ReportControl* rc, MmsValue* newDatSet,
dataSet = MmsMapping_createDataSetByNamedVariableList(mapping, mmsVariableList);
}
}
}
/* check for VMD specific data set */
else if (dataSetName[0] == '/') {
MmsNamedVariableList mmsVariableList = MmsDevice_getNamedVariableListWithName(mapping->mmsDevice, dataSetName + 1);
if (mmsVariableList != NULL)
dataSet = MmsMapping_createDataSetByNamedVariableList(mapping, mmsVariableList);
}
}
if (dataSet == NULL)
@ -634,7 +658,7 @@ refreshTriggerOptions(ReportControl* rc)
static void
purgeBuf(ReportControl* rc)
{
if (DEBUG_IED_SERVER) printf("reporting.c: run purgeBuf\n");
if (DEBUG_IED_SERVER) printf("IED_SERVER: reporting.c: run purgeBuf\n");
ReportBuffer* reportBuffer = rc->reportBuffer;
@ -836,15 +860,23 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
rcb->name = copyString(reportControlBlock->name);
rcb->type = MMS_STRUCTURE;
int brcbElementCount;
#if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
brcbElementCount = 15;
#else
brcbElementCount = 14;
#endif
MmsValue* mmsValue = (MmsValue*) GLOBAL_CALLOC(1, sizeof(MmsValue));
mmsValue->deleteValue = false;
mmsValue->type = MMS_STRUCTURE;
mmsValue->value.structure.size = 15;
mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(15, sizeof(MmsValue*));
mmsValue->value.structure.size = brcbElementCount;
mmsValue->value.structure.components = (MmsValue**) GLOBAL_CALLOC(brcbElementCount, sizeof(MmsValue*));
rcb->typeSpec.structure.elementCount = 15;
rcb->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(15,
rcb->typeSpec.structure.elementCount = brcbElementCount;
rcb->typeSpec.structure.elements = (MmsVariableSpecification**) GLOBAL_CALLOC(brcbElementCount,
sizeof(MmsVariableSpecification*));
MmsVariableSpecification* namedVariable =
@ -957,19 +989,24 @@ createBufferedReportControlBlock(ReportControlBlock* reportControlBlock,
reportControl->timeOfEntry = mmsValue->value.structure.components[12];
int currentIndex = 13;
#if (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1)
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("ResvTms");
namedVariable->type = MMS_UNSIGNED;
namedVariable->typeSpec.unsignedInteger = 32;
rcb->typeSpec.structure.elements[13] = namedVariable;
mmsValue->value.structure.components[13] = MmsValue_newUnsigned(32);
namedVariable->type = MMS_INTEGER;
namedVariable->typeSpec.integer = 16;
rcb->typeSpec.structure.elements[currentIndex] = namedVariable;
mmsValue->value.structure.components[currentIndex] = MmsValue_newInteger(16);
currentIndex++;
#endif /* (CONFIG_IEC61850_BRCB_WITH_RESVTMS == 1) */
namedVariable = (MmsVariableSpecification*) GLOBAL_CALLOC(1, sizeof(MmsVariableSpecification));
namedVariable->name = copyString("Owner");
namedVariable->type = MMS_OCTET_STRING;
namedVariable->typeSpec.octetString = -64;
rcb->typeSpec.structure.elements[14] = namedVariable;
mmsValue->value.structure.components[14] = MmsValue_newOctetString(0, 4); /* size 4 is enough to store client IPv4 address */
rcb->typeSpec.structure.elements[currentIndex] = namedVariable;
mmsValue->value.structure.components[currentIndex] = MmsValue_newOctetString(0, 128); /* size 4 is enough to store client IPv4 address */
reportControl->rcbValues = mmsValue;
@ -1143,6 +1180,24 @@ updateOwner(ReportControl* rc, MmsServerConnection connection)
#endif /* CONFIG_REPORTING_SUPPORTS_OWNER == 1*/
}
static bool
checkForZeroEntryID(MmsValue* value)
{
uint8_t* buffer = MmsValue_getOctetStringBuffer(value);
int i = 0;
while (i < 8) {
if (buffer[i] != 0)
return false;
i++;
}
return true;
}
static bool
checkReportBufferForEntryID(ReportControl* rc, MmsValue* value)
{
@ -1154,18 +1209,14 @@ checkReportBufferForEntryID(ReportControl* rc, MmsValue* value)
if (memcmp(entry->entryId, value->value.octetString.buf, 8) == 0) {
ReportBufferEntry* nextEntryForResync = entry->next;
if (nextEntryForResync != NULL) {
rc->reportBuffer->nextToTransmit = nextEntryForResync;
rc->isResync = true;
}
else {
rc->isResync = false;
rc->reportBuffer->nextToTransmit = NULL;
}
retVal = true;
break;
}
entry = entry->next;
}
return retVal;
@ -1202,7 +1253,7 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
}
if (DEBUG_IED_SERVER)
printf("Activate report for client %s\n",
printf("IED_SERVER: Activate report for client %s\n",
MmsServerConnection_getClientAddress(connection));
if (updateReportDataset(self, rc, NULL, connection)) {
@ -1213,8 +1264,17 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
MmsValue_update(rptEna, value);
rc->enabled = true;
if (rc->buffered) {
if (rc->isResync == false) {
rc->reportBuffer->nextToTransmit = rc->reportBuffer->oldestReport;
rc->reportBuffer->isOverflow = true;
}
rc->isResync = false;
}
rc->enabled = true;
rc->gi = false;
refreshBufferTime(rc);
@ -1245,10 +1305,14 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
}
if (DEBUG_IED_SERVER)
printf("Deactivate report for client %s\n",
printf("IED_SERVER: Deactivate report for client %s\n",
MmsServerConnection_getClientAddress(connection));
if (rc->buffered == false) {
if (rc->buffered) {
rc->reportBuffer->isOverflow = true;
rc->isResync = false;
}
else {
GLOBAL_FREEMEM(rc->inclusionFlags);
rc->inclusionFlags = NULL;
@ -1270,8 +1334,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
if (strcmp(elementName, "GI") == 0) {
if ((rc->enabled) && (rc->clientConnection == connection)) {
if (MmsValue_getBoolean(value))
if (MmsValue_getBoolean(value)) {
if (rc->triggerOps & TRG_OPT_GI)
rc->gi = true;
}
retVal = DATA_ACCESS_ERROR_SUCCESS;
goto exit_function;
@ -1321,7 +1387,6 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
increaseConfRev(rc);
}
else {
printf("BBBBBB\n");
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
@ -1360,19 +1425,30 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
goto exit_function;
}
else if (strcmp(elementName, "EntryId") == 0) {
else if (strcmp(elementName, "EntryID") == 0) {
if (MmsValue_getOctetStringSize(value) != 8) {
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
if (checkForZeroEntryID(value) == false) {
if (!checkReportBufferForEntryID(rc, value)) {
rc->reportBuffer->isOverflow = true;
retVal = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
goto exit_function;
}
MmsValue* entryID = ReportControl_getRCBValue(rc, elementName);
rc->reportBuffer->isOverflow = false;
}
else {
rc->reportBuffer->nextToTransmit = rc->reportBuffer->oldestReport;
rc->reportBuffer->isOverflow = true;
rc->isResync = false;
}
MmsValue* entryID = ReportControl_getRCBValue(rc, elementName);
MmsValue_update(entryID, value);
goto exit_function;
@ -1392,13 +1468,12 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
goto exit_function;
}
else if ((strcmp(elementName, "ConfRev") == 0) || (strcmp(elementName, "SqNum") == 0)) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "RptID") == 0) {
MmsValue* rptId = ReportControl_getRCBValue(rc, elementName);
if (rc->buffered)
purgeBuf(rc);
if (strlen(MmsValue_toString(value)) == 0)
updateWithDefaultRptId(rc, rptId);
else
@ -1406,6 +1481,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
goto exit_function;
}
else if (strcmp(elementName, "ConfRev") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "SqNum") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
@ -1414,6 +1493,10 @@ Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* eleme
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
else if (strcmp(elementName, "TimeofEntry") == 0) {
retVal = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto exit_function;
}
MmsValue* rcbValue = ReportControl_getRCBValue(rc, elementName);
@ -1474,6 +1557,7 @@ printEnqueuedReports(ReportControl* reportControl)
{
ReportBuffer* rb = reportControl->reportBuffer;
#if 0
printf("IED_SERVER: --- Enqueued reports ---\n");
if (rb->oldestReport == NULL) {
@ -1504,7 +1588,8 @@ printEnqueuedReports(ReportControl* reportControl)
entry = entry->next;
}
}
printf("IED_SERVER: reports: %i\n", rb->reportsCount);
#endif
printf("IED_SERVER: BRCB %s reports: %i\n", reportControl->name, rb->reportsCount);
printf("IED_SERVER: -------------------------\n");
}
@ -1518,6 +1603,42 @@ printReportId(ReportBufferEntry* report)
}
#endif
static void
removeAllGIReportsFromReportBuffer(ReportBuffer* reportBuffer)
{
ReportBufferEntry* currentReport = reportBuffer->oldestReport;
ReportBufferEntry* lastReport = NULL;
while (currentReport != NULL) {
if (currentReport->flags & 2) {
if (currentReport == reportBuffer->oldestReport) {
reportBuffer->oldestReport = currentReport->next;
}
else {
lastReport->next = currentReport->next;
}
#if (DEBUG_IED_SERVER == 1)
printf("IED_SERVER: REMOVE old GI report with ID ");
printReportId(currentReport);
printf("\n");
#endif
if (reportBuffer->nextToTransmit == currentReport)
reportBuffer->nextToTransmit = currentReport->next;
currentReport = currentReport->next;
}
else {
lastReport = currentReport;
currentReport = currentReport->next;
}
}
}
static void
enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_t timeOfEntry)
{
@ -1582,6 +1703,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
return;
}
if (isGI) removeAllGIReportsFromReportBuffer(buffer);
uint8_t* entryBufPos = NULL;
uint8_t* entryStartPos;
@ -1605,7 +1728,7 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if (DEBUG_IED_SERVER) printf ("IED_SERVER: Last buffer offset: %i\n", (int) ((uint8_t*) buffer->lastEnqueuedReport - buffer->memoryBlock));
if (buffer->lastEnqueuedReport == buffer->oldestReport) { // --> buffer->reportsCount = 1?
if (buffer->lastEnqueuedReport == buffer->oldestReport) { /* --> buffer->reportsCount == 1 */
assert(buffer->reportsCount == 1);
entryBufPos = (uint8_t*) ((uint8_t*) buffer->lastEnqueuedReport + buffer->lastEnqueuedReport->entryLength);
@ -1639,11 +1762,14 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if ((entryBufPos + bufferEntrySize) > (buffer->memoryBlock + buffer->memoryBlockSize)) { /* buffer overflow */
entryBufPos = buffer->memoryBlock;
/* remove old reports until enough space for new entry is available */
while ((entryBufPos + bufferEntrySize) > (uint8_t*) buffer->oldestReport) {
assert(buffer->oldestReport != NULL);
if (buffer->nextToTransmit == buffer->oldestReport)
if (buffer->nextToTransmit == buffer->oldestReport) {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
}
#if (DEBUG_IED_SERVER == 1)
printf("IED_SERVER: REMOVE report with ID ");
@ -1651,8 +1777,6 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
printf("\n");
#endif
buffer->isOverflow = true;
buffer->oldestReport = buffer->oldestReport->next;
buffer->reportsCount--;
@ -1677,8 +1801,10 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
while ((uint8_t*) buffer->oldestReport > buffer->memoryBlock) {
assert(buffer->oldestReport != NULL);
if (buffer->nextToTransmit == buffer->oldestReport)
if (buffer->nextToTransmit == buffer->oldestReport) {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
}
#if (DEBUG_IED_SERVER == 1)
printf("IED_SERVER: REMOVE report with ID ");
@ -1697,8 +1823,10 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
assert(buffer->oldestReport != NULL);
if (buffer->nextToTransmit == buffer->oldestReport)
if (buffer->nextToTransmit == buffer->oldestReport) {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
}
#if (DEBUG_IED_SERVER == 1)
printf("IED_SERVER: REMOVE report with ID ");
@ -1718,8 +1846,10 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
assert(buffer->oldestReport != NULL);
if (buffer->nextToTransmit == buffer->oldestReport)
if (buffer->nextToTransmit == buffer->oldestReport) {
buffer->nextToTransmit = buffer->oldestReport->next;
buffer->isOverflow = true;
}
#if (DEBUG_IED_SERVER == 1)
printf("IED_SERVER: REMOVE report with ID ");
@ -1930,8 +2060,10 @@ sendNextReportEntry(ReportControl* self)
if (timeOfEntry == NULL) goto return_out_of_memory;
timeOfEntry->deleteValue = 0;
timeOfEntry->type = MMS_UTC_TIME;
MmsValue_setUtcTimeMs(timeOfEntry, report->timeOfEntry);
timeOfEntry->type = MMS_BINARY_TIME;
timeOfEntry->value.binaryTime.size = 6;
MmsValue_setBinaryTime(timeOfEntry, report->timeOfEntry);
if (MemAllocLinkedList_add(reportElements, timeOfEntry) == NULL)
goto return_out_of_memory;

@ -35,12 +35,12 @@ DataAttribute*
CAC_AnalogueValue_create(const char* name, ModelNode* parent, FunctionalConstraint fc, uint8_t triggerOptions,
bool isIntegerNotFloat)
{
DataAttribute* analogeValue = DataAttribute_create(name, parent, CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute* analogeValue = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, fc, triggerOptions, 0, 0);
if (isIntegerNotFloat)
DataAttribute_create("i", (ModelNode*) analogeValue, INT32, fc, triggerOptions, 0, 0);
DataAttribute_create("i", (ModelNode*) analogeValue, IEC61850_INT32, fc, triggerOptions, 0, 0);
else
DataAttribute_create("f", (ModelNode*) analogeValue, FLOAT32, fc, triggerOptions, 0, 0);
DataAttribute_create("f", (ModelNode*) analogeValue, IEC61850_FLOAT32, fc, triggerOptions, 0, 0);
return analogeValue;
}
@ -48,12 +48,12 @@ CAC_AnalogueValue_create(const char* name, ModelNode* parent, FunctionalConstrai
DataAttribute*
CAC_ValWithTrans_create(const char* name, ModelNode* parent, FunctionalConstraint fc, uint8_t triggerOptions, bool hasTransientIndicator)
{
DataAttribute* valWithTrans = DataAttribute_create(name, parent, CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute* valWithTrans = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute_create("posVal", (ModelNode*) valWithTrans, INT8, fc, triggerOptions, 0, 0);
DataAttribute_create("posVal", (ModelNode*) valWithTrans, IEC61850_INT8, fc, triggerOptions, 0, 0);
if (hasTransientIndicator)
DataAttribute_create("transInd", (ModelNode*) valWithTrans, BOOLEAN, fc, triggerOptions, 0, 0);
DataAttribute_create("transInd", (ModelNode*) valWithTrans, IEC61850_BOOLEAN, fc, triggerOptions, 0, 0);
return valWithTrans;
}
@ -64,7 +64,7 @@ CAC_ValWithTrans_create(const char* name, ModelNode* parent, FunctionalConstrain
DataAttribute*
CAC_Vector_create(const char* name, ModelNode* parent, uint32_t options, FunctionalConstraint fc, uint8_t triggerOptions)
{
DataAttribute* vector = DataAttribute_create(name, parent, CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute* vector = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, fc, triggerOptions, 0, 0);
CAC_AnalogueValue_create("mag", (ModelNode*) vector, fc, triggerOptions, false);
@ -77,13 +77,13 @@ CAC_Vector_create(const char* name, ModelNode* parent, uint32_t options, Functio
DataAttribute*
CAC_Point_create(const char* name, ModelNode* parent, FunctionalConstraint fc, uint8_t triggerOptions, bool hasZVal)
{
DataAttribute* point = DataAttribute_create(name, parent, CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute* point = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, fc, triggerOptions, 0, 0);
DataAttribute_create("xVal", (ModelNode*) point, FLOAT32, fc, triggerOptions, 0, 0);
DataAttribute_create("yVal", (ModelNode*) point, FLOAT32, fc, triggerOptions, 0, 0);
DataAttribute_create("xVal", (ModelNode*) point, IEC61850_FLOAT32, fc, triggerOptions, 0, 0);
DataAttribute_create("yVal", (ModelNode*) point, IEC61850_FLOAT32, fc, triggerOptions, 0, 0);
if (hasZVal)
DataAttribute_create("zVal", (ModelNode*) point, FLOAT32, fc, triggerOptions, 0, 0);
DataAttribute_create("zVal", (ModelNode*) point, IEC61850_FLOAT32, fc, triggerOptions, 0, 0);
return point;
}
@ -91,10 +91,10 @@ CAC_Point_create(const char* name, ModelNode* parent, FunctionalConstraint fc, u
DataAttribute*
CAC_ScaledValueConfig_create(const char* name, ModelNode* parent)
{
DataAttribute* scaling = DataAttribute_create(name, parent, CONSTRUCTED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute* scaling = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("scaleFactor", (ModelNode*) scaling, FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("offset", (ModelNode*) scaling, FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("scaleFactor", (ModelNode*) scaling, IEC61850_FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("offset", (ModelNode*) scaling, IEC61850_FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
return scaling;
}
@ -102,12 +102,12 @@ CAC_ScaledValueConfig_create(const char* name, ModelNode* parent)
DataAttribute*
CAC_Unit_create(const char* name, ModelNode* parent, bool hasMagnitude)
{
DataAttribute* unit = DataAttribute_create(name, parent, CONSTRUCTED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute* unit = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("SIUnit", (ModelNode*) unit, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("SIUnit", (ModelNode*) unit, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
if (hasMagnitude)
DataAttribute_create("multiplier", (ModelNode*) unit, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("multiplier", (ModelNode*) unit, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
return unit;
}
@ -119,10 +119,10 @@ CAC_Unit_create(const char* name, ModelNode* parent, bool hasMagnitude)
static void
addOriginator(char* name, ModelNode* parent, FunctionalConstraint fc)
{
DataAttribute* origin = DataAttribute_create(name, parent, CONSTRUCTED, fc, 0 ,0 ,0);
DataAttribute* origin = DataAttribute_create(name, parent, IEC61850_CONSTRUCTED, fc, 0 ,0 ,0);
DataAttribute_create("orCat", (ModelNode*) origin, ENUMERATED, fc, 0, 0, 0);
DataAttribute_create("orIdent", (ModelNode*) origin, OCTET_STRING_64, fc, 0, 0, 0);
DataAttribute_create("orCat", (ModelNode*) origin, IEC61850_ENUMERATED, fc, 0, 0, 0);
DataAttribute_create("orIdent", (ModelNode*) origin, IEC61850_OCTET_STRING_64, fc, 0, 0, 0);
}
@ -132,38 +132,38 @@ addGenericOperateElements(DataAttribute* oper, DataAttributeType type, bool isTi
DataAttribute_create("ctlVal", (ModelNode*) oper, type, IEC61850_FC_CO, 0, 0, 0);
if (isTimeActivated)
DataAttribute_create("operTm", (ModelNode*) oper, TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("operTm", (ModelNode*) oper, IEC61850_TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
addOriginator("origin", (ModelNode*) oper, IEC61850_FC_CO);
DataAttribute_create("ctlNum", (ModelNode*) oper, INT8U, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("T", (ModelNode*) oper, TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Test", (ModelNode*) oper, BOOLEAN, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("ctlNum", (ModelNode*) oper, IEC61850_INT8U, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("T", (ModelNode*) oper, IEC61850_TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Test", (ModelNode*) oper, IEC61850_BOOLEAN, IEC61850_FC_CO, 0, 0, 0);
if (hasCheck)
DataAttribute_create("Check", (ModelNode*) oper, CHECK, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Check", (ModelNode*) oper, IEC61850_CHECK, IEC61850_FC_CO, 0, 0, 0);
}
static void
addCommonOperateElements(DataAttribute* oper, bool isTimeActivated, bool hasCheck)
{
if (isTimeActivated)
DataAttribute_create("operTm", (ModelNode*) oper, TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("operTm", (ModelNode*) oper, IEC61850_TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
addOriginator("origin", (ModelNode*) oper, IEC61850_FC_CO);
DataAttribute_create("ctlNum", (ModelNode*) oper, INT8U, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("T", (ModelNode*) oper, TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Test", (ModelNode*) oper, BOOLEAN, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("ctlNum", (ModelNode*) oper, IEC61850_INT8U, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("T", (ModelNode*) oper, IEC61850_TIMESTAMP, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Test", (ModelNode*) oper, IEC61850_BOOLEAN, IEC61850_FC_CO, 0, 0, 0);
if (hasCheck)
DataAttribute_create("Check", (ModelNode*) oper, CHECK, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("Check", (ModelNode*) oper, IEC61850_CHECK, IEC61850_FC_CO, 0, 0, 0);
}
static DataAttribute*
CDA_Oper(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
{
DataAttribute* oper = DataAttribute_create("Oper", parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* oper = DataAttribute_create("Oper", parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
addGenericOperateElements(oper, type, isTImeActivated, true);
@ -173,7 +173,7 @@ CDA_Oper(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
static DataAttribute*
CDA_SBOw(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
{
DataAttribute* oper = DataAttribute_create("SBOw", parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* oper = DataAttribute_create("SBOw", parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
addGenericOperateElements(oper, type, isTImeActivated, true);
@ -183,7 +183,7 @@ CDA_SBOw(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
static DataAttribute*
CDA_Cancel(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
{
DataAttribute* oper = DataAttribute_create("Cancel", parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* oper = DataAttribute_create("Cancel", parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
addGenericOperateElements(oper, type, isTImeActivated, false);
@ -199,8 +199,8 @@ CDA_Cancel(ModelNode* parent, DataAttributeType type, bool isTImeActivated)
static void
CDC_addTimeQuality(DataObject* dataObject, FunctionalConstraint fc)
{
DataAttribute_create("q", (ModelNode*) dataObject, QUALITY, fc, TRG_OPT_QUALITY_CHANGED, 0, 0);
DataAttribute_create("t", (ModelNode*) dataObject, TIMESTAMP, fc, 0, 0, 0);
DataAttribute_create("q", (ModelNode*) dataObject, IEC61850_QUALITY, fc, TRG_OPT_QUALITY_CHANGED, 0, 0);
DataAttribute_create("t", (ModelNode*) dataObject, IEC61850_TIMESTAMP, fc, 0, 0, 0);
}
static void
@ -213,21 +213,21 @@ CDC_addStatusToDataObject(DataObject* dataObject, DataAttributeType statusType)
static void
CDC_addOptionPicsSubst(DataObject* dataObject, DataAttributeType type)
{
DataAttribute_create("subEna", (ModelNode*) dataObject, BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subEna", (ModelNode*) dataObject, IEC61850_BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subVal", (ModelNode*) dataObject, type, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subQ", (ModelNode*) dataObject, QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) dataObject, VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subQ", (ModelNode*) dataObject, IEC61850_QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) dataObject, IEC61850_VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
}
static void
CDC_addOptionPicsSubstValWithTrans(DataObject* dataObject, bool hasTransientIndicator)
{
DataAttribute_create("subEna", (ModelNode*) dataObject, BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subEna", (ModelNode*) dataObject, IEC61850_BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
CAC_ValWithTrans_create("subVal", (ModelNode*) dataObject, IEC61850_FC_SV, 0, hasTransientIndicator);
DataAttribute_create("subQ", (ModelNode*) dataObject, QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) dataObject, VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subQ", (ModelNode*) dataObject, IEC61850_QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) dataObject, IEC61850_VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
}
/* Add optional attributes for extension (name spaces) and textual descriptions */
@ -236,18 +236,18 @@ CDC_addStandardOptions(DataObject* dataObject, uint32_t options)
{
/* Standard options ? */
if (options & CDC_OPTION_DESC)
DataAttribute_create("d",(ModelNode*) dataObject, VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
DataAttribute_create("d",(ModelNode*) dataObject, IEC61850_VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
if (options & CDC_OPTION_DESC_UNICODE)
DataAttribute_create("dU", (ModelNode*) dataObject, UNICODE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
DataAttribute_create("dU", (ModelNode*) dataObject, IEC61850_UNICODE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
if (options & CDC_OPTION_AC_DLNDA) {
DataAttribute_create("cdcNs", (ModelNode*) dataObject, VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
DataAttribute_create("cdcName", (ModelNode*) dataObject, VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
DataAttribute_create("cdcNs", (ModelNode*) dataObject, IEC61850_VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
DataAttribute_create("cdcName", (ModelNode*) dataObject, IEC61850_VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
}
if (options & CDC_OPTION_AC_DLN)
DataAttribute_create("dataNs", (ModelNode*) dataObject, VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
DataAttribute_create("dataNs", (ModelNode*) dataObject, IEC61850_VISIBLE_STRING_255, IEC61850_FC_EX, 0, 0, 0);
}
/************************************************
@ -259,13 +259,13 @@ CDC_SPS_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newSPS = DataObject_create(dataObjectName, parent, 0);
CDC_addStatusToDataObject(newSPS, BOOLEAN);
CDC_addStatusToDataObject(newSPS, IEC61850_BOOLEAN);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newSPS, BOOLEAN);
CDC_addOptionPicsSubst(newSPS, IEC61850_BOOLEAN);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newSPS, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newSPS, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newSPS, options);
@ -277,13 +277,13 @@ CDC_DPS_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newDPS = DataObject_create(dataObjectName, parent, 0);
CDC_addStatusToDataObject(newDPS, CODEDENUM);
CDC_addStatusToDataObject(newDPS, IEC61850_CODEDENUM);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newDPS, CODEDENUM);
CDC_addOptionPicsSubst(newDPS, IEC61850_CODEDENUM);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newDPS, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newDPS, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newDPS, options);
@ -295,13 +295,13 @@ CDC_INS_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newINS = DataObject_create(dataObjectName, parent, 0);
CDC_addStatusToDataObject(newINS, INT32);
CDC_addStatusToDataObject(newINS, IEC61850_INT32);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newINS, INT32);
CDC_addOptionPicsSubst(newINS, IEC61850_INT32);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newINS, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newINS, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newINS, options);
@ -314,13 +314,13 @@ CDC_ENS_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newENS = DataObject_create(dataObjectName, parent, 0);
CDC_addStatusToDataObject(newENS, ENUMERATED);
CDC_addStatusToDataObject(newENS, IEC61850_ENUMERATED);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newENS, ENUMERATED);
CDC_addOptionPicsSubst(newENS, IEC61850_ENUMERATED);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newENS, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newENS, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newENS, options);
@ -332,25 +332,25 @@ CDC_BCR_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newBCR = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("actVal", (ModelNode*) newBCR, INT64, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("actVal", (ModelNode*) newBCR, IEC61850_INT64, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_FROZEN_VALUE) {
DataAttribute_create("frVal", (ModelNode*) newBCR, INT64, IEC61850_FC_ST, TRG_OPT_DATA_UPDATE, 0, 0);
DataAttribute_create("frTm", (ModelNode*) newBCR, TIMESTAMP, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("frVal", (ModelNode*) newBCR, IEC61850_INT64, IEC61850_FC_ST, TRG_OPT_DATA_UPDATE, 0, 0);
DataAttribute_create("frTm", (ModelNode*) newBCR, IEC61850_TIMESTAMP, IEC61850_FC_ST, 0, 0, 0);
}
CDC_addTimeQuality(newBCR, IEC61850_FC_ST);
if (options & CDC_OPTION_UNIT)
DataAttribute_create("units", (ModelNode*) newBCR, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("units", (ModelNode*) newBCR, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("pulsQty", (ModelNode*) newBCR, FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("pulsQty", (ModelNode*) newBCR, IEC61850_FLOAT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_FROZEN_VALUE) {
DataAttribute_create("frEna", (ModelNode*) newBCR, BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("strTm", (ModelNode*) newBCR, TIMESTAMP, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("frPd", (ModelNode*) newBCR, INT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("frRs", (ModelNode*) newBCR, BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("frEna", (ModelNode*) newBCR, IEC61850_BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("strTm", (ModelNode*) newBCR, IEC61850_TIMESTAMP, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("frPd", (ModelNode*) newBCR, IEC61850_INT32, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("frRs", (ModelNode*) newBCR, IEC61850_BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
}
CDC_addStandardOptions(newBCR, options);
@ -363,15 +363,15 @@ CDC_SEC_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newSEC = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("cnt", (ModelNode*) newSEC, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("sev", (ModelNode*) newSEC, ENUMERATED, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("t", (ModelNode*) newSEC, TIMESTAMP, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("cnt", (ModelNode*) newSEC, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("sev", (ModelNode*) newSEC, IEC61850_ENUMERATED, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("t", (ModelNode*) newSEC, IEC61850_TIMESTAMP, IEC61850_FC_ST, 0, 0, 0);
if (options & CDC_OPTION_ADDR)
DataAttribute_create("addr", (ModelNode*) newSEC, OCTET_STRING_64, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("addr", (ModelNode*) newSEC, IEC61850_OCTET_STRING_64, IEC61850_FC_ST, 0, 0, 0);
if (options & CDC_OPTION_ADDINFO)
DataAttribute_create("addInfo", (ModelNode*) newSEC, VISIBLE_STRING_64, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("addInfo", (ModelNode*) newSEC, IEC61850_VISIBLE_STRING_64, IEC61850_FC_ST, 0, 0, 0);
CDC_addStandardOptions(newSEC, options);
@ -397,7 +397,7 @@ CDC_MV_create(const char* dataObjectName, ModelNode* parent, uint32_t options, b
CAC_AnalogueValue_create("mag", (ModelNode*) newMV, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED | TRG_OPT_DATA_UPDATE, isIntegerNotFloat);
if (options & CDC_OPTION_RANGE)
DataAttribute_create("range", (ModelNode*) newMV, ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("range", (ModelNode*) newMV, IEC61850_ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addTimeQuality(newMV, IEC61850_FC_MX);
@ -424,10 +424,10 @@ CDC_CMV_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
CAC_Vector_create("cVal", (ModelNode*) newMV, options, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED | TRG_OPT_DATA_UPDATE);
if (options & CDC_OPTION_RANGE)
DataAttribute_create("range", (ModelNode*) newMV, ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("range", (ModelNode*) newMV, IEC61850_ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_RANGE_ANG)
DataAttribute_create("rangeAng", (ModelNode*) newMV, ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("rangeAng", (ModelNode*) newMV, IEC61850_ENUMERATED, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addTimeQuality(newMV, IEC61850_FC_MX);
@ -477,17 +477,17 @@ CDC_HST_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
{
DataObject* newHST = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("hstVal", (ModelNode*) newHST, INT32, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED | TRG_OPT_DATA_UPDATE, maxPts, 0);
DataAttribute_create("hstVal", (ModelNode*) newHST, IEC61850_INT32, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED | TRG_OPT_DATA_UPDATE, maxPts, 0);
CDC_addTimeQuality(newHST, IEC61850_FC_ST);
DataAttribute_create("numPts", (ModelNode*) newHST, INT16U, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("numPts", (ModelNode*) newHST, IEC61850_INT16U, IEC61850_FC_CF, 0, 0, 0);
//TODO add mandatory attribute "hstRangeC"
CAC_Unit_create("units", (ModelNode*) newHST, options & CDC_OPTION_UNIT_MULTIPLIER);
DataAttribute_create("maxPts", (ModelNode*) newHST, INT16U, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("maxPts", (ModelNode*) newHST, IEC61850_INT16U, IEC61850_FC_CF, 0, 0, 0);
CDC_addStandardOptions(newHST, options);
@ -499,7 +499,7 @@ static void
addControls(DataObject* parent, DataAttributeType type, uint32_t controlOptions)
{
DataAttribute* ctlModel =
DataAttribute_create("ctlModel", (ModelNode*) parent, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("ctlModel", (ModelNode*) parent, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
int controlModel = controlOptions & 0x07;
@ -508,7 +508,7 @@ addControls(DataObject* parent, DataAttributeType type, uint32_t controlOptions)
if (controlModel > 0) {
if (controlModel == CDC_CTL_MODEL_SBO_NORMAL)
DataAttribute_create("SBO", (ModelNode*) parent, VISIBLE_STRING_129, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("SBO", (ModelNode*) parent, IEC61850_VISIBLE_STRING_129, IEC61850_FC_CO, 0, 0, 0);
bool isTimeActivated = false;
@ -533,7 +533,7 @@ addOriginatorAndCtlNumOptions(ModelNode* parent, uint32_t controlOptions)
addOriginator("origin", parent, IEC61850_FC_ST);
if (controlOptions & CDC_CTL_OPTION_CTL_NUM)
DataAttribute_create("ctlNum", parent, INT8U, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("ctlNum", parent, IEC61850_INT8U, IEC61850_FC_ST, 0, 0, 0);
}
/**
@ -552,15 +552,15 @@ CDC_SPC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addOriginatorAndCtlNumOptions((ModelNode*) newSPC, controlOptions);
CDC_addStatusToDataObject(newSPC, BOOLEAN);
CDC_addStatusToDataObject(newSPC, IEC61850_BOOLEAN);
addControls(newSPC, BOOLEAN, controlOptions);
addControls(newSPC, IEC61850_BOOLEAN, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newSPC, BOOLEAN);
CDC_addOptionPicsSubst(newSPC, IEC61850_BOOLEAN);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newSPC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newSPC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newSPC, options);
@ -583,15 +583,15 @@ CDC_DPC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addOriginatorAndCtlNumOptions((ModelNode*) newDPC, controlOptions);
CDC_addStatusToDataObject(newDPC, CODEDENUM);
CDC_addStatusToDataObject(newDPC, IEC61850_CODEDENUM);
addControls(newDPC, BOOLEAN, controlOptions);
addControls(newDPC, IEC61850_BOOLEAN, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newDPC, CODEDENUM);
CDC_addOptionPicsSubst(newDPC, IEC61850_CODEDENUM);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newDPC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newDPC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newDPC, options);
@ -602,7 +602,7 @@ static void
addAnalogControls(DataObject* parent, uint32_t controlOptions, bool isIntegerNotFloat)
{
DataAttribute* ctlModel =
DataAttribute_create("ctlModel", (ModelNode*) parent, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("ctlModel", (ModelNode*) parent, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
int controlModel = controlOptions & 0x07;
@ -611,7 +611,7 @@ addAnalogControls(DataObject* parent, uint32_t controlOptions, bool isIntegerNot
if (controlModel != CDC_CTL_MODEL_NONE) {
if (controlModel == CDC_CTL_MODEL_SBO_NORMAL)
DataAttribute_create("SBO", (ModelNode*) parent, VISIBLE_STRING_129, IEC61850_FC_CO, 0, 0, 0);
DataAttribute_create("SBO", (ModelNode*) parent, IEC61850_VISIBLE_STRING_129, IEC61850_FC_CO, 0, 0, 0);
bool isTimeActivated = false;
@ -619,21 +619,21 @@ addAnalogControls(DataObject* parent, uint32_t controlOptions, bool isIntegerNot
isTimeActivated = true;
if (controlModel == CDC_CTL_MODEL_SBO_ENHANCED) {
DataAttribute* sBOw = DataAttribute_create("SBOw", (ModelNode*) parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* sBOw = DataAttribute_create("SBOw", (ModelNode*) parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
CAC_AnalogueValue_create("ctlVal", (ModelNode*) sBOw, IEC61850_FC_CO, 0, isIntegerNotFloat);
addCommonOperateElements(sBOw, isTimeActivated, true);
}
DataAttribute* oper = DataAttribute_create("Oper", (ModelNode*) parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* oper = DataAttribute_create("Oper", (ModelNode*) parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
CAC_AnalogueValue_create("ctlVal", (ModelNode*) oper, IEC61850_FC_CO, 0, isIntegerNotFloat);
addCommonOperateElements(oper, isTimeActivated, true);
if (controlOptions & CDC_CTL_MODEL_HAS_CANCEL) {
DataAttribute* cancel = DataAttribute_create("SBOw", (ModelNode*) parent, CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
DataAttribute* cancel = DataAttribute_create("SBOw", (ModelNode*) parent, IEC61850_CONSTRUCTED, IEC61850_FC_CO, 0, 0, 0);
CAC_AnalogueValue_create("ctlVal", (ModelNode*) cancel, IEC61850_FC_CO, 0, isIntegerNotFloat);
@ -652,33 +652,33 @@ CDC_APC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addOriginator("origin", (ModelNode*) newAPC, IEC61850_FC_MX);
if (controlOptions & CDC_CTL_OPTION_CTL_NUM)
DataAttribute_create("ctlNum", (ModelNode*) newAPC, INT8U, IEC61850_FC_MX, 0, 0, 0);
DataAttribute_create("ctlNum", (ModelNode*) newAPC, IEC61850_INT8U, IEC61850_FC_MX, 0, 0, 0);
CAC_AnalogueValue_create("mxVal", (ModelNode*) newAPC, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, isIntegerNotFloat);
CDC_addTimeQuality(newAPC, IEC61850_FC_MX);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("stSeld", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_OP_RCVD)
DataAttribute_create("opRcvd", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("opRcvd", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_OP_OK)
DataAttribute_create("opOk", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("opOk", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_T_OP_OK)
DataAttribute_create("tOpOk", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("tOpOk", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PICS_SUBST) {
DataAttribute_create("subEna", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subEna", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
CAC_AnalogueValue_create("subVal", (ModelNode*) newAPC, IEC61850_FC_SV, 0, isIntegerNotFloat);
DataAttribute_create("subQ", (ModelNode*) newAPC, QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) newAPC, VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subQ", (ModelNode*) newAPC, IEC61850_QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) newAPC, IEC61850_VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
}
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newAPC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
addAnalogControls(newAPC, controlOptions, isIntegerNotFloat);
@ -695,24 +695,24 @@ CDC_INC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addOriginatorAndCtlNumOptions((ModelNode*) newINC, controlOptions);
CDC_addStatusToDataObject(newINC, INT32);
CDC_addStatusToDataObject(newINC, IEC61850_INT32);
addControls(newINC, INT32, controlOptions);
addControls(newINC, IEC61850_INT32, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newINC, INT32);
CDC_addOptionPicsSubst(newINC, IEC61850_INT32);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newINC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newINC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
if (options & CDC_OPTION_MIN)
DataAttribute_create("minVal", (ModelNode*) newINC, INT32, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("minVal", (ModelNode*) newINC, IEC61850_INT32, IEC61850_FC_CF, 0, 0, 0);
if (options & CDC_OPTION_MAX)
DataAttribute_create("maxVal", (ModelNode*) newINC, INT32, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("maxVal", (ModelNode*) newINC, IEC61850_INT32, IEC61850_FC_CF, 0, 0, 0);
if (options & CDC_OPTION_STEP_SIZE)
DataAttribute_create("stepSize", (ModelNode*) newINC, INT32U, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("stepSize", (ModelNode*) newINC, IEC61850_INT32U, IEC61850_FC_CF, 0, 0, 0);
CDC_addStandardOptions(newINC, options);
@ -726,15 +726,15 @@ CDC_ENC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addOriginatorAndCtlNumOptions((ModelNode*) newENC, controlOptions);
CDC_addStatusToDataObject(newENC, ENUMERATED);
CDC_addStatusToDataObject(newENC, IEC61850_ENUMERATED);
addControls(newENC, ENUMERATED, controlOptions);
addControls(newENC, IEC61850_ENUMERATED, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newENC, ENUMERATED);
CDC_addOptionPicsSubst(newENC, IEC61850_ENUMERATED);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newENC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newENC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newENC, options);
@ -751,15 +751,15 @@ CDC_BSC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
CAC_ValWithTrans_create("valWTr", (ModelNode*) newBSC, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, hasTransientIndicator);
CDC_addTimeQuality(newBSC, IEC61850_FC_ST);
DataAttribute_create("persistent", (ModelNode*) newBSC, BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("persistent", (ModelNode*) newBSC, IEC61850_BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
addControls(newBSC, CODEDENUM, controlOptions);
addControls(newBSC, IEC61850_CODEDENUM, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubstValWithTrans(newBSC, hasTransientIndicator);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newBSC, BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("blkEna", (ModelNode*) newBSC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
CDC_addStandardOptions(newBSC, options);
@ -771,8 +771,8 @@ CDC_LPL_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newLPL = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("vendor", (ModelNode*) newLPL, VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
DataAttribute_create("swRev", (ModelNode*) newLPL, VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
DataAttribute_create("vendor", (ModelNode*) newLPL, IEC61850_VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
DataAttribute_create("swRev", (ModelNode*) newLPL, IEC61850_VISIBLE_STRING_255, IEC61850_FC_DC, 0, 0, 0);
CDC_addStandardOptions(newLPL, options);
@ -785,27 +785,27 @@ CDC_ACD_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newACD = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("general", (ModelNode*) newACD, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirGeneral", (ModelNode*) newACD, ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("general", (ModelNode*) newACD, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirGeneral", (ModelNode*) newACD, IEC61850_ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PHASE_A) {
DataAttribute_create("phsA", (ModelNode*) newACD, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsA", (ModelNode*) newACD, ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsA", (ModelNode*) newACD, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsA", (ModelNode*) newACD, IEC61850_ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
}
if (options & CDC_OPTION_PHASE_B) {
DataAttribute_create("phsB", (ModelNode*) newACD, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsB", (ModelNode*) newACD, ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsB", (ModelNode*) newACD, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsB", (ModelNode*) newACD, IEC61850_ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
}
if (options & CDC_OPTION_PHASE_C) {
DataAttribute_create("phsC", (ModelNode*) newACD, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsC", (ModelNode*) newACD, ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsC", (ModelNode*) newACD, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirPhsC", (ModelNode*) newACD, IEC61850_ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
}
if (options & CDC_OPTION_PHASE_NEUT) {
DataAttribute_create("neut", (ModelNode*) newACD, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirNeut", (ModelNode*) newACD, ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("neut", (ModelNode*) newACD, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("dirNeut", (ModelNode*) newACD, IEC61850_ENUMERATED, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
}
CDC_addTimeQuality(newACD, IEC61850_FC_ST);
@ -820,19 +820,19 @@ CDC_ACT_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newACT = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("general", (ModelNode*) newACT, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("general", (ModelNode*) newACT, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PHASE_A)
DataAttribute_create("phsA", (ModelNode*) newACT, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsA", (ModelNode*) newACT, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PHASE_B)
DataAttribute_create("phsB", (ModelNode*) newACT, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsB", (ModelNode*) newACT, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PHASE_C)
DataAttribute_create("phsC", (ModelNode*) newACT, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("phsC", (ModelNode*) newACT, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_PHASE_NEUT)
DataAttribute_create("neut", (ModelNode*) newACT, BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("neut", (ModelNode*) newACT, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addTimeQuality(newACT, IEC61850_FC_ST);
@ -856,7 +856,7 @@ CDC_WYE_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
CDC_CMV_create("res", (ModelNode*) newWYE, options);
if (options & CDC_OPTION_ANGLE_REF)
DataAttribute_create("angRef", (ModelNode*) newWYE, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("angRef", (ModelNode*) newWYE, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newWYE, options);
@ -875,7 +875,7 @@ CDC_DEL_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
CDC_CMV_create("phsCA", (ModelNode*) newDEL, options);
if (options & CDC_OPTION_ANGLE_REF)
DataAttribute_create("angRef", (ModelNode*) newDEL, ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("angRef", (ModelNode*) newDEL, IEC61850_ENUMERATED, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newDEL, options);
@ -888,7 +888,7 @@ CDC_SPG_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newSPG = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("setVal", (ModelNode*) newSPG, BOOLEAN, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("setVal", (ModelNode*) newSPG, IEC61850_BOOLEAN, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newSPG, options);
@ -900,7 +900,7 @@ CDC_ENG_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newENG = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("setVal", (ModelNode*) newENG, ENUMERATED, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("setVal", (ModelNode*) newENG, IEC61850_ENUMERATED, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newENG, options);
@ -912,19 +912,19 @@ CDC_ING_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{
DataObject* newING = DataObject_create(dataObjectName, parent, 0);
DataAttribute_create("setVal", (ModelNode*) newING, INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("setVal", (ModelNode*) newING, IEC61850_INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_UNIT)
CAC_Unit_create("units", (ModelNode*) newING, options & CDC_OPTION_UNIT_MULTIPLIER);
if (options & CDC_OPTION_MIN)
DataAttribute_create("minVal", (ModelNode*) newING, INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("minVal", (ModelNode*) newING, IEC61850_INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_MAX)
DataAttribute_create("maxVal", (ModelNode*) newING, INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("maxVal", (ModelNode*) newING, IEC61850_INT32, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
if (options & CDC_OPTION_STEP_SIZE)
DataAttribute_create("stepSize", (ModelNode*) newING, INT32U, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("stepSize", (ModelNode*) newING, IEC61850_INT32U, IEC61850_FC_SP, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newING, options);
@ -997,10 +997,10 @@ CDC_SPV_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
CAC_AnalogueValue_create("maxVal", (ModelNode*) newSPV, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, false);
if (wpOptions & CDC_OPTION_61400_SP_ACS)
DataAttribute_create("spAcs", (ModelNode*) newSPV, CODEDENUM, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("spAcs", (ModelNode*) newSPV, IEC61850_CODEDENUM, IEC61850_FC_CF, 0, 0, 0);
if (wpOptions & CDC_OPTION_61400_CHA_PER_RS)
DataAttribute_create("chaPerRs", (ModelNode*) newSPV, CODEDENUM, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("chaPerRs", (ModelNode*) newSPV, IEC61850_CODEDENUM, IEC61850_FC_CF, 0, 0, 0);
CDC_addStandardOptions(newSPV, options);
@ -1064,7 +1064,7 @@ CDC_CMD_create(const char* dataObjectName, ModelNode* parent,
CDC_INS_create("oldSt", (ModelNode*) newCMD, 0);
if (wpOptions & CDC_OPTION_61400_CM_ACS)
DataAttribute_create("cmAcs", (ModelNode*) newCMD, INT8U, IEC61850_FC_CF, 0, 0, 0);
DataAttribute_create("cmAcs", (ModelNode*) newCMD, IEC61850_INT8U, IEC61850_FC_CF, 0, 0, 0);
CDC_addStandardOptions(newCMD, options);
@ -1094,19 +1094,19 @@ CDC_CTE_create(const char* dataObjectName, ModelNode* parent,
CDC_INS_create("oldCtVal", (ModelNode*) newCTE, 0);
if (wpOptions & CDC_OPTION_61400_TM_TOT)
DataAttribute_create("ctTot", (ModelNode*) newCTE, INT32U, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("ctTot", (ModelNode*) newCTE, IEC61850_INT32U, IEC61850_FC_ST, 0, 0, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_DAILY)
DataAttribute_create("dly", (ModelNode*) newCTE, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 32, 0);
DataAttribute_create("dly", (ModelNode*) newCTE, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 32, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_MONTHLY)
DataAttribute_create("mly", (ModelNode*) newCTE, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 13, 0);
DataAttribute_create("mly", (ModelNode*) newCTE, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 13, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_YEARLY)
DataAttribute_create("mly", (ModelNode*) newCTE, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 21, 0);
DataAttribute_create("mly", (ModelNode*) newCTE, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 21, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_TOTAL)
DataAttribute_create("tot", (ModelNode*) newCTE, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("tot", (ModelNode*) newCTE, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newCTE, options);
@ -1133,19 +1133,19 @@ CDC_TMS_create(const char* dataObjectName, ModelNode* parent,
CDC_INS_create("oldTmVal", (ModelNode*) newTMS, 0);
if (wpOptions & CDC_OPTION_61400_TM_TOT)
DataAttribute_create("tmTot", (ModelNode*) newTMS, INT32U, IEC61850_FC_ST, 0, 0, 0);
DataAttribute_create("tmTot", (ModelNode*) newTMS, IEC61850_INT32U, IEC61850_FC_ST, 0, 0, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_DAILY)
DataAttribute_create("dly", (ModelNode*) newTMS, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 32, 0);
DataAttribute_create("dly", (ModelNode*) newTMS, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 32, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_MONTHLY)
DataAttribute_create("mly", (ModelNode*) newTMS, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 13, 0);
DataAttribute_create("mly", (ModelNode*) newTMS, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 13, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_YEARLY)
DataAttribute_create("mly", (ModelNode*) newTMS, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 21, 0);
DataAttribute_create("mly", (ModelNode*) newTMS, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 21, 0);
if (wpOptions & CDC_OPTION_61400_COUNTING_TOTAL)
DataAttribute_create("tot", (ModelNode*) newTMS, INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
DataAttribute_create("tot", (ModelNode*) newTMS, IEC61850_INT32U, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
CDC_addStandardOptions(newTMS, options);

@ -292,7 +292,7 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
if (valueIndicator != NULL) {
switch (dataAttribute->type) {
case UNICODE_STRING_255:
case IEC61850_UNICODE_STRING_255:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
@ -300,11 +300,11 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case VISIBLE_STRING_255:
case VISIBLE_STRING_129:
case VISIBLE_STRING_65:
case VISIBLE_STRING_64:
case VISIBLE_STRING_32:
case IEC61850_VISIBLE_STRING_255:
case IEC61850_VISIBLE_STRING_129:
case IEC61850_VISIBLE_STRING_65:
case IEC61850_VISIBLE_STRING_64:
case IEC61850_VISIBLE_STRING_32:
{
char* stringStart = valueIndicator + 2;
terminateString(stringStart, '"');
@ -312,12 +312,12 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case INT8:
case INT16:
case INT32:
case INT64:
case INT128:
case ENUMERATED:
case IEC61850_INT8:
case IEC61850_INT16:
case IEC61850_INT32:
case IEC61850_INT64:
case IEC61850_INT128:
case IEC61850_ENUMERATED:
{
int32_t intValue;
if (sscanf(valueIndicator + 1, "%i", &intValue) != 1) goto exit_error;
@ -325,10 +325,10 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case INT8U:
case INT16U:
case INT24U:
case INT32U:
case IEC61850_INT8U:
case IEC61850_INT16U:
case IEC61850_INT24U:
case IEC61850_INT32U:
{
uint32_t uintValue;
if (sscanf(valueIndicator + 1, "%u", &uintValue) != 1) goto exit_error;
@ -336,7 +336,7 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case FLOAT32:
case IEC61850_FLOAT32:
{
float floatValue;
if (sscanf(valueIndicator + 1, "%f", &floatValue) != 1) goto exit_error;
@ -344,7 +344,7 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case FLOAT64:
case IEC61850_FLOAT64:
{
double doubleValue;
if (sscanf(valueIndicator + 1, "%lf", &doubleValue) != 1) goto exit_error;
@ -352,7 +352,7 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
}
break;
case BOOLEAN:
case IEC61850_BOOLEAN:
{
int boolean;
if (sscanf(valueIndicator + 1, "%i", &boolean) != 1) goto exit_error;
@ -395,9 +395,13 @@ ConfigFileParser_createModelFromConfigFile(FileHandle fileHandle)
if (StringUtils_createBufferFromHexString(nameString, (uint8_t*) nameString2) != 6)
goto exit_error;
PhyComAddress_create(currentGoCB, (uint8_t) vlanPrio, (uint16_t) vlanId, (uint16_t) appId,
PhyComAddress* dstAddress =
PhyComAddress_create((uint8_t) vlanPrio, (uint16_t) vlanId, (uint16_t) appId,
(uint8_t*) nameString2);
GSEControlBlock_addPhyComAddress(currentGoCB, dstAddress);
}
else
goto exit_error;

@ -327,7 +327,7 @@ GSEControlBlock_create(const char* name, LogicalNode* parent, char* appId, char*
else
self->dataSetName = NULL;
self->confRef = confRef;
self->confRev = confRef;
self->fixedOffs = fixedOffs;
self->minTime = minTime;
self->maxTime = maxTime;
@ -342,14 +342,47 @@ GSEControlBlock_create(const char* name, LogicalNode* parent, char* appId, char*
return self;
}
static void
SVControlBlock*
SVControlBlock_create(const char* name, LogicalNode* parent, char* svID, char* dataSet, uint32_t confRev, uint8_t smpMod,
uint16_t smpRate, uint8_t optFlds, bool isUnicast)
{
SVControlBlock* self = (SVControlBlock*) GLOBAL_MALLOC(sizeof(SVControlBlock));
self->name = copyString(name);
self->parent = parent;
self->svId = copyString(svID); /* Is there a default value? */
if (dataSet)
self->dataSetName = copyString(dataSet);
else
self->dataSetName = NULL;
self->confRev = confRev;
self->smpMod = smpMod;
self->smpRate = smpRate;
self->optFlds = optFlds;
self->isUnicast = isUnicast;
return self;
}
void
SVControlBlock_addPhyComAddress(SVControlBlock* self, PhyComAddress* phyComAddress)
{
self->dstAddress = phyComAddress;
}
void
GSEControlBlock_addPhyComAddress(GSEControlBlock* self, PhyComAddress* phyComAddress)
{
self->address = phyComAddress;
}
PhyComAddress*
PhyComAddress_create(GSEControlBlock* parent, uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint8_t dstAddress[])
PhyComAddress_create(uint8_t vlanPriority, uint16_t vlanId, uint16_t appId, uint8_t dstAddress[])
{
PhyComAddress* self = (PhyComAddress*) GLOBAL_MALLOC(sizeof(PhyComAddress));
@ -359,9 +392,6 @@ PhyComAddress_create(GSEControlBlock* parent, uint8_t vlanPriority, uint16_t vla
memcpy(self->dstAddress, dstAddress, 6);
if (parent != NULL)
GSEControlBlock_addPhyComAddress(parent, self);
return self;
}

@ -292,7 +292,8 @@ MmsConnection_getVariableListNamesAssociationSpecific(MmsConnection self, MmsErr
* \param itemId name of the variable to be read
*
* \return Returns a MmsValue object or NULL if the request failed. The MmsValue object can
* either be a simple value or a complex value or array.
* either be a simple value or a complex value or array. It is also possible that the return value is NULL
* even if mmsError = MMS_ERROR_NON. This is the case when the servers returns an empty result list.
*/
MmsValue*
MmsConnection_readVariable(MmsConnection self, MmsError* mmsError, const char* domainId, const char* itemId);
@ -383,6 +384,9 @@ MmsConnection_getVariableAccessAttributes(MmsConnection self, MmsError* mmsError
/**
* \brief Read the values of a domain specific named variable list
*
* The resulting named variable list will either be of domain scope (when the domainId argument
* is present) or VMD scope when the domainId argument is NULL.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
* \param domainId the domain name of the requested variables.
@ -415,7 +419,10 @@ MmsConnection_readNamedVariableListValuesAssociationSpecific(MmsConnection self,
const char* listName, bool specWithResult);
/**
* \brief Define a new named variable list at the server.
* \brief Define a new VMD or domain scoped named variable list at the server.
*
* The resulting named variable list will either be of domain scope (when the domainId argument
* is present) or VMD scope when the domainId argument is NULL.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
@ -445,6 +452,9 @@ MmsConnection_defineNamedVariableListAssociationSpecific(MmsConnection self, Mms
/**
* \brief Read the entry list of a named variable list at the server.
*
* The resulting named variable list will either be of domain scope (when the domainId argument
* is present) or VMD scope when the domainId argument is NULL.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
* \param domainId the domain name of the domain of the variable list
@ -476,6 +486,9 @@ MmsConnection_readNamedVariableListDirectoryAssociationSpecific(MmsConnection se
/**
* \brief Delete a named variable list at the server.
*
* The resulting named variable list will either be of domain scope (when the domainId argument
* is present) or VMD scope when the domainId argument is NULL.
*
* \param self MmsConnection instance to operate on
* \param mmsError user provided variable to store error code
* \param domainId the domain name of the domain of the variable list

@ -116,7 +116,7 @@ void
MmsDomain_deleteNamedVariableList(MmsDomain* self, char* variableListName);
MmsNamedVariableList
MmsDomain_getNamedVariableList(MmsDomain* self, char* variableListName);
MmsDomain_getNamedVariableList(MmsDomain* self, const char* variableListName);
LinkedList
MmsDomain_getNamedVariableLists(MmsDomain* self);
@ -182,6 +182,9 @@ MmsDevice_getNamedVariable(MmsDevice* self, char* variableName);
LinkedList
MmsDevice_getNamedVariableLists(MmsDevice* self);
MmsNamedVariableList
MmsDevice_getNamedVariableListWithName(MmsDevice* self, const char* variableListName);
/**@}*/
#ifdef __cplusplus

@ -935,6 +935,18 @@ MmsValue_getSubElement(MmsValue* self, MmsVariableSpecification* varSpec, char*
char*
MmsValue_getTypeString(MmsValue* self);
/**
* \brief create a string representation of the MmsValue object in the provided buffer
*
* NOTE: This function is for debugging purposes only. It may not be aimed to be used
* in embedded systems. It requires a full featured snprintf function.
*
* \param self the MmsValue instance
* \param buffer the buffer where to copy the string representation
* \param bufferSize the size of the provided buffer
*
* \return a pointer to the start of the buffer
*/
char*
MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize);

@ -272,6 +272,9 @@ mmsServer_getLowIndex(AlternateAccess_t* alternateAccess);
int
mmsServer_getNumberOfElements(AlternateAccess_t* alternateAccess);
MmsNamedVariableList
mmsServer_getNamedVariableListWithName(LinkedList namedVariableLists, const char* variableListName);
void
mmsServer_deleteVariableList(LinkedList namedVariableLists, char* variableListName);

@ -54,11 +54,18 @@ mmsClient_createDeleteNamedVariableListRequest(long invokeId, ByteBuffer* writeB
request->listOfVariableListName->list.array = (ObjectName_t**) GLOBAL_CALLOC(1, sizeof(ObjectName_t*));
request->listOfVariableListName->list.array[0] = (ObjectName_t*) GLOBAL_CALLOC(1, sizeof(ObjectName_t));
if (domainId != NULL) {
request->listOfVariableListName->list.array[0]->present = ObjectName_PR_domainspecific;
request->listOfVariableListName->list.array[0]->choice.domainspecific.domainId.size = strlen(domainId);
request->listOfVariableListName->list.array[0]->choice.domainspecific.domainId.buf = (uint8_t*) copyString(domainId);
request->listOfVariableListName->list.array[0]->choice.domainspecific.itemId.size = strlen(listNameId);
request->listOfVariableListName->list.array[0]->choice.domainspecific.itemId.buf = (uint8_t*) copyString(listNameId);
}
else {
request->listOfVariableListName->list.array[0]->present = ObjectName_PR_vmdspecific;
request->listOfVariableListName->list.array[0]->choice.vmdspecific.size = strlen(listNameId);
request->listOfVariableListName->list.array[0]->choice.vmdspecific.buf = (uint8_t*) copyString(listNameId);
}
request->scopeOfDelete = (INTEGER_t*) GLOBAL_CALLOC(1, sizeof(INTEGER_t));
asn_long2INTEGER(request->scopeOfDelete, DeleteNamedVariableListRequest__scopeOfDelete_specific);
@ -156,6 +163,7 @@ mmsClient_createGetNamedVariableListAttributesRequest(uint32_t invokeId, ByteBuf
GetNamedVariableListAttributesRequest_t* request =
&(mmsPdu->choice.confirmedRequestPdu.confirmedServiceRequest.choice.getNamedVariableListAttributes);
if (domainId != NULL) {
request->present = ObjectName_PR_domainspecific;
request->choice.domainspecific.domainId.size = strlen(domainId);
@ -163,6 +171,13 @@ mmsClient_createGetNamedVariableListAttributesRequest(uint32_t invokeId, ByteBuf
request->choice.domainspecific.itemId.size = strlen(listNameId);
request->choice.domainspecific.itemId.buf = (uint8_t*) copyString(listNameId);
}
else {
request->present = ObjectName_PR_vmdspecific;
request->choice.vmdspecific.size = strlen(listNameId);
request->choice.vmdspecific.buf = (uint8_t*) copyString(listNameId);
}
der_encode(&asn_DEF_MmsPdu, mmsPdu,
(asn_app_consume_bytes_f*) mmsClient_write_out, (void*) writeBuffer);
@ -277,6 +292,7 @@ mmsClient_createDefineNamedVariableListRequest(
request->variableListName.choice.aaspecific.buf = (uint8_t*) copyString(listNameId);
}
else {
if (domainId != NULL) { /* domain scope */
request->variableListName.present = ObjectName_PR_domainspecific;
request->variableListName.choice.domainspecific.domainId.size = strlen(domainId);
@ -285,6 +301,13 @@ mmsClient_createDefineNamedVariableListRequest(
request->variableListName.choice.domainspecific.itemId.size = strlen(listNameId);
request->variableListName.choice.domainspecific.itemId.buf = (uint8_t*) copyString(listNameId);
}
else { /* VMD scope */
request->variableListName.present = ObjectName_PR_vmdspecific;
request->variableListName.choice.vmdspecific.size = strlen(listNameId);
request->variableListName.choice.vmdspecific.buf = (uint8_t*) copyString(listNameId);
}
}
int listSize = LinkedList_size(listOfVariables);

@ -307,6 +307,8 @@ mmsClient_createReadNamedVariableListRequest(uint32_t invokeId, const char* doma
ObjectName_t* objectName = &(readRequest->variableAccessSpecification.choice.variableListName);
if (domainId != NULL) {
objectName->present = ObjectName_PR_domainspecific;
objectName->choice.domainspecific.domainId.buf = (uint8_t*) copyString(domainId);
@ -314,6 +316,13 @@ mmsClient_createReadNamedVariableListRequest(uint32_t invokeId, const char* doma
objectName->choice.domainspecific.itemId.buf = (uint8_t*) copyString(itemId);
objectName->choice.domainspecific.itemId.size = strlen(itemId);
}
else {
objectName->present = ObjectName_PR_vmdspecific;
objectName->choice.vmdspecific.buf = (uint8_t*) copyString(itemId);
objectName->choice.vmdspecific.size = strlen(itemId);
}
asn_enc_rval_t rval;

@ -1,7 +1,7 @@
/*
* MmsValue.c
*
* Copyright 2013 Michael Zillgith
* Copyright 2013-2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -1995,19 +1995,36 @@ MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize)
}
}
if (bufPos < (bufferSize - 1)) {
buffer[bufPos++] = '}';
buffer[bufPos] = 0;
}
else
buffer[bufferSize - 1] = 0;
}
break;
case MMS_BINARY_TIME:
Conversions_msTimeToGeneralizedTime(MmsValue_getBinaryTimeAsUtcMs(self), (uint8_t*) buffer);
{
uint8_t tempBuf[20];
Conversions_msTimeToGeneralizedTime(MmsValue_getBinaryTimeAsUtcMs(self), tempBuf);
snprintf(buffer, bufferSize, "%s", tempBuf);
}
break;
case MMS_BIT_STRING:
{
int bufPos = 0;
int size = MmsValue_getBitStringSize(self);
/* Behave like strncpy and fill buffer with zeros */
if (size > bufferSize) {
memset(buffer, 0, bufferSize);
break;
}
int i;
for (i = 0; i < size; i++) {
if (MmsValue_getBitStringBit(self, i))
@ -2018,24 +2035,40 @@ MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize)
buffer[bufPos] = 0;
}
break;
case MMS_BOOLEAN:
if (MmsValue_getBoolean(self))
strncpy(buffer, "true", bufferSize);
else
strncpy(buffer, "false", bufferSize);
/* Ensure buffer is always 0 terminated */
if (bufferSize > 0)
buffer[bufferSize - 1] = 0;
break;
case MMS_DATA_ACCESS_ERROR:
snprintf(buffer, bufferSize, "error %i", self->value.dataAccessError);
break;
case MMS_FLOAT:
snprintf(buffer, bufferSize, "%f", MmsValue_toFloat(self));
break;
case MMS_GENERALIZED_TIME:
case MMS_GENERALIZED_TIME: /* type not supported */
strncpy(buffer, "generalized time", bufferSize);
/* Ensure buffer is always 0 terminated */
if (bufferSize > 0)
buffer[bufferSize - 1] = 0;
break;
case MMS_INTEGER:
snprintf(buffer, bufferSize, "%i", MmsValue_toInt32(self));
break;
case MMS_OCTET_STRING:
{
int size = MmsValue_getOctetStringSize(self);
@ -2049,20 +2082,37 @@ MmsValue_printToBuffer(MmsValue* self, char* buffer, int bufferSize)
break;
}
}
break;
case MMS_UNSIGNED:
snprintf(buffer, bufferSize, "%u", MmsValue_toUint32(self));
break;
case MMS_UTC_TIME:
Conversions_msTimeToGeneralizedTime(MmsValue_getUtcTimeInMs(self), (uint8_t*) buffer);
{
uint8_t tempBuf[20];
Conversions_msTimeToGeneralizedTime(MmsValue_getUtcTimeInMs(self), tempBuf);
snprintf(buffer, bufferSize, "%s", tempBuf);
}
break;
case MMS_STRING:
case MMS_VISIBLE_STRING:
strncpy(buffer, MmsValue_toString(self), bufferSize);
/* Ensure buffer is always 0 terminated */
if (bufferSize > 0)
buffer[bufferSize - 1] = 0;
break;
default:
strncpy(buffer, "unknown type", bufferSize);
/* Ensure buffer is always 0 terminated */
if (bufferSize > 0)
buffer[bufferSize - 1] = 0;
break;
}

@ -127,3 +127,10 @@ MmsDevice_getNamedVariableLists(MmsDevice* self)
{
return self->namedVariableLists;
}
MmsNamedVariableList
MmsDevice_getNamedVariableListWithName(MmsDevice* self, const char* variableListName)
{
return mmsServer_getNamedVariableListWithName(self->namedVariableLists, variableListName);
}

@ -77,26 +77,14 @@ MmsDomain_addNamedVariableList(MmsDomain* self, MmsNamedVariableList variableLis
}
MmsNamedVariableList
MmsDomain_getNamedVariableList(MmsDomain* self, char* variableListName)
MmsDomain_getNamedVariableList(MmsDomain* self, const char* variableListName)
{
MmsNamedVariableList variableList = NULL;
if (self == NULL)
goto exit_function;
LinkedList element = LinkedList_getNext(self->namedVariableLists);
while (element != NULL) {
MmsNamedVariableList varList = (MmsNamedVariableList) element->data;
if (strcmp(MmsNamedVariableList_getName(varList), variableListName) == 0) {
variableList = varList;
break;
}
element = LinkedList_getNext(element);
}
variableList = mmsServer_getNamedVariableListWithName(self->namedVariableLists, variableListName);
exit_function:
return variableList;

@ -437,7 +437,7 @@ encodeFileSpecification(uint8_t tag, char* fileSpecification, uint8_t* buffer, i
}
static int
addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char* continueAfterFileName, bool* moreFollows)
addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* directoryName, char** continueAfterFileName, bool* moreFollows)
{
int directoryNameLength = strlen(directoryName);
@ -464,9 +464,10 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
break;
}
else {
if (continueAfterFileName != NULL) {
if (strcmp(continueAfterFileName, directoryName) == 0)
continueAfterFileName = NULL;
if (*continueAfterFileName != NULL) {
if (strcmp(*continueAfterFileName, directoryName) == 0) {
*continueAfterFileName = NULL;
}
}
else {
uint64_t msTime;
@ -517,9 +518,9 @@ addFileEntriesToResponse(uint8_t* buffer, int bufPos, int maxBufSize, char* dire
}
static void
createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, char* directoryName, char* continueAfterFileName)
createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, int maxPduSize, char* directoryName, char* continueAfterFileName)
{
int maxSize = response->maxSize - 3; /* reserve space for moreFollows */
int maxSize = maxPduSize - 3; /* reserve space for moreFollows */
uint8_t* buffer = response->buffer;
bool moreFollows = false;
@ -533,7 +534,7 @@ createFileDirectoryResponse(uint32_t invokeId, ByteBuffer* response, char* direc
continueAfterFileName = NULL;
}
tempCurPos = addFileEntriesToResponse(buffer, tempCurPos, maxSize, directoryName, continueAfterFileName, &moreFollows);
tempCurPos = addFileEntriesToResponse(buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows);
if (tempCurPos < 0) {
@ -708,7 +709,9 @@ mmsServer_handleFileDirectoryRequest(
}
createFileDirectoryResponse(invokeId, response, filename, continueAfter);
int maxPduSize = connection->maxPduSize;
createFileDirectoryResponse(invokeId, response, maxPduSize, filename, continueAfter);
}
#endif /* MMS_FILE_SERVICE == 1 */

@ -266,7 +266,7 @@ getNamedVariableListsDomainSpecific(MmsServerConnection connection, char* domain
}
static LinkedList
getnamedVariableListsVMDSpecific(MmsServerConnection connection)
getNamedVariableListsVMDSpecific(MmsServerConnection connection)
{
MmsDevice* device = MmsServer_getDevice(connection->server);
@ -555,7 +555,7 @@ mmsServer_handleGetNameListRequest(
#if (MMS_DATA_SET_SERVICE == 1)
else if (objectClass == OBJECT_CLASS_NAMED_VARIABLE_LIST) {
LinkedList nameList = getnamedVariableListsVMDSpecific(connection);
LinkedList nameList = getNamedVariableListsVMDSpecific(connection);
#if (CONFIG_MMS_SORT_NAME_LIST == 1)
StringUtils_sortList(nameList);

@ -179,6 +179,24 @@ mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
}
}
}
else if (request->listOfVariableListName->list.array[i]->present == ObjectName_PR_vmdspecific) {
char listName[65];
mmsMsg_copyAsn1IdentifierToStringBuffer(request->listOfVariableListName->list.array[i]->choice.vmdspecific,
listName, 65);
MmsNamedVariableList variableList = mmsServer_getNamedVariableListWithName(device->namedVariableLists, listName);
if (variableList != NULL) {
numberMatched++;
if (mmsServer_callVariableListChangedHandler(false, MMS_VMD_SPECIFIC, NULL, listName, connection)
== MMS_ERROR_NONE) {
numberDeleted++;
mmsServer_deleteVariableList(device->namedVariableLists, listName);
}
}
}
}
createDeleteNamedVariableListResponse(invokeId, response, numberMatched, numberDeleted);
@ -451,6 +469,7 @@ mmsServer_handleDefineNamedVariableListRequest(
char variableListName[65];
if (request->variableListName.choice.aaspecific.size > 64) {
//TODO send reject PDU instead?
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
goto exit_free_struct;
}
@ -487,6 +506,48 @@ mmsServer_handleDefineNamedVariableListRequest(
else
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_CAPABILITY_UNAVAILABLE);
}
else if (request->variableListName.present == ObjectName_PR_vmdspecific) {
LinkedList vmdScopeNVLs = MmsDevice_getNamedVariableLists(connection->server->device);
if (LinkedList_size(vmdScopeNVLs) < CONFIG_MMS_MAX_NUMBER_OF_VMD_SPECIFIC_DATA_SETS) {
char variableListName[65];
if (request->variableListName.choice.vmdspecific.size > 64) {
//TODO send reject PDU instead?
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
goto exit_free_struct;
}
StringUtils_createStringFromBufferInBuffer(variableListName,
request->variableListName.choice.vmdspecific.buf,
request->variableListName.choice.vmdspecific.size);
if (mmsServer_getNamedVariableListWithName(MmsDevice_getNamedVariableLists(connection->server->device), variableListName) != NULL) {
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_OBJECT_EXISTS);
}
else {
MmsError mmsError;
MmsNamedVariableList namedVariableList = createNamedVariableList(NULL, device,
request, variableListName, &mmsError);
if (namedVariableList != NULL) {
if (mmsServer_callVariableListChangedHandler(true, MMS_VMD_SPECIFIC, NULL, variableListName, connection)
== MMS_ERROR_NONE) {
LinkedList_add(vmdScopeNVLs, (void*) namedVariableList);
createDefineNamedVariableListResponse(invokeId, response);
}
else {
MmsNamedVariableList_destroy(namedVariableList);
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
}
}
}
}
}
else
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_DEFINITION_TYPE_UNSUPPORTED);
@ -635,6 +696,26 @@ mmsServer_handleGetNamedVariableListAttributesRequest(
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
else if (request->present == ObjectName_PR_vmdspecific) {
char listName[65];
if (request->choice.vmdspecific.size > 64) {
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OTHER);
goto exit_function;
}
StringUtils_createStringFromBufferInBuffer(listName, request->choice.vmdspecific.buf,
request->choice.vmdspecific.size);
MmsDevice* mmsDevice = MmsServer_getDevice(connection->server);
MmsNamedVariableList varList = mmsServer_getNamedVariableListWithName(mmsDevice->namedVariableLists, listName);
if (varList != NULL)
createGetNamedVariableListAttributesResponse(invokeId, response, varList);
else
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
}
else {
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);
}

@ -663,6 +663,29 @@ handleReadNamedVariableListRequest(
}
}
}
else if (read->variableAccessSpecification.choice.variableListName.present == ObjectName_PR_vmdspecific)
{
char listName[65];
mmsMsg_copyAsn1IdentifierToStringBuffer(read->variableAccessSpecification.choice.variableListName.choice.vmdspecific,
listName, 65);
MmsNamedVariableList namedList = mmsServer_getNamedVariableListWithName(connection->server->device->namedVariableLists, listName);
if (namedList == NULL)
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
else {
VarAccessSpec accessSpec;
accessSpec.isNamedVariableList = true;
accessSpec.specific = 0;
accessSpec.domainId = NULL;
accessSpec.itemId = listName;
createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec);
}
}
#if (MMS_DYNAMIC_DATA_SETS == 1)
else if (read->variableAccessSpecification.choice.variableListName.present ==
ObjectName_PR_aaspecific)
@ -674,6 +697,9 @@ handleReadNamedVariableListRequest(
MmsNamedVariableList namedList = MmsServerConnection_getNamedVariableList(connection, listName);
if (namedList == NULL)
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
else {
VarAccessSpec accessSpec;
accessSpec.isNamedVariableList = true;
@ -681,11 +707,9 @@ handleReadNamedVariableListRequest(
accessSpec.domainId = NULL;
accessSpec.itemId = listName;
if (namedList == NULL)
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT);
else
createNamedVariableListResponse(connection, namedList, invokeId, response, read, &accessSpec);
}
}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */
else
mmsServer_createConfirmedErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_UNSUPPORTED);

@ -201,6 +201,28 @@ mmsServer_getNumberOfElements(AlternateAccess_t* alternateAccess)
return 0;
}
MmsNamedVariableList
mmsServer_getNamedVariableListWithName(LinkedList namedVariableLists, const char* variableListName)
{
MmsNamedVariableList variableList = NULL;
LinkedList element = LinkedList_getNext(namedVariableLists);
while (element != NULL) {
MmsNamedVariableList varList = (MmsNamedVariableList) element->data;
if (strcmp(MmsNamedVariableList_getName(varList), variableListName) == 0) {
variableList = varList;
break;
}
element = LinkedList_getNext(element);
}
return variableList;
}
void
mmsServer_deleteVariableList(LinkedList namedVariableLists, char* variableListName)
{

@ -355,23 +355,7 @@ MmsServerConnection_deleteNamedVariableList(MmsServerConnection self, char* list
MmsNamedVariableList
MmsServerConnection_getNamedVariableList(MmsServerConnection self, const char* variableListName)
{
//TODO remove code duplication - similar to MmsDomain_getNamedVariableList !
MmsNamedVariableList variableList = NULL;
LinkedList element = LinkedList_getNext(self->namedVariableLists);
while (element != NULL) {
MmsNamedVariableList varList = (MmsNamedVariableList) element->data;
if (strcmp(MmsNamedVariableList_getName(varList), variableListName) == 0) {
variableList = varList;
break;
}
element = LinkedList_getNext(element);
}
return variableList;
return mmsServer_getNamedVariableListWithName(self->namedVariableLists, variableListName);
}
#endif /* (MMS_DYNAMIC_DATA_SETS == 1) */

@ -0,0 +1,621 @@
/*
* sv_receiver.c
*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#include "stack_config.h"
#include "libiec61850_platform_includes.h"
#include "hal_ethernet.h"
#include "hal_thread.h"
#include "ber_decode.h"
#include "ber_encoder.h"
#include "sv_subscriber.h"
#ifndef DEBUG_SV_SUBSCRIBER
#define DEBUG_SV_SUBSCRIBER 1
#endif
#define ETH_BUFFER_LENGTH 1518
#define ETH_P_SV 0x88ba
struct sSVReceiver {
bool running;
bool stopped;
bool checkDestAddr; /* option: check destination address (additionally to AppID) to identify application */
char* interfaceId;
uint8_t* buffer;
EthernetSocket ethSocket;
LinkedList subscriberList;
};
struct sSVSubscriber {
uint8_t ethAddr[6];
uint16_t appId;
SVUpdateListener listener;
void* listenerParameter;
};
struct sSVClientASDU {
char* svId;
uint8_t* smpCnt;
uint8_t* confRev;
uint8_t* smpSynch;
int dataBufferLength;
uint8_t* dataBuffer;
};
SVReceiver
SVReceiver_create(void)
{
SVReceiver self = (SVReceiver) GLOBAL_CALLOC(1, sizeof(struct sSVReceiver));
if (self != NULL) {
self->subscriberList = LinkedList_create();
self->buffer = (uint8_t*) GLOBAL_MALLOC(ETH_BUFFER_LENGTH);
self->checkDestAddr = false;
}
return self;
}
void
SVReceiver_setInterfaceId(SVReceiver self, const char* interfaceId)
{
if (self->interfaceId != NULL)
GLOBAL_FREEMEM(self->interfaceId);
self->interfaceId = copyString(interfaceId);
}
void
SVReceiver_disableDestAddrCheck(SVReceiver self)
{
self->checkDestAddr = false;
}
void
SVReceiver_addSubscriber(SVReceiver self, SVSubscriber subscriber)
{
LinkedList_add(self->subscriberList, (void*) subscriber);
}
void
SVReceiver_removeSubscriber(SVReceiver self, SVSubscriber subscriber)
{
LinkedList_remove(self->subscriberList, (void*) subscriber);
}
static void
svReceiverLoop(void* threadParameter)
{
SVReceiver self = (SVReceiver) threadParameter;
self->running = true;
self->stopped = false;
SVReceiver_startThreadless(self);
while (self->running) {
if (SVReceiver_tick(self) == false)
Thread_sleep(1);
}
SVReceiver_stopThreadless(self);
self->stopped = true;
}
void
SVReceiver_start(SVReceiver self)
{
Thread thread = Thread_create((ThreadExecutionFunction) svReceiverLoop, (void*) self, true);
if (thread != NULL) {
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: SV receiver started for interface %s\n", self->interfaceId);
Thread_start(thread);
}
else {
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Starting SV receiver failed for interface %s\n", self->interfaceId);
}
}
void
SVReceiver_stop(SVReceiver self)
{
self->running = false;
while (self->stopped == false)
Thread_sleep(1);
}
void
SVReceiver_destroy(SVReceiver self)
{
LinkedList_destroyDeep(self->subscriberList,
(LinkedListValueDeleteFunction) SVSubscriber_destroy);
GLOBAL_FREEMEM(self->buffer);
GLOBAL_FREEMEM(self);
}
void
SVReceiver_startThreadless(SVReceiver self)
{
if (self->interfaceId == NULL)
self->ethSocket = Ethernet_createSocket(CONFIG_ETHERNET_INTERFACE_ID, NULL);
else
self->ethSocket = Ethernet_createSocket(self->interfaceId, NULL);
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV);
self->running = true;
}
void
SVReceiver_stopThreadless(SVReceiver self)
{
Ethernet_destroySocket(self->ethSocket);
self->running = false;
}
static void
parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
{
int bufPos = 0;
struct sSVClientASDU asdu;
memset(&asdu, 0, sizeof(struct sSVClientASDU));
int svIdLength = 0;
while (bufPos < length) {
int elementLength;
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
switch (tag) {
case 0x80:
asdu.svId = (char*) (buffer + bufPos);
svIdLength = elementLength;
break;
case 0x82:
asdu.smpCnt = buffer + bufPos;
break;
case 0x83:
asdu.confRev = buffer + bufPos;
break;
case 0x85:
asdu.smpSynch = buffer + bufPos;
break;
case 0x87:
asdu.dataBuffer = buffer + bufPos;
asdu.dataBufferLength = elementLength;
break;
default: /* ignore unknown tag */
break;
}
bufPos += elementLength;
}
if (asdu.svId != NULL)
asdu.svId[svIdLength] = 0;
/* Call callback handler */
if (subscriber->listener != NULL)
subscriber->listener(subscriber, subscriber->listenerParameter, &asdu);
}
static void
parseSequenceOfASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
{
int bufPos = 0;
while (bufPos < length) {
int elementLength;
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
switch (tag) {
case 0x30:
parseASDU(self, subscriber, buffer + bufPos, elementLength);
break;
default: /* ignore unknown tag */
break;
}
bufPos += elementLength;
}
}
static void
parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int apduLength)
{
int bufPos = 0;
if (buffer[bufPos++] == 0x60) {
int elementLength;
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength);
int svEnd = bufPos + elementLength;
while (bufPos < svEnd) {
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd);
if (bufPos + elementLength > apduLength) {
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Malformed message: sub element is too large!\n");
goto exit_error;
}
if (bufPos == -1)
goto exit_error;
switch(tag) {
case 0x80: /* noASDU (INTEGER) */
/* ignore */
break;
case 0xa2: /* asdu (SEQUENCE) */
parseSequenceOfASDU(self, subscriber, buffer + bufPos, elementLength);
break;
default: /* ignore unknown tag */
break;
}
bufPos += elementLength;
}
return;
}
exit_error:
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Invalid SV message!\n");
return;
}
static void
parseSVMessage(SVReceiver self, int numbytes)
{
int bufPos;
bool subscriberFound = false;
uint8_t* buffer = self->buffer;
if (numbytes < 22) return;
/* Ethernet source address */
uint8_t* srcAddr = buffer;
/* skip ethernet addresses */
bufPos = 12;
int headerLength = 14;
/* check for VLAN tag */
if ((buffer[bufPos] == 0x81) && (buffer[bufPos + 1] == 0x00)) {
bufPos += 4; /* skip VLAN tag */
headerLength += 4;
}
/* check for SV Ethertype */
if (buffer[bufPos++] != 0x88)
return;
if (buffer[bufPos++] != 0xba)
return;
uint16_t appId;
appId = buffer[bufPos++] * 0x100;
appId += buffer[bufPos++];
uint16_t length;
length = buffer[bufPos++] * 0x100;
length += buffer[bufPos++];
/* skip reserved fields */
bufPos += 4;
int apduLength = length - 8;
if (numbytes < length + headerLength) {
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Invalid PDU size\n");
return;
}
if (DEBUG_SV_SUBSCRIBER) {
printf("SV_SUBSCRIBER: SV message: ----------------\n");
printf("SV_SUBSCRIBER: APPID: %u\n", appId);
printf("SV_SUBSCRIBER: LENGTH: %u\n", length);
printf("SV_SUBSCRIBER: APDU length: %i\n", apduLength);
}
/* check if there is a matching subscriber */
LinkedList element = LinkedList_getNext(self->subscriberList);
SVSubscriber subscriber;
while (element != NULL) {
subscriber = (SVSubscriber) LinkedList_getData(element);
if (subscriber->appId == appId) {
if (self->checkDestAddr) {
if (memcmp(srcAddr, subscriber->ethAddr, 6) == 0) {
subscriberFound = true;
break;
}
else
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: Checking ethernet src address failed!\n");
}
else {
subscriberFound = true;
break;
}
}
element = LinkedList_getNext(element);
}
if (subscriberFound)
parseSVPayload(self, subscriber, buffer + bufPos, apduLength);
else {
if (DEBUG_SV_SUBSCRIBER)
printf("SV_SUBSCRIBER: SV message ignored due to unknown APPID value\n");
}
}
bool
SVReceiver_tick(SVReceiver self)
{
int packetSize = Ethernet_receivePacket(self->ethSocket, self->buffer, ETH_BUFFER_LENGTH);
if (packetSize > 0) {
parseSVMessage(self, packetSize);
return true;
}
else
return false;
}
SVSubscriber
SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID)
{
SVSubscriber self = (SVSubscriber) GLOBAL_CALLOC(1, sizeof(struct sSVSubscriber));
if (self != NULL) {
self->appId = appID;
if (ethAddr != NULL)
memcpy(self->ethAddr, ethAddr, 6);
}
return self;
}
void
SVSubscriber_destroy(SVSubscriber self)
{
if (self != NULL)
GLOBAL_FREEMEM(self);
}
void
SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter)
{
self->listener = listener;
self->listenerParameter = parameter;
}
uint16_t
SVClientASDU_getSmpCnt(SVClientASDU self)
{
uint16_t retVal;
uint8_t* valBytes = (uint8_t*) &retVal;
#if (ORDER_LITTLE_ENDIAN == 1)
valBytes[0] = self->smpCnt[1];
valBytes[1] = self->smpCnt[0];
#else
valBytes[0] = self->smpCnt[0];
valBytes[1] = self->smpCnt[1];
#endif
return retVal;
}
const char*
SVClientASDU_getSvId(SVClientASDU self)
{
return self->svId;
}
uint32_t
SVClientASDU_getConfRev(SVClientASDU self)
{
uint32_t retVal = *((uint32_t*) (self->confRev));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 4);
#endif
return retVal;
}
int8_t
SVClientASDU_getINT8(SVClientASDU self, int index)
{
int8_t retVal = *((int8_t*) (self->dataBuffer + index));
return retVal;
}
int16_t
SVClientASDU_getINT16(SVClientASDU self, int index)
{
int16_t retVal = *((int16_t*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 2);
#endif
return retVal;
}
int32_t
SVClientASDU_getINT32(SVClientASDU self, int index)
{
int32_t retVal = *((int32_t*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 4);
#endif
return retVal;
}
uint8_t
SVClientASDU_getINT8U(SVClientASDU self, int index)
{
uint8_t retVal = *((uint8_t*) (self->dataBuffer + index));
return retVal;
}
uint16_t
SVClientASDU_getINT16U(SVClientASDU self, int index)
{
uint16_t retVal = *((uint16_t*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 2);
#endif
return retVal;
}
uint32_t
SVClientASDU_getINT32U(SVClientASDU self, int index)
{
uint32_t retVal = *((uint32_t*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 4);
#endif
return retVal;
}
float
SVClientASDU_getFLOAT32(SVClientASDU self, int index)
{
float retVal = *((float*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 4);
#endif
return retVal;
}
double
SVClientASDU_getFLOAT64(SVClientASDU self, int index)
{
double retVal = *((double*) (self->dataBuffer + index));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 8);
#endif
return retVal;
}
int
SVClientASDU_getDataSize(SVClientASDU self)
{
return self->dataBufferLength;
}

@ -0,0 +1,376 @@
/*
* sv_subscriber_api.h
*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
#ifndef SAMPLED_VALUES_SV_SUBSCRIBER_H_
#define SAMPLED_VALUES_SV_SUBSCRIBER_H_
#include "libiec61850_common_api.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup sv_subscriber_api_group IEC 61850 sampled values (SV) subscriber API
*
* The sampled values (SV) subscriber API consists of three different objects.
* The \ref SVReceiver object is responsible for handling all SV Ethernet messages
* for a specific Ethernet interface. If you want to receive SV messages on multiple
* Ethernet interfaces you have to use several \ref SVReceiver instances.
* An \ref SVSubscriber object is associated to a SV data stream that is identified by its appID
* and destination Ethernet address. The \reg SVSubscriber object is used to install a callback
* handler \ref SVUpdateListener that is invoked for each ASDU (application service data unit) received for the
* associated stream. An \ref SVClientASDU is an object that represents a single ASDU. Each ASDU contains
* some meta information that can be obtained by specific access functions like e.g.
* \ref SVClientASDU_getSmpCnt to access the "SmpCnt" (sample count) attribute of the ASDU. The actual
* measurement data contained in the ASDU does not consist of structured ASN.1 data but stored as raw binary
* data. Without a priori knowledge of the dataset associated with the ASDU data stream it is not
* possible to interpret the received data correctly. Therefore you have to provide the data access functions
* with an index value to indicate the data type and the start of the data in the data block of the ASDU.
* E.g. reading a data set consisting of two FLOAT32 values you can use two subsequent calls of
* \ref SVClientASDU_getFLOAT32 one with index = 0 and the second one with index = 4.
*
* | IEC 61850 type | required bytes |
* | -------------- | -------------- |
* | BOOLEAN | 1 byte |
* | INT8 | 1 byte |
* | INT16 | 2 byte |
* | INT32 | 4 byte |
* | INT64 | 8 byte |
* | INT8U | 1 byte |
* | INT16U | 2 byte |
* | INT24U | 3 byte |
* | INT32U | 4 byte |
* | FLOAT32 | 4 byte |
* | FLOAT64 | 8 byte |
* | ENUMERATED | 4 byte |
* | CODED ENUM | 4 byte |
* | OCTET STRING | 20 byte |
* | VISIBLE STRING | 35 byte |
* | TimeStamp | 8 byte |
* | EntryTime | 6 byte |
* | BITSTRING | 4 byte |
*
* The SV subscriber API can be used independent of the IEC 61850 client API. In order to access the SVCB via MMS you
* have to use the IEC 61850 client API. Please see \ref ClientSVControlBlock object in section \ref IEC61850_CLIENT_SV.
*
*/
/**@{*/
/**
* \brief opaque handle to a SV ASDU (Application service data unit) instance.
*
* Sampled Values (SV) ASDUs (application service data units) are the basic units for
* sampled value data. Each ASDU represents a single sample consisting of multiple measurement
* values with a single dedicated timestamp.
*
* NOTE: SVClientASDU are statically allocated and are only valid inside of the SVUpdateListener
* function when called by the library. If you need the data contained in the ASDU elsewhere
* you have to copy and store the data by yourself!
*/
typedef struct sSVClientASDU* SVClientASDU;
/**
* \brief opaque handle to a SV subscriber instance
*
* A subscriber is an instance associated with a single stream of measurement data. It is identified
* by the Ethernet destination address, the appID value (both are on SV message level) and the svID value
* that is part of each ASDU (SVClientASDU object).
*/
typedef struct sSVSubscriber* SVSubscriber;
/**
* \brief Callback function for received SV messages
*
* Will be called for each ASDU contained in a SV message!
*
* \param subscriber the subscriber that was associated with the received SV message
* \param parameter a user provided parameter that is simply passed to the callback
* \param asdu SV ASDU data structure. This structure is only valid inside of the callback function
*/
typedef void (*SVUpdateListener)(SVSubscriber subscriber, void* parameter, SVClientASDU asdu);
/**
* \brief opaque handle to a SV receiver instance
*/
typedef struct sSVReceiver* SVReceiver;
/**
* \brief Create a new SV receiver instance.
*
* A receiver is responsible for processing all SV message for a single Ethernet interface.
* In order to process messages from multiple Ethernet interfaces you have to create multiple
* instances.
*
* \return the newly created receiver instance
*/
SVReceiver
SVReceiver_create(void);
/**
* \brief Disable check for destination address of the received SV messages
*
* Per default both the appID and the destination address are checked to identify
* relevant SV messages. Destination address check can be disabled for performance
* reason when the appIDs are unique in the local system.
*
* \param self the receiver instance reference
*/
void
SVReceiver_disableDestAddrCheck(SVReceiver self);
/**
* \brief Set the Ethernet interface ID for the receiver instance
*
* Use this function if you want to use a different interface than
* the default interface set by CONFIG_ETHERNET_INTERFACE_ID (stack_config.h)
* NOTE: This function has to be called before calling SVReceiver_start.
*
* \param self the receiver instance reference
* \param interfaceId the Ethernet interface id (platform specific e.g. eth0 for linux).
*/
void
SVReceiver_setInterfaceId(SVReceiver self, const char* interfaceId);
/**
* \brief Add a subscriber instance to the receiver
*
* The given subscriber will be connected to the receiver instance.
*
* \param self the receiver instance reference
* \param subscriber the subscriber instance to connect
*/
void
SVReceiver_addSubscriber(SVReceiver self, SVSubscriber subscriber);
/**
* \brief Disconnect subscriber and receiver
*
* \param self the receiver instance reference
* \param subscriber the subscriber instance to disconnect
*/
void
SVReceiver_removeSubscriber(SVReceiver self, SVSubscriber subscriber);
/**
* \brief Receiver starts listening for SV messages.
*
* NOTE: This call will start a new background thread.
*
* \param self the receiver instance reference
*/
void
SVReceiver_start(SVReceiver self);
/**
* \brief Receiver stops listening for SV messages
*
* \param self the receiver instance reference
*/
void
SVReceiver_stop(SVReceiver self);
/**
* \brief Destroy receiver instance (cleanup resources)
*
* \param self the receiver instance reference
*/
void
SVReceiver_destroy(SVReceiver self);
/***************************************
* Functions for non-threaded operation
***************************************/
void
SVReceiver_startThreadless(SVReceiver self);
void
SVReceiver_stopThreadless(SVReceiver self);
bool
SVReceiver_tick(SVReceiver self);
/*
* Subscriber
*/
SVSubscriber
SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID);
/**
* \brief Set a callback handler to process received SV messages
*
* If the received SV message contains multiple ASDUs (application service data units) the callback
* function will be called for each ASDU separately. If a callback function has already been installed
* for this SVSubscriber object the old callback will be replaced.
*
* \param self The subscriber object
* \param listener the callback function to install
* \param a user provided parameter that is provided to the callback function
*
*/
void
SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter);
void
SVSubscriber_destroy(SVSubscriber self);
/*************************************************************************
* SVClientASDU object methods
**************************************************************************/
/**
* \brief return the SmpCnt value included in the SV ASDU
*
* The SmpCnt (sample counter) is increased for each ASDU to
* identify the sample.
*
* \param self ASDU object instance
*/
uint16_t
SVClientASDU_getSmpCnt(SVClientASDU self);
/**
* \brief return the SvID value included in the SV ASDU
*
* \param self ASDU object instance
*/
const char*
SVClientASDU_getSvId(SVClientASDU self);
/**
* \brief return the ConfRev value included in the SV ASDU
*
* \param self ASDU object instance
*/
uint32_t
SVClientASDU_getConfRev(SVClientASDU self);
/**
* \brief Get an INT8 data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
int8_t
SVClientASDU_getINT8(SVClientASDU self, int index);
/**
* \brief Get an INT16 data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
int16_t
SVClientASDU_getINT16(SVClientASDU self, int index);
/**
* \brief Get an INT32 data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
int32_t
SVClientASDU_getINT32(SVClientASDU self, int index);
/**
* \brief Get an INT8U data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
uint8_t
SVClientASDU_getINT8U(SVClientASDU self, int index);
/**
* \brief Get an INT16U data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
uint16_t
SVClientASDU_getINT16U(SVClientASDU self, int index);
/**
* \brief Get an INT32U data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
uint32_t
SVClientASDU_getINT32U(SVClientASDU self, int index);
/**
* \brief Get an FLOAT32 data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
float
SVClientASDU_getFLOAT32(SVClientASDU self, int index);
/**
* \brief Get an FLOAT64 data value in the data part of the ASDU
*
* \param self ASDU object instance
* \param index the index (byte position of the start) of the data in the data part
*
* \return SV data
*/
double
SVClientASDU_getFLOAT64(SVClientASDU self, int index);
/**
* \brief Returns the size of the data part of the ASDU
*
* \param self ASDU object instance
*
* \return size of the ASDU data part in bytes.
*/
int
SVClientASDU_getDataSize(SVClientASDU self);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* SAMPLED_VALUES_SV_SUBSCRIBER_ */

@ -495,3 +495,22 @@ EXPORTS
LogicalNode_getDataSet
ClientReport_getDataSetName
MmsValue_getStringSize
SVControlBlock_create
SVControlBlock_addPhyComAddress
GSEControlBlock_addPhyComAddress
ClientSVControlBlock_create
ClientSVControlBlock_destroy
ClientSVControlBlock_isMulticast
ClientSVControlBlock_getLastComError
ClientSVControlBlock_setSvEna
ClientSVControlBlock_getSvEna
ClientSVControlBlock_setResv
ClientSVControlBlock_getResv
ClientSVControlBlock_getMsvID
ClientSVControlBlock_getDatSet
ClientSVControlBlock_getConfRev
ClientSVControlBlock_getSmpRate
ClientSVControlBlock_getDstAddress
ClientSVControlBlock_getOptFlds
ClientSVControlBlock_getSmpMod
ClientSVControlBlock_getNoASDU

@ -519,3 +519,48 @@ EXPORTS
LogicalNode_getDataSet
ClientReport_getDataSetName
MmsValue_getStringSize
SVControlBlock_create
SVControlBlock_addPhyComAddress
GSEControlBlock_addPhyComAddress
GooseSubscriber_getConfRev
SVReceiver_create
SVReceiver_setInterfaceId
SVReceiver_addSubscriber
SVReceiver_removeSubscriber
SVReceiver_start
SVReceiver_stop
SVReceiver_destroy
SVReceiver_startThreadless
SVReceiver_stopThreadless
SVReceiver_tick
SVSubscriber_create
SVSubscriber_setListener
SVSubscriber_destroy
SVClientASDU_getSmpCnt
SVClientASDU_getSvId
SVClientASDU_getConfRev
SVClientASDU_getINT8
SVClientASDU_getINT16
SVClientASDU_getINT32
SVClientASDU_getINT8U
SVClientASDU_getINT16U
SVClientASDU_getINT32U
SVClientASDU_getFLOAT32
SVClientASDU_getFLOAT64
SVClientASDU_getDataSize
ClientSVControlBlock_create
ClientSVControlBlock_destroy
ClientSVControlBlock_isMulticast
ClientSVControlBlock_getLastComError
ClientSVControlBlock_setSvEna
ClientSVControlBlock_getSvEna
ClientSVControlBlock_setResv
ClientSVControlBlock_getResv
ClientSVControlBlock_getMsvID
ClientSVControlBlock_getDatSet
ClientSVControlBlock_getConfRev
ClientSVControlBlock_getSmpRate
ClientSVControlBlock_getDstAddress
ClientSVControlBlock_getOptFlds
ClientSVControlBlock_getSmpMod
ClientSVControlBlock_getNoASDU

@ -0,0 +1,2 @@
For GOOSE support add winpcap source and headers here. Rerun cmake to configure the build system for GOOSE support.

@ -0,0 +1,12 @@
#!/bin/sh
mkdir build
find src/ -name "*.java" > listFile.tmp
javac -target 1.6 -source 1.6 -d build @listFile.tmp
jar cfm modelviewer.jar manifest-modelviewer.mf -C build/ com/
rm listFile.tmp
rm -r build

@ -0,0 +1,2 @@
Manifest-Version: 1.0
Main-Class: com.libiec61850.tools.ModelViewer

@ -62,28 +62,47 @@ public class SclParser {
private List<IED> ieds;
private Communication communication;
private TypeDeclarations typeDeclarations;
public static boolean withOutput = true;
public TypeDeclarations getTypeDeclarations() {
return typeDeclarations;
}
private Node scl;
public SclParser(InputStream stream) throws SclParserException {
public SclParser(InputStream stream, boolean withOutput) throws SclParserException {
this.withOutput = withOutput;
Document doc = parseXmlDocument(stream);
scl = getRootNode(doc);
if (withOutput)
System.out.println("parse data type templates ...");
typeDeclarations = parseTypeDeclarations();
if (withOutput)
System.out.println("parse IED section ...");
parseIedSections();
if (withOutput)
System.out.println("parse communication section ...");
communication = parseCommunicationSection();
if (communication == null)
if (withOutput)
System.out.println("WARNING: No communication section found!");
}
public IED getIedByteName(String iedName) {
public SclParser(InputStream stream) throws SclParserException {
this(stream, true);
}
public IED getIedByName(String iedName) {
for (IED ied : ieds) {
if (ied.getName().equals(iedName))
return ied;
@ -280,6 +299,7 @@ public class SclParser {
if (connectedAP.getApName().equals(accessPointName)) {
if (withOutput)
System.out.println("Found connectedAP " + accessPointName + " for IED " + ied.getName());
return connectedAP;

@ -35,6 +35,7 @@ public class ConnectedAP {
private String apName;
private List<GSE> gses;
private List<SMV> smvs;
public ConnectedAP(Node node) throws SclParserException {
iedName = ParserUtils.parseAttribute(node, "iedName");
@ -47,9 +48,15 @@ public class ConnectedAP {
List<Node> gseNodes = ParserUtils.getChildNodesWithTag(node, "GSE");
for (Node gseNode : gseNodes) {
for (Node gseNode : gseNodes)
gses.add(new GSE(gseNode));
}
smvs = new LinkedList<SMV>();
List<Node> smvNodes = ParserUtils.getChildNodesWithTag(node, "SMV");
for (Node smvNode : smvNodes)
smvs.add(new SMV(smvNode));
}
public String getIedName() {
@ -64,7 +71,11 @@ public class ConnectedAP {
return gses;
}
public GSEAddress lookupGSEAddress(String logicalDeviceName, String name) {
public List<SMV> getSmvs() {
return smvs;
}
public PhyComAddress lookupGSEAddress(String logicalDeviceName, String name) {
for (GSE gse : this.getGses()) {
if (gse.getLdInst().equals(logicalDeviceName)) {
@ -76,4 +87,16 @@ public class ConnectedAP {
return null;
}
public PhyComAddress lookupSMVAddress(String logicalDeviceName, String name) {
for (SMV smv : this.getSmvs()) {
if (smv.getLdInst().equals(logicalDeviceName)) {
if (smv.getCbName().equals(name))
return smv.getAddress();
}
}
return null;
}
}

@ -31,7 +31,7 @@ public class GSE {
private String ldInst;
private String cbName;
private GSEAddress address;
private PhyComAddress address;
public GSE(Node gseNode) throws SclParserException {
ldInst = ParserUtils.parseAttribute(gseNode, "ldInst");
@ -45,7 +45,7 @@ public class GSE {
if (addressNode == null)
throw new SclParserException(gseNode, "GSE is missing address definition!");
address = new GSEAddress(addressNode);
address = new PhyComAddress(addressNode);
}
public String getLdInst() {
@ -56,7 +56,7 @@ public class GSE {
return cbName;
}
public GSEAddress getAddress() {
public PhyComAddress getAddress() {
return address;
}

@ -29,14 +29,14 @@ import org.w3c.dom.Node;
import com.libiec61850.scl.ParserUtils;
import com.libiec61850.scl.SclParserException;
public class GSEAddress {
public class PhyComAddress {
private Integer vlanId = null;
private Integer vlanPriority = null;
private Integer appId = null;
private int[] macAddress = null;
public GSEAddress(Node addressNode) throws DOMException, SclParserException {
public PhyComAddress(Node addressNode) throws DOMException, SclParserException {
List<Node> pNodes = ParserUtils.getChildNodesWithTag(addressNode, "P");

@ -0,0 +1,61 @@
package com.libiec61850.scl.communication;
import org.w3c.dom.Node;
import com.libiec61850.scl.ParserUtils;
import com.libiec61850.scl.SclParserException;
/*
* Copyright 2015 Michael Zillgith
*
* This file is part of libIEC61850.
*
* libIEC61850 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* libIEC61850 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
public class SMV {
private String ldInst;
private String cbName;
private PhyComAddress address;
public SMV(Node gseNode) throws SclParserException {
ldInst = ParserUtils.parseAttribute(gseNode, "ldInst");
cbName = ParserUtils.parseAttribute(gseNode, "cbName");
if ((ldInst == null) || (cbName == null))
throw new SclParserException(gseNode, "SMV is missing required attribute");
Node addressNode = ParserUtils.getChildNodeWithTag(gseNode, "Address");
if (addressNode == null)
throw new SclParserException(gseNode, "SMV is missing address definition!");
address = new PhyComAddress(addressNode);
}
public String getLdInst() {
return ldInst;
}
public String getCbName() {
return cbName;
}
public PhyComAddress getAddress() {
return address;
}
}

@ -87,6 +87,8 @@ public class DataAttribute implements DataModelNode {
if (!(this.sclType instanceof EnumerationType))
throw new SclParserException("Wrong type definition for enumerated data attribute");
this.sclType.setUsed(true);
}
private void createConstructedAttribute(DataAttributeDefinition daDefinition, TypeDeclarations typeDeclarations)
@ -99,6 +101,8 @@ public class DataAttribute implements DataModelNode {
if (!(this.sclType instanceof DataAttributeType))
throw new SclParserException("Wrong type definition for constructed data attribute");
this.sclType.setUsed(true);
DataAttributeType dataAttributeType = (DataAttributeType) this.sclType;
List<DataAttributeDefinition> daDefinitions = dataAttributeType.getSubDataAttributes();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save