From 09d5daf0b5ad5e7ec451b9827747819021e6c697 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 9 Nov 2017 22:48:58 +0100 Subject: [PATCH] sampled values: add support for 64 bit integers --- src/sampled_values/sv_publisher.c | 49 ++++++++++++++++++++++++- src/sampled_values/sv_publisher.h | 6 +++ src/sampled_values/sv_subscriber.c | 27 ++++++++++++++ src/sampled_values/sv_subscriber.h | 59 +++++++++++++++++++++--------- 4 files changed, 122 insertions(+), 19 deletions(-) diff --git a/src/sampled_values/sv_publisher.c b/src/sampled_values/sv_publisher.c index bc777fe8..9f395ec9 100644 --- a/src/sampled_values/sv_publisher.c +++ b/src/sampled_values/sv_publisher.c @@ -220,6 +220,34 @@ encodeInt32FixedSize(int32_t value, uint8_t* buffer, int bufPos) return bufPos; } +static int +encodeInt64FixedSize(int64_t value, uint8_t* buffer, int bufPos) +{ + uint8_t* valueArray = (uint8_t*) &value; + +#if (ORDER_LITTLE_ENDIAN == 1) + buffer[bufPos++] = valueArray[7]; + buffer[bufPos++] = valueArray[6]; + buffer[bufPos++] = valueArray[5]; + buffer[bufPos++] = valueArray[4]; + buffer[bufPos++] = valueArray[3]; + buffer[bufPos++] = valueArray[2]; + buffer[bufPos++] = valueArray[1]; + buffer[bufPos++] = valueArray[0]; +#else + buffer[bufPos++] = valueArray[0]; + buffer[bufPos++] = valueArray[1]; + buffer[bufPos++] = valueArray[2]; + buffer[bufPos++] = valueArray[3]; + buffer[bufPos++] = valueArray[4]; + buffer[bufPos++] = valueArray[5]; + buffer[bufPos++] = valueArray[6]; + buffer[bufPos++] = valueArray[7]; +#endif + + return bufPos; +} + static int encodeUtcTime(uint64_t timeval, uint8_t* buffer, int bufPos) { @@ -508,6 +536,22 @@ SV_ASDU_setINT32(SV_ASDU self, int index, int32_t value) encodeInt32FixedSize(value, self->_dataBuffer, index); } +int +SV_ASDU_addINT64(SV_ASDU self) +{ + int index = self->dataSize; + + self->dataSize += 8; + + return index; +} + +void +SV_ASDU_setINT64(SV_ASDU self, int index, int64_t value) +{ + encodeInt64FixedSize(value, self->_dataBuffer, index); +} + int SV_ASDU_addFLOAT(SV_ASDU self) { @@ -523,7 +567,6 @@ SV_ASDU_setFLOAT(SV_ASDU self, int index, float value) { uint8_t* buf = (uint8_t*) &value; - #if (ORDER_LITTLE_ENDIAN == 1) BerEncoder_revertByteOrder(buf, 4); #endif @@ -550,11 +593,15 @@ void SV_ASDU_setFLOAT64(SV_ASDU self, int index, double value) { uint8_t* buf = (uint8_t*) &value; + #if (ORDER_LITTLE_ENDIAN == 1) BerEncoder_revertByteOrder(buf, 8); #endif + int i; + uint8_t* buffer = self->_dataBuffer + index; + for (i = 0; i < 8; i++) { buffer[i] = buf[i]; } diff --git a/src/sampled_values/sv_publisher.h b/src/sampled_values/sv_publisher.h index 458b00b2..08ddf528 100644 --- a/src/sampled_values/sv_publisher.h +++ b/src/sampled_values/sv_publisher.h @@ -85,6 +85,12 @@ SV_ASDU_addINT32(SV_ASDU self); void SV_ASDU_setINT32(SV_ASDU self, int index, int32_t value); +int +SV_ASDU_addINT64(SV_ASDU self); + +void +SV_ASDU_setINT64(SV_ASDU self, int index, int64_t value); + int SV_ASDU_addFLOAT(SV_ASDU self); diff --git a/src/sampled_values/sv_subscriber.c b/src/sampled_values/sv_subscriber.c index 4d2f70fc..1a0e2583 100644 --- a/src/sampled_values/sv_subscriber.c +++ b/src/sampled_values/sv_subscriber.c @@ -637,6 +637,20 @@ SVClientASDU_getINT32(SVClientASDU self, int index) return retVal; } +int64_t +SVClientASDU_getINT64(SVClientASDU self, int index) +{ + int64_t retVal = *((int64_t*) (self->dataBuffer + index)); + +#if (ORDER_LITTLE_ENDIAN == 1) + uint8_t* buf = (uint8_t*) (&retVal); + + BerEncoder_revertByteOrder(buf, 8); +#endif + + return retVal; +} + uint8_t SVClientASDU_getINT8U(SVClientASDU self, int index) { @@ -673,6 +687,19 @@ SVClientASDU_getINT32U(SVClientASDU self, int index) return retVal; } +uint64_t +SVClientASDU_getINT64U(SVClientASDU self, int index) +{ + uint64_t retVal = *((uint64_t*) (self->dataBuffer + index)); + +#if (ORDER_LITTLE_ENDIAN == 1) + uint8_t* buf = (uint8_t*) (&retVal); + + BerEncoder_revertByteOrder(buf, 8); +#endif + + return retVal; +} float SVClientASDU_getFLOAT32(SVClientASDU self, int index) diff --git a/src/sampled_values/sv_subscriber.h b/src/sampled_values/sv_subscriber.h index eefcbaa4..16ae7443 100644 --- a/src/sampled_values/sv_subscriber.h +++ b/src/sampled_values/sv_subscriber.h @@ -52,24 +52,25 @@ extern "C" { * * | IEC 61850 type | required bytes | * | -------------- | -------------- | - * | BOOLEAN | 1 byte | - * | INT8 | 1 byte | - * | INT16 | 2 byte | - * | INT32 | 4 byte | - * | INT64 | 8 byte | - * | INT8U | 1 byte | - * | INT16U | 2 byte | - * | INT24U | 3 byte | - * | INT32U | 4 byte | - * | FLOAT32 | 4 byte | - * | FLOAT64 | 8 byte | - * | ENUMERATED | 4 byte | - * | CODED ENUM | 4 byte | - * | OCTET STRING | 20 byte | - * | VISIBLE STRING | 35 byte | - * | TimeStamp | 8 byte | - * | EntryTime | 6 byte | - * | BITSTRING | 4 byte | + * | BOOLEAN | 1 byte | + * | INT8 | 1 byte | + * | INT16 | 2 byte | + * | INT32 | 4 byte | + * | INT64 | 8 byte | + * | INT8U | 1 byte | + * | INT16U | 2 byte | + * | INT24U | 3 byte | + * | INT32U | 4 byte | + * | INT64U | 8 byte | + * | FLOAT32 | 4 byte | + * | FLOAT64 | 8 byte | + * | ENUMERATED | 4 byte | + * | CODED ENUM | 4 byte | + * | OCTET STRING | 20 byte | + * | VISIBLE STRING | 35 byte | + * | TimeStamp | 8 byte | + * | EntryTime | 6 byte | + * | BITSTRING | 4 byte | * * The SV subscriber API can be used independent of the IEC 61850 client API. In order to access the SVCB via MMS you * have to use the IEC 61850 client API. Please see \ref ClientSVControlBlock object in section \ref IEC61850_CLIENT_SV. @@ -321,6 +322,17 @@ SVClientASDU_getINT16(SVClientASDU self, int index); int32_t SVClientASDU_getINT32(SVClientASDU self, int index); +/** + * \brief Get an INT64 data value in the data part of the ASDU + * + * \param self ASDU object instance + * \param index the index (byte position of the start) of the data in the data part + * + * \return SV data + */ +int64_t +SVClientASDU_getINT64(SVClientASDU self, int index); + /** * \brief Get an INT8U data value in the data part of the ASDU * @@ -354,6 +366,17 @@ SVClientASDU_getINT16U(SVClientASDU self, int index); uint32_t SVClientASDU_getINT32U(SVClientASDU self, int index); +/** + * \brief Get an INT64U data value in the data part of the ASDU + * + * \param self ASDU object instance + * \param index the index (byte position of the start) of the data in the data part + * + * \return SV data + */ +uint64_t +SVClientASDU_getINT64U(SVClientASDU self, int index); + /** * \brief Get an FLOAT32 data value in the data part of the ASDU *