iec61850_model.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. * model.h
  3. *
  4. * Copyright 2013-2024 Michael Zillgith
  5. *
  6. * This file is part of libIEC61850.
  7. *
  8. * libIEC61850 is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * libIEC61850 is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with libIEC61850. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. * See COPYING file for the complete license text.
  22. */
  23. #ifndef MODEL_H_
  24. #define MODEL_H_
  25. #include "iec61850_common.h"
  26. #ifdef __cplusplus
  27. extern "C" {
  28. #endif
  29. /** \addtogroup server_api_group
  30. * @{
  31. */
  32. /**
  33. * @defgroup DATA_MODEL General data model definitions, access and iteration functions
  34. *
  35. * \brief Functions and structures to access and iterate the IEC 61850 data model
  36. *
  37. * @{
  38. */
  39. /**
  40. * \brief abstract base type for IEC 61850 data model nodes
  41. */
  42. typedef struct sModelNode ModelNode;
  43. /**
  44. * \brief IEC 61850 data model element of type data attribute
  45. */
  46. typedef struct sDataAttribute DataAttribute;
  47. /**
  48. * \brief IEC 61850 data model element of type data object
  49. */
  50. typedef struct sDataObject DataObject;
  51. /**
  52. * \brief IEC 61850 data model element of type logical node
  53. */
  54. typedef struct sLogicalNode LogicalNode;
  55. /**
  56. * \brief IEC 61850 data model element of type logical device
  57. */
  58. typedef struct sLogicalDevice LogicalDevice;
  59. /**
  60. * \brief Root node of the IEC 61850 data model. This is usually created by the model generator tool (genmodel.jar)
  61. */
  62. typedef struct sIedModel IedModel;
  63. typedef struct sDataSet DataSet;
  64. typedef struct sReportControlBlock ReportControlBlock;
  65. /**
  66. * \brief IEC 61850 data model of setting group control block (SGCB)
  67. */
  68. typedef struct sSettingGroupControlBlock SettingGroupControlBlock;
  69. typedef struct sGSEControlBlock GSEControlBlock;
  70. typedef struct sSVControlBlock SVControlBlock;
  71. typedef struct sLogControlBlock LogControlBlock;
  72. typedef struct sLog Log;
  73. typedef enum {
  74. IEC61850_UNKNOWN_TYPE = -1,
  75. IEC61850_BOOLEAN = 0,/* int */
  76. IEC61850_INT8 = 1, /* int8_t */
  77. IEC61850_INT16 = 2, /* int16_t */
  78. IEC61850_INT32 = 3, /* int32_t */
  79. IEC61850_INT64 = 4, /* int64_t */
  80. IEC61850_INT128 = 5, /* no native mapping! */
  81. IEC61850_INT8U = 6, /* uint8_t */
  82. IEC61850_INT16U = 7, /* uint16_t */
  83. IEC61850_INT24U = 8, /* uint32_t */
  84. IEC61850_INT32U = 9, /* uint32_t */
  85. IEC61850_FLOAT32 = 10, /* float */
  86. IEC61850_FLOAT64 = 11, /* double */
  87. IEC61850_ENUMERATED = 12,
  88. IEC61850_OCTET_STRING_64 = 13,
  89. IEC61850_OCTET_STRING_6 = 14,
  90. IEC61850_OCTET_STRING_8 = 15,
  91. IEC61850_VISIBLE_STRING_32 = 16,
  92. IEC61850_VISIBLE_STRING_64 = 17,
  93. IEC61850_VISIBLE_STRING_65 = 18,
  94. IEC61850_VISIBLE_STRING_129 = 19,
  95. IEC61850_VISIBLE_STRING_255 = 20,
  96. IEC61850_UNICODE_STRING_255 = 21,
  97. IEC61850_TIMESTAMP = 22,
  98. IEC61850_QUALITY = 23,
  99. IEC61850_CHECK = 24,
  100. IEC61850_CODEDENUM = 25,
  101. IEC61850_GENERIC_BITSTRING = 26,
  102. IEC61850_CONSTRUCTED = 27,
  103. IEC61850_ENTRY_TIME = 28,
  104. IEC61850_PHYCOMADDR = 29,
  105. IEC61850_CURRENCY = 30,
  106. IEC61850_OPTFLDS = 31, /* bit-string(10) */
  107. IEC61850_TRGOPS = 32 /* bit-string(6) */
  108. } DataAttributeType;
  109. typedef enum {
  110. LogicalDeviceModelType,
  111. LogicalNodeModelType,
  112. DataObjectModelType,
  113. DataAttributeModelType
  114. } ModelNodeType;
  115. struct sIedModel {
  116. char* name;
  117. LogicalDevice* firstChild;
  118. DataSet* dataSets;
  119. ReportControlBlock* rcbs;
  120. GSEControlBlock* gseCBs;
  121. SVControlBlock* svCBs;
  122. SettingGroupControlBlock* sgcbs;
  123. LogControlBlock* lcbs;
  124. Log* logs;
  125. void (*initializer) (void);
  126. };
  127. struct sLogicalDevice {
  128. ModelNodeType modelType;
  129. char* name; /* LD instance */
  130. ModelNode* parent;
  131. ModelNode* sibling;
  132. ModelNode* firstChild;
  133. char* ldName; /* ldName (when using functional naming) */
  134. };
  135. struct sModelNode {
  136. ModelNodeType modelType;
  137. char* name;
  138. ModelNode* parent;
  139. ModelNode* sibling;
  140. ModelNode* firstChild;
  141. };
  142. struct sLogicalNode {
  143. ModelNodeType modelType;
  144. char* name;
  145. ModelNode* parent;
  146. ModelNode* sibling;
  147. ModelNode* firstChild;
  148. };
  149. struct sDataObject {
  150. ModelNodeType modelType;
  151. char* name;
  152. ModelNode* parent;
  153. ModelNode* sibling;
  154. ModelNode* firstChild;
  155. int elementCount; /* value > 0 if this is an array */
  156. int arrayIndex; /* value > -1 when this is an array element */
  157. };
  158. struct sDataAttribute {
  159. ModelNodeType modelType;
  160. char* name;
  161. ModelNode* parent;
  162. ModelNode* sibling;
  163. ModelNode* firstChild;
  164. int elementCount; /* value > 0 if this is an array */
  165. int arrayIndex; /* value > -1 when this is an array element */
  166. FunctionalConstraint fc;
  167. DataAttributeType type;
  168. uint8_t triggerOptions; /* TRG_OPT_DATA_CHANGED | TRG_OPT_QUALITY_CHANGED | TRG_OPT_DATA_UPDATE */
  169. MmsValue* mmsValue;
  170. uint32_t sAddr; /* TODO remove in version 2.0 */
  171. };
  172. typedef struct sDataSetEntry {
  173. char* logicalDeviceName; /* logical device instance name */
  174. bool isLDNameDynamicallyAllocated;
  175. char* variableName;
  176. int index;
  177. char* componentName;
  178. MmsValue* value;
  179. struct sDataSetEntry* sibling;
  180. } DataSetEntry;
  181. struct sDataSet {
  182. char* logicalDeviceName; /* logical device instance name */
  183. char* name; /* eg. MMXU1$dataset1 */
  184. int elementCount;
  185. DataSetEntry* fcdas;
  186. DataSet* sibling;
  187. };
  188. struct sReportControlBlock {
  189. LogicalNode* parent;
  190. char* name;
  191. char* rptId;
  192. bool buffered;
  193. char* dataSetName; /* pre loaded with relative name in logical node */
  194. uint32_t confRef; /* ConfRef - configuration revision */
  195. uint8_t trgOps; /* TrgOps - trigger conditions */
  196. uint8_t options; /* OptFlds */
  197. uint32_t bufferTime; /* BufTm - time to buffer events until a report is generated */
  198. uint32_t intPeriod; /* IntgPd - integrity period */
  199. /* type (first byte) and address of the pre-configured client
  200. type can be one of (0 - no reservation, 4 - IPv4 client, 6 - IPv6 client) */
  201. uint8_t clientReservation[17];
  202. ReportControlBlock* sibling; /* next control block in list or NULL if this is the last entry
  203. * at runtime reuse as pointer to ReportControl instance!
  204. **/
  205. };
  206. struct sLogControlBlock {
  207. LogicalNode* parent;
  208. char* name;
  209. char* dataSetName;
  210. char* logRef; /* object reference to the journal */
  211. uint8_t trgOps; /* TrgOps - trigger conditions */
  212. uint32_t intPeriod; /* IntgPd - integrity period */
  213. bool logEna; /* enable log by default */
  214. bool reasonCode; /* include reason code in log */
  215. LogControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
  216. };
  217. struct sLog {
  218. LogicalNode* parent;
  219. char* name;
  220. Log* sibling; /* next log instance in list or NULL if this is the last entry */
  221. };
  222. struct sSettingGroupControlBlock {
  223. LogicalNode* parent;
  224. uint8_t actSG; /* value from SCL file */
  225. uint8_t numOfSGs; /* value from SCL file */
  226. uint8_t editSG; /* 0 at power-up */
  227. bool cnfEdit; /* false at power-up */
  228. uint64_t timestamp;
  229. uint16_t resvTms;
  230. SettingGroupControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
  231. };
  232. struct sGSEControlBlock {
  233. LogicalNode* parent;
  234. char* name;
  235. char* appId;
  236. char* dataSetName; /* pre loaded with relative name in logical node */
  237. uint32_t confRev; /* ConfRev - configuration revision */
  238. bool fixedOffs; /* fixed offsets */
  239. PhyComAddress* address; /* GSE communication parameters */
  240. int minTime; /* optional minTime parameter --> -1 if not present */
  241. int maxTime; /* optional maxTime parameter --> -1 if not present */
  242. GSEControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
  243. };
  244. struct sSVControlBlock {
  245. LogicalNode* parent;
  246. char* name;
  247. char* svId; /* MsvUD/UsvID */
  248. char* dataSetName; /* pre loaded with relative name in logical node */
  249. uint8_t optFlds;
  250. uint8_t smpMod;
  251. uint16_t smpRate;
  252. uint32_t confRev; /* ConfRev - configuration revision */
  253. PhyComAddress* dstAddress; /* SV communication parameters */
  254. bool isUnicast;
  255. int noASDU;
  256. SVControlBlock* sibling; /* next control block in list or NULL if this is the last entry */
  257. };
  258. /**
  259. * \brief get the number of direct children of a model node
  260. *
  261. * \param self the model node instance
  262. *
  263. * \return the number of children of the model node
  264. * ¸
  265. */
  266. LIB61850_API int
  267. ModelNode_getChildCount(ModelNode* self);
  268. /**
  269. * \brief return a child model node
  270. *
  271. * \param self the model node instance
  272. * \param name the name of the child model node
  273. *
  274. * \return the model node instance or NULL if model node does not exist.
  275. */
  276. LIB61850_API ModelNode*
  277. ModelNode_getChild(ModelNode* self, const char* name);
  278. /**
  279. * \brief return the child node of an array or other structure
  280. *
  281. * \param self the model node instance
  282. * \param idx the index (e.g. array index) starting with 0
  283. *
  284. * \return the model node instance or NULL if model node with given index does not exist.
  285. */
  286. LIB61850_API ModelNode*
  287. ModelNode_getChildWithIdx(ModelNode* self, int idx);
  288. /**
  289. * \brief return a child model node with a given functional constraint
  290. *
  291. * Sometimes the name is not enough to identify a model node. This is the case when
  292. * editable setting groups are used. In this case the setting group members have two different
  293. * model nodes associated that differ in their FC (SG and SE).
  294. *
  295. * \param self the model node instance
  296. * \param name the name of the child model node
  297. * \param fc the functional constraint of the model node
  298. *
  299. * \return the model node instance or NULL if model node does not exist.
  300. */
  301. LIB61850_API ModelNode*
  302. ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint fc);
  303. /**
  304. * \brief Return the IEC 61850 object reference of a model node
  305. *
  306. * \param self the model node instance
  307. * \param objectReference pointer to a buffer where to write the object reference string. If NULL
  308. * is given the buffer is allocated by the function.
  309. *
  310. * \return the object reference string
  311. */
  312. LIB61850_API char*
  313. ModelNode_getObjectReference(ModelNode* self, char* objectReference);
  314. /**
  315. * \brief Return the IEC 61850 object reference of a model node
  316. *
  317. * \param self the model node instance
  318. * \param objectReference pointer to a buffer where to write the object reference string. If NULL
  319. * is given the buffer is allocated by the function.
  320. * \param withoutIedName create object reference without IED name part
  321. *
  322. * \return the object reference string
  323. */
  324. LIB61850_API char*
  325. ModelNode_getObjectReferenceEx(ModelNode* node, char* objectReference, bool withoutIedName);
  326. /**
  327. * \brief Get the type of the ModelNode
  328. *
  329. * \param self the ModelNode instance
  330. *
  331. * \return the type of the ModelNode (one of LD, LN, DO, DA)
  332. */
  333. LIB61850_API ModelNodeType
  334. ModelNode_getType(ModelNode* self);
  335. /**
  336. * \brief Get the name of the ModelNode
  337. *
  338. * \param self the ModelNode instance
  339. *
  340. * \return the name of the ModelNode
  341. */
  342. LIB61850_API const char*
  343. ModelNode_getName(ModelNode* self);
  344. /**
  345. * \brief Get the parent ModelNode of this ModelNode instance
  346. *
  347. * \param self the ModelNode instance
  348. *
  349. * \return the parent instance, or NULL when the ModelNode has no parent
  350. */
  351. LIB61850_API ModelNode*
  352. ModelNode_getParent(ModelNode* self);
  353. /**
  354. * \brief Get the list of direct child nodes
  355. *
  356. * \param self the ModelNode instance
  357. *
  358. * \return the list of private child nodes, or NULL when the node has no children
  359. */
  360. LIB61850_API LinkedList
  361. ModelNode_getChildren(ModelNode* self);
  362. /**
  363. * \brief Set the name of the IED
  364. *
  365. * This will change the default name (usualy "TEMPLATE") to a user configured values.
  366. * NOTE: This function has to be called before IedServer_create !
  367. *
  368. * \param model the IedModel instance
  369. * \param the name of the configured IED
  370. */
  371. LIB61850_API void
  372. IedModel_setIedName(IedModel* self, const char* iedName);
  373. /**
  374. * \brief Lookup a model node by its object reference
  375. *
  376. * This function uses the full logical device name as part of the object reference
  377. * as it happens to appear on the wire. E.g. if IED name in SCL file would be "IED1"
  378. * and the logical device "WD1" the resulting LD name would be "IED1WD".
  379. * When using functional naming in the LD (with ldName attribute) then the logical
  380. * device name is identical with the ldName attribute.
  381. *
  382. * \param self the IedModel instance that holds the model node
  383. * \param objectReference the IEC 61850 object reference
  384. *
  385. * \return the model node instance or NULL if model node does not exist.
  386. */
  387. LIB61850_API ModelNode*
  388. IedModel_getModelNodeByObjectReference(IedModel* self, const char* objectReference);
  389. LIB61850_API SVControlBlock*
  390. IedModel_getSVControlBlock(IedModel* self, LogicalNode* parentLN, const char* svcbName);
  391. /**
  392. * \brief Lookup a model node by its short (normalized) reference
  393. *
  394. * This version uses the object reference that does not contain the
  395. * IED name or functional name as part of the logical device name.
  396. * Instead the LD part consists of the LD instance name ("inst" attribute).
  397. * This function is useful for
  398. * devices where the IED name can be configured.
  399. *
  400. * \param self the IedModel instance that holds the model node
  401. * \param objectReference the IEC 61850 object reference
  402. *
  403. * \return the model node instance or NULL if model node does not exist.
  404. */
  405. LIB61850_API ModelNode*
  406. IedModel_getModelNodeByShortObjectReference(IedModel* self, const char* objectReference);
  407. /**
  408. * \brief Lookup a model node by its short address
  409. *
  410. * Short address is a 32 bit unsigned integer as specified in the "sAddr" attribute of
  411. * the ICD file or in the configuration file.
  412. *
  413. * \param self the IedModel instance that holds the model node
  414. * \param shortAddress
  415. *
  416. * \return the model node instance or NULL if model node does not exist.
  417. */
  418. LIB61850_API ModelNode*
  419. IedModel_getModelNodeByShortAddress(IedModel* self, uint32_t shortAddress);
  420. /**
  421. * \brief Lookup logical device (LD) by device instance name (SCL attribute "inst")
  422. *
  423. * \param self IedModel instance
  424. * \param ldInst the logical device instance name (SCL attribute "inst")
  425. *
  426. * \return The matching LogicalDevice instance
  427. */
  428. LIB61850_API LogicalDevice*
  429. IedModel_getDeviceByInst(IedModel* self, const char* ldInst);
  430. /**
  431. * \brief Lookup logical device (LD) instance by index
  432. *
  433. * \param self IedModel instance
  434. * \param index the index of the LD in the range (0 .. number of LDs - 1)
  435. *
  436. * \return the corresponding LogicalDevice* object or NULL if the index is out of range
  437. */
  438. LIB61850_API LogicalDevice*
  439. IedModel_getDeviceByIndex(IedModel* self, int index);
  440. /**
  441. * \brief Lookup a logical node by name that is part of the given logical device
  442. *
  443. * \param device the logical device instance
  444. * \param lnName the logical node name
  445. *
  446. * \return the logical device instance or NULL if it does not exist
  447. */
  448. LIB61850_API LogicalNode*
  449. LogicalDevice_getLogicalNode(LogicalDevice* self, const char* lnName);
  450. /**
  451. * \brief Get the setting group control block (SGCB) of the logical device
  452. *
  453. * \param device the logical device instance
  454. *
  455. * \return the SGCB instance or NULL if no SGCB is available
  456. */
  457. LIB61850_API SettingGroupControlBlock*
  458. LogicalDevice_getSettingGroupControlBlock(LogicalDevice* self);
  459. /**@}*/
  460. /**@}*/
  461. /**
  462. * \brief unset all MmsValue references in the data model
  463. *
  464. * \param self the IedModel instance that holds the model node
  465. */
  466. LIB61850_API void
  467. IedModel_setAttributeValuesToNull(IedModel* self);
  468. /**
  469. * \brief Lookup logical device (LD) by device name
  470. *
  471. * \param self IedModel instance
  472. * \param ldInst the logical device name (as it is seen from the protocol side - MMS domain name)
  473. *
  474. * \return The matching LogicalDevice instance
  475. */
  476. LIB61850_API LogicalDevice*
  477. IedModel_getDevice(IedModel* self, const char* ldName);
  478. /**
  479. * \brief Lookup a data set in the IED model
  480. *
  481. * \param self IedModel instance
  482. * \param dataSetReference MMS mapping object reference! e.g. ied1Inverter/LLN0$dataset1
  483. *
  484. * \return The matching DataSet instance
  485. */
  486. LIB61850_API DataSet*
  487. IedModel_lookupDataSet(IedModel* self, const char* dataSetReference);
  488. /**
  489. * \brief Lookup a DataAttribute instance with the corresponding MmsValue instance
  490. *
  491. * \param self IedModel instance
  492. * \param value the MmsValue instance (from the MMS value cache)
  493. *
  494. * \return the matching DataAttribute instance
  495. */
  496. LIB61850_API DataAttribute*
  497. IedModel_lookupDataAttributeByMmsValue(IedModel* self, MmsValue* value);
  498. /**
  499. * \brief Get the number of logical devices
  500. *
  501. * \param self IedModel instance
  502. *
  503. * \return the number of logical devices
  504. */
  505. LIB61850_API int
  506. IedModel_getLogicalDeviceCount(IedModel* self);
  507. LIB61850_API int
  508. LogicalDevice_getLogicalNodeCount(LogicalDevice* self);
  509. LIB61850_API ModelNode*
  510. LogicalDevice_getChildByMmsVariableName(LogicalDevice* self, const char* mmsVariableName);
  511. LIB61850_API bool
  512. LogicalNode_hasFCData(LogicalNode* self, FunctionalConstraint fc);
  513. LIB61850_API bool
  514. LogicalNode_hasBufferedReports(LogicalNode* self);
  515. LIB61850_API bool
  516. LogicalNode_hasUnbufferedReports(LogicalNode* self);
  517. /**
  518. * \brief get a data set instance
  519. *
  520. * \param self the logical node instance of the data set
  521. * \param dataSetName the name of the data set
  522. *
  523. * \return the data set instance or NULL if the data set does not exist
  524. */
  525. LIB61850_API DataSet*
  526. LogicalNode_getDataSet(LogicalNode* self, const char* dataSetName);
  527. LIB61850_API bool
  528. DataObject_hasFCData(DataObject* self, FunctionalConstraint fc);
  529. #ifdef __cplusplus
  530. }
  531. #endif
  532. #endif /* MODEL_H_ */