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.

Mapping collection

  • miron
  • Topic Author
  • Visitor
  • Visitor
19 Feb 2015 13:42 #2814 by miron
Replied by miron on topic Mapping collection
Ok. I understand.
Thank you.

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

More
18 Feb 2015 08:37 #2803 by support
Replied by support on topic Mapping collection
I admit that I have these questions basically to verify that the requirements are as I thought. The answer, unfortunately, is negative - we currently do not have a support for this in Live Mapping. It is something that we have on the list of possible future enhancements already.

You can probably achieve the goal by mapping the known objects first, and then invoke the mapping repeatedly for the objects that should reside in the collection and put them into the collection yourself, similarly as you have don in the example you have provided in the beginning.

Best regards
The following user(s) said Thank You: miron

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
17 Feb 2015 09:01 #2796 by miron
Replied by miron on topic Mapping collection
1. Yes, its is normal C# collection. Thant means this object implements System.Collections.IEnumerable.
2. It could be e.g.: List<T>, Array<T>[]
3. Yes, number of instances is not know during compilation time
4. There is some key of naming branches for items .e.g.: dev1, dev2, ....

Bigger example:
 
[DAType]
public class DeviceA
{
 
   [DASubPath]
   public string DeviceIdCode {get;set;}
 
   [DANode()] 
   [DAItem()]
   public int SomeStatus {get;set;}
}
 
[DAType]
public class DeviceB
{
   [DASubPath]
   public string DeviceIdCode {get;set;}
 
   [DANode()] 
   [DAItem()]
   public int SomeStatus {get;set;}
}
 
[DAType]
public class ProductionLine
{
       [DANode()] 
       [DAItem()]
	public int OtherSomeStatuses {get;set;}
 
	[DANode()] //<--- ??????
	public List<DeviceA> DevicesA {get;set;}
 
	[DANode()] //<--- ??????
	public List<DeviceB> DevicesB {get;set;}
}


And question is:
How I could mapp this type.
//1. Loading devices from configuration
 
  ProductionLine pl = LoadFromConfiguration();
 
 
//now "pl" contains e.g. 10 devices A and 15 devices B.
 
 
//2. Now I would like mapp this object (with out loop)
 
  var mapper = new DAClientMapper();   
 
  mapper.Map(pl, new DAMappingContext                                            
   {                                                                               
     ServerDescriptor = sd,   // local OPC server                                                      
			NodeDescriptor = new DANodeDescriptor 
                       { BrowsePath = "/TestChannel/MainGroup/ProductionLine/"}, 
			GroupParameters = 1000,  
		});               				
     }


Goal would be that I could send "pl" (ProductionLine) to mapper,
and mapper could work with object in collection, and make mapping by some key.
It could use e.g. some property which contain "sub path" for each property.

I have added [DASubPath] attribute.

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

More
16 Feb 2015 20:21 #2792 by support
Replied by support on topic Mapping collection
Can you please explain what you mean by collection? Is it a case similar to (or identical with) the example in this thread, where you have e.g. multiple numbered devices, each with its own branch in the OPC address space, and you do not want to map them to explicitly coded individual members, but instead you want to take advantage of the fact that they are somehow numbered, and then map them to a .NET "collection" (such as array, list, or a true collection)? The use case being that the number of such branches is either not known at compile time, or is quite high?

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
15 Feb 2015 20:45 - 15 Feb 2015 21:36 #2772 by miron
Replied by miron on topic Mapping collection
That means we could concentrate on question:
What is good practice of mapping C# collection?
Maybe I could use attribute DANode or DAItemIdTemplate to mark collection?
That means the main question is: how to pass information to mapper about how to map item of collection?.

(I have made investigation and it works when I add object to mapping to one instance of mapper or to separate).
Last edit: 15 Feb 2015 21:36 by miron.

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
15 Feb 2015 20:40 - 15 Feb 2015 22:26 #2771 by miron
Replied by miron on topic Mapping collection
Thank you for your quick answer.

I have made mistake with addressing simulation tag.
Variables are type of 'long' but address which I put overlapped addresses.
And one write was interfered to another. I am sorry.


Linq Pad is very useful to quick scrat code. File Linq beside C# code, also contains
reference to assembly and declaration of namespaces.
To execute code it is not necessary build code.
Last edit: 15 Feb 2015 22:26 by miron.

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

More
15 Feb 2015 19:34 #2770 by support
Replied by support on topic Mapping collection
By quickly glancing over your code, I do not see anything wrong with it. In fact, the approach taken is quite good. One reservation I have is that I am not sure if you actually intended that ALL mapped properties should be written back. If not, there are ways to influence it.

To Question 2: If you meant to use separate mapper instances, then the answer is negative: It should not be necessary.

I will run your code when I get back to the office (tomorrow, likely), and let you know my findings then.

One last thing: Please switch to latest version (5.32).

Best regards

BTW, just in case we need it in future, I have enabled the .CSV a .LINQ file extensions on the forums now.

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
15 Feb 2015 16:46 - 15 Feb 2015 17:01 #2769 by miron
Mapping collection was created by miron
Hi,
Question 1. I have question about best practice in mapping collection by live mapping.
I have made simple example in linq pad.

Generally: I have one class Line which could contain several object of type Device.
public class Line
{
    public List<Device> Devices {get;set;}
}


In my example I have created mapping for each object of Device. Maybe there is another good way to do this.


I also could observed strange behavior. It looked that some values was not initialized correct value after
execution procedure.See screens.

When I crate simple loop in the end of program I have seen some randomize values.

for(int x = 0; i < 20; i++)
{
mapper.Write();
Thread.Sleep(2000);

}

Question 2:
Maybe several object of the same type should be mapped by separate instance?


C# example which could be run in LiqPad:
=================================================
[DAType]
public class Device
{
 
   public string DeviceCode {get;set;}
 
   [DANode()] 
   [DAItem()]
   public bool  IsRunning {get;set;}   
 
   [DANode()] 
   [DAItem()]
   public int Speed {get;set;}
 
 
   [DANode()] 
   [DAItem()]
   public int Position {get;set;}
}
 
 
 
public class LineDef
{
   public LineDef()
	{
	  Devices = new List<Device>();
	}
   public List<Device> Devices {get;set;}
}
 
 
void Main()
{
 
    var sd = "Kepware.KEPServerEX.V5";
    //initialization object
	var line = new LineDef();
    line.Devices.Add(new Device() { DeviceCode="dev1"});
	line.Devices.Add(new Device() { DeviceCode="dev2"});
	line.Devices.Add(new Device() { DeviceCode="dev3"});
	line.Devices.Add(new Device() { DeviceCode="dev4"});
	line.Devices.Add(new Device() { DeviceCode="dev5"});
 
     //preparing mapping
     var mapper = new DAClientMapper();   
 
	 foreach(var dev in line.Devices)
	 {
		mapper.Map(dev, new DAMappingContext                                            
		{                                                                               
			ServerDescriptor = sd,   // local OPC server                                                      
			NodeDescriptor = new DANodeDescriptor { BrowsePath = "/TestChannel/MainGroup/Line1/" + dev.DeviceCode}, 
			GroupParameters = 1000,  
		});                                                                             
	 }
 
	mapper.Read();
 
	var i = 1;
	foreach(var dev in line.Devices)
	{
	   dev.IsRunning = true;
	   dev.Position = 10 * i;
	   dev.Speed = 30;
	   i++;
	}
 
	mapper.Write();
}


I have attached:
  1. C# example - which could be run directly in linq pad (www.linqpad.net/) (changed extension to txt)
  2. Picutre with not correct values from opc client
  3. csv definition exported from OPCKeepServer (changed extension to txt)
Attachments:
Last edit: 15 Feb 2015 17:01 by miron.

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

Moderators: support
Time to create page: 0.098 seconds