diff --git a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
index a6a0adc6..b9e01bcf 100644
--- a/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
+++ b/dotnet/IEC61850forCSharp/IEC61850ClientAPI.cs
@@ -1,7 +1,7 @@
/*
* IEC61850ClientAPI.cs
*
- * Copyright 2014 Michael Zillgith
+ * Copyright 2014-2016 Michael Zillgith
*
* This file is part of libIEC61850.
*
@@ -266,6 +266,10 @@ namespace IEC61850
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
static extern void MmsValue_delete (IntPtr self);
+
+ [DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
+ static extern int MmsValue_getDataAccessError(IntPtr self);
+
/****************
* IedConnection
***************/
@@ -838,7 +842,7 @@ namespace IEC61850
if (error != 0)
throw new IedConnectionException ("Reading value failed", error);
- if (mmsValue.ToInt32 () == 0)
+ if (mmsValue == IntPtr.Zero)
throw new IedConnectionException ("Variable not found on server", error);
return mmsValue;
@@ -856,6 +860,22 @@ namespace IEC61850
return new MmsValue (value, true);
}
+ private IntPtr readObjectInternalAndCheckDataAccessError(string objectReference, FunctionalConstraint fc)
+ {
+ IntPtr mmsValue = readObjectInternal (objectReference, fc);
+
+ if (MmsValue_getType(mmsValue) == (int) MmsType.MMS_DATA_ACCESS_ERROR) {
+
+ int dataAccessError = MmsValue_getDataAccessError (mmsValue);
+
+ MmsValue_delete (mmsValue);
+
+ throw new IedConnectionException ("Data access error", dataAccessError);
+ }
+
+ return mmsValue;
+ }
+
/// Read the value of a basic data attribute (BDA) of type boolean.
/// The object reference of a BDA.
/// The functional constraint (FC) of the object
@@ -863,12 +883,18 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public bool ReadBooleanValue (string objectReference, FunctionalConstraint fc)
{
- var mmsValue = ReadValue (objectReference, fc);
+ IntPtr mmsValue = readObjectInternalAndCheckDataAccessError (objectReference, fc);
- if (mmsValue.GetType () == MmsType.MMS_BOOLEAN)
- return mmsValue.GetBoolean ();
- else
+ if (MmsValue_getType (mmsValue) != (int) MmsType.MMS_BOOLEAN) {
+ MmsValue_delete (mmsValue);
throw new IedConnectionException ("Result is not of type boolean (MMS_BOOLEAN)", 0);
+ }
+
+ bool value = MmsValue_getBoolean (mmsValue);
+
+ MmsValue_delete (mmsValue);
+
+ return value;
}
/// Read the value of a basic data attribute (BDA) of type float.
@@ -877,10 +903,12 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public float ReadFloatValue (string objectReference, FunctionalConstraint fc)
{
- IntPtr mmsValue = readObjectInternal (objectReference, fc);
+ IntPtr mmsValue = readObjectInternalAndCheckDataAccessError (objectReference, fc);
- if (MmsValue_getType (mmsValue) != (int)MmsType.MMS_FLOAT)
- throw new IedConnectionException ("Result is not of type float", 0);
+ if (MmsValue_getType (mmsValue) != (int)MmsType.MMS_FLOAT) {
+ MmsValue_delete (mmsValue);
+ throw new IedConnectionException ("Result is not of type float (MMS_FLOAT)", 0);
+ }
float value = MmsValue_toFloat (mmsValue);
@@ -895,7 +923,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public string ReadStringValue (string objectReference, FunctionalConstraint fc)
{
- IntPtr mmsValue = readObjectInternal (objectReference, fc);
+ IntPtr mmsValue = readObjectInternalAndCheckDataAccessError (objectReference, fc);
if (!((MmsValue_getType (mmsValue) == (int)MmsType.MMS_VISIBLE_STRING) || (MmsValue_getType (mmsValue) == (int)MmsType.MMS_STRING))) {
MmsValue_delete (mmsValue);
@@ -917,7 +945,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public Quality ReadQualityValue (string objectReference, FunctionalConstraint fc)
{
- IntPtr mmsValue = readObjectInternal (objectReference, fc);
+ IntPtr mmsValue = readObjectInternalAndCheckDataAccessError (objectReference, fc);
if (MmsValue_getType (mmsValue) == (int)MmsType.MMS_BIT_STRING) {
int bitStringValue = (int)MmsValue_getBitStringAsInteger (mmsValue);
@@ -936,7 +964,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public int ReadBitStringValue (string objectReference, FunctionalConstraint fc)
{
- IntPtr mmsValue = readObjectInternal (objectReference, fc);
+ IntPtr mmsValue = readObjectInternalAndCheckDataAccessError (objectReference, fc);
if (MmsValue_getType (mmsValue) == (int)MmsType.MMS_BIT_STRING) {
int bitStringValue = (int)MmsValue_getBitStringAsInteger (mmsValue);
@@ -955,11 +983,11 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public UInt64 ReadTimestampValue (string objectReference, FunctionalConstraint fc)
{
- var mmsValuePtr = readObjectInternal (objectReference, fc);
+ var mmsValuePtr = readObjectInternalAndCheckDataAccessError (objectReference, fc);
var mmsValue = new MmsValue (mmsValuePtr, true);
- if (mmsValue.GetType () == MmsType.MMS_UTC_TIME)
+ if (mmsValue.GetType () == MmsType.MMS_UTC_TIME)
return mmsValue.GetUtcTimeInMs ();
else
throw new IedConnectionException ("Result is not of type timestamp (MMS_UTC_TIME)", 0);
@@ -973,7 +1001,7 @@ namespace IEC61850
/// This exception is thrown if there is a connection or service error
public Int64 ReadIntegerValue (string objectReference, FunctionalConstraint fc)
{
- var mmsValuePtr = readObjectInternal (objectReference, fc);
+ var mmsValuePtr = readObjectInternalAndCheckDataAccessError (objectReference, fc);
var mmsValue = new MmsValue (mmsValuePtr, true);
diff --git a/dotnet/IEC61850forCSharp/MmsValue.cs b/dotnet/IEC61850forCSharp/MmsValue.cs
index 12b6b6d4..08298c22 100644
--- a/dotnet/IEC61850forCSharp/MmsValue.cs
+++ b/dotnet/IEC61850forCSharp/MmsValue.cs
@@ -174,8 +174,7 @@ namespace IEC61850
valueReference = value;
this.responsableForDeletion = false;
}
-
- // TODO make internal
+
internal MmsValue (IntPtr value, bool responsableForDeletion)
{
valueReference = value;
diff --git a/dotnet/tests/Test.cs b/dotnet/tests/Test.cs
index 8925422c..1ff1cce3 100644
--- a/dotnet/tests/Test.cs
+++ b/dotnet/tests/Test.cs
@@ -165,6 +165,30 @@ namespace tests
iedServer.Destroy ();
}
+ [Test ()]
+ public void ReadNonExistingObject()
+ {
+ IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile ("../../model.cfg");
+
+ IedServer iedServer = new IedServer (iedModel);
+
+ iedServer.Start (10002);
+
+ IedConnection connection = new IedConnection ();
+
+ connection.Connect ("localhost", 10002);
+
+ MmsValue value = connection.ReadValue ("simpleIOGenericIO/GGIO1.SPCSO1.stVal", FunctionalConstraint.MX);
+
+ Assert.IsNotNull (value);
+
+ Assert.AreEqual (MmsType.MMS_DATA_ACCESS_ERROR, value.GetType ());
+
+ iedServer.Stop ();
+
+ iedServer.Destroy ();
+ }
+
[Test ()]
public void AccessDataModelServerSide()
{