Merge pull request #39 from stv0g/sv-goose-bugfixes

Smaller bug fixes for SV & Goose
pull/143/head
Michael Zillgith 8 years ago committed by GitHub
commit bd92dc299e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,7 +11,7 @@ project(libiec61850)
ENABLE_TESTING() ENABLE_TESTING()
set(LIB_VERSION_MAJOR "1") set(LIB_VERSION_MAJOR "1")
set(LIB_VERSION_MINOR "1") set(LIB_VERSION_MINOR "2")
set(LIB_VERSION_PATCH "0") set(LIB_VERSION_PATCH "0")
set(LIB_VERSION "${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}") set(LIB_VERSION "${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}")
@ -46,16 +46,35 @@ set(CONFIG_REPORTING_DEFAULT_REPORT_BUFFER_SIZE "8000" CACHE STRING "Default buf
# advanced options # advanced options
option(DEBUG "Enable debugging mode (include assertions)" OFF) option(DEBUG "Enable debugging mode (include assertions)" OFF)
option(DEBUG_SOCKET "Enable printf debugging for socket layer" OFF) option(DEBUG_SOCKET "Enable printf debugging for socket layer" ${DEBUG})
option(DEBUG_COTP "Enable COTP printf debugging" OFF) option(DEBUG_COTP "Enable COTP printf debugging" ${DEBUG})
option(DEBUG_ISO_SERVER "Enable ISO SERVER printf debugging" OFF) option(DEBUG_ISO_SERVER "Enable ISO SERVER printf debugging" ${DEBUG})
option(DEBUG_ISO_CLIENT "Enable ISO CLIENT printf debugging" OFF) option(DEBUG_ISO_CLIENT "Enable ISO CLIENT printf debugging" ${DEBUG})
option(DEBUG_IED_SERVER "Enable IED SERVER printf debugging" OFF) option(DEBUG_IED_SERVER "Enable IED SERVER printf debugging" ${DEBUG})
option(DEBUG_IED_CLIENT "Enable IED CLIENT printf debugging" OFF) option(DEBUG_IED_CLIENT "Enable IED CLIENT printf debugging" ${DEBUG})
option(DEBUG_MMS_SERVER "Enable MMS SERVER printf debugging" OFF) option(DEBUG_MMS_SERVER "Enable MMS SERVER printf debugging" ${DEBUG})
option(DEBUG_MMS_CLIENT "Enable MMS CLIENT printf debugging" OFF) option(DEBUG_MMS_CLIENT "Enable MMS CLIENT printf debugging" ${DEBUG})
#mark_as_advanced(DEBUG DEBUG_COTP DEBUG_ISO_SERVER DEBUG_ISO_CLIENT DEBUG_IED_SERVER option(DEBUG_GOOSE_SUBSCRIBER "Enable GOOSE subscriber printf debugging" ${DEBUG})
# DEBUG_IED_CLIENT DEBUG_MMS_SERVER DEBUG_MMS_CLIENT) option(DEBUG_GOOSE_PUBLISHER "Enable GOOSE publisher printf debugging" ${DEBUG})
option(DEBUG_SV_SUBSCRIBER "Enable Sampled Values subscriber debugging" ${DEBUG})
option(DEBUG_SV_PUBLISHER "Enable Sampled Values publisher debugging" ${DEBUG})
option(DEBUG_HAL_ETHERNET "Enable Ethernet HAL printf debugging" ${DEBUG})
#mark_as_advanced(
# DEBUG_SOCKET
# DEBUG_COTP
# DEBUG_ISO_SERVER
# DEBUG_ISO_CLIENT
# DEBUG_IED_SERVER
# DEBUG_IED_CLIENT
# DEBUG_MMS_SERVER
# DEBUG_MMS_CLIENT
# DEBUG_GOOSE_SUBSCRIBER
# DEBUG_GOOSE_PUBLISHER
# DEBUG_SV_SUBSCRIBER
# DEBUG_SV_PUBLISHER
# DEBUG_HAL_ETHERNET
#)
include_directories( include_directories(
${CMAKE_CURRENT_BINARY_DIR}/config ${CMAKE_CURRENT_BINARY_DIR}/config

@ -129,6 +129,10 @@ parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues)
MmsValue* value = MmsValue_getElement(dataSetValues, elementIndex); MmsValue* value = MmsValue_getElement(dataSetValues, elementIndex);
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
if (bufPos < 0) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
}
if (bufPos + elementLength > allDataLength) { if (bufPos + elementLength > allDataLength) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n");
@ -277,6 +281,10 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
if (bufPos < 0) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
}
if (bufPos + elementLength > allDataLength) { if (bufPos + elementLength > allDataLength) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n");
@ -331,6 +339,10 @@ parseAllDataUnknownValue(GooseSubscriber self, uint8_t* buffer, int allDataLengt
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength);
if (bufPos < 0) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
}
if (bufPos + elementLength > allDataLength) { if (bufPos + elementLength > allDataLength) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n");
@ -461,6 +473,10 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
if (buffer[bufPos++] == 0x61) { if (buffer[bufPos++] == 0x61) {
int gooseLength; int gooseLength;
bufPos = BerDecoder_decodeLength(buffer, &gooseLength, bufPos, apduLength); bufPos = BerDecoder_decodeLength(buffer, &gooseLength, bufPos, apduLength);
if (bufPos < 0) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
}
int gooseEnd = bufPos + gooseLength; int gooseEnd = bufPos + gooseLength;
@ -469,6 +485,10 @@ parseGoosePayload(GooseReceiver self, uint8_t* buffer, int apduLength)
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength);
if (bufPos < 0) {
if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return 0;
}
if (bufPos + elementLength > apduLength) { if (bufPos + elementLength > apduLength) {
if (DEBUG_GOOSE_SUBSCRIBER) if (DEBUG_GOOSE_SUBSCRIBER)
@ -774,7 +794,7 @@ GooseReceiver_destroy(GooseReceiver self)
/*************************************** /***************************************
* Functions for non-threaded operation * Functions for non-threaded operation
***************************************/ ***************************************/
void EthernetSocket
GooseReceiver_startThreadless(GooseReceiver self) GooseReceiver_startThreadless(GooseReceiver self)
{ {
if (self->interfaceId == NULL) if (self->interfaceId == NULL)
@ -788,6 +808,8 @@ GooseReceiver_startThreadless(GooseReceiver self)
} }
else else
self->running = false; self->running = false;
return self->ethSocket;
} }
void void
@ -811,10 +833,3 @@ GooseReceiver_tick(GooseReceiver self)
else else
return false; return false;
} }
void
GooseReceiver_addHandleSet(GooseReceiver self, EthernetHandleSet handles)
{
return EthernetHandleSet_addSocket(handles, self->ethSocket);
}

@ -30,6 +30,7 @@ extern "C" {
#include <stdbool.h> #include <stdbool.h>
typedef struct sEthernetSocket* EthernetSocket;
/** /**
* \addtogroup goose_api_group * \addtogroup goose_api_group
@ -116,7 +117,7 @@ GooseReceiver_destroy(GooseReceiver self);
/*************************************** /***************************************
* Functions for non-threaded operation * Functions for non-threaded operation
***************************************/ ***************************************/
void EthernetSocket
GooseReceiver_startThreadless(GooseReceiver self); GooseReceiver_startThreadless(GooseReceiver self);
void void
@ -134,20 +135,6 @@ GooseReceiver_stopThreadless(GooseReceiver self);
bool bool
GooseReceiver_tick(GooseReceiver self); GooseReceiver_tick(GooseReceiver self);
/* Forward declaration */
typedef struct sEthernetHandleSet* EthernetHandleSet;
/**
* \brief Add the receiver to a handleset for multiplexed asynchronous IO.
*
* Note: This function must only be called after GooseReceiver_startThreadless().
*
* \param[in] self The SVReceiver instance.
* \param[inout] handles The EthernetHandleSet to which the EthernetSocket of this receiver should be added.
*/
void
GooseReceiver_addHandleSet(GooseReceiver self, EthernetHandleSet handles);
/**@}*/ /**@}*/
#ifdef __cplusplus #ifdef __cplusplus

@ -43,8 +43,8 @@
#define SV_MAX_MESSAGE_SIZE 1518 #define SV_MAX_MESSAGE_SIZE 1518
struct sSVPublisher_ASDU { struct sSVPublisher_ASDU {
char* svID; const char* svID;
char* datset; const char* datset;
int dataSize; int dataSize;
bool hasRefrTm; bool hasRefrTm;
@ -296,7 +296,7 @@ SVPublisher_create(CommParameters* parameters, const char* interfaceId)
} }
SVPublisher_ASDU SVPublisher_ASDU
SVPublisher_addASDU(SVPublisher self, char* svID, char* datset, uint32_t confRev) SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint32_t confRev)
{ {
SVPublisher_ASDU newAsdu = (SVPublisher_ASDU) GLOBAL_CALLOC(1, sizeof(struct sSVPublisher_ASDU)); SVPublisher_ASDU newAsdu = (SVPublisher_ASDU) GLOBAL_CALLOC(1, sizeof(struct sSVPublisher_ASDU));
@ -398,8 +398,10 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
buffer[bufPos++] = self->smpSynch; buffer[bufPos++] = self->smpSynch;
/* SmpRate */ /* SmpRate */
if (self->hasSmpRate) {
bufPos = BerEncoder_encodeTL(0x86, 2, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x86, 2, buffer, bufPos);
bufPos = encodeUInt16FixedSize(self->smpRate, buffer, bufPos); bufPos = encodeUInt16FixedSize(self->smpRate, buffer, bufPos);
}
/* Sample */ /* Sample */
bufPos = BerEncoder_encodeTL(0x87, self->dataSize, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x87, self->dataSize, buffer, bufPos);
@ -410,7 +412,7 @@ SVPublisher_ASDU_encodeToBuffer(SVPublisher_ASDU self, uint8_t* buffer, int bufP
/* SmpMod */ /* SmpMod */
if (self->hasSmpMod) { if (self->hasSmpMod) {
bufPos = BerEncoder_encodeTL(0x88, 4, buffer, bufPos); bufPos = BerEncoder_encodeTL(0x88, 2, buffer, bufPos);
bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos); bufPos = encodeUInt16FixedSize(self->smpMod, buffer, bufPos);
} }

@ -85,7 +85,7 @@ SVPublisher_create(CommParameters* parameters, const char* interfaceId);
* \return the new ASDU instance. * \return the new ASDU instance.
*/ */
SVPublisher_ASDU SVPublisher_ASDU
SVPublisher_addASDU(SVPublisher self, char* svID, char* datset, uint32_t confRev); SVPublisher_addASDU(SVPublisher self, const char* svID, const char* datset, uint32_t confRev);
/** /**
* \brief Prepare the publisher for publishing. * \brief Prepare the publisher for publishing.

@ -70,20 +70,20 @@ struct sSVSubscriber {
struct sSVSubscriber_ASDU { struct sSVSubscriber_ASDU {
char* svId; char* svId;
char* datSet;
uint8_t* smpCnt; uint8_t* smpCnt;
uint8_t* confRev; uint8_t* confRev;
uint8_t* refrTm; uint8_t* refrTm;
uint8_t* smpSynch; uint8_t* smpSynch;
uint8_t* smpMod;
uint8_t* smpRate;
int dataBufferLength; int dataBufferLength;
uint8_t* dataBuffer; uint8_t* dataBuffer;
}; };
SVReceiver SVReceiver
SVReceiver_create(void) SVReceiver_create(void)
{ {
@ -208,7 +208,7 @@ SVReceiver_destroy(SVReceiver self)
GLOBAL_FREEMEM(self); GLOBAL_FREEMEM(self);
} }
void EthernetSocket
SVReceiver_startThreadless(SVReceiver self) SVReceiver_startThreadless(SVReceiver self)
{ {
if (self->interfaceId == NULL) if (self->interfaceId == NULL)
@ -219,6 +219,8 @@ SVReceiver_startThreadless(SVReceiver self)
Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV); Ethernet_setProtocolFilter(self->ethSocket, ETH_P_SV);
self->running = true; self->running = true;
return self->ethSocket;
} }
void void
@ -229,29 +231,26 @@ SVReceiver_stopThreadless(SVReceiver self)
self->running = false; self->running = false;
} }
void
SVReceiver_addHandleSet(SVReceiver self, EthernetHandleSet handles)
{
return EthernetHandleSet_addSocket(handles, self->ethSocket);
}
static void static void
parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length) parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
{ {
int bufPos = 0; int bufPos = 0;
int svIdLength = 0;
int datSetLength = 0;
struct sSVSubscriber_ASDU asdu; struct sSVSubscriber_ASDU asdu;
memset(&asdu, 0, sizeof(struct sSVSubscriber_ASDU)); memset(&asdu, 0, sizeof(struct sSVSubscriber_ASDU));
int svIdLength = 0;
while (bufPos < length) { while (bufPos < length) {
int elementLength; int elementLength;
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
if (bufPos < 0) {
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return;
}
switch (tag) { switch (tag) {
@ -260,6 +259,11 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
svIdLength = elementLength; svIdLength = elementLength;
break; break;
case 0x81:
asdu.datSet = (char*) (buffer + bufPos);
datSetLength = elementLength;
break;
case 0x82: case 0x82:
asdu.smpCnt = buffer + bufPos; asdu.smpCnt = buffer + bufPos;
break; break;
@ -276,12 +280,21 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
asdu.smpSynch = buffer + bufPos; asdu.smpSynch = buffer + bufPos;
break; break;
case 0x86:
asdu.smpRate = buffer + bufPos;
break;
case 0x87: case 0x87:
asdu.dataBuffer = buffer + bufPos; asdu.dataBuffer = buffer + bufPos;
asdu.dataBufferLength = elementLength; asdu.dataBufferLength = elementLength;
break; break;
case 0x88:
asdu.smpMod = buffer + bufPos;
break;
default: /* ignore unknown tag */ default: /* ignore unknown tag */
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: found unknown tag %02x\n", tag);
break; break;
} }
@ -290,6 +303,25 @@ parseASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int length)
if (asdu.svId != NULL) if (asdu.svId != NULL)
asdu.svId[svIdLength] = 0; asdu.svId[svIdLength] = 0;
if (asdu.datSet != NULL)
asdu.datSet[datSetLength] = 0;
if (DEBUG_SV_SUBSCRIBER) {
printf("SV_SUBSCRIBER: SV ASDU: ----------------\n");
printf("SV_SUBSCRIBER: DataLength: %d\n", asdu.dataBufferLength);
printf("SV_SUBSCRIBER: SvId: %s\n", asdu.svId);
printf("SV_SUBSCRIBER: SmpCnt: %d\n", SVSubscriber_ASDU_getSmpCnt(&asdu));
printf("SV_SUBSCRIBER: ConfRev: %d\n", SVSubscriber_ASDU_getConfRev(&asdu));
if (SVSubscriber_ASDU_hasDatSet(&asdu))
printf("SV_SUBSCRIBER: DatSet: %s\n", asdu.datSet);
if (SVSubscriber_ASDU_hasRefrTm(&asdu))
printf("SV_SUBSCRIBER: RefrTm: %lu\n", SVSubscriber_ASDU_getRefrTmAsMs(&asdu));
if (SVSubscriber_ASDU_hasSmpMod(&asdu))
printf("SV_SUBSCRIBER: SmpMod: %d\n", SVSubscriber_ASDU_getSmpMod(&asdu));
if (SVSubscriber_ASDU_hasSmpRate(&asdu))
printf("SV_SUBSCRIBER: SmpRate: %d\n", SVSubscriber_ASDU_getSmpRate(&asdu));
}
/* Call callback handler */ /* Call callback handler */
if (subscriber->listener != NULL) if (subscriber->listener != NULL)
@ -307,6 +339,10 @@ parseSequenceOfASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, i
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, length);
if (bufPos < 0) {
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return;
}
switch (tag) { switch (tag) {
case 0x30: case 0x30:
@ -314,6 +350,7 @@ parseSequenceOfASDU(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, i
break; break;
default: /* ignore unknown tag */ default: /* ignore unknown tag */
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: found unknown tag %02x\n", tag);
break; break;
} }
@ -330,6 +367,10 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap
int elementLength; int elementLength;
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, apduLength);
if (bufPos < 0) {
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return;
}
int svEnd = bufPos + elementLength; int svEnd = bufPos + elementLength;
@ -337,6 +378,10 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, svEnd);
if (bufPos < 0) {
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: Malformed message: failed to decode BER length tag!\n");
return;
}
if (bufPos + elementLength > apduLength) { if (bufPos + elementLength > apduLength) {
if (DEBUG_SV_SUBSCRIBER) if (DEBUG_SV_SUBSCRIBER)
@ -358,6 +403,7 @@ parseSVPayload(SVReceiver self, SVSubscriber subscriber, uint8_t* buffer, int ap
break; break;
default: /* ignore unknown tag */ default: /* ignore unknown tag */
if (DEBUG_SV_SUBSCRIBER) printf("SV_SUBSCRIBER: found unknown tag %02x\n", tag);
break; break;
} }
@ -585,6 +631,23 @@ SVSubscriber_ASDU_hasRefrTm(SVSubscriber_ASDU self)
return (self->refrTm != NULL); return (self->refrTm != NULL);
} }
bool
SVSubscriber_ASDU_hasDatSet(SVSubscriber_ASDU self)
{
return (self->datSet != NULL);
}
bool
SVSubscriber_ASDU_hasSmpRate(SVSubscriber_ASDU self)
{
return (self->smpRate != NULL);
}
bool
SVSubscriber_ASDU_hasSmpMod(SVSubscriber_ASDU self)
{
return (self->smpMod != NULL);
}
const char* const char*
SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self) SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self)
@ -592,6 +655,12 @@ SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self)
return self->svId; return self->svId;
} }
const char*
SVSubscriber_ASDU_getDatSet(SVSubscriber_ASDU self)
{
return self->datSet;
}
uint32_t uint32_t
SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self) SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self)
{ {
@ -606,6 +675,28 @@ SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self)
return retVal; return retVal;
} }
uint8_t
SVSubscriber_ASDU_getSmpMod(SVSubscriber_ASDU self)
{
uint8_t retVal = *((uint8_t*) (self->smpMod));
return retVal;
}
uint16_t
SVSubscriber_ASDU_getSmpRate(SVSubscriber_ASDU self)
{
uint16_t retVal = *((uint16_t*) (self->smpRate));
#if (ORDER_LITTLE_ENDIAN == 1)
uint8_t* buf = (uint8_t*) (&retVal);
BerEncoder_revertByteOrder(buf, 2);
#endif
return retVal;
}
int8_t int8_t
SVSubscriber_ASDU_getINT8(SVSubscriber_ASDU self, int index) SVSubscriber_ASDU_getINT8(SVSubscriber_ASDU self, int index)
{ {

@ -1,5 +1,5 @@
/* /*
* sv_subscriber_api.h * sv_subscriber.h
* *
* Copyright 2015 Michael Zillgith * Copyright 2015 Michael Zillgith
* *
@ -30,6 +30,8 @@
extern "C" { extern "C" {
#endif #endif
typedef struct sEthernetSocket* EthernetSocket;
/** /**
* \defgroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) subscriber API * \defgroup sv_subscriber_api_group IEC 61850 Sampled Values (SV) subscriber API
* *
@ -204,7 +206,7 @@ SVReceiver_destroy(SVReceiver self);
* Functions for non-threaded operation * Functions for non-threaded operation
***************************************/ ***************************************/
void EthernetSocket
SVReceiver_startThreadless(SVReceiver self); SVReceiver_startThreadless(SVReceiver self);
void void
@ -222,20 +224,6 @@ SVReceiver_stopThreadless(SVReceiver self);
bool bool
SVReceiver_tick(SVReceiver self); SVReceiver_tick(SVReceiver self);
/* Forward declaration */
typedef struct sEthernetHandleSet* EthernetHandleSet;
/**
* \brief Add the receiver to a handleset for multiplexed asynchronous IO.
*
* Note: This function must only be called after SVReceiver_startThreadless().
*
* \param[in] self The SVReceiver instance.
* \param[inout] handles The EthernetHandleSet to which the EthernetSocket of this receiver should be added.
*/
void
SVReceiver_addHandleSet(SVReceiver self, EthernetHandleSet handles);
/* /*
* Subscriber * Subscriber
*/ */
@ -289,6 +277,14 @@ SVSubscriber_ASDU_getSmpCnt(SVSubscriber_ASDU self);
const char* const char*
SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self); SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self);
/**
* \brief return the DatSet value included in the SV ASDU
*
* \param self ASDU object instance
*/
const char*
SVSubscriber_ASDU_getDatSet(SVSubscriber_ASDU self);
/** /**
* \brief return the ConfRev value included in the SV ASDU * \brief return the ConfRev value included in the SV ASDU
* *
@ -297,6 +293,32 @@ SVSubscriber_ASDU_getSvId(SVSubscriber_ASDU self);
uint32_t uint32_t
SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self); SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self);
/**
* \brief return the SmpMod value included in the SV ASDU
*
* \param self ASDU object instance
*/
uint8_t
SVSubscriber_ASDU_getSmpMod(SVSubscriber_ASDU self);
/**
* \brief return the SmpRate value included in the SV ASDU
*
* \param self ASDU object instance
*/
uint16_t
SVSubscriber_ASDU_getSmpRate(SVSubscriber_ASDU self);
/**
* \brief Check if DatSet value is included in the SV ASDU
*
* \param self ASDU object instance
*
* \return true if DatSet value is present, false otherwise
*/
bool
SVSubscriber_ASDU_hasDatSet(SVSubscriber_ASDU self);
/** /**
* \brief Check if RefrTm value is included in the SV ASDU * \brief Check if RefrTm value is included in the SV ASDU
* *
@ -307,6 +329,26 @@ SVSubscriber_ASDU_getConfRev(SVSubscriber_ASDU self);
bool bool
SVSubscriber_ASDU_hasRefrTm(SVSubscriber_ASDU self); SVSubscriber_ASDU_hasRefrTm(SVSubscriber_ASDU self);
/**
* \brief Check if SmpMod value is included in the SV ASDU
*
* \param self ASDU object instance
*
* \return true if SmpMod value is present, false otherwise
*/
bool
SVSubscriber_ASDU_hasSmpMod(SVSubscriber_ASDU self);
/**
* \brief Check if SmpRate value is included in the SV ASDU
*
* \param self ASDU object instance
*
* \return true if SmpRate value is present, false otherwise
*/
bool
SVSubscriber_ASDU_hasSmpRate(SVSubscriber_ASDU self);
/** /**
* \brief Get the RefrTim value included in SV ASDU as ms timestamp * \brief Get the RefrTim value included in SV ASDU as ms timestamp
* *

Loading…
Cancel
Save