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.

How to make operation for only one property in live mapping

More
20 Feb 2015 07:25 - 20 Feb 2015 07:25 #2824 by support
That is a very reasonable suggestion, thank you. Yes, will consider it for some future version.

There is one underlying method that in the end does all live mapping "writes", on DAClientMapper:
public void Write([NotNull] IEnumerable<IDAClientMapping> mappings)
Many other methods just take the DAClientMapper.Mappings collection, filter it using various criteria, and then pass the result to this function. Until the suggested extension is implemented, you can do the same on your side. A following method might be helpful. It already exists in our code, but for efficiency, ideally it should be also extended to directly support the list of objects. With less efficiency, it can also be called in a loop, for each tested target object. I am posting the source code (slightly redacted), as you may find it helpful to understand how the filtering is done:
/// <summary>
/// Determines whether a given target object belongs to this mapping.
/// </summary>
/// <param name="abstractMapping">The mapping.</param>
/// <param name="targetObject">The target object to be tested.</param>
/// <param name="recurse"><c>false</c> if the target object must belong directly to this mapping; <c>true</c>
/// if the target object can also belong to the parent, recursively.</param>
/// <returns><c>true</c> if the target object belongs to this mapping; <c>false</c> otherwise.</returns>
static public bool BelongsTo([NotNull] this AbstractMapping abstractMapping, [NotNull] object targetObject,
        bool recurse)
{
    if (targetObject == abstractMapping.GetTargetObject())
        return true;
    if (!recurse)
        return false;
    AbstractMapping parent = abstractMapping.Parent;
    if (parent == null)
        return false;
    return parent.BelongsTo(targetObject, true);
}

Best regards
Last edit: 20 Feb 2015 07:25 by support.

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
19 Feb 2015 13:44 #2816 by miron
Thank you.
Could you consider to add method WriteTarget with array of objects?

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

More
16 Feb 2015 20:13 #2790 by admin
Well, first of all, not everything comes out as elegant code with Live Mapping. Sometimes the other (procedural) model is better, and sometimes it makes sense to combine them.

I understand the issues with Tags, but that's what they are... Some if it can be overcome by using named string constants both where the tags are placed, AND where they are referred to. It is not quite clear to me why you say that the tags would have to be unique for each instance.

I am (pleasantly) surprised by the fact that [DAType] works with generics. It is an innovative solution. I do not think there is a problem with it performance-wise. I understand the suggestion about WriteTarget and an array, but currently it's not there (because the mechanism envisioned was to use the tags). For advanced usages, we have (on DAClientMapper)
public void Write([NotNull] IEnumerable<IDAClientMapping> mappings)
which is actually the underlying method for all live mapping Writes, but then you would need to assemble the list of IDAClientMapping - probably doable; if you come to conclusion that you want to go this way, let me know and we can have a look at details of it.

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
16 Feb 2015 15:07 #2782 by miron
I have made work around by creating "value box" for primitive types:
[DAType]
public class ValBox<T>
{
   [DANode(BrowsePath="")] 
   [DAItem()]
   public T Value {get;set;}
 
   [DANode(BrowsePath = "")]
   [DAItem(Kind = DAItemMappingKind.Result)]
   public OperationResult Result {get;set;}       
 
}

This definition I could use to define my type:
[DAType]
public class Device
{
 
  	public Device()
	{
	   IsRunning = new ValBox<bool>();	   
	   Position = new ValBox<int>();
	   Speed = new ValBox<int>();
	}
 
   public string DeviceCode {get;set;}
 
   [DANode()]    
   public ValBox<bool>  IsRunning {get;set;}   
 
   [DANode()]   
   public ValBox<int> Speed {get;set;}
 
   [DANode()] 
   public ValBox<int> Position {get;set;}
 
}

And next I could use it:
 
  Device d = ....
 
  mapper.WriteTarget(d,true); // <- operation for while Device
  mapper.WriteTarget(d.Speed,true); // <- operation for given property

Remarks:
  • It is working. But I don't know that is correct way (Performance). I would like ask about comment.
  • If yes, would be useful to extend WriteTarget to pass array of object.

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

  • miron
  • Topic Author
  • Visitor
  • Visitor
16 Feb 2015 15:02 - 16 Feb 2015 15:18 #2781 by miron
Let's consider situation:

I have definition of Device:
[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;}
}

I have 10 instances of this class which I mapped.

And in my case I would like to read / write data for devices. (mapper.Write(), mapper.Read());
And sometime use one given property to make some operation.
I would like to use something like:
Device d = .....
mapper.WriteTarget(d.IsRunning ,false);

for one given value.

I know that is not possible because IsRunning is just int.


I could use MappingTag attribute to mark values for selected operation.
But in my case I had to mark each property by unique value.
Also each tag had to be unique for 10 instances.
And in code I had to use string (for selecting operation) instand of strong typing.

Is there any better solution?
Last edit: 16 Feb 2015 15:18 by miron.

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

Moderators: support
Time to create page: 0.083 seconds