- added functions Timestamp_create, Timestamp_destroy, Timestamp_setByMmsUtcTime

- C# API: Added Timestamp class
- C# API: Added missing UpdateAttribute methods to IedServer
This commit is contained in:
Michael Zillgith 2017-04-06 22:58:22 +02:00
parent 69dbbcf306
commit f3b75dd3fc
12 changed files with 316 additions and 17 deletions

View file

@ -12,7 +12,7 @@ ENABLE_TESTING()
set(LIB_VERSION_MAJOR "1")
set(LIB_VERSION_MINOR "0")
set(LIB_VERSION_PATCH "1")
set(LIB_VERSION_PATCH "2")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/third_party/cmake/modules/")

View file

@ -987,14 +987,14 @@ namespace IEC61850
/// <param name="objectReference">The object reference of a BDA.</param>
/// <param name="fc">The functional constraint (FC) of the object</param>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt64 ReadTimestampValue (string objectReference, FunctionalConstraint fc)
public Timestamp ReadTimestampValue (string objectReference, FunctionalConstraint fc)
{
var mmsValuePtr = readObjectInternalAndCheckDataAccessError (objectReference, fc);
var mmsValue = new MmsValue (mmsValuePtr, true);
if (mmsValue.GetType () == MmsType.MMS_UTC_TIME)
return mmsValue.GetUtcTimeInMs ();
if (mmsValue.GetType () == MmsType.MMS_UTC_TIME)
return new Timestamp (mmsValue);
else
throw new IedConnectionException ("Result is not of type timestamp (MMS_UTC_TIME)", 0);
}

View file

@ -140,6 +140,203 @@ namespace IEC61850
}
}
/// <summary>
/// Timestamp (represents IEC 61850 timestamps e.g. "t" attribute)
/// </summary>
public class Timestamp
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr Timestamp_create ();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_destroy (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_clearFlags (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_isLeapSecondKnown (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setLeapSecondKnown (IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_hasClockFailure (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockFailure (IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool Timestamp_isClockNotSynchronized (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setClockNotSynchronized (IntPtr self, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int Timestamp_getSubsecondPrecision (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setSubsecondPrecision(IntPtr self, int subsecondPrecision);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setTimeInSeconds (IntPtr self, UInt32 secondsSinceEpoch);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setTimeInMilliseconds (IntPtr self, UInt64 millisSinceEpoch);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 Timestamp_getTimeInSeconds (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt64 Timestamp_getTimeInMs (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void Timestamp_setByMmsUtcTime (IntPtr self, IntPtr mmsValue);
internal IntPtr timestampRef = IntPtr.Zero;
private bool responsableForDeletion;
internal Timestamp(IntPtr timestampRef, bool selfAllocated)
{
this.timestampRef = timestampRef;
this.responsableForDeletion = selfAllocated;
}
public Timestamp (DateTime timestamp) : this ()
{
SetDateTime (timestamp);
}
public Timestamp (MmsValue mmsUtcTime) : this()
{
SetByMmsUtcTime (mmsUtcTime);
}
public Timestamp()
{
timestampRef = Timestamp_create ();
LeapSecondKnown = true;
responsableForDeletion = true;
}
~Timestamp ()
{
if (responsableForDeletion)
Timestamp_destroy (timestampRef);
}
public void ClearFlags()
{
Timestamp_clearFlags (timestampRef);
}
public void SetDateTime(DateTime timestamp)
{
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime timestampUTC = timestamp.ToUniversalTime();
TimeSpan timeDiff = timestampUTC - epoch;
ulong timeVal = Convert.ToUInt64(timeDiff.TotalMilliseconds);
SetTimeInMilliseconds (timeVal);
}
public bool LeapSecondKnown {
get { return IsLeapSecondKnown ();}
set { SetLeapSecondKnow (value);}
}
public bool IsLeapSecondKnown()
{
return Timestamp_isLeapSecondKnown (timestampRef);
}
public void SetLeapSecondKnow(bool value)
{
Timestamp_setLeapSecondKnown (timestampRef, value);
}
public bool ClockFailure {
get { return HasClockFailure ();}
set { SetClockFailure (value);}
}
public bool HasClockFailure()
{
return Timestamp_hasClockFailure (timestampRef);
}
public void SetClockFailure(bool value)
{
Timestamp_setClockFailure (timestampRef, value);
}
public bool ClockNotSynchronized {
get { return IsClockNotSynchronized (); }
set { SetClockNotSynchronized (value); }
}
public bool IsClockNotSynchronized() {
return Timestamp_isClockNotSynchronized(timestampRef);
}
public void SetClockNotSynchronized(bool value) {
Timestamp_setClockNotSynchronized (timestampRef, value);
}
public int SubsecondPrecision {
get { return GetSubsecondPrecision (); }
set { SetSubsecondPrecision (value); }
}
public int GetSubsecondPrecision() {
return Timestamp_getSubsecondPrecision (timestampRef);
}
public void SetSubsecondPrecision(int subsecondPrecision) {
Timestamp_setSubsecondPrecision (timestampRef, subsecondPrecision);
}
public UInt32 TimeInSeconds {
get { return GetTimeInSeconds (); }
set { SetTimeInSeconds (value); }
}
public UInt32 GetTimeInSeconds()
{
return Timestamp_getTimeInSeconds (timestampRef);
}
public void SetTimeInSeconds(UInt32 secondsSinceEpoch)
{
Timestamp_setTimeInSeconds (timestampRef, secondsSinceEpoch);
}
public UInt64 TimeInMilliseconds {
get { return GetTimeInMilliseconds (); }
set { SetTimeInMilliseconds (value); }
}
public UInt64 GetTimeInMilliseconds()
{
return Timestamp_getTimeInMs (timestampRef);
}
public void SetTimeInMilliseconds(UInt64 millisSinceEpoch) {
Timestamp_setTimeInMilliseconds (timestampRef, millisSinceEpoch);
}
public void SetByMmsUtcTime(MmsValue mmsValue)
{
Timestamp_setByMmsUtcTime (timestampRef, mmsValue.valueReference);
}
}
public enum ACSIClass
{
/** data objects */

View file

@ -227,7 +227,8 @@ namespace IEC61850
GENERIC_BITSTRING = 26,
CONSTRUCTED = 27,
ENTRY_TIME = 28,
PHYCOMADDR = 29
PHYCOMADDR = 29,
CURRENCY = 30
}
public enum ModeValues
@ -246,7 +247,12 @@ namespace IEC61850
ALARM = 3
}
public class CDC {
/// <summary>
/// The CDC class contains helper functions to create DataObject instances for the
/// most common Common Data Classes.
/// </summary>
public class CDC
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr CDC_SPS_create(string name, IntPtr parent, uint options);
@ -573,12 +579,18 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_unlockDataModel(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateAttributeValue(IntPtr self, IntPtr DataAttribute, IntPtr MmsValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateBooleanAttributeValue(IntPtr self, IntPtr dataAttribute, bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateInt32AttributeValue(IntPtr self, IntPtr dataAttribute, int value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateInt64AttributeValue(IntPtr self, IntPtr dataAttribute, Int64 value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateFloatAttributeValue(IntPtr self, IntPtr dataAttribute, float value);
@ -588,6 +600,9 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateUTCTimeAttributeValue(IntPtr self, IntPtr dataAttribute, ulong value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateTimestampAttributeValue(IntPtr self, IntPtr dataAttribute, IntPtr timestamp);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_updateQuality(IntPtr self, IntPtr dataAttribute, ushort value);
@ -892,24 +907,34 @@ namespace IEC61850
IedServer_unlockDataModel(self);
}
public void UpdateBooleanAttributeValue(DataAttribute dataAttr, bool val)
public void UpdateAttributeValue(DataAttribute dataAttr, MmsValue value)
{
IedServer_updateBooleanAttributeValue(self, dataAttr.self, val);
IedServer_updateAttributeValue (self, dataAttr.self, value.valueReference);
}
public void UpdateFloatAttributeValue(DataAttribute dataAttr, float val)
public void UpdateBooleanAttributeValue(DataAttribute dataAttr, bool value)
{
IedServer_updateFloatAttributeValue(self, dataAttr.self, val);
IedServer_updateBooleanAttributeValue(self, dataAttr.self, value);
}
public void UpdateInt32AttributeValue(DataAttribute dataAttr, int val)
public void UpdateFloatAttributeValue(DataAttribute dataAttr, float value)
{
IedServer_updateInt32AttributeValue(self, dataAttr.self, val);
IedServer_updateFloatAttributeValue(self, dataAttr.self, value);
}
public void UpdateVisibleStringAttributeValue(DataAttribute dataAttr, string val)
public void UpdateInt32AttributeValue(DataAttribute dataAttr, int value)
{
IedServer_updateVisibleStringAttributeValue(self, dataAttr.self, val);
IedServer_updateInt32AttributeValue(self, dataAttr.self, value);
}
public void UpdateInt64AttributeValue(DataAttribute dataAttr, Int64 value)
{
IedServer_updateInt64AttributeValue (self, dataAttr.self, value);
}
public void UpdateVisibleStringAttributeValue(DataAttribute dataAttr, string value)
{
IedServer_updateVisibleStringAttributeValue(self, dataAttr.self, value);
}
public void UpdateUTCTimeAttributeValue(DataAttribute dataAttr, DateTime timestamp)
@ -923,6 +948,11 @@ namespace IEC61850
IedServer_updateUTCTimeAttributeValue(self, dataAttr.self, timeVal);
}
public void UpdateTimestampAttributeValue(DataAttribute dataAttr, Timestamp timestamp)
{
IedServer_updateTimestampAttributeValue (self, dataAttr.self, timestamp.timestampRef);
}
public void UpdateQuality(DataAttribute dataAttr, ushort value)
{
IedServer_updateQuality(self, dataAttr.self, value);

View file

@ -44,8 +44,18 @@ namespace server1
GC.Collect ();
DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference ("GenericIO/GGIO1.AnIn1");
DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild ("mag.f");
DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild ("t");
float floatVal = 1.0f;
while (running) {
Thread.Sleep (1);
floatVal += 1f;
iedServer.UpdateTimestampAttributeValue (ggio1AnIn1T, new Timestamp (DateTime.Now));
iedServer.UpdateFloatAttributeValue (ggio1AnIn1magF, floatVal);
Thread.Sleep (100);
}
iedServer.Stop ();

View file

@ -105,6 +105,30 @@ namespace tests
Assert.AreEqual (val.ToFloat (), (float)0.1234);
}
[Test ()]
public void Timestamps()
{
Timestamp timestamp = new Timestamp ();
Assert.IsTrue (timestamp.LeapSecondKnown);
Assert.IsFalse (timestamp.ClockFailure);
Assert.IsFalse (timestamp.ClockNotSynchronized);
timestamp.LeapSecondKnown = false;
Assert.IsFalse (timestamp.LeapSecondKnown);
timestamp.ClockFailure = true;
Assert.IsTrue (timestamp.ClockFailure);
timestamp.ClockNotSynchronized = true;
Assert.IsTrue (timestamp.ClockNotSynchronized);
Assert.AreEqual (0, timestamp.SubsecondPrecision);
timestamp.SubsecondPrecision = 10;
Assert.AreEqual (10, timestamp.SubsecondPrecision);
}
[Test ()]
public void CreateModelFromNonExistingFile()
{

View file

@ -15,7 +15,7 @@
#include "platform_endian.h"
#define LIBIEC61850_VERSION "1.0.1"
#define LIBIEC61850_VERSION "1.0.2"
#ifndef CONFIG_DEFAULT_MMS_VENDOR_NAME
#define CONFIG_DEFAULT_MMS_VENDOR_NAME "libiec61850.com"

View file

@ -18,7 +18,7 @@ DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "libIEC61850"
PROJECT_NUMBER = 1.0.0
PROJECT_NUMBER = 1.0.2
PROJECT_BRIEF = "Open-source IEC 61850 MMS/GOOSE/SV server and client library"

View file

@ -26,6 +26,7 @@
#include "libiec61850_platform_includes.h"
#include "conversions.h"
#include "mms_value_internal.h"
Validity
Quality_getValidity(Quality* self)
@ -223,6 +224,21 @@ FunctionalConstraint_fromString(const char* fcString)
return IEC61850_FC_NONE;
}
Timestamp*
Timestamp_create()
{
Timestamp* self = (Timestamp*) GLOBAL_CALLOC(1, sizeof(Timestamp));
return self;
}
void
Timestamp_destroy(Timestamp* self)
{
if (self != NULL)
GLOBAL_FREEMEM(self);
}
void
Timestamp_clearFlags(Timestamp* self)
{
@ -382,6 +398,13 @@ Timestamp_getTimeInMs(Timestamp* self)
return (uint64_t) msVal;
}
void
Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue)
{
if (MmsValue_getType(mmsValue) == MMS_UTC_TIME)
memcpy(self->val, mmsValue->value.utcTime, 8);
}
char*
LibIEC61850_getVersionString()
{

View file

@ -353,6 +353,12 @@ typedef union {
uint8_t val[8];
} Timestamp;
Timestamp*
Timestamp_create(void);
void
Timestamp_destroy(Timestamp* self);
void
Timestamp_clearFlags(Timestamp* self);
@ -397,6 +403,9 @@ Timestamp_setTimeInSeconds(Timestamp* self, uint32_t secondsSinceEpoch);
void
Timestamp_setTimeInMilliseconds(Timestamp* self, uint64_t millisSinceEpoch);
void
Timestamp_setByMmsUtcTime(Timestamp* self, MmsValue* mmsValue);
/**
* \brief Get the version of the library as string
*

View file

@ -558,3 +558,6 @@ EXPORTS
MmsConnection_obtainFile
IedConnection_setFile
IedConnection_readInt64Value
Timestamp_create
Timestamp_destroy
Timestamp_setByMmsUtcTime

View file

@ -636,3 +636,6 @@ EXPORTS
MmsConnection_obtainFile
IedConnection_setFile
IedConnection_readInt64Value
Timestamp_create
Timestamp_destroy
Timestamp_setByMmsUtcTime