Merge remote-tracking branch 'upstream/v1.4' into feature/set-urcbs-buffer-size-dotnet

Resolved conflicts.
pull/216/head
Andrew Moorcroft 6 years ago
commit 0073c3eca7

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 2.8.12)
# automagically detect if we should cross-compile
if(DEFINED ENV{TOOLCHAIN})
@ -169,3 +169,5 @@ if(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")
include(CPack)
endif(EXISTS "${CMAKE_ROOT}/Modules/CPack.cmake")

@ -164,6 +164,9 @@
/* allow user to control read access by callback */
#define CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL 1
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1

@ -154,6 +154,9 @@
/* allow user to control read access by callback */
#cmakedefine01 CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL
/* allow application to set server identity (for MMS identity service) at runtime */
#define CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY 1
/* Force memory alignment - required for some platforms (required more memory for buffered reporting) */
#define CONFIG_IEC61850_FORCE_MEMORY_ALIGNMENT 1

@ -1114,6 +1114,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateQuality(IntPtr self, IntPtr dataAttribute, ushort value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_setServerIdentity(IntPtr self, string vendor, string model, string revision);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedServer_getAttributeValue(IntPtr self, IntPtr dataAttribute);
@ -1388,6 +1391,21 @@ namespace IEC61850
internalConnectionHandler = null;
}
/// <summary>
/// Set the identify for the MMS identify service
/// </summary>
/// <param name="vendor">the IED vendor name</param>
/// <param name="model">the IED model name</param>
/// <param name="revision">the IED revision/version number</param>
public void SetServerIdentity(string vendor, string model, string revision)
{
IedServer_setServerIdentity(self, vendor, model, revision);
}
/// <summary>
/// Check if server is running (accepting client connections)
/// </summary>
/// <returns><c>true</c>, if running, <c>false</c> otherwise.</returns>
public bool IsRunning()
{
return IedServer_isRunning(self);

@ -534,41 +534,58 @@ namespace IEC61850
}
/// <summary>
/// Sets the element of an array of structure
/// Sets the element of an array or structure
/// </summary>
/// <remarks>
/// After calling this function the native memory of the element will be managed by the array or structure.
/// Therefore an element can only be used in a single array or structure.
/// When the value is required in multiple arrays or structures
/// a clone has to be created before using this function!
/// To be save, always use a clone for setting the element.
/// </remarks>
/// <param name="index">index of the element starting with 0</param>
/// <param name="elementValue">MmsValue instance that will be used as element value</param>
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
/// <exception cref="MmsValueException">This exception is thrown if the index is out of range.</exception>
public void SetElement(int index, MmsValue elementValue)
{
MmsType elementType = GetType ();
MmsType elementType = GetType();
if ((elementType == MmsType.MMS_ARRAY) || (elementType == MmsType.MMS_STRUCTURE)) {
if ((elementType == MmsType.MMS_ARRAY) || (elementType == MmsType.MMS_STRUCTURE))
{
if ((index >= 0) && (index < Size()))
{
if ((index >= 0) && (index < Size ())) {
if (elementValue != null)
MmsValue_setElement (valueReference, index, elementValue.valueReference);
else
MmsValue_setElement (valueReference, index, IntPtr.Zero);
{
MmsValue_setElement(valueReference, index, elementValue.valueReference);
} else
throw new MmsValueException ("Index out of bounds");
/* will be deleted by structure */
elementValue.responsableForDeletion = false;
}
else
MmsValue_setElement(valueReference, index, IntPtr.Zero);
} else
throw new MmsValueException ("Value is of wrong type");
}
else
throw new MmsValueException("Index out of bounds");
}
else
throw new MmsValueException("Value is of wrong type");
}
public MmsDataAccessError GetDataAccessError ()
public MmsDataAccessError GetDataAccessError()
{
if (GetType () == MmsType.MMS_DATA_ACCESS_ERROR) {
int errorCode = MmsValue_getDataAccessError (valueReference);
if (GetType() == MmsType.MMS_DATA_ACCESS_ERROR)
{
int errorCode = MmsValue_getDataAccessError(valueReference);
return (MmsDataAccessError)errorCode;
}
else
throw new MmsValueException ("Value is of wrong type");
throw new MmsValueException("Value is of wrong type");
}
/// <summary>

@ -294,9 +294,6 @@ namespace tests
{
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("../../model.cfg");
ModelNode ind1 = iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.Ind1.stVal");
Assert.IsTrue (ind1.GetType ().Equals (typeof(IEC61850.Server.DataAttribute)));
@ -556,6 +553,45 @@ namespace tests
Assert.AreEqual (Validity.QUESTIONABLE, q.Validity);
}
[Test()]
public void MmsValaueCreateStructureAndAddElement()
{
MmsValue structure1 = MmsValue.NewEmptyStructure(1);
MmsValue structure2 = MmsValue.NewEmptyStructure(1);
MmsValue element = MmsValue.NewEmptyStructure(1);
structure1.SetElement(0, element);
/* Clone is required when adding the value to another structure or element */
MmsValue elementClone = element.Clone();
structure2.SetElement(0, elementClone);
element.Dispose();
structure1.Dispose();
structure2.Dispose();
Assert.AreEqual(true, true);
}
[Test()]
public void MmsValueClone()
{
MmsValue boolValue = new MmsValue(true);
MmsValue boolClone = boolValue.Clone();
boolValue.Dispose();
boolClone.Dispose();
MmsValue structure = MmsValue.NewEmptyStructure(1);
MmsValue structureClone = structure.Clone();
structure.Dispose();
structureClone.Dispose();
}
}
}

@ -114,6 +114,9 @@ main(int argc, char** argv)
/* configuration object is no longer required */
IedServerConfig_destroy(config);
/* set the identity values for MMS identify service */
IedServer_setServerIdentity(iedServer, "MZ", "basic io", "1.4.2");
/* Install handler for operate command */
IedServer_setControlHandler(iedServer, IEDMODEL_GenericIO_GGIO1_SPCSO1,
(ControlHandler) controlHandlerForBinaryOutput,

@ -164,3 +164,18 @@ target_link_libraries(hal
${CMAKE_CURRENT_SOURCE_DIR}/../third_party/winpcap/Lib/packet.lib
)
ENDIF(WITH_WPCAP)
set(BINDIR "bin")
set(LIBDIR "lib")
if(UNIX)
# GNUInstallDirs is required for Debian multiarch
include(GNUInstallDirs)
set(LIBDIR ${CMAKE_INSTALL_LIBDIR})
set(BINDIR ${CMAKE_INSTALL_BINDIR})
endif()
install (TARGETS hal hal-shared
RUNTIME DESTINATION ${BINDIR} COMPONENT Applications
ARCHIVE DESTINATION ${LIBDIR} COMPONENT Libraries
LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries
)

@ -345,6 +345,15 @@ target_link_libraries(iec61850-shared
)
ENDIF(WITH_WPCAP)
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM)
configure_file(doxygen/Doxyfile.NET.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.NET @ONLY)
add_custom_target(doc-net ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.NET WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)
set(BINDIR "bin")
set(LIBDIR "lib")
@ -361,18 +370,9 @@ if(UNIX)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libiec61850.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/pkgconfig")
endif()
find_package(Doxygen)
if(DOXYGEN_FOUND)
configure_file(Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM)
configure_file(doxygen/Doxyfile.NET.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.NET @ONLY)
add_custom_target(doc-net ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.NET WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM)
endif(DOXYGEN_FOUND)
install (TARGETS iec61850 iec61850-shared hal hal-shared
install (TARGETS iec61850 iec61850-shared
RUNTIME DESTINATION ${BINDIR} COMPONENT Applications
ARCHIVE DESTINATION ${LIBDIR} COMPONENT Libraries
LIBRARY DESTINATION ${LIBDIR} COMPONENT Libraries
)

@ -496,11 +496,33 @@ CDC_ENC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
LIB61850_API DataObject*
CDC_BSC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool hasTransientIndicator);
/**
* \brief Integer controlled step position information (ISC)
*
* CDC_OPTION_IS_TIME_ACTICATED
*
* substitution options
* CDC_OPTION_BLK_ENA
* standard description and namespace options
*
* \param dataObjectName the name of the new object
* \param parent the parent of the new data object (either a LogicalNode or another DataObject)
* \param options bit mask to encode required optional elements
* \param controlOptions specify which control model to set as default and other control specific options
* \param hasTransientIndicator specifies if the step position information contains the transient indicator
*
*/
LIB61850_API DataObject*
CDC_ISC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool hasTransientIndicator);
/**
* \brief Controllable analogue process value (APC)
*
* CDC_OPTION_IS_TIME_ACTICATED
*
* CDC_OPTION_MIN
* CDC_OPTION_MAX
*
* substitution options
* CDC_OPTION_BLK_ENA
* standard description and namespace options
@ -514,6 +536,28 @@ CDC_BSC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
LIB61850_API DataObject*
CDC_APC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool isIntegerNotFloat);
/**
* \brief Binary controlled ananlogue process value (BAC)
*
* CDC_OPTION_IS_TIME_ACTICATED
*
* CDC_OPTION_MIN
* CDC_OPTION_MAX
* CDC_OPTION_STEP_SIZE
*
* substitution options
* CDC_OPTION_BLK_ENA
* standard description and namespace options
*
* \param dataObjectName the name of the new object
* \param parent the parent of the new data object (either a LogicalNode or another DataObject)
* \param options bit mask to encode required optional elements
* \param controlOptions specify which control model to set as default and other control specific options
* \param isIntegerNotFloat
*/
LIB61850_API DataObject*
CDC_BAC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool isIntegerNotFloat);
/** Minimum measured value */
#define CDC_OPTION_61400_MIN_MX_VAL (1 << 10)

@ -347,6 +347,19 @@ IedServer_destroy(IedServer self);
LIB61850_API void
IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress);
/**
* \brief Set the identify for the MMS identify service
*
* CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY required
*
* \param self the IedServer instance
* \param vendor the IED vendor name
* \param model the IED model name
* \param revision the IED revision/version number
*/
LIB61850_API void
IedServer_setServerIdentity(IedServer self, const char* vendor, const char* model, const char* revision);
/**
* \brief Set the virtual filestore basepath for the MMS file services
*

@ -61,6 +61,12 @@ struct sIedServer
Thread serverThread;
#endif
#if (CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY == 1)
char* vendorName;
char* modelName;
char* revision;
#endif
uint8_t edition;
bool running;

@ -548,6 +548,18 @@ IedServer_destroy(IedServer self)
Semaphore_destroy(self->clientConnectionsLock);
#endif
#if (CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY == 1)
if (self->vendorName)
GLOBAL_FREEMEM(self->vendorName);
if (self->modelName)
GLOBAL_FREEMEM(self->modelName);
if (self->revision)
GLOBAL_FREEMEM(self->revision);
#endif /* (CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY == 1) */
GLOBAL_FREEMEM(self);
}
@ -1530,6 +1542,28 @@ IedServer_setLogStorage(IedServer self, const char* logRef, LogStorage logStorag
#endif
}
void
IedServer_setServerIdentity(IedServer self, const char* vendor, const char* model, const char* revision)
{
#if (CONFIG_IEC61850_SUPPORT_SERVER_IDENTITY == 1)
if (self->vendorName)
GLOBAL_FREEMEM(self->vendorName);
if (self->modelName)
GLOBAL_FREEMEM(self->modelName);
if (self->revision)
GLOBAL_FREEMEM(self->revision);
self->vendorName = StringUtils_copyString(vendor);
self->modelName = StringUtils_copyString(model);
self->revision = StringUtils_copyString(revision);
MmsServer_setServerIdentity(self->mmsServer, self->vendorName, self->modelName, self->revision);
#endif
}
ClientConnection
private_IedServer_getClientConnectionByHandle(IedServer self, void* serverConnectionHandle)
{

@ -1435,6 +1435,13 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
if (checkValidityOfOriginParameter(origin) == false) {
indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
ControlObject_sendLastApplError(controlObject, connection, "SBOw", CONTROL_ERROR_NO_ERROR,
ADD_CAUSE_SELECT_FAILED, ctlNum, origin, true);
if (DEBUG_IED_SERVER)
printf("IED_SERVER: SBOw - invalid origin value\n");
goto free_and_return;
}
@ -1571,6 +1578,8 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
CONTROL_ERROR_NO_ERROR, ADD_CAUSE_INCONSISTENT_PARAMETERS,
ctlNum, origin, true);
unselectObject(controlObject);
goto free_and_return;
}
}
@ -1654,6 +1663,9 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
setOpRcvd(controlObject, false);
abortControlOperation(controlObject);
if ((controlObject->ctlModel == 2) || (controlObject->ctlModel == 4))
unselectObject(controlObject);
}
}

@ -2104,6 +2104,8 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
ReportBufferEntry* entry = (ReportBufferEntry*) entryBufPos;
entry->timeOfEntry = timeOfEntry;
if (isBuffered) {
/* ENTRY_ID is set to system time in ms! */
uint64_t entryId = timeOfEntry;
@ -2111,8 +2113,6 @@ enqueueReport(ReportControl* reportControl, bool isIntegrity, bool isGI, uint64_
if (entryId <= reportControl->lastEntryId)
entryId = reportControl->lastEntryId + 1;
entry->timeOfEntry = entryId;
#if (ORDER_LITTLE_ENDIAN == 1)
memcpyReverseByteOrder(entry->entryId, (uint8_t*) &entryId, 8);
#else

@ -554,6 +554,19 @@ addOriginatorAndCtlNumOptions(ModelNode* parent, uint32_t controlOptions)
DataAttribute_create("ctlNum", parent, IEC61850_INT8U, IEC61850_FC_ST, 0, 0, 0);
}
static void
addCommonControlAttributes(DataObject* dobj, uint32_t controlOptions)
{
if (controlOptions & CDC_CTL_OPTION_OP_RCVD)
DataAttribute_create("opRcvd", (ModelNode*) dobj, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_OP_OK)
DataAttribute_create("opOk", (ModelNode*) dobj, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_T_OP_OK)
DataAttribute_create("tOpOk", (ModelNode*) dobj, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
}
/**
*
* CDC_OPTION_IS_TIME_ACTICATED
@ -574,6 +587,11 @@ CDC_SPC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addControls(newSPC, IEC61850_BOOLEAN, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newSPC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newSPC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newSPC, IEC61850_BOOLEAN);
@ -605,6 +623,11 @@ CDC_DPC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addControls(newDPC, IEC61850_BOOLEAN, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newDPC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newDPC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newDPC, IEC61850_CODEDENUM);
@ -661,16 +684,22 @@ addAnalogControls(DataObject* parent, uint32_t controlOptions, bool isIntegerNot
}
}
static void
addControlStatusAttributesForAnalogControl(DataObject* dobj, uint32_t controlOptions)
{
if (controlOptions & CDC_CTL_OPTION_ORIGIN)
addOriginator("origin", (ModelNode*) dobj, IEC61850_FC_MX);
if (controlOptions & CDC_CTL_OPTION_CTL_NUM)
DataAttribute_create("ctlNum", (ModelNode*) dobj, IEC61850_INT8U, IEC61850_FC_MX, 0, 0, 0);
}
DataObject*
CDC_APC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool isIntegerNotFloat)
{
DataObject* newAPC = DataObject_create(dataObjectName, parent, 0);
if (controlOptions & CDC_CTL_OPTION_ORIGIN)
addOriginator("origin", (ModelNode*) newAPC, IEC61850_FC_MX);
if (controlOptions & CDC_CTL_OPTION_CTL_NUM)
DataAttribute_create("ctlNum", (ModelNode*) newAPC, IEC61850_INT8U, IEC61850_FC_MX, 0, 0, 0);
addControlStatusAttributesForAnalogControl(newAPC, controlOptions);
CAC_AnalogueValue_create("mxVal", (ModelNode*) newAPC, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, isIntegerNotFloat);
@ -679,14 +708,7 @@ CDC_APC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
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, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
if (controlOptions & CDC_CTL_OPTION_OP_OK)
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, IEC61850_BOOLEAN, IEC61850_FC_OR, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newAPC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST) {
DataAttribute_create("subEna", (ModelNode*) newAPC, IEC61850_BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
@ -705,7 +727,6 @@ CDC_APC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
return newAPC;
}
DataObject*
CDC_INC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions)
{
@ -717,6 +738,11 @@ CDC_INC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addControls(newINC, IEC61850_INT32, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newINC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newINC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newINC, IEC61850_INT32);
@ -748,6 +774,11 @@ CDC_ENC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addControls(newENC, IEC61850_ENUMERATED, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newENC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newENC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubst(newENC, IEC61850_ENUMERATED);
@ -773,6 +804,11 @@ CDC_BSC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
addControls(newBSC, IEC61850_CODEDENUM, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newBSC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newBSC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubstValWithTrans(newBSC, hasTransientIndicator);
@ -784,6 +820,84 @@ CDC_BSC_create(const char* dataObjectName, ModelNode* parent, uint32_t options,
return newBSC;
}
DataObject*
CDC_ISC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool hasTransientIndicator)
{
DataObject* newISC = DataObject_create(dataObjectName, parent, 0);
addOriginatorAndCtlNumOptions((ModelNode*) newISC, controlOptions);
CAC_ValWithTrans_create("valWTr", (ModelNode*) newISC, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, hasTransientIndicator);
CDC_addTimeQuality(newISC, IEC61850_FC_ST);
addControls(newISC, IEC61850_INT8, controlOptions);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newISC, IEC61850_BOOLEAN, IEC61850_FC_ST, TRG_OPT_DATA_CHANGED, 0, 0);
addCommonControlAttributes(newISC, controlOptions);
if (options & CDC_OPTION_PICS_SUBST)
CDC_addOptionPicsSubstValWithTrans(newISC, hasTransientIndicator);
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newISC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
if (options & CDC_OPTION_MIN)
DataAttribute_create("minVal", (ModelNode*) newISC, IEC61850_INT32, IEC61850_FC_CF, 0, 0, 0);
if (options & CDC_OPTION_MAX)
DataAttribute_create("maxVal", (ModelNode*) newISC, IEC61850_INT32, IEC61850_FC_CF, 0, 0, 0);
CDC_addStandardOptions(newISC, options);
return newISC;
}
DataObject*
CDC_BAC_create(const char* dataObjectName, ModelNode* parent, uint32_t options, uint32_t controlOptions, bool isIntegerNotFloat)
{
DataObject* newBAC = DataObject_create(dataObjectName, parent, 0);
addControlStatusAttributesForAnalogControl(newBAC, controlOptions);
CAC_AnalogueValue_create("mxVal", (ModelNode*) newBAC, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, isIntegerNotFloat);
CDC_addTimeQuality(newBAC, IEC61850_FC_MX);
if (controlOptions & CDC_CTL_OPTION_ST_SELD)
DataAttribute_create("stSeld", (ModelNode*) newBAC, IEC61850_BOOLEAN, IEC61850_FC_MX, TRG_OPT_DATA_CHANGED, 0, 0);
addControls(newBAC, IEC61850_INT8, controlOptions);
if (options & CDC_OPTION_PICS_SUBST) {
DataAttribute_create("subEna", (ModelNode*) newBAC, IEC61850_BOOLEAN, IEC61850_FC_SV, 0, 0, 0);
CAC_AnalogueValue_create("subVal", (ModelNode*) newBAC, IEC61850_FC_SV, 0, isIntegerNotFloat);
DataAttribute_create("subQ", (ModelNode*) newBAC, IEC61850_QUALITY, IEC61850_FC_SV, 0, 0, 0);
DataAttribute_create("subID", (ModelNode*) newBAC, IEC61850_VISIBLE_STRING_64, IEC61850_FC_SV, 0, 0, 0);
}
if (options & CDC_OPTION_BLK_ENA)
DataAttribute_create("blkEna", (ModelNode*) newBAC, IEC61850_BOOLEAN, IEC61850_FC_BL, 0, 0, 0);
DataAttribute_create("persistent", (ModelNode*) newBAC, IEC61850_BOOLEAN, IEC61850_FC_CF, TRG_OPT_DATA_CHANGED, 0, 0);
addAnalogControls(newBAC, controlOptions, isIntegerNotFloat);
if (options & CDC_OPTION_MIN)
CAC_AnalogueValue_create("minVal", (ModelNode*) newBAC, IEC61850_FC_CF, 0, isIntegerNotFloat);
if (options & CDC_OPTION_MAX)
CAC_AnalogueValue_create("maxVal", (ModelNode*) newBAC, IEC61850_FC_CF, 0, isIntegerNotFloat);
if (options & CDC_OPTION_STEP_SIZE)
CAC_AnalogueValue_create("stepSize", (ModelNode*) newBAC, IEC61850_FC_CF, 0, isIntegerNotFloat);
CDC_addStandardOptions(newBAC, options);
return newBAC;
}
DataObject*
CDC_LPL_create(const char* dataObjectName, ModelNode* parent, uint32_t options)
{

Loading…
Cancel
Save