diff --git a/src/goose/goose_publisher.c b/src/goose/goose_publisher.c index 4540e487..c14b9e64 100644 --- a/src/goose/goose_publisher.c +++ b/src/goose/goose_publisher.c @@ -44,6 +44,7 @@ struct sGoosePublisher { EthernetSocket ethernetSocket; int lengthField; int payloadStart; + int payloadLength; char* goID; char* goCBRef; @@ -145,6 +146,18 @@ GoosePublisher_setSimulation(GoosePublisher self, bool simulation) self->simulation = simulation; } +void +GoosePublisher_setStNum(GoosePublisher self, uint32_t stNum) +{ + self->stNum = stNum; +} + +void +GoosePublisher_setSqNum(GoosePublisher self, uint32_t sqNum) +{ + self->sqNum = sqNum; +} + void GoosePublisher_setNeedsCommission(GoosePublisher self, bool ndsCom) { @@ -390,9 +403,9 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) size_t maxPayloadSize = GOOSE_MAX_MESSAGE_SIZE - self->payloadStart; - int32_t payloadLength = createGoosePayload(self, dataSet, buffer, maxPayloadSize); + self->payloadLength = createGoosePayload(self, dataSet, buffer, maxPayloadSize); - if (payloadLength == -1) + if (self->payloadLength == -1) return -1; self->sqNum++; @@ -402,7 +415,7 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) int lengthIndex = self->lengthField; - size_t gooseLength = payloadLength + 8; + size_t gooseLength = self->payloadLength + 8; self->buffer[lengthIndex] = gooseLength / 256; self->buffer[lengthIndex + 1] = gooseLength & 0xff; @@ -410,7 +423,26 @@ GoosePublisher_publish(GoosePublisher self, LinkedList dataSet) if (DEBUG_GOOSE_PUBLISHER) printf("GOOSE_PUBLISHER: send GOOSE message\n"); - Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + payloadLength); + Ethernet_sendPacket(self->ethernetSocket, self->buffer, self->payloadStart + self->payloadLength); return 0; } + +int +GoosePublisher_publishAndDump(GoosePublisher self, LinkedList dataSet, char *msgBuf, int32_t *msgLen, int32_t bufSize) +{ + int rc = GoosePublisher_publish(self, dataSet); + + if (rc == 0) + { + int copied = self->payloadStart + self->payloadLength; + + if (bufSize < copied) + copied = bufSize; + + memcpy(msgBuf, self->buffer, copied); + *msgLen = copied; + } + + return rc; +} diff --git a/src/goose/goose_publisher.h b/src/goose/goose_publisher.h index 412a4e7b..c8fcf9c3 100644 --- a/src/goose/goose_publisher.h +++ b/src/goose/goose_publisher.h @@ -1,7 +1,7 @@ /* * goose_publisher.h * - * Copyright 2013-2018 Michael Zillgith + * Copyright 2013-2020 Michael Zillgith * * This file is part of libIEC61850. * @@ -46,42 +46,163 @@ typedef struct sCommParameters { typedef struct sGoosePublisher* GoosePublisher; +/** + * \brief Create a new GoosePublisher instance + * + * NOTE: The created GoosePublisher instance uses VLAN tags + * + * \param parameters GOOSE communication parameters + * \param interfaceId name of the Ethernet interface to use (e.g. "eth0") + */ LIB61850_API GoosePublisher GoosePublisher_create(CommParameters* parameters, const char* interfaceID); +/** + * \brief Create a new GoosePublisher instance + * + * \param parameters GOOSE communication parameters + * \param interfaceId name of the Ethernet interface to use (e.g. "eth0") + * \param useVlanTag enable or disable the usage of VLAN tags in GOOSE messages + */ LIB61850_API GoosePublisher GoosePublisher_createEx(CommParameters* parameters, const char* interfaceID, bool useVlanTag); +/** + * \brief Release all resources of the GoosePublisher instance + * + * \param self GoosePublisher instance + */ LIB61850_API void GoosePublisher_destroy(GoosePublisher self); +/** + * \brief Publish a GOOSE message + * + * NOTE: This function also increased the sequence number of the GOOSE publisher + * + * \param self GoosePublisher instance + * \param dataSet the GOOSE data set to send + */ LIB61850_API int GoosePublisher_publish(GoosePublisher self, LinkedList dataSet); +/** + * \brief Publish a GOOSE message and store the sent message in the provided buffer + * + * \param self GoosePublisher instance + * \param dataSet the GOOSE data set to send + * \param msgBuf to store the sent message + * \param[out] msgLen the length of the sent message + * \param bufSize the size of the buffer to store the sent message + */ +LIB61850_API int +GoosePublisher_publishAndDump(GoosePublisher self, LinkedList dataSet, char* msgBuf, int32_t* msgLen, int32_t bufSize); + +/** + * \brief Sets the GoID used by the GoosePublisher instance + * + * \param self GoosePublisher instance + * \param goID the GoId string + */ LIB61850_API void GoosePublisher_setGoID(GoosePublisher self, char* goID); +/** + * \brief Sets the GoCB reference used by the GoosePublisher instance + * + * \param self GoosePublisher instance + * \param goCbRef the GoCB reference string + */ LIB61850_API void GoosePublisher_setGoCbRef(GoosePublisher self, char* goCbRef); +/** + * \brief Sets the time allowed to live value of the GOOSE messages + * + * \param self GoosePublisher instance + * \param timeAllowedToLive the time allowed to live value in milliseconds + */ LIB61850_API void GoosePublisher_setTimeAllowedToLive(GoosePublisher self, uint32_t timeAllowedToLive); +/** + * \brief Sets the data set reference used by the GoosePublisher instance + * + * \param self GoosePublisher instance + * \param dataSetRef the data set reference string + */ LIB61850_API void GoosePublisher_setDataSetRef(GoosePublisher self, char* dataSetRef); +/** + * \brief Sets the configuration revision used by the GoosePublisher instance + * + * \param self GoosePublisher instance + * \param confRev the configuration revision value + */ LIB61850_API void GoosePublisher_setConfRev(GoosePublisher self, uint32_t confRev); +/** + * \brief Sets simulation flag in sent GOOSE messages + * + * \param self GoosePublisher instance + * \param simulation the value of the simulation flag + */ LIB61850_API void GoosePublisher_setSimulation(GoosePublisher self, bool simulation); +/** + * \brief Manually sets the state number (stNum) of the GoosePublisher instance + * + * NOTE: Only for testing! Use \ref GoosePublisher_increaseStNum instead whenever + * a data set member changes. + * + * \param self GoosePublisher instance + * \param stNum the state number of the next GOOSE message to send + */ +LIB61850_API void +GoosePublisher_setStNum(GoosePublisher self, uint32_t stNum); + +/** + * \brief Manually sets the sequence number (sqNum) of the GoosePublisher instance + * + * NOTE: Only for testing! The sequence number is increase manually whenever \ref GoosePublisher_publish is called. + * + * \param self GoosePublisher instance + * \param stNum the state number of the next GOOSE message to send + */ +LIB61850_API void +GoosePublisher_setSqNum(GoosePublisher self, uint32_t sqNum); + +/** + * \brief Sets the needs commission flag in sent GOOSE messages + * + * \param self GoosePublisher instance + * \param ndsCom the value of the needs commission flag + */ LIB61850_API void GoosePublisher_setNeedsCommission(GoosePublisher self, bool ndsCom); +/** + * \brief Increase the state number (stNum) of the GoosePublisher instance + * + * The state number should be increased whenever a member of the GOOSE data set changed + * + * NOTE: This function also resets the sequence number (sqNum) + * + * \param self GoosePublisher instance + */ LIB61850_API uint64_t GoosePublisher_increaseStNum(GoosePublisher self); +/** + * \brief Reset state and sequence number of the GoosePublisher instance + * + * This function will set the state number (stNum) to 1 and the sequence number (sqNum) to 0. + * + * \param self GoosePublisher instance + */ LIB61850_API void GoosePublisher_reset(GoosePublisher self);