- SV Publisher: added support for optional gmIdentity field

v1.6
Michael Zillgith 7 months ago
parent 899a2bbe2e
commit 32768ed7ca

@ -1,7 +1,7 @@
/*
* sv_publisher.c
*
* Copyright 2016-2024 Michael Zillgith
* Copyright 2016-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,14 +21,14 @@
* See COPYING file for the complete license text.
*/
#include "stack_config.h"
#include "libiec61850_platform_includes.h"
#include "stack_config.h"
#include <stdbool.h>
#include "sv_publisher.h"
#include <stdbool.h>
#include "hal_ethernet.h"
#include "ber_encoder.h"
#include "hal_ethernet.h"
#include "r_session_internal.h"
@ -44,14 +44,17 @@
#define SV_MAX_MESSAGE_SIZE 1518
struct sSVPublisher_ASDU {
struct sSVPublisher_ASDU
{
const char* svID;
const char* datset;
int dataSize;
/* flags to indicate presence of optional fields */
bool hasRefrTm;
bool hasSmpRate;
bool hasSmpMod;
bool hasGmIdentity;
uint8_t* _dataBuffer;
@ -60,6 +63,8 @@ struct sSVPublisher_ASDU {
uint16_t smpCntLimit;
uint32_t confRev;
uint8_t gmIdentity[8];
Timestamp* refrTm;
uint8_t smpMod;
uint16_t smpRate;
@ -70,7 +75,8 @@ struct sSVPublisher_ASDU {
SVPublisher_ASDU _next;
};
struct sSVPublisher {
struct sSVPublisher
{
uint8_t* buffer;
uint16_t appId;
@ -288,7 +294,8 @@ SVPublisher_createRemote(RSession session, uint16_t appId)
{
SVPublisher self = (SVPublisher)GLOBAL_CALLOC(1, sizeof(struct sSVPublisher));
if (self) {
if (self)
{
self->asduList = NULL;
self->buffer = (uint8_t*)GLOBAL_MALLOC(SV_MAX_MESSAGE_SIZE);
@ -321,7 +328,6 @@ SVPublisher_createEx(CommParameters* parameters, const char* interfaceId, bool u
SVPublisher_destroy(self);
self = NULL;
}
}
return self;
@ -339,6 +345,8 @@ SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint
{
SVPublisher_ASDU newAsdu = (SVPublisher_ASDU)GLOBAL_CALLOC(1, sizeof(struct sSVPublisher_ASDU));
if (newAsdu)
{
newAsdu->svID = svID;
newAsdu->datset = datset;
newAsdu->confRev = confRev;
@ -357,6 +365,7 @@ SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint
lastAsdu->_next = newAsdu;
}
}
return newAsdu;
}
@ -385,7 +394,7 @@ SVPublisher_ASDU_getEncodedSize(SVPublisher_ASDU self)
/* refrTm */
if (self->hasRefrTm)
encodedSize += 10; /* ??? */
encodedSize += 10;
/* smpSynch */
encodedSize += 3;
@ -402,6 +411,10 @@ SVPublisher_ASDU_getEncodedSize(SVPublisher_ASDU self)
if (self->hasSmpMod)
encodedSize += 4;
/* gmIdentity */
if (self->hasGmIdentity)
encodedSize += 10;
return encodedSize;
}
@ -463,6 +476,12 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos);
}
/* gmIdentity */
if (self->hasGmIdentity)
{
bufPos = BerEncoder_encodeOctetString(0x89, self->gmIdentity, 8, buffer, bufPos);
}
return bufPos;
}
@ -518,7 +537,8 @@ SVPublisher_setupComplete(SVPublisher self)
size_t msgLength = payloadLength + 8;
if (self->lengthField != 0) {
if (self->lengthField != 0)
{
int lengthIndex = self->lengthField;
self->buffer[lengthIndex] = msgLength / 256;
@ -547,7 +567,8 @@ SVPublisher_publish(SVPublisher self)
if (DEBUG_SV_PUBLISHER)
printf("SV_PUBLISHER: send R-SV message\n");
RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_SV, self->simulation, self->appId, self->buffer, self->payloadLength);
RSession_sendMessage(self->remoteSession, RSESSION_SPDU_ID_SV, self->simulation, self->appId, self->buffer,
self->payloadLength);
}
#endif /* (CONFIG_IEC61850_R_SMV == 1) */
}
@ -818,3 +839,10 @@ SVPublisher_ASDU_setSmpSynch(SVPublisher_ASDU self, uint16_t smpSynch)
self->smpSynch = smpSynch;
*(self->smpSynchBuf) = self->smpSynch;
}
void
SVPublisher_ASDU_setGmIdentity(SVPublisher_ASDU self, uint8_t* gmIdentity)
{
self->hasGmIdentity = true;
memcpy(self->gmIdentity, gmIdentity, 8);
}

@ -1,7 +1,7 @@
/*
* sv_publisher.h
*
* Copyright 2016-2022 Michael Zillgith
* Copyright 2016-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,7 +21,6 @@
* See COPYING file for the complete license text.
*/
#ifndef LIBIEC61850_SRC_SAMPLED_VALUES_SV_PUBLISHER_H_
#define LIBIEC61850_SRC_SAMPLED_VALUES_SV_PUBLISHER_H_
@ -29,13 +28,15 @@
#include "r_session.h"
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#ifndef GOOSE_SV_COMM_PARAMETERS
#define GOOSE_SV_COMM_PARAMETERS
typedef struct sCommParameters {
typedef struct sCommParameters
{
uint8_t vlanPriority;
uint16_t vlanId;
uint16_t appId;
@ -75,6 +76,7 @@ typedef struct sSVPublisher_ASDU* SVPublisher_ASDU;
*
* \param[in] interfaceId the name of the interface over which the SV publisher should send SV packets.
* \param[in] parameters optional parameters for setting VLAN options and destination MAC address. Use NULL for default values.
*
* \return the new SV publisher instance.
*/
LIB61850_API SVPublisher
@ -84,8 +86,10 @@ SVPublisher_create(CommParameters* parameters, const char* interfaceId);
* \brief Create a new IEC61850-9-2 Sampled Values publisher.
*
* \param[in] interfaceId the name of the interface over which the SV publisher should send SV packets.
* \param[in] parameters optional parameters for setting VLAN options and destination MAC address. Use NULL for default values.
* \param[in] parameters optional parameters for setting VLAN options and destination MAC address. Use NULL for default
* values.
* \param[in] useVlanTags enable(true)/disable(false) VLAN tagging
*
* \return the new SV publisher instance.
*/
LIB61850_API SVPublisher
@ -107,7 +111,8 @@ SVPublisher_createRemote(RSession session, uint16_t appId);
*
* \param[in] svID
* \param[in] datset
* \param[in] confRev Configuration revision number. Should be incremented each time that the configuration of the logical device changes.
* \param[in] confRev Configuration revision number. Should be incremented each time that the configuration of the
* logical device changes.
* \return the new ASDU instance.
*/
LIB61850_API SVPublisher_ASDU
@ -159,6 +164,7 @@ SVPublisher_ASDU_resetBuffer(SVPublisher_ASDU self);
* \brief Reserve memory for a signed 8-bit integer in the ASDU.
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes within the ASDU data block.
*/
LIB61850_API int
@ -178,6 +184,7 @@ SVPublisher_ASDU_setINT8(SVPublisher_ASDU self, int index, int8_t value);
* \brief Reserve memory for a signed 32-bit integer in the ASDU.
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes within the ASDU data block.
*/
LIB61850_API int
@ -197,6 +204,7 @@ SVPublisher_ASDU_setINT32(SVPublisher_ASDU self, int index, int32_t value);
* \brief Reserve memory for a signed 64-bit integer in the ASDU.
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes of the new element within the ASDU data block.
*/
LIB61850_API int
@ -216,6 +224,7 @@ SVPublisher_ASDU_setINT64(SVPublisher_ASDU self, int index, int64_t value);
* \brief Reserve memory for a single precision floating point number in the ASDU.
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes of the new element within the ASDU data block.
*/
LIB61850_API int
@ -235,6 +244,7 @@ SVPublisher_ASDU_setFLOAT(SVPublisher_ASDU self, int index, float value);
* \brief Reserve memory for a double precision floating point number in the ASDU.
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes of the new element within the ASDU data block.
*/
LIB61850_API int
@ -254,6 +264,7 @@ SVPublisher_ASDU_setFLOAT64(SVPublisher_ASDU self, int index, double value);
* \brief Reserve memory for a 64 bit time stamp in the ASDU
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes of the new element within the ASDU data block.
*/
LIB61850_API int
@ -275,6 +286,7 @@ SVPublisher_ASDU_setTimestamp(SVPublisher_ASDU self, int index, Timestamp value)
* NOTE: Quality is encoded as BITSTRING (4 byte)
*
* \param[in] self the Sampled Values ASDU instance.
*
* \return the offset in bytes of the new element within the ASDU data block.
*/
LIB61850_API int
@ -310,9 +322,9 @@ SVPublisher_ASDU_getSmpCnt(SVPublisher_ASDU self);
/**
* \brief Increment the sample count attribute of the ASDU.
*
* The parameter SmpCnt shall contain the values of a counter, which is incremented each time a new sample of the analogue value is taken.
* The sample values shall be kept in the right order.
* If the counter is used to indicate time consistency of various sampled values, the counter shall be reset by an external synchronization event.
* The parameter SmpCnt shall contain the values of a counter, which is incremented each time a new sample of the
* analogue value is taken. The sample values shall be kept in the right order. If the counter is used to indicate time
* consistency of various sampled values, the counter shall be reset by an external synchronization event.
*
* \param[in] self the Sampled Values ASDU instance.
*/
@ -372,13 +384,14 @@ SVPublisher_ASDU_setRefrTmByTimestamp(SVPublisher_ASDU self, Timestamp* refrTm);
/**
* \brief Set the sample mode attribute of the ASDU.
*
* The attribute SmpMod shall specify if the sample rate is defined in units of samples per nominal period, samples per second or seconds per sample.
* If it is missing, the default value is samples per period.
* The attribute SmpMod shall specify if the sample rate is defined in units of samples per nominal period, samples per
* second or seconds per sample. If it is missing, the default value is samples per period.
*
* NOTE: Function has to be called before calling \ref SVPublisher_setupComplete
*
* \param[in] self the Sampled Values ASDU instance.
* \param[in] smpMod one of IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD, IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND or IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE
* \param[in] smpMod one of IEC61850_SV_SMPMOD_PER_NOMINAL_PERIOD, IEC61850_SV_SMPMOD_SAMPLES_PER_SECOND or
* IEC61850_SV_SMPMOD_SECONDS_PER_SAMPLE
*/
LIB61850_API void
SVPublisher_ASDU_setSmpMod(SVPublisher_ASDU self, uint8_t smpMod);
@ -414,6 +427,15 @@ SVPublisher_ASDU_setSmpRate(SVPublisher_ASDU self, uint16_t smpRate);
LIB61850_API void
SVPublisher_ASDU_setSmpSynch(SVPublisher_ASDU self, uint16_t smpSynch);
/**
* \brief Set the gmIdentity value
*
* \param[in] self the Sampled Values ASDU instance.
* \param[in] gmIdentity the gmIdentity value (octet string/byte array of size 8 bytes)
*/
LIB61850_API void
SVPublisher_ASDU_setGmIdentity(SVPublisher_ASDU self, uint8_t* gmIdentity);
/**@} @}*/
#ifndef DEPRECATED

Loading…
Cancel
Save