private bool Write(WriteValueCollection nodesToWrite)
{
bool success = true;
StatusCodeCollection results = null;
DiagnosticInfoCollection diagnosticInfos = null;
RequestHeader requestHeader = new RequestHeader();
requestHeader.ReturnDiagnostics = 0;
try
{
Session.Write(
requestHeader,
nodesToWrite,
out results,
out diagnosticInfos);
}
catch (System.ServiceModel.CommunicationException e)
{
Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
catch (System.Xml.XmlException e)
{
Log("WARNING: XML parsing error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
catch (ServiceResultException e)
{
if (e.StatusCode == StatusCodes.BadEncodingLimitsExceeded)
{
Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
throw new ServiceResultException(new ServiceResult(e));
}
ClientBase.ValidateResponse(results, nodesToWrite);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToWrite);
// check diagnostics.
if (diagnosticInfos != null && diagnosticInfos.Count > 0)
{
Log("Returned non-empty DiagnosticInfos array during Write.");
return false;
}
// check results.
ReadValueIdCollection nodesToRead = new ReadValueIdCollection();
for (int ii = 0; ii < nodesToWrite.Count; ii++)
{
WriteValue request = nodesToWrite[ii];
TestVariable variable = (TestVariable)request.Handle;
if (results[ii] == StatusCodes.BadUserAccessDenied)
{
continue;
}
if (results[ii] == StatusCodes.BadNotWritable)
{
Log(
"Write failed when writing a writeable value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
request.Value.WrappedValue,
results[ii]);
success = false;
break;
}
if (StatusCode.IsBad(results[ii]))
{
if (request.Value.StatusCode != StatusCodes.Good)
{
if (results[ii] != StatusCodes.BadWriteNotSupported)
{
Log(
"Unexpected error when writing the StatusCode for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
request.Value.WrappedValue,
results[ii]);
success = false;
break;
}
continue;
}
if (request.Value.SourceTimestamp != DateTime.MinValue || request.Value.ServerTimestamp != DateTime.MinValue)
{
if (results[ii] != StatusCodes.BadWriteNotSupported)
{
Log(
"Unexpected error when writing the Timestamp for a Value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
request.Value.WrappedValue,
results[ii]);
success = false;
break;
}
continue;
}
if (results[ii] != StatusCodes.BadTypeMismatch && results[ii] != StatusCodes.BadOutOfRange)
{
Log(
"Unexpected error when writing a valid value '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
request.Value.WrappedValue,
results[ii]);
success = false;
break;
}
continue;
}
ReadValueId nodeToRead = new ReadValueId();
nodeToRead.NodeId = request.NodeId;
nodeToRead.AttributeId = request.AttributeId;
nodeToRead.IndexRange = request.IndexRange;
nodeToRead.Handle = request.Handle;
nodesToRead.Add(nodeToRead);
}
// skip read back on failed.
if (!success)
{
return success;
}
// check if nothing more do to.
if (nodesToRead.Count == 0)
{
return true;
}
requestHeader = new RequestHeader();
requestHeader.ReturnDiagnostics = 0;
DataValueCollection values = new DataValueCollection();
try
{
Session.Read(
requestHeader,
0,
TimestampsToReturn.Both,
nodesToRead,
out values,
out diagnosticInfos);
}
catch (System.ServiceModel.CommunicationException e)
{
Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
catch (System.Xml.XmlException e)
{
Log("WARNING: XML parsing error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
catch (ServiceResultException e)
{
if (e.StatusCode == StatusCodes.BadEncodingLimitsExceeded)
{
Log("WARNING: Communication error (random data may have resulted in a message that is too large). {0}", e.Message);
return true;
}
throw new ServiceResultException(new ServiceResult(e));
}
ClientBase.ValidateResponse(values, nodesToRead);
ClientBase.ValidateDiagnosticInfos(diagnosticInfos, nodesToRead);
// check diagnostics.
if (diagnosticInfos != null && diagnosticInfos.Count > 0)
{
Log("Returned non-empty DiagnosticInfos array during Read.");
return false;
}
for (int ii = 0; ii < nodesToRead.Count; ii++)
{
ReadValueId request = nodesToRead[ii];
TestVariable variable = (TestVariable)request.Handle;
DataValue valueWritten = variable.Values[variable.Values.Count-1];
if (StatusCode.IsBad(values[ii].StatusCode) && StatusCode.IsNotBad(valueWritten.StatusCode))
{
Log(
"Could not read back the value written '{0}'. NodeId = {1}, Value = {2}, StatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
valueWritten.WrappedValue,
values[ii].StatusCode);
success = false;
break;
}
Opc.Ua.Test.DataComparer comparer = new Opc.Ua.Test.DataComparer(Session.MessageContext);
comparer.ThrowOnError = false;
if (!comparer.CompareVariant(values[ii].WrappedValue, valueWritten.WrappedValue))
{
Log(
"Read back value does not match the value written '{0}'. NodeId = {1}, Value = {2}, ReadValue = {3}",
variable.Variable,
variable.Variable.NodeId,
valueWritten.WrappedValue,
values[ii].WrappedValue);
success = false;
break;
}
if (valueWritten.StatusCode != StatusCodes.Good)
{
if (values[ii].StatusCode != valueWritten.StatusCode)
{
Log(
"Read back StatusCode does not match the StatusCode written '{0}'. NodeId = {1}, StatusCode = {2}, ReadStatusCode = {3}",
variable.Variable,
variable.Variable.NodeId,
valueWritten.StatusCode,
values[ii].StatusCode);
success = false;
break;
}
}
if (valueWritten.SourceTimestamp != DateTime.MinValue)
{
if (values[ii].SourceTimestamp != valueWritten.SourceTimestamp)
{
Log(
"Read back ServerTimestamp does not match the ServerTimestamp written '{0}'. NodeId = {1}, Timestamp = {2}, ReadTimestamp = {3}",
variable.Variable,
variable.Variable.NodeId,
valueWritten.SourceTimestamp,
values[ii].SourceTimestamp);
success = false;
break;
}
}
}
return success;
}