- Posts: 4
- Thank you received: 0
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.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Reading, Writing, Subscriptions, Property Access
- Newbie question: Best method for item identification from callback
Newbie question: Best method for item identification from callback
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.
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
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
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.
Please Log in or Create an account to join the conversation.
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)})
Please Log in or Create an account to join the conversation.
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.
Please Log in or Create an account to join the conversation.
Hanssing wrote: Followup questions:
- Does the client handle all sort of disconnect, etc on subscribed items?
AFAIK it does maintain the items until unsubscribed, right?
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.
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.
Please Log in or Create an account to join the conversation.
- 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.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Reading, Writing, Subscriptions, Property Access
- Newbie question: Best method for item identification from callback