07/19/2017
Hi,
I'm trying to exchange data with an injection molding machine which has got an OPC UA server built in.
I can read and write all scalar values and I can call methods too but I'm not able to write a particular node which represents a list of orders.
The node structure stated in the machine manual is the following:
UaExpert Client show a Variant Array[-1] type while dataFEED Client show a Variant type with <null/> value:
I have tried to write a variant array from UaExpert Client but I receive BadTypeMismatch error:
I have tried to implement the following code in a C# project but I always obtain the same error:
Opc.Ua.Variant[] dataValue = {
new Opc.Ua.Variant((UInt16)1),
new Opc.Ua.Variant((UInt32)2),
new Opc.Ua.Variant((string)"3"),
new Opc.Ua.Variant((string)"4"),
new Opc.Ua.Variant((string)"5"),
new Opc.Ua.Variant((string)"6"),
new Opc.Ua.Variant((string)"7"),
new Opc.Ua.Variant((string)"8"),
new Opc.Ua.Variant((string)"9") };
DataValue dataValue1 = new DataValue() { Value = dataValue };
WriteValue valueToWrite = new WriteValue();
valueToWrite.Value = dataValue1;
valueToWrite.NodeId = nodeId;
valueToWrite.AttributeId = Attributes.Value;
WriteValueCollection valuesToWrite = new WriteValueCollection();
valuesToWrite.Add(valueToWrite);
mSession.Write(null, valuesToWrite, out result, out diagnostics);
The same code works fine with another demo OPC UA Server which contains a real Variant Array node.
I have made other attemps with object array (mono and bidimensionals) and extension objects with no luck.
I assume I cannot understand what the real data type of the node (perhaps...because value is null?).
How can I retrieve the real data type to use? Could you help me please?
Thanks in advance for your reply.
05/30/2017
You need to read the DataType and ValueRank of the Node and provide an instance that matches that exactly.
If the DataType is Structure (which is abstract) then it should accept any Structure.
You initialize a Variant with a Structure by wrapping it in a ExtensionObject.
e.g. new Variant(new ExtensionObject(new Range() { High = 100, Low = 1 }));
07/19/2017
The DataType and ValueRank are visible in the UAExpert screenshot but I can retrieve the same values with the following code:
ReadValueIdCollection itemsToRead = new ReadValueIdCollection();
ReadValueId itemToRead1 = new ReadValueId();
itemToRead1.NodeId = "ns=2;i=115682";
itemToRead1.AttributeId = Attributes.DataType;
itemsToRead.Add(itemToRead1);
ReadValueId itemToRead2 = new ReadValueId();
itemToRead2.NodeId = "ns=2;i=115682";
itemToRead2.AttributeId = Attributes.ValueRank;
itemsToRead.Add(itemToRead2);
DataValueCollection values = null;
DiagnosticInfoCollection diagnosticInfos = null;
ResponseHeader responseHeader = m_Server.Session.Read(null,0,TimestampsToReturn.Both,itemsToRead,out values,out diagnosticInfos);
Results:
values[0]: i=24
values[1]: -1
i=24 is BaseDataType (namespace 0)
So it seem to be a scalar value I suppose...but I would expect an array or structure as shown in the manual.
Thanks.
05/30/2017
The DataType and ValueRank are visible in the UAExpert screenshot but I can retrieve the same values with the following code:
I am not taking about the type associated with a variant value. I am talking about the value for the DataType and ValueRank attributes.
The value of these attributes tell you what you have to write.
07/19/2017
I'm sorry but it's not clear to me...
With the code in my previous reply I read the value for the DataType and ValueRank attributes of the Node "ns=2;i=115682". Correct?
I notice the node has the reference HasTypeDefinition: ArbVTypeOrderList
If I read the value for the DataType and ValueRank attributes of this Node ("ns=2;i=906090") I obtain the same values i=24 and -1.
What am I doing wrong?
Thanks.
05/30/2017
Ok - so the a ValueRank = -1 is Scalar which means you cannot write an Array to the value. You can only write a scalar value.
DataType = BaseDataType means you can write any value as long as it is scalar.
I can see why it is confusing because the server appears to set the default value to an array which violates the contract specified by the DataType/ValueRank. If the Server wanted to allow arrays the ValueRank should be -2.
07/19/2017
Therefore the ValueRank seems to be wrong. If the server set the default value to an array should be ok, according to the structure in the manual.
I think I cannot change ValueRank from client. It is a readonly attribute and I do not have access to the server.
If the server expects a scalar value I should be able to write an integer number for example but I tried all available scalar data types and I always receive BadTypeMismatch error.
What else could I try?
I just don't known what to do...
05/30/2017
You need to contact the Server vendor and explain the bug.
Have you tried an array of int[] instead of an Array of Variants?
int[] dataValue = { 1, 2, 3 };
You can try using an IndexRange to write a single element but I doubt that will work since you are still passing a 1 element array.
07/19/2017
I've tried with int[] array but it doesn't work.
I've tried with IndexRange as you suggested using this code:
Array dataValue6 = Array.CreateInstance(typeof(Opc.Ua.Variant), 9);
dataValue6.SetValue(new Variant((UInt16)1), 0);
dataValue6.SetValue(new Variant((UInt32)2), 1);
dataValue6.SetValue(new Variant((string)"3"), 2);
dataValue6.SetValue(new Variant((string)"4"), 3);
dataValue6.SetValue(new Variant((string)"5"), 4);
dataValue6.SetValue(new Variant((string)"6"), 5);
dataValue6.SetValue(new Variant((string)"7"), 6);
dataValue6.SetValue(new Variant((string)"8"), 7);
dataValue6.SetValue(new Variant((string)"9"), 8);
DataValue dataValue1 = new DataValue() { Value = dataValue6 };
WriteValue valueToWrite = new WriteValue();
valueToWrite.Value = dataValue1;
valueToWrite.NodeId = nodeId;
valueToWrite.AttributeId = Attributes.Value;
valueToWrite.IndexRange = "0:8";
NumericRange indexRange;
ServiceResult result1 = NumericRange.Validate(valueToWrite.IndexRange, out indexRange);
object valueToWrite1 = valueToWrite.Value.Value;
result1 = indexRange.ApplyRange(ref valueToWrite1);
if (ServiceResult.IsGood(result1))
{
valueToWrite.Value.Value = valueToWrite1;
}
valuesToWrite.Add(valueToWrite);
mSession.Write(null, valuesToWrite, out result, out diagnostics);
"indexRange.ApplyRange" is ok but "mSession.Write" returns BadIndexRangeNoData
07/19/2017
The only way it returns no error is with byte arrays (minimum two dimensions, one dimension gives error) but the target node remains empty.
For example:
Byte[,] byteArr = { { 1 }, { 2 }, { 3 } };
DataValue dataValue1 = new DataValue() { Value = byteArr };
WriteValue valueToWrite = new WriteValue();
valueToWrite.Value = dataValue1;
valueToWrite.NodeId = nodeId;
valueToWrite.AttributeId = Attributes.Value;
valuesToWrite.Add(valueToWrite);
mSession.Write(null, valuesToWrite, out result, out diagnostics);
1 Guest(s)