- added function MmsValue_getUtcTimeInMsWithUs to C and C# API
This commit is contained in:
parent
48b02ec1b0
commit
e84da95752
11 changed files with 113 additions and 10 deletions
|
@ -91,6 +91,9 @@ namespace IEC61850
|
||||||
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
|
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern ulong MmsValue_getUtcTimeInMs (IntPtr self);
|
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)]
|
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
|
||||||
static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self);
|
static extern UInt32 MmsValue_toUnixTimestamp (IntPtr self);
|
||||||
|
|
||||||
|
@ -385,6 +388,33 @@ namespace IEC61850
|
||||||
throw new MmsValueException ("Value is not a time type");
|
throw new MmsValueException ("Value is not a time type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the timestamp value as UTC time in ms and the additional us part.
|
||||||
|
/// </summary>
|
||||||
|
/// <description>
|
||||||
|
/// 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.
|
||||||
|
/// </description>
|
||||||
|
/// <param name='usec'>
|
||||||
|
/// returns the usec part of the time value
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// The UTC time in ms.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="MmsValueException">This exception is thrown if the value has the wrong type.</exception>
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convert a millisecond time (milliseconds since epoch) to DataTimeOffset
|
/// Convert a millisecond time (milliseconds since epoch) to DataTimeOffset
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -106,6 +106,10 @@ namespace IEC61850
|
||||||
[return: MarshalAs(UnmanagedType.I1)]
|
[return: MarshalAs(UnmanagedType.I1)]
|
||||||
static extern bool ClientReport_hasBufOvfl(IntPtr self);
|
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)]
|
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
|
||||||
[return: MarshalAs(UnmanagedType.I1)]
|
[return: MarshalAs(UnmanagedType.I1)]
|
||||||
static extern bool ClientReport_hasDataReference(IntPtr self);
|
static extern bool ClientReport_hasDataReference(IntPtr self);
|
||||||
|
@ -180,6 +184,11 @@ namespace IEC61850
|
||||||
return ClientReport_hasBufOvfl(self);
|
return ClientReport_hasBufOvfl(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool GetBufOvfl ()
|
||||||
|
{
|
||||||
|
return ClientReport_getBufOvfl(self);
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasSeqNum ()
|
public bool HasSeqNum ()
|
||||||
{
|
{
|
||||||
return ClientReport_hasSeqNum(self);
|
return ClientReport_hasSeqNum(self);
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace control
|
||||||
|
|
||||||
Console.WriteLine(objectReference + " has control model " + controlModel.ToString());
|
Console.WriteLine(objectReference + " has control model " + controlModel.ToString());
|
||||||
|
|
||||||
if (controlModel != ControlModel.CONTROL_MODEL_STATUS_ONLY)
|
if (controlModel != ControlModel.STATUS_ONLY)
|
||||||
control.Operate(true);
|
control.Operate(true);
|
||||||
|
|
||||||
if (!control.Operate(true))
|
if (!control.Operate(true))
|
||||||
|
@ -54,7 +54,7 @@ namespace control
|
||||||
controlModel = control.GetControlModel();
|
controlModel = control.GetControlModel();
|
||||||
Console.WriteLine(objectReference + " has control model " + controlModel.ToString());
|
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.SetCommandTerminationHandler(commandTerminationHandler, null);
|
||||||
|
|
||||||
control.Operate(true);
|
control.Operate(true);
|
||||||
|
@ -62,8 +62,6 @@ namespace control
|
||||||
Thread.Sleep(1000);
|
Thread.Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
con.Abort();
|
con.Abort();
|
||||||
}
|
}
|
||||||
catch (IedConnectionException e)
|
catch (IedConnectionException e)
|
||||||
|
|
|
@ -54,6 +54,7 @@ struct sClientReport
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
uint16_t seqNum;
|
uint16_t seqNum;
|
||||||
uint32_t confRev;
|
uint32_t confRev;
|
||||||
|
bool bufOverflow;
|
||||||
};
|
};
|
||||||
|
|
||||||
char*
|
char*
|
||||||
|
@ -190,6 +191,12 @@ ClientReport_hasBufOvfl(ClientReport self)
|
||||||
return self->hasBufOverflow;
|
return self->hasBufOverflow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ClientReport_getBufOvfl(ClientReport self)
|
||||||
|
{
|
||||||
|
return self->bufOverflow;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ClientReport_hasDataReference(ClientReport self)
|
ClientReport_hasDataReference(ClientReport self)
|
||||||
{
|
{
|
||||||
|
@ -390,9 +397,13 @@ private_IedConnection_handleReport(IedConnection self, MmsValue* value)
|
||||||
if (DEBUG_IED_CLIENT)
|
if (DEBUG_IED_CLIENT)
|
||||||
printf("DEBUG_IED_CLIENT: Found enabled report!\n");
|
printf("DEBUG_IED_CLIENT: Found enabled report!\n");
|
||||||
|
|
||||||
/* skip bufOvfl */
|
/* check bufOvfl */
|
||||||
if (MmsValue_getBitStringBit(optFlds, 6) == true) {
|
if (MmsValue_getBitStringBit(optFlds, 6) == true) {
|
||||||
|
MmsValue* bufOverflow = MmsValue_getElement(value, inclusionIndex);
|
||||||
|
|
||||||
matchingReport->hasBufOverflow = true;
|
matchingReport->hasBufOverflow = true;
|
||||||
|
matchingReport->bufOverflow = MmsValue_getBoolean(bufOverflow);
|
||||||
|
|
||||||
inclusionIndex++;
|
inclusionIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -730,9 +730,26 @@ ClientReport_hasConfRev(ClientReport self);
|
||||||
uint32_t
|
uint32_t
|
||||||
ClientReport_getConfRev(ClientReport self);
|
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
|
bool
|
||||||
ClientReport_hasBufOvfl(ClientReport self);
|
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
|
* \brief Indicates if the report contains data references for the reported data set members
|
||||||
*
|
*
|
||||||
|
|
|
@ -527,8 +527,6 @@ ModelNode_getChildWithFc(ModelNode* self, const char* name, FunctionalConstraint
|
||||||
return matchingNode;
|
return matchingNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline
|
|
||||||
LogicalNode*
|
LogicalNode*
|
||||||
LogicalDevice_getLogicalNode(LogicalDevice* self, const char* nodeName)
|
LogicalDevice_getLogicalNode(LogicalDevice* self, const char* nodeName)
|
||||||
{
|
{
|
||||||
|
|
|
@ -459,6 +459,17 @@ MmsValue_getUtcTimeBuffer(MmsValue* self);
|
||||||
uint64_t
|
uint64_t
|
||||||
MmsValue_getUtcTimeInMs(const MmsValue* value);
|
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
|
* \brief set the TimeQuality byte of the UtcTime
|
||||||
*
|
*
|
||||||
|
|
|
@ -755,6 +755,33 @@ MmsValue_getUtcTimeInMs(const MmsValue* self)
|
||||||
return msVal;
|
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*
|
MmsValue*
|
||||||
|
|
|
@ -479,7 +479,7 @@ IsoServer_startListening(IsoServer self)
|
||||||
if (DEBUG_ISO_SERVER)
|
if (DEBUG_ISO_SERVER)
|
||||||
printf("ISO_SERVER: new iso server thread started\n");
|
printf("ISO_SERVER: new iso server thread started\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* (CONFIG_MMS_THREADLESS_STACK != 1) */
|
||||||
|
|
||||||
void
|
void
|
||||||
IsoServer_startListeningThreadless(IsoServer self)
|
IsoServer_startListeningThreadless(IsoServer self)
|
||||||
|
|
|
@ -487,4 +487,5 @@ EXPORTS
|
||||||
Timestamp_clearFlags
|
Timestamp_clearFlags
|
||||||
IedServer_setGooseInterfaceId
|
IedServer_setGooseInterfaceId
|
||||||
MmsServerIdentity_destroy
|
MmsServerIdentity_destroy
|
||||||
|
ClientReport_getBufOvfl
|
||||||
|
MmsValue_getUtcTimeInMsWithUs
|
||||||
|
|
|
@ -511,4 +511,5 @@ EXPORTS
|
||||||
Timestamp_clearFlags
|
Timestamp_clearFlags
|
||||||
IedServer_setGooseInterfaceId
|
IedServer_setGooseInterfaceId
|
||||||
MmsServerIdentity_destroy
|
MmsServerIdentity_destroy
|
||||||
|
ClientReport_getBufOvfl
|
||||||
|
MmsValue_getUtcTimeInMsWithUs
|
||||||
|
|
Loading…
Add table
Reference in a new issue