sv_subscriber.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*
  2. * sv_subscriber.h
  3. *
  4. * Copyright 2015-2018 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 SAMPLED_VALUES_SV_SUBSCRIBER_H_
  24. #define SAMPLED_VALUES_SV_SUBSCRIBER_H_
  25. #include "libiec61850_common_api.h"
  26. #include "iec61850_common.h"
  27. #include "hal_ethernet.h"
  28. #ifdef __cplusplus
  29. extern "C" {
  30. #endif
  31. /**
  32. * \defgroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) subscriber API
  33. *
  34. * The sampled values (SV) subscriber API consists of three different objects.
  35. * The \ref SVReceiver object is responsible for handling all SV Ethernet messages
  36. * for a specific Ethernet interface. If you want to receive SV messages on multiple
  37. * Ethernet interfaces you have to use several \ref SVReceiver instances.
  38. * An \ref SVSubscriber object is associated to a SV data stream that is identified by its appID
  39. * and destination Ethernet address. The \reg SVSubscriber object is used to install a callback
  40. * handler \ref SVUpdateListener that is invoked for each ASDU (application service data unit) received for the
  41. * associated stream. An \ref SVSubscriber_ASDU is an object that represents a single ASDU. Each ASDU contains
  42. * some meta information that can be obtained by specific access functions like e.g.
  43. * \ref SVSubscriber_ASDU_getSmpCnt to access the "SmpCnt" (sample count) attribute of the ASDU. The actual
  44. * measurement data contained in the ASDU does not consist of structured ASN.1 data but stored as raw binary
  45. * data. Without a priori knowledge of the dataset associated with the ASDU data stream it is not
  46. * possible to interpret the received data correctly. Therefore you have to provide the data access functions
  47. * with an index value to indicate the data type and the start of the data in the data block of the ASDU.
  48. * E.g. reading a data set consisting of two FLOAT32 values you can use two subsequent calls of
  49. * \ref SVSubscriber_ASDU_getFLOAT32 one with index = 0 and the second one with index = 4.
  50. *
  51. * | IEC 61850 type | required bytes |
  52. * | -------------- | -------------- |
  53. * | BOOLEAN | 1 byte |
  54. * | INT8 | 1 byte |
  55. * | INT16 | 2 byte |
  56. * | INT32 | 4 byte |
  57. * | INT64 | 8 byte |
  58. * | INT8U | 1 byte |
  59. * | INT16U | 2 byte |
  60. * | INT24U | 3 byte |
  61. * | INT32U | 4 byte |
  62. * | INT64U | 8 byte |
  63. * | FLOAT32 | 4 byte |
  64. * | FLOAT64 | 8 byte |
  65. * | ENUMERATED | 4 byte |
  66. * | CODED ENUM | 4 byte |
  67. * | OCTET STRING | 20 byte |
  68. * | VISIBLE STRING | 35 byte |
  69. * | TimeStamp | 8 byte |
  70. * | EntryTime | 6 byte |
  71. * | BITSTRING | 4 byte |
  72. * | Quality | 4 byte |
  73. *
  74. * The SV subscriber API can be used independent of the IEC 61850 client API. In order to access the SVCB via MMS you
  75. * have to use the IEC 61850 client API. Please see \ref ClientSVControlBlock object in section \ref IEC61850_CLIENT_SV.
  76. *
  77. */
  78. /**@{*/
  79. /**
  80. * \brief opaque handle to a SV ASDU (Application service data unit) instance.
  81. *
  82. * Sampled Values (SV) ASDUs (application service data units) are the basic units for
  83. * sampled value data. Each ASDU represents a single sample consisting of multiple measurement
  84. * values with a single dedicated timestamp.
  85. *
  86. * NOTE: SVSubscriber_ASDU are statically allocated and are only valid inside of the SVUpdateListener
  87. * function when called by the library. If you need the data contained in the ASDU elsewhere
  88. * you have to copy and store the data by yourself!
  89. */
  90. typedef struct sSVSubscriber_ASDU* SVSubscriber_ASDU;
  91. /**
  92. * \brief opaque handle to a SV subscriber instance
  93. *
  94. * A subscriber is an instance associated with a single stream of measurement data. It is identified
  95. * by the Ethernet destination address, the appID value (both are on SV message level) and the svID value
  96. * that is part of each ASDU (SVSubscriber_ASDU object).
  97. */
  98. typedef struct sSVSubscriber* SVSubscriber;
  99. /**
  100. * \brief Callback function for received SV messages
  101. *
  102. * Will be called for each ASDU contained in a SV message!
  103. *
  104. * \param subscriber the subscriber that was associated with the received SV message
  105. * \param parameter a user provided parameter that is simply passed to the callback
  106. * \param asdu SV ASDU data structure. This structure is only valid inside of the callback function
  107. */
  108. typedef void (*SVUpdateListener)(SVSubscriber subscriber, void* parameter, SVSubscriber_ASDU asdu);
  109. /**
  110. * \brief opaque handle to a SV receiver instance
  111. */
  112. typedef struct sSVReceiver* SVReceiver;
  113. /**
  114. * \brief Create a new SV receiver instance.
  115. *
  116. * A receiver is responsible for processing all SV message for a single Ethernet interface.
  117. * In order to process messages from multiple Ethernet interfaces you have to create multiple
  118. * instances.
  119. *
  120. * \return the newly created receiver instance
  121. */
  122. LIB61850_API SVReceiver
  123. SVReceiver_create(void);
  124. /**
  125. * \brief Disable check for destination address of the received SV messages
  126. *
  127. * \param self the receiver instance reference
  128. */
  129. LIB61850_API void
  130. SVReceiver_disableDestAddrCheck(SVReceiver self);
  131. /**
  132. * \brief Enable check for destination address of the received SV messages
  133. *
  134. * Per default only the appID is checked to identify relevant SV messages and the
  135. * destination address is ignored for performance reasons. This only works when the
  136. * appIDs are unique in the local system. Otherwise the destination address check
  137. * has to be enabled.
  138. *
  139. * \param self the receiver instance reference
  140. */
  141. LIB61850_API void
  142. SVReceiver_enableDestAddrCheck(SVReceiver self);
  143. /**
  144. * \brief Set the Ethernet interface ID for the receiver instance
  145. *
  146. * Use this function if you want to use a different interface than
  147. * the default interface set by CONFIG_ETHERNET_INTERFACE_ID (stack_config.h)
  148. * NOTE: This function has to be called before calling SVReceiver_start.
  149. *
  150. * \param self the receiver instance reference
  151. * \param interfaceId the Ethernet interface id (platform specific e.g. eth0 for linux).
  152. */
  153. LIB61850_API void
  154. SVReceiver_setInterfaceId(SVReceiver self, const char* interfaceId);
  155. /**
  156. * \brief Add a subscriber instance to the receiver
  157. *
  158. * The given subscriber will be connected to the receiver instance.
  159. *
  160. * \param self the receiver instance reference
  161. * \param subscriber the subscriber instance to connect
  162. */
  163. LIB61850_API void
  164. SVReceiver_addSubscriber(SVReceiver self, SVSubscriber subscriber);
  165. /**
  166. * \brief Disconnect subscriber and receiver
  167. *
  168. * \param self the receiver instance reference
  169. * \param subscriber the subscriber instance to disconnect
  170. */
  171. LIB61850_API void
  172. SVReceiver_removeSubscriber(SVReceiver self, SVSubscriber subscriber);
  173. /**
  174. * \brief Receiver starts listening for SV messages.
  175. *
  176. * NOTE: This call will start a new background thread.
  177. *
  178. * \param self the receiver instance reference
  179. */
  180. LIB61850_API void
  181. SVReceiver_start(SVReceiver self);
  182. /**
  183. * \brief Receiver stops listening for SV messages
  184. *
  185. * \param self the receiver instance reference
  186. */
  187. LIB61850_API void
  188. SVReceiver_stop(SVReceiver self);
  189. /**
  190. * \brief Check if SV receiver is running
  191. *
  192. * Can be used to check if \ref SVReceiver_start has been successful.
  193. *
  194. * \param self the receiver instance reference
  195. *
  196. * \return true if SV receiver is running, false otherwise
  197. */
  198. LIB61850_API bool
  199. SVReceiver_isRunning(SVReceiver self);
  200. /**
  201. * \brief Destroy receiver instance (cleanup resources)
  202. *
  203. * \param self the receiver instance reference
  204. */
  205. LIB61850_API void
  206. SVReceiver_destroy(SVReceiver self);
  207. /***************************************
  208. * Functions for non-threaded operation
  209. ***************************************/
  210. LIB61850_API EthernetSocket
  211. SVReceiver_startThreadless(SVReceiver self);
  212. LIB61850_API void
  213. SVReceiver_stopThreadless(SVReceiver self);
  214. /**
  215. * \brief Parse SV messages if they are available.
  216. *
  217. * Call after reception of ethernet frame and periodically to to house keeping tasks
  218. *
  219. * \param self the receiver object
  220. *
  221. * \return true if a message was available and has been parsed, false otherwise
  222. */
  223. LIB61850_API bool
  224. SVReceiver_tick(SVReceiver self);
  225. /*
  226. * \brief Create a new SV subscriber instance
  227. *
  228. * \param ethAddr optional destination address (NULL to not specify the destination address)
  229. * \param appID the APP-ID to identify matching SV messages
  230. *
  231. * \return the new subscriber instance
  232. */
  233. LIB61850_API SVSubscriber
  234. SVSubscriber_create(const uint8_t* ethAddr, uint16_t appID);
  235. /**
  236. * \brief Set a callback handler to process received SV messages
  237. *
  238. * If the received SV message contains multiple ASDUs (application service data units) the callback
  239. * function will be called for each ASDU separately. If a callback function has already been installed
  240. * for this SVSubscriber object the old callback will be replaced.
  241. *
  242. * \param self The subscriber object
  243. * \param listener the callback function to install
  244. * \param a user provided parameter that is provided to the callback function
  245. */
  246. LIB61850_API void
  247. SVSubscriber_setListener(SVSubscriber self, SVUpdateListener listener, void* parameter);
  248. LIB61850_API void
  249. SVSubscriber_destroy(SVSubscriber self);
  250. /*************************************************************************
  251. * SVSubscriber_ASDU object methods
  252. **************************************************************************/
  253. /**
  254. * \addtogroup sv_subscriber_asdu_group Values Application Service Data Unit (ASDU)
  255. * @{
  256. */
  257. /**
  258. * \brief return the SmpCnt value included in the SV ASDU
  259. *
  260. * The SmpCnt (sample counter) is increased for each ASDU to
  261. * identify the sample.
  262. *
  263. * \param self ASDU object instance
  264. */
  265. LIB61850_API uint16_t
  266. SVSubscriber_ASDU_getSmpCnt(SVSubscriber_ASDU self);
  267. /**
  268. * \brief return the SvID value included in the SV ASDU
  269. *
  270. * \param self ASDU object instance
  271. */
  272. LIB61850_API const char*
  273. SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self);
  274. /**
  275. * \brief return the DatSet value included in the SV ASDU
  276. *
  277. * \param self ASDU object instance
  278. */
  279. LIB61850_API const char*
  280. SVSubscriber_ASDU_getDatSet(SVSubscriber_ASDU self);
  281. /**
  282. * \brief return the ConfRev value included in the SV ASDU
  283. *
  284. * \param self ASDU object instance
  285. */
  286. LIB61850_API uint32_t
  287. SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self);
  288. /**
  289. * \brief return the SmpMod value included in the SV ASDU
  290. *
  291. * \param self ASDU object instance
  292. */
  293. LIB61850_API uint8_t
  294. SVSubscriber_ASDU_getSmpMod(SVSubscriber_ASDU self);
  295. /**
  296. * \brief return the SmpRate value included in the SV ASDU
  297. *
  298. * \param self ASDU object instance
  299. */
  300. LIB61850_API uint16_t
  301. SVSubscriber_ASDU_getSmpRate(SVSubscriber_ASDU self);
  302. /**
  303. * \brief Check if DatSet value is included in the SV ASDU
  304. *
  305. * \param self ASDU object instance
  306. *
  307. * \return true if DatSet value is present, false otherwise
  308. */
  309. LIB61850_API bool
  310. SVSubscriber_ASDU_hasDatSet(SVSubscriber_ASDU self);
  311. /**
  312. * \brief Check if RefrTm value is included in the SV ASDU
  313. *
  314. * \param self ASDU object instance
  315. *
  316. * \return true if RefrTm value is present, false otherwise
  317. */
  318. LIB61850_API bool
  319. SVSubscriber_ASDU_hasRefrTm(SVSubscriber_ASDU self);
  320. /**
  321. * \brief Check if SmpMod value is included in the SV ASDU
  322. *
  323. * \param self ASDU object instance
  324. *
  325. * \return true if SmpMod value is present, false otherwise
  326. */
  327. LIB61850_API bool
  328. SVSubscriber_ASDU_hasSmpMod(SVSubscriber_ASDU self);
  329. /**
  330. * \brief Check if SmpRate value is included in the SV ASDU
  331. *
  332. * \param self ASDU object instance
  333. *
  334. * \return true if SmpRate value is present, false otherwise
  335. */
  336. LIB61850_API bool
  337. SVSubscriber_ASDU_hasSmpRate(SVSubscriber_ASDU self);
  338. /**
  339. * \brief Get the RefrTim value included in SV ASDU as milliseconds timestamp
  340. *
  341. * \param self ASDU object instance
  342. *
  343. * \return the time value as ms timestamp or 0 if RefrTm is not present in the SV ASDU
  344. */
  345. LIB61850_API uint64_t
  346. SVSubscriber_ASDU_getRefrTmAsMs(SVSubscriber_ASDU self);
  347. /**
  348. * \brief Get the RefrTim value included in SV ASDU as nanoseconds timestamp
  349. *
  350. * \param self ASDU object instance
  351. *
  352. * \return the time value as nanoseconds timestamp or 0 if RefrTm is not present in the SV ASDU
  353. */
  354. LIB61850_API nsSinceEpoch
  355. SVSubscriber_ASDU_getRefrTmAsNs(SVSubscriber_ASDU self);
  356. /**
  357. * \brief Get an INT8 data value in the data part of the ASDU
  358. *
  359. * \param self ASDU object instance
  360. * \param index the index (byte position of the start) of the data in the data part
  361. *
  362. * \return SV data
  363. */
  364. LIB61850_API int8_t
  365. SVSubscriber_ASDU_getINT8(SVSubscriber_ASDU self, int index);
  366. /**
  367. * \brief Get an INT16 data value in the data part of the ASDU
  368. *
  369. * \param self ASDU object instance
  370. * \param index the index (byte position of the start) of the data in the data part
  371. *
  372. * \return SV data
  373. */
  374. LIB61850_API int16_t
  375. SVSubscriber_ASDU_getINT16(SVSubscriber_ASDU self, int index);
  376. /**
  377. * \brief Get an INT32 data value in the data part of the ASDU
  378. *
  379. * \param self ASDU object instance
  380. * \param index the index (byte position of the start) of the data in the data part
  381. *
  382. * \return SV data
  383. */
  384. LIB61850_API int32_t
  385. SVSubscriber_ASDU_getINT32(SVSubscriber_ASDU self, int index);
  386. /**
  387. * \brief Get an INT64 data value in the data part of the ASDU
  388. *
  389. * \param self ASDU object instance
  390. * \param index the index (byte position of the start) of the data in the data part
  391. *
  392. * \return SV data
  393. */
  394. LIB61850_API int64_t
  395. SVSubscriber_ASDU_getINT64(SVSubscriber_ASDU self, int index);
  396. /**
  397. * \brief Get an INT8U data value in the data part of the ASDU
  398. *
  399. * \param self ASDU object instance
  400. * \param index the index (byte position of the start) of the data in the data part
  401. *
  402. * \return SV data
  403. */
  404. LIB61850_API uint8_t
  405. SVSubscriber_ASDU_getINT8U(SVSubscriber_ASDU self, int index);
  406. /**
  407. * \brief Get an INT16U data value in the data part of the ASDU
  408. *
  409. * \param self ASDU object instance
  410. * \param index the index (byte position of the start) of the data in the data part
  411. *
  412. * \return SV data
  413. */
  414. LIB61850_API uint16_t
  415. SVSubscriber_ASDU_getINT16U(SVSubscriber_ASDU self, int index);
  416. /**
  417. * \brief Get an INT32U data value in the data part of the ASDU
  418. *
  419. * \param self ASDU object instance
  420. * \param index the index (byte position of the start) of the data in the data part
  421. *
  422. * \return SV data
  423. */
  424. LIB61850_API uint32_t
  425. SVSubscriber_ASDU_getINT32U(SVSubscriber_ASDU self, int index);
  426. /**
  427. * \brief Get an INT64U data value in the data part of the ASDU
  428. *
  429. * \param self ASDU object instance
  430. * \param index the index (byte position of the start) of the data in the data part
  431. *
  432. * \return SV data
  433. */
  434. LIB61850_API uint64_t
  435. SVSubscriber_ASDU_getINT64U(SVSubscriber_ASDU self, int index);
  436. /**
  437. * \brief Get an FLOAT32 data value in the data part of the ASDU
  438. *
  439. * \param self ASDU object instance
  440. * \param index the index (byte position of the start) of the data in the data part
  441. *
  442. * \return SV data
  443. */
  444. LIB61850_API float
  445. SVSubscriber_ASDU_getFLOAT32(SVSubscriber_ASDU self, int index);
  446. /**
  447. * \brief Get an FLOAT64 data value in the data part of the ASDU
  448. *
  449. * \param self ASDU object instance
  450. * \param index the index (byte position of the start) of the data in the data part
  451. *
  452. * \return SV data
  453. */
  454. LIB61850_API double
  455. SVSubscriber_ASDU_getFLOAT64(SVSubscriber_ASDU self, int index);
  456. /**
  457. * \brief Get a timestamp data value in the data part of the ASDU
  458. *
  459. * \param self ASDU object instance
  460. * \param index the index (byte position of the start) of the data in the data part
  461. *
  462. * \return SV data
  463. */
  464. LIB61850_API Timestamp
  465. SVSubscriber_ASDU_getTimestamp(SVSubscriber_ASDU self, int index);
  466. /**
  467. * \brief Get a quality value in the data part of the ASDU
  468. *
  469. * NOTE: Quality is encoded as BITSTRING (4 byte)
  470. *
  471. * \param self ASDU object instance
  472. * \param index the index (byte position of the start) of the data in the data part
  473. *
  474. * \return SV data
  475. */
  476. LIB61850_API Quality
  477. SVSubscriber_ASDU_getQuality(SVSubscriber_ASDU self, int index);
  478. /**
  479. * \brief Returns the size of the data part of the ASDU
  480. *
  481. * \param self ASDU object instance
  482. *
  483. * \return size of the ASDU data part in bytes.
  484. */
  485. LIB61850_API int
  486. SVSubscriber_ASDU_getDataSize(SVSubscriber_ASDU self);
  487. /**
  488. * \brief return the SmpSynch value included in the SV ASDU
  489. *
  490. * The SmpSynch gives information about the clock synchronization.
  491. *
  492. * \param self ASDU object instance
  493. */
  494. uint8_t
  495. SVSubscriber_ASDU_getSmpSynch(SVSubscriber_ASDU self);
  496. #ifndef DEPRECATED
  497. #if defined(__GNUC__) || defined(__clang__)
  498. #define DEPRECATED __attribute__((deprecated))
  499. #else
  500. #define DEPRECATED
  501. #endif
  502. #endif
  503. /**
  504. * \addtogroup sv_subscriber_deprecated_api_group Deprecated API
  505. * \ingroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) publisher API
  506. * \deprecated
  507. * @{
  508. */
  509. typedef struct sSVSubscriberASDU* SVClientASDU;
  510. LIB61850_API DEPRECATED uint16_t
  511. SVClientASDU_getSmpCnt(SVSubscriber_ASDU self);
  512. LIB61850_API DEPRECATED const char*
  513. SVClientASDU_getSvId(SVSubscriber_ASDU self);
  514. LIB61850_API DEPRECATED uint32_t
  515. SVClientASDU_getConfRev(SVSubscriber_ASDU self);
  516. LIB61850_API DEPRECATED bool
  517. SVClientASDU_hasRefrTm(SVSubscriber_ASDU self);
  518. LIB61850_API DEPRECATED uint64_t
  519. SVClientASDU_getRefrTmAsMs(SVSubscriber_ASDU self);
  520. LIB61850_API DEPRECATED int8_t
  521. SVClientASDU_getINT8(SVSubscriber_ASDU self, int index);
  522. LIB61850_API DEPRECATED int16_t
  523. SVClientASDU_getINT16(SVSubscriber_ASDU self, int index);
  524. LIB61850_API DEPRECATED int32_t
  525. SVClientASDU_getINT32(SVSubscriber_ASDU self, int index);
  526. LIB61850_API DEPRECATED int64_t
  527. SVClientASDU_getINT64(SVSubscriber_ASDU self, int index);
  528. LIB61850_API DEPRECATED uint8_t
  529. SVClientASDU_getINT8U(SVSubscriber_ASDU self, int index);
  530. LIB61850_API DEPRECATED uint16_t
  531. SVClientASDU_getINT16U(SVSubscriber_ASDU self, int index);
  532. LIB61850_API DEPRECATED uint32_t
  533. SVClientASDU_getINT32U(SVSubscriber_ASDU self, int index);
  534. LIB61850_API DEPRECATED uint64_t
  535. SVClientASDU_getINT64U(SVSubscriber_ASDU self, int index);
  536. LIB61850_API DEPRECATED float
  537. SVClientASDU_getFLOAT32(SVSubscriber_ASDU self, int index);
  538. LIB61850_API DEPRECATED double
  539. SVClientASDU_getFLOAT64(SVSubscriber_ASDU self, int index);
  540. LIB61850_API DEPRECATED int
  541. SVClientASDU_getDataSize(SVSubscriber_ASDU self);
  542. /**@} @}*/
  543. #ifdef __cplusplus
  544. }
  545. #endif
  546. #endif /* SAMPLED_VALUES_SV_SUBSCRIBER_ */