diff --git a/dotnet/IEC61850forCSharp/MmsValue.cs b/dotnet/IEC61850forCSharp/MmsValue.cs index c545fca..3f69b7b 100644 --- a/dotnet/IEC61850forCSharp/MmsValue.cs +++ b/dotnet/IEC61850forCSharp/MmsValue.cs @@ -91,6 +91,9 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern ulong MmsValue_getUtcTimeInMs (IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern ulong MmsValue_getUtcTimeInMsWithUs(IntPtr self, [Out] uint usec); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self); @@ -385,6 +388,33 @@ namespace IEC61850 throw new MmsValueException ("Value is not a time type"); } + /// + /// Gets the timestamp value as UTC time in ms and the additional us part. + /// + /// + /// Return the value as milliseconds since epoch (1.1.1970 UTC) and the additional us part. + /// The value has to be of type MMS_UTC_TIME. + /// + /// + /// returns the usec part of the time value + /// + /// + /// The UTC time in ms. + /// + /// This exception is thrown if the value has the wrong type. + public ulong GetUtcTimeInMsWithUs(out int usec) + { + if (GetType() == MmsType.MMS_UTC_TIME) + { + uint uusec = 0; + var msVal = MmsValue_getUtcTimeInMsWithUs(valueReference, uusec); + usec = (int)uusec; + return msVal; + } + else + throw new MmsValueException("Value is not a time type"); + } + /// /// Convert a millisecond time (milliseconds since epoch) to DataTimeOffset /// diff --git a/dotnet/IEC61850forCSharp/Reporting.cs b/dotnet/IEC61850forCSharp/Reporting.cs index 583627f..e88f5ff 100644 --- a/dotnet/IEC61850forCSharp/Reporting.cs +++ b/dotnet/IEC61850forCSharp/Reporting.cs @@ -106,6 +106,10 @@ namespace IEC61850 [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReport_hasBufOvfl(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + static extern bool ClientReport_getBufOvfl(IntPtr self); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReport_hasDataReference(IntPtr self); @@ -180,6 +184,11 @@ namespace IEC61850 return ClientReport_hasBufOvfl(self); } + public bool GetBufOvfl () + { + return ClientReport_getBufOvfl(self); + } + public bool HasSeqNum () { return ClientReport_hasSeqNum(self); diff --git a/dotnet/control/ControlExample.cs b/dotnet/control/ControlExample.cs index 1ca2b51..7fc136a 100644 --- a/dotnet/control/ControlExample.cs +++ b/dotnet/control/ControlExample.cs @@ -41,7 +41,7 @@ namespace control Console.WriteLine(objectReference + " has control model " + controlModel.ToString()); - if (controlModel != ControlModel.CONTROL_MODEL_STATUS_ONLY) + if (controlModel != ControlModel.STATUS_ONLY) control.Operate(true); if (!control.Operate(true)) @@ -54,7 +54,7 @@ namespace control controlModel = control.GetControlModel(); Console.WriteLine(objectReference + " has control model " + controlModel.ToString()); - if (controlModel == ControlModel.CONTROL_MODEL_DIRECT_ENHANCED) { + if (controlModel == ControlModel.DIRECT_ENHANCED) { control.SetCommandTerminationHandler(commandTerminationHandler, null); control.Operate(true); @@ -62,8 +62,6 @@ namespace control Thread.Sleep(1000); } - - con.Abort(); } catch (IedConnectionException e) diff --git a/src/iec61850/client/client_report.c b/src/iec61850/client/client_report.c index bf944ee..4381544 100644 --- a/src/iec61850/client/client_report.c +++ b/src/iec61850/client/client_report.c @@ -54,6 +54,7 @@ struct sClientReport uint64_t timestamp; uint16_t seqNum; uint32_t confRev; + bool bufOverflow; }; char* @@ -190,6 +191,12 @@ ClientReport_hasBufOvfl(ClientReport self) return self->hasBufOverflow; } +bool +ClientReport_getBufOvfl(ClientReport self) +{ + return self->bufOverflow; +} + bool ClientReport_hasDataReference(ClientReport self) { @@ -390,9 +397,13 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value) if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: Found enabled report!\n"); - /* skip bufOvfl */ + /* check bufOvfl */ if (MmsValue_getBitStringBit(optFlds, 6) == true) { + MmsValue* bufOverflow = MmsValue_getElement(value, inclusionIndex); + matchingReport->hasBufOverflow = true; + matchingReport->bufOverflow = MmsValue_getBoolean(bufOverflow); + inclusionIndex++; } diff --git a/src/iec61850/inc/iec61850_client.h b/src/iec61850/inc/iec61850_client.h index b1b3401..95bead9 100644 --- a/src/iec61850/inc/iec61850_client.h +++ b/src/iec61850/inc/iec61850_client.h @@ -730,9 +730,26 @@ ClientReport_hasConfRev(ClientReport self); uint32_t ClientReport_getConfRev(ClientReport self); +/** + * \brief Indicates if the report contains the bufOvfl (buffer overflow) flag + * + * \param self the ClientReport instance + * + * \returns true if the report contains the bufOvfl flag, false otherwise + */ bool ClientReport_hasBufOvfl(ClientReport self); +/** + * \brief Get the value of the bufOvfl flag + * + * \param self the ClientReport instance + * + * \returns true if bufOvfl is set, false otherwise + */ +bool +ClientReport_getBufOvfl(ClientReport self); + /** * \brief Indicates if the report contains data references for the reported data set members * diff --git a/src/iec61850/server/model/model.c b/src/iec61850/server/model/model.c index 2a5d5aa..8aef85e 100644 --- a/src/iec61850/server/model/model.c +++ b/src/iec61850/server/model/model.c @@ -527,8 +527,6 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint return matchingNode; } - -inline LogicalNode* LogicalDevice_getLogicalNode(LogicalDevice* self, const char* nodeName) { diff --git a/src/mms/inc/mms_value.h b/src/mms/inc/mms_value.h index 11d1818..7f11956 100644 --- a/src/mms/inc/mms_value.h +++ b/src/mms/inc/mms_value.h @@ -459,6 +459,17 @@ MmsValue_getUtcTimeBuffer(MmsValue* self); uint64_t MmsValue_getUtcTimeInMs(const MmsValue* value); +/** + * \brief Get a millisecond time value and optional us part from an MmsValue object of MMS_UTCTIME type. + * + * \param self MmsValue instance to operate on. Has to be of a type MMS_UTCTIME. + * \param usec a pointer to store the us (microsecond) value. + * + * \return the value in milliseconds since epoch (1970/01/01 00:00 UTC) + */ +uint64_t +MmsValue_getUtcTimeInMsWithUs(const MmsValue* self, uint32_t* usec); + /** * \brief set the TimeQuality byte of the UtcTime * diff --git a/src/mms/iso_mms/common/mms_value.c b/src/mms/iso_mms/common/mms_value.c index ff821a3..7093736 100644 --- a/src/mms/iso_mms/common/mms_value.c +++ b/src/mms/iso_mms/common/mms_value.c @@ -755,6 +755,33 @@ MmsValue_getUtcTimeInMs(const MmsValue* self) return msVal; } +uint64_t +MmsValue_getUtcTimeInMsWithUs(const MmsValue* self, uint32_t* usec) +{ + uint32_t timeval32; + const uint8_t* valueArray = self->value.utcTime; + +#if (ORDER_LITTLE_ENDIAN == 1) + memcpyReverseByteOrder((uint8_t*) &timeval32, valueArray, 4); +#else + memcpy((uint8_t*)&timeval32, valueArray, 4); +#endif + + uint64_t fractionOfSecond = 0; + + fractionOfSecond = (valueArray[4] << 16); + fractionOfSecond += (valueArray[5] << 8); + fractionOfSecond += (valueArray[6]); + + uint64_t remainder = fractionOfSecond * 1000000ULL / 0x1000000ULL; // in usec + + uint64_t msVal = (timeval32 * 1000LL) + (remainder / 1000LL); + + if (usec != NULL) + *usec = remainder % 1000LL; + + return msVal; +} MmsValue* diff --git a/src/mms/iso_server/iso_server.c b/src/mms/iso_server/iso_server.c index 7bcb8f0..65bc885 100644 --- a/src/mms/iso_server/iso_server.c +++ b/src/mms/iso_server/iso_server.c @@ -479,7 +479,7 @@ IsoServer_startListening(IsoServer self) if (DEBUG_ISO_SERVER) printf("ISO_SERVER: new iso server thread started\n"); } -#endif +#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */ void IsoServer_startListeningThreadless(IsoServer self) diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index 8459efe..8a8b60a 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -487,4 +487,5 @@ EXPORTS Timestamp_clearFlags IedServer_setGooseInterfaceId MmsServerIdentity_destroy - \ No newline at end of file + ClientReport_getBufOvfl + MmsValue_getUtcTimeInMsWithUs diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index cbfa888..b944370 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -511,4 +511,5 @@ EXPORTS Timestamp_clearFlags IedServer_setGooseInterfaceId MmsServerIdentity_destroy - + ClientReport_getBufOvfl + MmsValue_getUtcTimeInMsWithUs