- Posts: 16
- Thank you received: 2
Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Reading, Writing, Subscriptions, Property Access
- Read an Array of structure
Read an Array of structure
Thank you for the great support!
Please Log in or Create an account to join the conversation.
Without further work, the Live Mapping works in such a way that the name of the mapped member (your property) is assumed to be the browse name of the node. In this case, since your property name is "diHMIDrawerVelocity", you are trying to map to a node with that browse name. But the actual browse name of that node, as can be seen on the screenshot, is "Application.PersistentVars.diHMIDrawerVelocity".
To resolve this, try to annotate the property with an additional
[UANode(BrowsePath = "/Application&.PersistentVars&.diHMIDrawerVelocity")]
Best regards
Please Log in or Create an account to join the conversation.
It's an OPC variable.
Here's the screenshot.
Please Log in or Create an account to join the conversation.
is "diHMIDrawerVelocity" an OPC UA Variable - isn't it an OPC UA Object? (an Object does not have a Value).
Can you send a screenshot of browsing for it using QuickOPC, or UAExpert?
Thank you
Please Log in or Create an account to join the conversation.
I was able to map the structure to a class using the UAGenericObject as suggested.
Another issue I ran into, is with a normal mapping of variables under the "PersistentVars" path (not the array and structure). I have around 20 variables that I want to map into a class called settings.
For example, to map:
Application.PersistentVars.diHMIDrawerHomeVelocity, I'm using:
mapper.Map(settings, new UAMappingContext
{
EndpointDescriptor = endpointDescriptor,
NodeDescriptor = new UANodeDescriptor
{
BrowsePath = UABrowsePath.Parse("[ObjectsFolder]/Application", "urn:Schneider:M262:customprovider")
}
}); ;
and
[UANamespace("urn:Schneider:M262:customprovider")]
[UAType]
class vlmSettings
{
[UANode(BrowsePath = "/PersistentVars")]
public Settings _settings = new();
}
[UANamespace("urn:Schneider:M262:customprovider")]
[UAType]
class Settings
{
[UAData(Operations = UADataMappingOperations.Read, Kind = UADataMappingKind.Result)]
public OperationResult? diHMIDrawerVelocity { get; set; }
}
But when I run, i get the following:
Drawer Velocity: Success; @MinValue @@2024-06-03T13:31:32.539; BadAttributeIdInvalid
Drawer Velocity: Success; @MinValue @@2024-06-03T13:31:35.840; BadAttributeIdInvalid
Can you please help on what I'm missing here?
Thanks!
Please Log in or Create an account to join the conversation.
To get you started, I suggest you check out and understand this:
- In the Master property (which is of type OperationResult), there is a .Value property, and when the Read succeeds, it will contain a non-null UAGenericObject (as you can already see in the output you provided)..
- Inside the UAGenericObject there a .GenericData object, which can contain different types, but in your case it will probably of type StructuredData, and it contains fields that you can access by their name and extract individually.
- If you break into the debugger and display, or write out from the program itself, the value of ((UAGenericObject)Master.Value).GenericData.DebugView, you will get a nicely formatted outline of the data received. Post it here if further help is needed.
Best regards
Please Log in or Create an account to join the conversation.
I changed it as you said and now I don't have any exception (Good!) but I still can't see the values inside the Master/Slave variables.
I changed my code to:
[UAData(Operations = UADataMappingOperations.Read, Kind = UADataMappingKind.Result)]
public OperationResult? Master { get; set; }
and got the following message: Rail[1] Master: Success; (nsu=urn:Schneider:M262:customprovider ;ns=2;Position) structured {UAGenericObject} @2024-05-31T11:16:20.667 @@2024-05-31T11:16:20.667; Good
Rail[1] Slave: 0
With this I assume that the software is returning me the variable on my array position [1], which is a structure right now (Position)
MY PLC CODE:
astRearPositions : ARRAY [0..300] OF Position;
TYPE Position :
STRUCT
Master : DINT := 0;
Slave : DINT := 0;
InUse : BOOL := FALSE;
InUseType : PositionType := PositionType.None;
END_STRUCT
END_TYPE
Please Log in or Create an account to join the conversation.
please make following changes:
1) shorten the root browse path:
BrowsePath = UABrowsePath.Parse("[ObjectsFolder]/Application/PersistentVars/Application&.PersistentVars&.astFrontRailPositions", "urn:Schneider:M262:customprovider")
2) remove the ampersand at the end (you did that already before I suppose):
[UANamespace("urn:Schneider:M262:customprovider")]
[UAType]
class PersistentVars
{
[UANode(BrowsePath = ".Application&.PersistentVars&.astFrontRailPositions[1]")]
public Rail _rail = new();
}
3) Add UANamespace attribute also to the Rail class:
[UANamespace("urn:Schneider:M262:customprovider")]
[UAType]
class Rail
{
Hopefully that will work, but if not, I am confident it is a step in the right direction, and we will go from there.
Best regards
Please Log in or Create an account to join the conversation.
Here is the first bit of the code:
public bool Execute(string machineIp)
{
EasyUAClient easyUAClient = new EasyUAClient();
UAEndpointDescriptor endpointDescriptor = $"opc.tcp://{machineIp}:4840";
var mapper = new UAClientMapper();
var railData = new PersistentVars(); //rail for testing
mapper.Map(railData, new UAMappingContext
{
EndpointDescriptor = endpointDescriptor,
NodeDescriptor = new UANodeDescriptor
{
BrowsePath = UABrowsePath.Parse("[ObjectsFolder]/Application/PersistentVars/Application&.PersistentVars&.astFrontRailPositions.Application&.PersistentVars&.astFrontRailPositions[1]", "urn:Schneider:M262:customprovider")
}
});;
try {
mapper.Read();
}
catch (MappingException ex)
{
Console.WriteLine(ex.Message);
};
Console.WriteLine($"Rail[1] Master: {railData._rail.Master}");
Console.WriteLine($"Rail[1] Slave: {railData._rail.Slave}");
Console.ReadLine();
return true;
}
and here is the second class:
[UANamespace("urn:Schneider:M262:customprovider")]
[UAType]
class PersistentVars
{
[UANode(BrowsePath = ".Application&.PersistentVars&.astFrontRailPositions[1]&")]
public Rail _rail = new();
}
[UAType]
class Rail
{
[UAData(Operations = UADataMappingOperations.Read)]
public Boolean InUse { get; set; }
[UAData(Operations = UADataMappingOperations.Read)]
public Int16 InUseType { get; set; }
[UAData(Operations = UADataMappingOperations.Read, Kind = UADataMappingKind.Exception)]
public Exception? Master { get; set; }
[UAData(Operations = UADataMappingOperations.Read)]
public Int32 Slave { get; set; }
}
Please Log in or Create an account to join the conversation.
What you have is not correct, and I will try to figure out how you should do it. For complete picture, however, I first need the missing piece(s) of the code first. Specifically, at this point, please post here how the 'railData' variable (in your mapper.Map(....)) is declared and instantiated.
Best regards
Please Log in or Create an account to join the conversation.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Reading, Writing, Subscriptions, Property Access
- Read an Array of structure