From 33fb9206b3ea9034de673dbcdb5071e099ceb5bb Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 2 Jan 2018 21:56:23 +0100 Subject: [PATCH] - .NET API: Added support for Timestamp and Quality to SV subscriber --- dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs | 26 ++++++++++++++++--- .../SampledValuesSubscriber.cs | 26 +++++++++++++++++++ dotnet/sv_subscriber/Program.cs | 8 ++++-- src/iec61850/common/iec61850_common.c | 15 +++++++++++ src/iec61850/inc/iec61850_common.h | 3 +++ src/vs/libiec61850-wo-goose.def | 3 ++- src/vs/libiec61850.def | 3 ++- 7 files changed, 76 insertions(+), 8 deletions(-) diff --git a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs index daed6660..3c4752f7 100644 --- a/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850CommonAPI.cs @@ -349,6 +349,9 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr Timestamp_create (); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr Timestamp_createFromByteArray(byte[] byteArry); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void Timestamp_destroy (IntPtr self); @@ -399,12 +402,12 @@ namespace IEC61850 static extern void Timestamp_setByMmsUtcTime (IntPtr self, IntPtr mmsValue); internal IntPtr timestampRef = IntPtr.Zero; - private bool responsableForDeletion; + private bool responsibleForDeletion; internal Timestamp(IntPtr timestampRef, bool selfAllocated) { this.timestampRef = timestampRef; - this.responsableForDeletion = selfAllocated; + this.responsibleForDeletion = selfAllocated; } public Timestamp (DateTime timestamp) : this () @@ -421,12 +424,18 @@ namespace IEC61850 { timestampRef = Timestamp_create (); LeapSecondKnown = true; - responsableForDeletion = true; + responsibleForDeletion = true; + } + + public Timestamp(byte[] value) + { + timestampRef = Timestamp_createFromByteArray (value); + responsibleForDeletion = true; } ~Timestamp () { - if (responsableForDeletion) + if (responsibleForDeletion) Timestamp_destroy (timestampRef); } @@ -536,6 +545,15 @@ namespace IEC61850 Timestamp_setByMmsUtcTime (timestampRef, mmsValue.valueReference); } + public DateTime AsDateTime() + { + DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + DateTime retVal = epoch.AddMilliseconds ((double) GetTimeInMilliseconds ()); + + return retVal; + } + } public enum ACSIClass diff --git a/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs b/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs index 7375367d..66a9091c 100644 --- a/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs +++ b/dotnet/IEC61850forCSharp/SampledValuesSubscriber.cs @@ -274,6 +274,9 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern double SVSubscriber_ASDU_getFLOAT64(IntPtr self, int index); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern UInt16 SVSubscriber_ASDU_getQuality(IntPtr self, int index); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern int SVSubscriber_ASDU_getDataSize(IntPtr self); @@ -389,6 +392,29 @@ namespace IEC61850 return SVSubscriber_ASDU_getFLOAT64 (self, index); } + private struct PTimestamp + { + [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)] + public byte[] val; + } + + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + private static extern PTimestamp SVSubscriber_ASDU_getTimestamp(IntPtr self, int index); + + public Timestamp GetTimestamp(int index) + { + PTimestamp retVal = SVSubscriber_ASDU_getTimestamp (self, index); + + return new Timestamp (retVal.val); + } + + public Quality GetQuality(int index) + { + UInt16 qValue = SVSubscriber_ASDU_getQuality (self, index); + + return new Quality (qValue); + } + /// /// Gets the size of the payload data in bytes. The payload comprises the data set data. /// diff --git a/dotnet/sv_subscriber/Program.cs b/dotnet/sv_subscriber/Program.cs index 9865356d..17426e6f 100644 --- a/dotnet/sv_subscriber/Program.cs +++ b/dotnet/sv_subscriber/Program.cs @@ -10,7 +10,7 @@ namespace sv_subscriber { private static void svUpdateListener(SVSubscriber subscriber, object parameter, SVSubscriberASDU asdu) { - Console.WriteLine ("svUpdateListener called"); + Console.WriteLine ("RECV ASDU:"); string svID = asdu.GetSvId (); @@ -22,7 +22,11 @@ namespace sv_subscriber if (asdu.GetDataSize () >= 8) { Console.WriteLine (" DATA[0]: " + asdu.GetFLOAT32(0)); - Console.WriteLine (" DATA[1]: " + asdu.GetFLOAT32(4)); + Console.WriteLine (" DATA[1]: " + asdu.GetFLOAT32 (4)); + } + + if (asdu.GetDataSize () >= 16) { + Console.WriteLine (" DATA[2]: " + asdu.GetTimestamp (8).AsDateTime().ToString()); } } diff --git a/src/iec61850/common/iec61850_common.c b/src/iec61850/common/iec61850_common.c index d2a68988..8e17c05c 100644 --- a/src/iec61850/common/iec61850_common.c +++ b/src/iec61850/common/iec61850_common.c @@ -232,6 +232,21 @@ Timestamp_create() return self; } +Timestamp* +Timestamp_createFromByteArray(uint8_t* byteArray) +{ + Timestamp* self = Timestamp_create(); + + if (self) { + int i; + + for (i = 0; i < 8; i++) + self->val[i] = byteArray[i]; + } + + return self; +} + void Timestamp_destroy(Timestamp* self) { diff --git a/src/iec61850/inc/iec61850_common.h b/src/iec61850/inc/iec61850_common.h index a48e8eda..5b5a14e4 100644 --- a/src/iec61850/inc/iec61850_common.h +++ b/src/iec61850/inc/iec61850_common.h @@ -356,6 +356,9 @@ typedef union { Timestamp* Timestamp_create(void); +Timestamp* +Timestamp_createFromByteArray(uint8_t* byteArray); + void Timestamp_destroy(Timestamp* self); diff --git a/src/vs/libiec61850-wo-goose.def b/src/vs/libiec61850-wo-goose.def index 133e0207..d296c09c 100644 --- a/src/vs/libiec61850-wo-goose.def +++ b/src/vs/libiec61850-wo-goose.def @@ -578,4 +578,5 @@ EXPORTS ClientGooseControlBlock_getDstAddress ClientGooseControlBlock_setDstAddress CDC_VSS_create - CDC_VSG_create \ No newline at end of file + CDC_VSG_create + Timestamp_createFromByteArray \ No newline at end of file diff --git a/src/vs/libiec61850.def b/src/vs/libiec61850.def index 68309da5..f6a6e8d2 100644 --- a/src/vs/libiec61850.def +++ b/src/vs/libiec61850.def @@ -704,4 +704,5 @@ EXPORTS SVPublisher_ASDU_setTimestamp SVSubscriber_ASDU_getQuality SVPublisher_ASDU_addQuality - SVPublisher_ASDU_setQuality \ No newline at end of file + SVPublisher_ASDU_setQuality + Timestamp_createFromByteArray \ No newline at end of file