123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632 |
- /*
- * model.h
- *
- * Copyright 2013-2024 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 MODEL_H_
- #define MODEL_H_
- #include "iec61850_common.h"
- #ifdef __cplusplus
- extern "C" {
- #endif
- /** \addtogroup server_api_group
- * @{
- */
- /**
- * @defgroup DATA_MODEL General data model definitions, access and iteration functions
- *
- * \brief Functions and structures to access and iterate the IEC 61850 data model
- *
- * @{
- */
- /**
- * \brief abstract base type for IEC 61850 data model nodes
- */
- typedef struct sModelNode ModelNode;
- /**
- * \brief IEC 61850 data model element of type data attribute
- */
- typedef struct sDataAttribute DataAttribute;
- /**
- * \brief IEC 61850 data model element of type data object
- */
- typedef struct sDataObject DataObject;
- /**
- * \brief IEC 61850 data model element of type logical node
- */
- typedef struct sLogicalNode LogicalNode;
- /**
- * \brief IEC 61850 data model element of type logical device
- */
- typedef struct sLogicalDevice LogicalDevice;
- /**
- * \brief Root node of the IEC 61850 data model. This is usually created by the model generator tool (genmodel.jar)
- */
- typedef struct sIedModel IedModel;
- typedef struct sDataSet DataSet;
- typedef struct sReportControlBlock ReportControlBlock;
- /**
- * \brief IEC 61850 data model of setting group control block (SGCB)
- */
- typedef struct sSettingGroupControlBlock SettingGroupControlBlock;
- typedef struct sGSEControlBlock GSEControlBlock;
- typedef struct sSVControlBlock SVControlBlock;
- typedef struct sLogControlBlock LogControlBlock;
- typedef struct sLog Log;
- typedef enum {
- IEC61850_UNKNOWN_TYPE = -1,
- 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,
- IEC61850_CURRENCY = 30,
- IEC61850_OPTFLDS = 31, /* bit-string(10) */
- IEC61850_TRGOPS = 32 /* bit-string(6) */
- } DataAttributeType;
- typedef enum {
- LogicalDeviceModelType,
- LogicalNodeModelType,
- DataObjectModelType,
- DataAttributeModelType
- } ModelNodeType;
- struct sIedModel {
- char* name;
- LogicalDevice* firstChild;
- DataSet* dataSets;
- ReportControlBlock* rcbs;
- GSEControlBlock* gseCBs;
- SVControlBlock* svCBs;
- SettingGroupControlBlock* sgcbs;
- LogControlBlock* lcbs;
- Log* logs;
- void (*initializer) (void);
- };
- struct sLogicalDevice {
- ModelNodeType modelType;
- char* name; /* LD instance */
- ModelNode* parent;
- ModelNode* sibling;
- ModelNode* firstChild;
- char* ldName; /* ldName (when using functional naming) */
- };
- struct sModelNode {
- ModelNodeType modelType;
- char* name;
- ModelNode* parent;
- ModelNode* sibling;
- ModelNode* firstChild;
- };
- struct sLogicalNode {
- ModelNodeType modelType;
- char* name;
- ModelNode* parent;
- ModelNode* sibling;
- ModelNode* firstChild;
- };
- struct sDataObject {
- ModelNodeType modelType;
- char* name;
- ModelNode* parent;
- ModelNode* sibling;
- ModelNode* firstChild;
- int elementCount; /* value > 0 if this is an array */
- int arrayIndex; /* value > -1 when this is an array element */
- };
- struct sDataAttribute {
- ModelNodeType modelType;
- char* name;
- ModelNode* parent;
- ModelNode* sibling;
- ModelNode* firstChild;
- int elementCount; /* value > 0 if this is an array */
- int arrayIndex; /* value > -1 when this is an array element */
- FunctionalConstraint fc;
- DataAttributeType type;
- uint8_t triggerOptions; /* TRG_OPT_DATA_CHANGED | TRG_OPT_QUALITY_CHANGED | TRG_OPT_DATA_UPDATE */
- MmsValue* mmsValue;
- uint32_t sAddr; /* TODO remove in version 2.0 */
- };
- typedef struct sDataSetEntry {
- char* logicalDeviceName; /* logical device instance name */
- bool isLDNameDynamicallyAllocated;
- char* variableName;
- int index;
- char* componentName;
- MmsValue* value;
- struct sDataSetEntry* sibling;
- } DataSetEntry;
- struct sDataSet {
- char* logicalDeviceName; /* logical device instance name */
- char* name; /* eg. MMXU1$dataset1 */
- int elementCount;
- DataSetEntry* fcdas;
- DataSet* sibling;
- };
- struct sReportControlBlock {
- LogicalNode* parent;
- char* name;
- char* rptId;
- bool buffered;
- char* dataSetName; /* pre loaded with relative name in logical node */
- uint32_t confRef; /* ConfRef - configuration revision */
- uint8_t trgOps; /* TrgOps - trigger conditions */
- uint8_t options; /* OptFlds */
- uint32_t bufferTime; /* BufTm - time to buffer events until a report is generated */
- uint32_t intPeriod; /* IntgPd - integrity period */
- /* type (first byte) and address of the pre-configured client
- type can be one of (0 - no reservation, 4 - IPv4 client, 6 - IPv6 client) */
- uint8_t clientReservation[17];
- ReportControlBlock* sibling; /* next control block in list or NULL if this is the last entry
- * at runtime reuse as pointer to ReportControl instance!
- **/
- };
- struct sLogControlBlock {
- LogicalNode* parent;
- char* name;
- char* dataSetName;
- char* logRef; /* object reference to the journal */
- uint8_t trgOps; /* TrgOps - trigger conditions */
- uint32_t intPeriod; /* IntgPd - integrity period */
- bool logEna; /* enable log by default */
- bool reasonCode; /* include reason code in log */
- LogControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
- };
- struct sLog {
- LogicalNode* parent;
- char* name;
- Log* sibling; /* next log instance in list or NULL if this is the last entry */
- };
- struct sSettingGroupControlBlock {
- LogicalNode* parent;
- uint8_t actSG; /* value from SCL file */
- uint8_t numOfSGs; /* value from SCL file */
- uint8_t editSG; /* 0 at power-up */
- bool cnfEdit; /* false at power-up */
- uint64_t timestamp;
- uint16_t resvTms;
- SettingGroupControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
- };
- struct sGSEControlBlock {
- LogicalNode* parent;
- char* name;
- char* appId;
- char* dataSetName; /* pre loaded with relative name in logical node */
- uint32_t confRev; /* ConfRev - configuration revision */
- bool fixedOffs; /* fixed offsets */
- PhyComAddress* address; /* GSE communication parameters */
- int minTime; /* optional minTime parameter --> -1 if not present */
- int maxTime; /* optional maxTime parameter --> -1 if not present */
- 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
- *
- * \param self the model node instance
- *
- * \return the number of children of the model node
- * ¸
- */
- LIB61850_API int
- ModelNode_getChildCount(ModelNode* self);
- /**
- * \brief return a child model node
- *
- * \param self the model node instance
- * \param name the name of the child model node
- *
- * \return the model node instance or NULL if model node does not exist.
- */
- LIB61850_API ModelNode*
- ModelNode_getChild(ModelNode* self, const char* name);
- /**
- * \brief return the child node of an array or other structure
- *
- * \param self the model node instance
- * \param idx the index (e.g. array index) starting with 0
- *
- * \return the model node instance or NULL if model node with given index does not exist.
- */
- LIB61850_API ModelNode*
- ModelNode_getChildWithIdx(ModelNode* self, int idx);
- /**
- * \brief return a child model node with a given functional constraint
- *
- * Sometimes the name is not enough to identify a model node. This is the case when
- * editable setting groups are used. In this case the setting group members have two different
- * model nodes associated that differ in their FC (SG and SE).
- *
- * \param self the model node instance
- * \param name the name of the child model node
- * \param fc the functional constraint of the model node
- *
- * \return the model node instance or NULL if model node does not exist.
- */
- LIB61850_API ModelNode*
- ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint fc);
- /**
- * \brief Return the IEC 61850 object reference of a model node
- *
- * \param self the model node instance
- * \param objectReference pointer to a buffer where to write the object reference string. If NULL
- * is given the buffer is allocated by the function.
- *
- * \return the object reference string
- */
- LIB61850_API char*
- ModelNode_getObjectReference(ModelNode* self, char* objectReference);
- /**
- * \brief Return the IEC 61850 object reference of a model node
- *
- * \param self the model node instance
- * \param objectReference pointer to a buffer where to write the object reference string. If NULL
- * is given the buffer is allocated by the function.
- * \param withoutIedName create object reference without IED name part
- *
- * \return the object reference string
- */
- LIB61850_API char*
- ModelNode_getObjectReferenceEx(ModelNode* node, char* objectReference, bool withoutIedName);
- /**
- * \brief Get the type of the ModelNode
- *
- * \param self the ModelNode instance
- *
- * \return the type of the ModelNode (one of LD, LN, DO, DA)
- */
- LIB61850_API ModelNodeType
- ModelNode_getType(ModelNode* self);
- /**
- * \brief Get the name of the ModelNode
- *
- * \param self the ModelNode instance
- *
- * \return the name of the ModelNode
- */
- LIB61850_API const char*
- ModelNode_getName(ModelNode* self);
- /**
- * \brief Get the parent ModelNode of this ModelNode instance
- *
- * \param self the ModelNode instance
- *
- * \return the parent instance, or NULL when the ModelNode has no parent
- */
- LIB61850_API ModelNode*
- ModelNode_getParent(ModelNode* self);
- /**
- * \brief Get the list of direct child nodes
- *
- * \param self the ModelNode instance
- *
- * \return the list of private child nodes, or NULL when the node has no children
- */
- LIB61850_API LinkedList
- ModelNode_getChildren(ModelNode* self);
- /**
- * \brief Set the name of the IED
- *
- * This will change the default name (usualy "TEMPLATE") to a user configured values.
- * NOTE: This function has to be called before IedServer_create !
- *
- * \param model the IedModel instance
- * \param the name of the configured IED
- */
- LIB61850_API void
- IedModel_setIedName(IedModel* self, const char* iedName);
- /**
- * \brief Lookup a model node by its object reference
- *
- * This function uses the full logical device name as part of the object reference
- * as it happens to appear on the wire. E.g. if IED name in SCL file would be "IED1"
- * and the logical device "WD1" the resulting LD name would be "IED1WD".
- * When using functional naming in the LD (with ldName attribute) then the logical
- * device name is identical with the ldName attribute.
- *
- * \param self the IedModel instance that holds the model node
- * \param objectReference the IEC 61850 object reference
- *
- * \return the model node instance or NULL if model node does not exist.
- */
- LIB61850_API ModelNode*
- IedModel_getModelNodeByObjectReference(IedModel* self, const char* objectReference);
- LIB61850_API SVControlBlock*
- IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* svcbName);
- /**
- * \brief Lookup a model node by its short (normalized) reference
- *
- * This version uses the object reference that does not contain the
- * IED name or functional name as part of the logical device name.
- * Instead the LD part consists of the LD instance name ("inst" attribute).
- * This function is useful for
- * devices where the IED name can be configured.
- *
- * \param self the IedModel instance that holds the model node
- * \param objectReference the IEC 61850 object reference
- *
- * \return the model node instance or NULL if model node does not exist.
- */
- LIB61850_API ModelNode*
- IedModel_getModelNodeByShortObjectReference(IedModel* self, const char* objectReference);
- /**
- * \brief Lookup a model node by its short address
- *
- * Short address is a 32 bit unsigned integer as specified in the "sAddr" attribute of
- * the ICD file or in the configuration file.
- *
- * \param self the IedModel instance that holds the model node
- * \param shortAddress
- *
- * \return the model node instance or NULL if model node does not exist.
- */
- LIB61850_API ModelNode*
- IedModel_getModelNodeByShortAddress(IedModel* self, uint32_t shortAddress);
- /**
- * \brief Lookup logical device (LD) by device instance name (SCL attribute "inst")
- *
- * \param self IedModel instance
- * \param ldInst the logical device instance name (SCL attribute "inst")
- *
- * \return The matching LogicalDevice instance
- */
- LIB61850_API LogicalDevice*
- IedModel_getDeviceByInst(IedModel* self, const char* ldInst);
- /**
- * \brief Lookup logical device (LD) instance by index
- *
- * \param self IedModel instance
- * \param index the index of the LD in the range (0 .. number of LDs - 1)
- *
- * \return the corresponding LogicalDevice* object or NULL if the index is out of range
- */
- LIB61850_API LogicalDevice*
- IedModel_getDeviceByIndex(IedModel* self, int index);
- /**
- * \brief Lookup a logical node by name that is part of the given logical device
- *
- * \param device the logical device instance
- * \param lnName the logical node name
- *
- * \return the logical device instance or NULL if it does not exist
- */
- LIB61850_API LogicalNode*
- LogicalDevice_getLogicalNode(LogicalDevice* self, const char* lnName);
- /**
- * \brief Get the setting group control block (SGCB) of the logical device
- *
- * \param device the logical device instance
- *
- * \return the SGCB instance or NULL if no SGCB is available
- */
- LIB61850_API SettingGroupControlBlock*
- LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self);
- /**@}*/
- /**@}*/
- /**
- * \brief unset all MmsValue references in the data model
- *
- * \param self the IedModel instance that holds the model node
- */
- LIB61850_API void
- IedModel_setAttributeValuesToNull(IedModel* self);
- /**
- * \brief Lookup logical device (LD) by device name
- *
- * \param self IedModel instance
- * \param ldInst the logical device name (as it is seen from the protocol side - MMS domain name)
- *
- * \return The matching LogicalDevice instance
- */
- LIB61850_API LogicalDevice*
- IedModel_getDevice(IedModel* self, const char* ldName);
- /**
- * \brief Lookup a data set in the IED model
- *
- * \param self IedModel instance
- * \param dataSetReference MMS mapping object reference! e.g. ied1Inverter/LLN0$dataset1
- *
- * \return The matching DataSet instance
- */
- LIB61850_API DataSet*
- IedModel_lookupDataSet(IedModel* self, const char* dataSetReference);
- /**
- * \brief Lookup a DataAttribute instance with the corresponding MmsValue instance
- *
- * \param self IedModel instance
- * \param value the MmsValue instance (from the MMS value cache)
- *
- * \return the matching DataAttribute instance
- */
- LIB61850_API DataAttribute*
- IedModel_lookupDataAttributeByMmsValue(IedModel* self, MmsValue* value);
- /**
- * \brief Get the number of logical devices
- *
- * \param self IedModel instance
- *
- * \return the number of logical devices
- */
- LIB61850_API int
- IedModel_getLogicalDeviceCount(IedModel* self);
- LIB61850_API int
- LogicalDevice_getLogicalNodeCount(LogicalDevice* self);
- LIB61850_API ModelNode*
- LogicalDevice_getChildByMmsVariableName(LogicalDevice* self, const char* mmsVariableName);
- LIB61850_API bool
- LogicalNode_hasFCData(LogicalNode* self, FunctionalConstraint fc);
- LIB61850_API bool
- LogicalNode_hasBufferedReports(LogicalNode* self);
- LIB61850_API bool
- LogicalNode_hasUnbufferedReports(LogicalNode* self);
- /**
- * \brief get a data set instance
- *
- * \param self the logical node instance of the data set
- * \param dataSetName the name of the data set
- *
- * \return the data set instance or NULL if the data set does not exist
- */
- LIB61850_API DataSet*
- LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
- LIB61850_API bool
- DataObject_hasFCData(DataObject* self, FunctionalConstraint fc);
- #ifdef __cplusplus
- }
- #endif
- #endif /* MODEL_H_ */
|