- 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:
parent
69dbbcf306
commit
f3b75dd3fc
12 changed files with 316 additions and 17 deletions
|
@ -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/")
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -558,3 +558,6 @@ EXPORTS
|
|||
MmsConnection_obtainFile
|
||||
IedConnection_setFile
|
||||
IedConnection_readInt64Value
|
||||
Timestamp_create
|
||||
Timestamp_destroy
|
||||
Timestamp_setByMmsUtcTime
|
|
@ -636,3 +636,6 @@ EXPORTS
|
|||
MmsConnection_obtainFile
|
||||
IedConnection_setFile
|
||||
IedConnection_readInt64Value
|
||||
Timestamp_create
|
||||
Timestamp_destroy
|
||||
Timestamp_setByMmsUtcTime
|
Loading…
Add table
Reference in a new issue