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.

Newbie question: Best method for item identification from callback

More
12 Feb 2016 16:29 #3853 by stathej
Point taken about time stamping the data. You are correct that the original method did make this easier to do but I can work around this with a subscription method. I don't actually need the current time the data was sent but actually just record the length its been sent over. Its probably not as accurate but I was going to use a system timer and add a column to the data table every time it gets a row added.

Another option is to tally the number of rows in the data table, its the response curve of the data that I'm interested in as the physical input to the process is fixed.

Thanks for the advice.

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

More
12 Feb 2016 16:10 #3852 by support
I do not want to propose another change; I just wanted to explain some things. Your original posts basically had 2 parts to it: 1) how to easily correlate the arguments to SubscribeMultipleItems method with the incoming event notifications - I think this part has been answered by now, and 2) how to build database rows with per-tag data with OPC subscriptions. It is this second part of the question that I want to comment. Perhaps you have already found s solution that works for you, but it's always good to have all the information.

If what you need to achieve is something like creating a table where each row corresponds to certain time, and the columns have the data values for certain tags, then the OPC subscription model does not directly fit with that, and some work on the coder's part is always required. In fact, the periodic reading approach (that you had originally), which is not otherwise recommended, make building such table much easier. OPC subscriptions are usually a preferred method, however there are some issues with them in this case:

1. Per the spec, OPC-DA servers only send data subscription notification for data values that have changed. That is, if the data has been collected anew from the device, but it has not changed the value, *nothing* gets sent to the client - therefore the client does not receive the new timestamp. It can assume that the data has not changed, but the timestamp is lost. This commonly makes life hard difficult for trending and logging packages based on OPC-DA. Some servers "get around" this by always or optionally sending data that have not changed as well, but strictly speaking, that's against the OPC specs. Newer specs (OPC Unified Architecture) allow the client to tell the server what the notification "trigger" should be - and it can be just a timestamp change.

2. OPC server are not required to send data collected "together" in one common ("packed") notification to the clients. While the physical data change notification contains one or more data changes, there is no guarantee that they belong together, and there is no guarantee that those that belong together are transferred at once. The "packing" is for physical (efficiency) purpose, not logical (semantics).

3. The above two apply generally to OPC-DA, this last one to QuickOPC only: Even if multiple data changes arrive to us together, we "unpack" them and have one notification to your code per data change - therefore you do not get to see the "packing" anyway. Given that the issue 2 above exists, this behavior itself should not be a cause for any additional problem, but it should be listed here for completeness.

What can you do then, if you want to use subscriptions, and generate a tabular log? You will probably need to put in some logic that will find the related data changes in the incoming stream of notifications (and you are probably doing that already). The logic may be based e.g. on the timestamps of the data (make a separate row if they are equal or close enough). There are many possible approaches - but they all require some extra coding.

One such example even comes with the product: If you open the Examples solution for C# or VB.NET and in the Solution Explorer, locate the project Console -> LogToSqlEnhanced, you will see it there.

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

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

More
12 Feb 2016 09:46 #3845 by stathej
Yes I can see that now, set the state as the array element and then and couple it to the array. Simple when you work it out just not thinking straight. I await to see what other change you intended.

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

More
12 Feb 2016 08:51 #3844 by support
I will start form the end, as there is an easy answer to your last question. You can get rid of the Select Case statement, and simplify the code, by directly passing the index into the _r array as the State argument.

That is, pass 0, 1, 2, ... 9 instead of "A", "B", "C", ... "J". Then, in the event handler, do something like (I have not run it through compiler, but the idea should be clear):

_r(CInt(e.Arguments.State)) = e.Vtq.Value

Best regards
(One more post will follow later)

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

More
11 Feb 2016 20:32 #3843 by support
Received both your posts... planning to provide an extensive answer tomorrow. Best regards.

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

More
11 Feb 2016 20:29 - 11 Feb 2016 20:33 #3842 by stathej
I have done a bit more investigating and experimenting with a dummy run on a test program, see below. It works well enough but is there a better way to get the opc results straight into a data table without the select case phase. Code below
Private Sub DataGrabber()
 
        AddHandler _client.ItemChanged, AddressOf LiveData
        Dim data = New DAItemGroupArguments(9) {}
 
        data(0) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "A")
        data(1) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "B")
        data(2) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "C")
        data(3) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "D")
        data(4) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "E")
        data(5) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "F")
        data(6) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "G")
        data(7) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "H")
        data(8) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "I")
        data(9) = New DAItemGroupArguments("", _server, "Simulation.Random", "50", "J")
 
 
        _client.SubscribeMultipleItems(data)
 
 
 
    End Sub
 
    Private Sub LiveData(ByVal sender As Object, ByVal e As EasyDAItemChangedEventArgs) Handles _client.ItemChanged
 
 
        Select Case e.Arguments.State
            Case Is = "A"
                _r(0) = e.Vtq.Value
            Case Is = "B"
                _r(1) = e.Vtq.Value
            Case Is = "C"
                _r(2) = e.Vtq.Value
            Case Is = "D"
                _r(3) = e.Vtq.Value
            Case Is = "E"
                _r(4) = e.Vtq.Value
            Case Is = "G"
                _r(6) = e.Vtq.Value
            Case Is = "H"
                _r(7) = e.Vtq.Value
            Case Is = "I"
                _r(8) = e.Vtq.Value
            Case Is = "J"
                _r(9) = e.Vtq.Value
        End Select
 
        UpdateDataTable(_r)
    End Sub
 
    Private Sub UpdateDataTable(ByVal _r() As double)
        ' Add a row of data
 
                Try
            _dt.Rows.Add(New Object() {_fin, _r(0), _r(1), _r(2), _r(3),
                                       _r(4), _r(5), _r(6), _r(7)})
Last edit: 11 Feb 2016 20:33 by support. Reason: code formatting

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

More
11 Feb 2016 16:35 #3841 by stathej
I am trying to achieve something similar. At present I have a system timer triggering a read multiple items call to gather the data into an array. After the data is gathered it is then passed into a datatable as a new row then the process is repeated next time the timer triggers.

When the sample period is completed the data table is then emptied into an excel chart. This all works well but is system intensive with the fairly rapid call's to read data from the OPC server.

I have reworked the code so that I subscribe and gather the sample points but I am struggling to find a method of passing the point's into an array so that I can build the data table. Do I define a state with each item that I gather the data for as shown in this post.
www.opclabs.com/forum/reading-writing-subscriptions-property...values-in-different-object-typ

Then use the item changed event to trigger adding a row to the data table.
If I use this method to build the data table what would be added when the item valve has not changed. I would still like to add a complete arrays worth of data at the creation of each new datatable row but zero values would disrupt the chart when it is made.

In short is the above post along the right path to create an array from a data subscription and would the subscribed array hold the old data values and just have the elements that have changed over written.

Sorry for not adding any code but I don't currently have it to hand.

Thanks for any advice.

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

More
18 Jan 2016 15:12 #3782 by support
Regarding MultipleItemsChanged : This has been dropped in newer versions altogether, because it has not brought the performance benefit for which it has been meant. Use ItemChanged instead.

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

More
18 Jan 2016 14:44 - 18 Jan 2016 14:44 #3781 by Hanssing

Hanssing wrote: Followup questions:

  • Does the client handle all sort of disconnect, etc on subscribed items?
    Ie. when subscribed, does the application need to do anything else than handle null-pointer/Bad-Quality when server connection fails?
    I did read section: 4.10.2 Errors in Subscriptions in the concpets but did not find this explicitly described.
  • AFAIK it does maintain the items until unsubscribed, right?


Ahh, found this:

Even if you are using the subscriptions to OPC items (in OPC Classic) or to monitored items (in OPC
UA) or events, QuickOPC creates illusion of their perseverance. The subscriptions outlive any
failures; you do not have to (and indeed, you should not) unsubscribe and then subscribe again in
case of error. After you receive event notification which indicates a problem, simply stay
subscribed, and the values will start coming in again at some future point.

Last edit: 18 Jan 2016 14:44 by Hanssing.

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

More
18 Jan 2016 14:14 #3779 by Hanssing
Followup questions:
  • Does the client handle all sort of disconnect, etc on subscribed items?
    Ie. when subscribed, does the application need to do anything else than handle null-pointer/Bad-Quality when server connection fails?
    I did read section: 4.10.2 Errors in Subscriptions in the concpets but did not find this explicitly described.
  • AFAIK it does maintain the items until unsubscribed, right?

Small suggestion for clarification in Concepts-document and documentation:
* Nowhere I could find does the documentation say, that MultipleItemsChanged will also be called when a single item has changed. Due to the naming one could be lead to believe that the event will only be passed if two or more items has changed, but it does get called with a single item-change. So there really is no need to use ItemChanged at all.

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

Moderators: support
Time to create page: 0.085 seconds