Professional OPC
Development Tools

logos

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.

Read an Array of structure

More
04 Jun 2024 19:44 #12845 by Twoaster
Replied by Twoaster on topic Read an Array of structure
Got it working!

Thank you for the great support!
The following user(s) said Thank You: support

Please Log in or Create an account to join the conversation.

More
04 Jun 2024 15:11 - 04 Jun 2024 15:12 #12843 by support
Replied by support on topic Read an Array of structure
Hello.

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
Last edit: 04 Jun 2024 15:12 by support.

Please Log in or Create an account to join the conversation.

More
04 Jun 2024 13:40 #12841 by Twoaster
Replied by Twoaster on topic Read an Array of structure
Hi!
It's an OPC variable.
Here's the screenshot.
Attachments:

Please Log in or Create an account to join the conversation.

More
04 Jun 2024 11:00 #12840 by support
Replied by support on topic Read an Array of structure
Hello,

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.

More
03 Jun 2024 18:37 #12839 by Twoaster
Replied by Twoaster on topic Read an Array of structure
That worked perfectly! thanks for the help.
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.

More
01 Jun 2024 08:29 #12835 by support
Replied by support on topic Read an Array of structure
Hello, this is a success. In terms of OPC UA Read, you *do* have a value already. Now you need to "unpack" it, because it is a custom data defined by the server. And yes, reversing my previous statement, now it is clear that you will need the Complex Data approach as well. Live Mapping, however, cannot be currently used to provide mapping of the custom structures to C# structures. The documentation part explaining the Complex Data is here: opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Late...omplex%20Data%20Extension.html .

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.

More
31 May 2024 16:36 #12834 by Twoaster
Replied by Twoaster on topic Read an Array of structure
Ok, good news, we are moving forward! But I still can't read the value.

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.

More
31 May 2024 15:58 #12833 by support
Replied by support on topic Read an Array of sctructure
Hello,
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.

More
31 May 2024 15:43 #12832 by Twoaster
Hi! Thanks for the reply.

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.

More
31 May 2024 14:29 #12831 by support
Replied by support on topic Read an Array of sctructure
Thanks. We are getting somewhere.

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.

Moderators: support
Time to create page: 0.064 seconds