Professional OPC
Development Tools

logos

Testing Demo version with Xojo

More
27 Apr 2020 13:43 #8404 by support
Thank you.

Best regards

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

More
25 Apr 2020 18:35 #8400 by Sacha
Hello,

the BrowserServer function without timeout exception is not a big problem.

Now the basic functions I need to manage OPC Client with COM works.

I Have attached a Xojo project where are available read / write functions, browse methods and timeout settings to help Xojo developers.

Best Regards

Sacha

File Attachment:

File Name: OPC.zip
File Size:18 KB
Attachments:

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

More
25 Apr 2020 09:26 - 26 Apr 2020 19:38 #8398 by support
Hello,
thank you for the details.

I found that BrowseServers indeed does behave this way (not just in Xojo). That is, it does not return an error in case of timeout or other problems, just an empty collection. There are some deep design/implementation reasons for this, but to save you from long talk, yes, it can be considered a bug in QuickOPC. Other methods behave OK in this respect.

Let me know how important for you is to have errors returned "normally" from BrowseServers - or whether you can accept the current behavior.

Best regards
Last edit: 26 Apr 2020 19:38 by support.

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

More
23 Apr 2020 11:17 #8393 by Sacha
Hello,

1/5-
the Window1 open Event Handler contains the following code :
'EasyDAClient and  IstanceParameters are declared as Window1 property
 
'OPC Client Object 
EasyDAClient  = New OleObject ("OPCLabs.EasyOpc.DataAccess.EasyDAClient")
'Istance parameters Object
IstanceParameters = new  OleObject ("OPCLabs.EasyOpc.DataAccess.Engine.EasyDAInstanceParameters")
'Timeouts parameters Object
TimeoutClient = new OleObject ("OPCLabs.EasyOpc.DataAccess.Engine.EasyDAClientTimeouts")
 
'Setting timeout parameters
 
'ReadItem timeout
TimeoutClient.ReadItem = 1000
'WriteItem timeout
TimeoutClient.WriteItem = 1000
'Browse Access timeout
TimeoutClient.BrowseAccessPaths = 1000
'Browse server timeout
TimeoutClient.BrowseServers = 10000
 
IstanceParameters.Timeouts = TimeoutClient
EasyDAClient.InstanceParameters = IstanceParameters

2/3- In case of timeout, BrowseServers returns a ServerCollection with 0 elements without timeout exception.
Dim ServerCollection as new OLEObject("OpcLabs.EasyOpc.ServerElementCollection")
ServerCollection =  EasyDAClient.BrowseServers("")
msgbox(str(ServerCollection.count))  'Returns 0

4- With other OPC Client i see only the ModbusOPC server, to load It the program needs 3 - 4 seconds

If you want, I can send you my test software.

Best Regard

Sacha

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

More
23 Apr 2020 09:10 #8389 by support
Thank you for update, I am glad you got it working, but your post raised multiple questions on my side - can you please answer?

1. There was no setting of the browse timeout in the code you posted - how comes?
2. In case of timeout, BrowseServers returns an error and not an empty collection. And the error (failed HRESULT) should be transformed to run-time error in Xojo I suppose. Were the errors somehow suppressed, or how is it possible that the execution continued after the itmeout?
3. You have not answered my question about the Count of the returned collection before the transformation.
4. Not clear why the browsing is so slow. That is no normal, for a local browse. Have you used some other OPC client (not based on QuickOPC), and is it also slow?
5. I do not understand "The other timeouts like writeitem / readitem give me a timeout exception.". Is that a new problem you want me to look at:? If so, create a separate forum topic for it (with possible link to this one).

Regards

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

More
22 Apr 2020 21:33 #8387 by Sacha
Hello,

The missing "as" is a copy / paste error.

I found the problem. The demo application Easy OPC - DA needs 7 - 10 seconds to shows the servers, more than the BrowseServer Timeout value in my application.

Note : The other timeouts like writeitem / readitem give me a timeout exception.

Thanks

PS: Working with COM is so hard :S

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

More
22 Apr 2020 19:51 #8386 by support
Hello,
your code works fine for me (except that you are missing "As" on the 2nd line).

Can you please provide some additional info? Thank you.

1. Can you take the Count of the ServerCollection itself (before the conversion)? Is it also 0?

2. When you run the (.NET-based) demo that comes with the product, does it show the servers (it has "Browse servers" button) or also nothing?

3. Have you tried other OPC clients on the same computer, and what were the results?

Best regards

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

More
22 Apr 2020 17:18 #8384 by Sacha
Thanks for the fast support. (5 stars + 1).

Your solution works great for reading nodes and leaves but for reading servers it doesn't return any value.

I have no compiler errors, the item's count returns 0 but the ServerCollection object is not NIL.

Code:
EasyDAClient  = New OleObject ("OPCLabs.EasyOpc.DataAccess.EasyDAClient")
Dim ServerCollection OLEObject
ServerCollection =  EasyDAClient.BrowseServers("") 'Epmpty string = Local machine
Dim AutomationUtilities As New OLEObject("OPCLabs.AutomationUtilities")
Dim NodeElementElasticVector As OLEObject
NodeElementElasticVector = AutomationUtilities.CollectionToElasticVector(ServerCollection)
Dim ServersArray() as string
Dim count as Integer
count = NodeElementElasticVector.Count
 
msgbox(str(count) + " Elements")
 
Dim i as Integer 
Dim NodeArray() as string
For i = 0 To count - 1
  Dim ServerElement As OLEObject
  ServerElement = NodeElementElasticVector.Item(i) 
  ServerArray.AddRow(ServerElement.toString)
Next

Thanks for your help, best regards

Sacha

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

More
21 Apr 2020 07:23 - 21 Apr 2020 07:26 #8381 by support
Here are some more results.

First of all, please understand that we are total Xojo beginners here - we cannot have advanced experience with all the tools and languages our software gets used from. So if I get something wrong, you may know better.

In my original test, I was declaring the enumerator as OLEObject, and GetEnumerator succeeded but the result was nil.
I then found COM.IEnumVARIANT ( docs.xojo.com/IEnumVARIANT ), which seems to be precisely for what we need. But declaring the output variable as COM.IEnumVARIANT gives NilObjectException. But I know that GetEnumerator works - other COM tools are using it - otherwise they wouldn't be able to consume this collection.

So at this point I would be lost; don't you have some working example COM.IEnumVARIANT (perhaps with other object), or some other ideas worth exploring?

But, I found a workaround then. Currently, it is a hack, we can improve it later. Here is what works:
I know we have an object in QuickOPC, called ElasticVector, which certainly can be consumed by Xojo. Besides other things, it is a COM collection indexed by an integer, which is what we need. We designed the ElasticVector to get around a different deficiency in other tool (PowerScript).

So what we need is to convert the DANodeElementCollection to ElasticVector. Unfortunately there is no method for that, but I wrote a little component in VBScript which can do it. This is the hackish part: This component needs to be registered on the machine, too. I am attaching the file (AutomationUtilities.wsc, zipped) to this post, and below is the listing.
<?XML version="1.0"?>
<!-- $Header: $ !-->
<!-- Copyright (c) CODE Consulting and Development, s.r.o., Plzen. All rights reserved. !-->
 
<!-- Automation utilities for various operations. -->
 
<?component error="false"?>
<component>
 
  <registration
    progid="OPCLabs.AutomationUtilities"
    classid="{E8601766-CF3E-4D0A-A29C-858883B52ED4}"
    description="OPC Labs Automation Utilities"
    version="1"
    remotable="true">
  </registration>
 
  <public>
    <method name="CollectionToElasticVector">
      <parameter name="Collection"/>
    </method>
  </public>
 
  <s-cript language="VBScript">
    <![CDATA[
Option Explicit
 
' Converts a collection to an elastic vector.
Function CollectionToElasticVector(Collection)
    Dim ElasticVector: Set ElasticVector = CreateObject("OpcLabs.BaseLib.Collections.ElasticVector")
    Dim Element: For Each Element in Collection
        ElasticVector.Add(Element)
    Next
    Set CollectionToElasticVector = ElasticVector
End Function
 
]]>
  </script>
 
</component>
 

File Attachment:

File Name: Automation...ties.zip
File Size:1 KB

You need to place the AutomationUtilities.wsc file on your machine, and - using elevated privileges (run the command line "As Administrator"), execute
regsvr32 AutomationUtilities.wsc

After that, the following code in Xojo can be used to access elements of DANodeElementCollection:
' Create EasyOPC-DA component
Dim Client As New OleObject ("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
 
Dim LeafElements As OLEObject
LeafElements = Client.BrowseLeaves("", "OPCLabs.KitServer.2", "Simulation")
 
Dim AutomationUtilities As New OLEObject("OPCLabs.AutomationUtilities")
Dim leafElementElasticVector As OLEObject
leafElementElasticVector = AutomationUtilities.CollectionToElasticVector(LeafElements)
 
Dim count as Integer
count = leafElementElasticVector.Count
 
Dim i as Integer 
For i = 0 To count - 1
  Dim LeafElement As OLEObject
  LeafElement = LeafElementElasticVector.Item(i) 
  // do something with LeafElement
Next

Ideally, in the future, we would like be able to do this without the external component (I found the need of additional conversion to ElasticVector as acceptable compromise for Xojo, but not the fact that an external component is needed for that). My envisioned solution would be a method (probably "AddRange") on the ElasticVector that would take all elements from any collection and add them to ElasticVector. I want this to become part of next version (QuickOPC 2020.3) if possible.

Best regards
Attachments:
Last edit: 21 Apr 2020 07:26 by support.

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

More
20 Apr 2020 17:09 #8379 by support
Hello,

I was able to reproduce the problem. I think it is because the GetEnumerator returns IEnumVARIANT which is not an automation or dual interface, it is a custom interface only. Most COM controllers have some kind of "For Each" statement precisely for this - to consume an enumerator without explicit programming on the developer's side.

And I think it is discussed here: forums.realsoftware.com/viewtopic.php?t=311 .

You might be able to access some collections using their Count and (indexed) Item properties. The DANodeElementCollection has them too, but the Item property is not indexed by an integer - it is a keyed collection, and the Item is indexed by the node name; and you do not know the node name, for that you would need the GetEnumerator.

This seems to be like a deficiency in Xojo - but one unlikely to be fixed/addressed. We are generally trying to provide some way of doing things in the tools we know about (and believe me, each COM API consumer has its own lot of problems, mostly different from the others). So I will think of whether we can find some way to do this for Xojo. I will make a new post here when I have an update (probably later this week).

Best regards

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

Moderators: support
Time to create page: 0.230 seconds

      

 Recommend this on Google