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.

Subscribe multiple items/display values in different object typ

More
28 Aug 2013 09:25 #1417 by support
Dear Sir,

we do not directly generate this error. It comes from the target OPC server, and unfortunately it does not give more details, the numeric code corresponds to "Unspecified error".

Most likely some of the method call arguments are wrong (could it be the Item ID? Or is the server really expecting a Single, and not e.g. an Int32? - just guessing). Can you please double check all of this.

If you do not find anything, we can deploy a tool called OPC Analyzer - it would log the communication between your client app and the OPC Server, and we would be able to tell more then.

Best regards
Zbynek Zahradnik

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

More
28 Aug 2013 07:51 #1416 by Ramirez
Hello,

The callback method works on the Festo OPC server.

Now I'm jist getting some issus when I read or write values to the server. I use the following method to test if a value entered is within tolérances before writting it to the server:

private void tb1_KeyPress(object sender, KeyPressEventArgs e)
{
//Teste si la touche "Enter" est pressée.
if (e.KeyChar == Constantes.enter)
{
if (Convert.ToSingle(tb1.Text) > Convert.ToSingle(easyDAClient1.ReadItemValue("", Constantes.serverName, this.machineName + Constantes.topMinTemp)) &&
Convert.ToSingle(tb1.Text) < Convert.ToSingle(easyDAClient1.ReadItemValue("", Constantes.serverName, this.machineName + Constantes.topMaxTemp)))
{
easyDAClient1.WriteItemValue("", Constantes.serverName, this.machineName + Constantes.setTopTemp, Convert.ToSingle(tb1.Text));
}

else
{
MessageBox.Show("La valeur à rentrer doit être comprise entre "
+ easyDAClient1.ReadItemValue("", Constantes.serverName, this.machineName + Constantes.topMinTemp).ToString()
+ " et " + easyDAClient1.ReadItemValue("", Constantes.serverName, this.machineName + Constantes.topMaxTemp).ToString());
}
}
}



Because the value type of thextBox is a string, I need to converted into a single which is the value type of the item read. The item value is also converted into a single type to be able to compare both values.

The problem is that I am getting an error message:

"The exception OpcException was not managed.
An OPC operation failure with error code -2147467259 (0x80004005) occurred, originating from 'FestoCoDeSys.OPC.02'. The inner exception contains details about the problem."

I don't know what could be the problem.

Thank you

David

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

More
22 Aug 2013 20:14 #1415 by Ramirez
Hello,

I just tested this method on the test server and it works. Tomorrow morning I will test with machines and see how it goes.

Thank you

David

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

More
22 Aug 2013 18:01 #1414 by support
You need to create 3 notification handlers with different names. Do not hook them to the ItemChanged event. Instead, use an additional argument to the SubscribeMultipleItems method; effectively, use this overload:
[NotNull]
        public int[] SubscribeMultipleItems([NotNull] DAItemGroupArguments[] itemGroupArgumentsArray,
            [CanBeNull] EventHandler<EasyDAItemChangedEventArgs> callback)
The second argument should be the name of your method, each time a different one, as needed.
The following user(s) said Thank You: Ramirez

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

More
22 Aug 2013 14:37 #1411 by Ramirez
I think I will have to code 3 callback methods like this:

1.For Text boxes

private void easyDAClient1_ItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
//cast de e.State en TextBox
var itemChanged = (TextBox)e.State;

string text;
if (e.Exception == null)
{
//Affiche la valeur en temps réel
text = e.Vtq.Value;
}
else
text = "*Error*";
itemChanged.Text = text;
}

2.
private void easyDAClient1_ItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
//cast de e.State en Label
var itemChanged = (Label)e.State;

string text;
if (e.Exception == null)
{
//Affiche la valeur en temps réel
text = e.Vtq.Value;
}
else
text = "*Error*";
itemChanged.Text = text;
}
3.
private void easyDAClient1_ItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
string AlarmLED;
string MachineStatus;

if (e.intemDescriptor == "OPCAlarmItem")
{
if (e.vtq.Value == True)
//Turn ON Alarm Graphic LED
else
//Turn OFF Alarm Graphic LED
}

if (e.intemDescriptor == "OPCMachineStatusItem")
{
if (e.vtq.Value == True)
//Turn ON Machine status Graphic LED
else
//Turn OFF Machine status Graphic LED
}

}

It is possible to have 3 callback methos with the same name "private void easyDAClient1_ItemChanged..."?

David Ramirez

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

More
22 Aug 2013 14:23 #1410 by Ramirez
You are right the second question can be solved with your answer to the 1st question. The difference is that I am not going to pass any object to the subscribe method cause I will just recover the value in the code to test it in real time and modify a LED status on the form (ON/OFF)

If I follow your solution 1c), I would do something like:

var argumentArrayTextBox = new DAItemGroupArguments[2];
var argumentArrayLabel = new DAItemGroupArguments[2];
var argumentArrayLED = new DAItemGroupArguments[2];


argumentArrayTextBox [0] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.setTopTemp, 100, tb1);
argumentArrayTextBox [1] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.setBotTemp, 100, tb3);

argumentArrayLabel[0] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.actualTopTemp, 100, lb8); argumentArrayLabel[1] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.actualBotTemp, 100, lb11);

argumentArrayLED[0] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.Alarm, 100, null);
argumentArrayLED[1] = new DAItemGroupArguments("", Constantes.serverName, this.nomMachine + Constantes.machineState, 100, null);


easyDAClient1.SubscribeMultipleItems(argumentArrayTB);
easyDAClient1.SubscribeMultipleItems(argumentArrayLB);
easyDAClient1.SubscribeMultipleItems(argumentArrayLED);

Now I don’k now how can I create 3 different methods «easyDAClient1_ItemChanged» to treat each different type of control.

Thanks

David Ramirez

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

More
22 Aug 2013 13:53 #1409 by support
Ad 1) There are several ways of doing this, for example:

1a) You may test the type of State object in the notification, by statement such as "if (e.State is TextBox)" or "if (e.State is Label)", and then proceed to corresponding part of the notification handler.

1b) You may use two EasyDAClient objects, one for each type of control/notification handler code. Then, you will subscribe TextBox-es to the first object, Label-s to the second objects, and so on. And you will have a notification handler on the first EasyDAClient that will know how to update TextBox controls, and a notification handler on the second EasyDAClient that will know how to update Label controls, and so on.

1c) You can keep using single EasyDAClient object, but instead of events, you may use callback procedures with SubscribeMultipleItems. You can call SubscribeMultipleItems several items, each time for different kind of control, and each time giving it a different callback (delegate) to be used.

Ad 2) I think the answer is the same as with 1). If I misunderstood this part, please let me know and explain somehow differently.

Ad 3) This is the design of the component. We realize that developers need to distinguish somehow between notifications coming from different items, but we cannot know upfront what kind of object the developer will need to pass. For this reason, the State parameter is the most general, 'object' type, which is easy to pass in. But when you receive the notification, your code only sees an 'object', not the concrete type, and that's why it needs to be type-casted.

Looking at what your code does, which is generally an "HMI"-kind of screen, are you aware of the Live Binding features in our product? With it, you can do most of these things without a single line of code - just by configuring it in Visual Studio Designer.
The following user(s) said Thank You: Ramirez

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

More
22 Aug 2013 12:54 #1407 by Ramirez
Hello,
I'm coding the interface to access to a PLC and I am facing some problems.

First:
I created a group of items into an OPC array and I subscribed them to the OPC server one by one by passing a textbox object as a state parameter.
Then with only one line I did the itemchanged method to recover values of each OPC item and display the value on every textbox passed as parameter.

The problem is when I pass a label as state object instead of textbox, I cannot anymore keep the itemchanged method as is. How can I manage different kind of state objects when I subscribe and do the itemchanged.

Second:
I also would like to subscribe to a bool item and change a led state depending on the item value true or false. I will put the item in a group of items with different types and call the method itemchanged to recover the value, test it and change the led color. For other values I just display the value.

Third:
Why am I obliged to cast "e.state" into texBox to be able to display the itemChanged on the textBox passed as state parameter during the subscription?

I join .cs files so you can check what I did so far.

Thank in in advance for your help.

David Ramirez

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

Moderators: support
Time to create page: 0.064 seconds