Recent

Author Topic: OPC client with Lazarus  (Read 38684 times)

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #45 on: October 12, 2021, 07:38:00 am »
When UA_Client_Service_read reads multiple nodes, the result will be UA_STATUSCODE_GOOD, but only the first node has data and the others are empty

Why is this happening?

This is part of the function, the connection to the server has been completed before the parameter client is passed in...

Code: Pascal  [Select][+][-]
  1. var
  2.   i:Integer;
  3.   retval: UA_StatusCode;
  4.  
  5.   Request: UA_ReadRequest;
  6.   Response: UA_ReadResponse;
  7.   ids: Array[0..2] of UA_ReadValueId;
  8.   res: UA_DataValue;
  9.   outValue: String;
  10. begin
  11.   Result:=UA_STATUSCODE_GOOD;
  12.   try
  13.     UA_ReadRequest_init(Request);
  14.     try
  15.       ids[0].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  16.       ids[0].nodeId := UA_NODEID_NUMERIC(5, 6024);    // Custom node on the server
  17.  
  18.       ids[1].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  19.       ids[1].nodeId := UA_NODEID_NUMERIC(5, 6025);    // Custom node on the server
  20.  
  21.       ids[2].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  22.       ids[2].nodeId := UA_NODEID_NUMERIC(5, 6026);    // Custom node on the server
  23.  
  24.       UA_ReadValueId_init(ids[0]);
  25.       Request.nodesToRead[0].nodeId:= ids[0].nodeId;
  26.       Request.nodesToRead[0].attributeId:=ids[0].attributeId;
  27.  
  28.       UA_ReadValueId_init(ids[1]);
  29.       Request.nodesToRead[1].nodeId:= ids[1].nodeId;
  30.       Request.nodesToRead[1].attributeId:=ids[1].attributeId;
  31.  
  32.       UA_ReadValueId_init(ids[2]);
  33.       Request.nodesToRead[2].nodeId:= ids[2].nodeId;
  34.       Request.nodesToRead[2].attributeId:=ids[2].attributeId;
  35.      
  36.       Request.nodesToRead:=@ids[0];
  37.       Request.nodesToReadSize:=3;
  38.  
  39.       Response:=UA_Client_Service_read(client, Request);
  40.       retval:=Response.responseHeader.serviceResult;
  41.       if retval=UA_STATUSCODE_GOOD then
  42.         if Response.resultsSize<>3 then
  43.         begin
  44.           UA_clear(@Response, @UA_TYPES[UA_TYPES_READRESPONSE]);
  45.           Result:=UA_STATUSCODE_BADUNEXPECTEDERROR;
  46.           Exit;
  47.         end;
  48.  
  49.       for i:=0 to 2 do
  50.       begin
  51.         outValue:='';
  52.         if Response.results[i].status<>UA_STATUSCODE_GOOD
  53.           then continue;
  54.  
  55.         res := Response.results[i];
  56.    (*     if Not res.hasvalue then
  57.         begin
  58.           valueItems.Append('');
  59.           break;
  60.         end;  *)
  61.  
  62.         if res.value._type=@UA_TYPES[UA_TYPES_INT32] then
  63.           outValue:=IntToStr(UA_Variant_getInteger(res.value))
  64.         else
  65.         if res.value._type=@UA_TYPES[UA_TYPES_INT16] then
  66.           outValue:=IntToStr(UA_Variant_getSmallint(res.value))
  67.         else
  68.         if res.value._type=@UA_TYPES[UA_TYPES_DOUBLE] then
  69.           outValue:=UA_Variant_getDouble(res.value).ToString;
  70.  
  71.  
  72.         valueItems.Append(outValue);
  73.       end;
  74.     except
  75.       //
  76.     end;
  77.   finally
  78.     UA_clear(@Response, @UA_TYPES[UA_TYPES_READRESPONSE]);
  79.   end;
  80. end;
  81.  
« Last Edit: October 12, 2021, 08:13:04 am by denny.chou »

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #46 on: October 12, 2021, 10:25:00 am »
in addition...
1. UA_Client_connect(client 1, IP_1);
You can connect to IP_1 normally

but...
2.
UA_Client_connect(client 1, IP_1);
UA_Client_connect(client 2, IP_2);
Only IP_1 can connect normally;
The return result of IP_2 is UA_STATUSCODE_BADINTERNALERROR = $80020000;

Can I connect to another server only after client_1 is disconnected?

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #47 on: October 14, 2021, 05:42:07 am »
Please help me with the subscription function...

Verified the results of the subscription function...
{$DEFINE HAVE_PROSYSSIMULATIONSERVER}
monResponse.statusCode returns UA_STATUSCODE_BADINTERNALERROR ($80020000)
The sample program you provided is used for verification: TestOpcUa1

More specifically... if lines 243-280 are removed, response.responseHeader.serviceResult will not be UA_STATUSCODE_GOOD

Why is this happening?

LacaK

  • Hero Member
  • *****
  • Posts: 650
Re: OPC client with Lazarus
« Reply #48 on: October 14, 2021, 07:31:58 pm »
I am sorry, but I have limited experience with this.
I did TestOpcUa program during testing implementation of Pascal port of library "open62541".
It worked for me in given test scenario with PROSYS SIMULATION SERVER ...

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #49 on: October 15, 2021, 08:20:29 am »
I'm sorry for not clarifying the environment I use, I am using delphi XE10, directly quote the open62541.pas you provided

I really don't know the difference between fp and xe10?

LacaK

  • Hero Member
  • *****
  • Posts: 650
Re: OPC client with Lazarus
« Reply #50 on: October 15, 2021, 06:56:38 pm »
open62541.pas should work with Delphi also.
I do not think that problem you described is caused by Delphi itself.

Take look at example: https://github.com/open62541/open62541/blob/master/src/client/ua_client_highlevel.c

In your example, you assign values it ids[0] and then you call UA_ReadValueId_init(ids[0]); which clears content. Is it okay?

Try:
Code: Pascal  [Select][+][-]
  1.       UA_ReadValueId_init(ids[0]);
  2.       ids[0].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  3.       ids[0].nodeId := UA_NODEID_NUMERIC(5, 6024);    // Custom node on the server
  4.  
  5.       UA_ReadValueId_init(ids[1]);
  6.       ids[1].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  7.       ids[1].nodeId := UA_NODEID_NUMERIC(5, 6025);    // Custom node on the server
  8.  
  9.       UA_ReadValueId_init(ids[2]);
  10.       ids[2].attributeId := ord(UA_ATTRIBUTEID_VALUE);  // 13
  11.       ids[2].nodeId := UA_NODEID_NUMERIC(5, 6026);    // Custom node on the server
  12.  
  13.       Request.nodesToRead:=@ids[0];
  14.       Request.nodesToReadSize:=3;
  15.  
« Last Edit: October 15, 2021, 07:09:10 pm by LacaK »

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #51 on: October 20, 2021, 10:50:13 am »
Finally, I changed to Lazarus's development platform to implement it, and none of the three issues mentioned above exist... :(

But there is a problem with the implementation of stateCallback, as long as UA_Client_connect is executed, an error will be reported:
... raised exception class'External:SIGSEGV'

why?

lupus-rain

  • Newbie
  • Posts: 2
Re: OPC client with Lazarus
« Reply #52 on: October 21, 2021, 11:04:25 am »
Finally, I changed to Lazarus's development platform to implement it, and none of the three issues mentioned above exist... :(

But there is a problem with the implementation of stateCallback, as long as UA_Client_connect is executed, an error will be reported:
... raised exception class'External:SIGSEGV'

why?

I stumbled upon the same problem the same day. Having connecion problems in my self written wrapper (based on open62541 V 0.3), i found this project and tried to include it into my components.

The open62541 c++ example works well with stateCallback, but as soon as i try stateCallback in Delphi, i get an Access violation.

One strange thing I observed: The callback procedure is called one time, and the Session State parameter has a value of -1, which is invalid. In c++ I don't see this value.

lupus-rain

  • Newbie
  • Posts: 2
Re: OPC client with Lazarus
« Reply #53 on: October 25, 2021, 11:19:56 am »
Found the fault in open62541.pas wrapper: record UA_ConnectionConfig was enhanced 24. Jan. 2020 to

  UA_ConnectionConfig = record
      protocolVersion: UA_UInt32;
      recvBufferSize: UA_UInt32;
      sendBufferSize: UA_UInt32;
      localMaxMessageSize: UA_UInt32; (*  (0 = unbounded) *)
      remoteMaxMessageSize: UA_UInt32;  (*  (0 = unbounded) *)
      localMaxChunkCount: UA_UInt32; (*  (0 = unbounded) *)
      remoteMaxChunkCount: UA_UInt32;  (*  (0 = unbounded) *)
  end;

LacaK

  • Hero Member
  • *****
  • Posts: 650
Re: OPC client with Lazarus
« Reply #54 on: October 26, 2021, 09:43:31 am »
Yes, you are right!
(probably this was changed in 1.0 -> 1.1 release branch)
Thank you!

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #55 on: November 02, 2021, 03:16:17 am »
Found the fault in open62541.pas wrapper: record UA_ConnectionConfig was enhanced 24. Jan. 2020 to

  UA_ConnectionConfig = record
      protocolVersion: UA_UInt32;
      recvBufferSize: UA_UInt32;
      sendBufferSize: UA_UInt32;
      localMaxMessageSize: UA_UInt32; (*  (0 = unbounded) *)
      remoteMaxMessageSize: UA_UInt32;  (*  (0 = unbounded) *)
      localMaxChunkCount: UA_UInt32; (*  (0 = unbounded) *)
      remoteMaxChunkCount: UA_UInt32;  (*  (0 = unbounded) *)
  end;

Wow, it was really unexpected. I tried to modify the definition of UA_ConnectionConfig synchronously. The problem of reporting an error as soon as the stateCallback executes UA_Client_connect did not happen anymore. Thank you very much.

olivluca

  • Newbie
  • Posts: 2
Re: OPC client with Lazarus
« Reply #56 on: November 04, 2021, 12:44:18 pm »
FYI, I'm trying to build v1.2.2 of the dll under windows (32 bits). I'm facing some problems I exposed on the open62541 mailing list (with no replies so far).
In case you're interesed and/or can help, this is the message:

https://groups.google.com/g/open62541/c/pTc8pSneN74

the problem is that the files types_generated.inc (with my modified tool) and types_generated.h (with the stock tool) are different under windows and linux, so I cannot generate consistent bindings that works under both platforms.

LacaK

  • Hero Member
  • *****
  • Posts: 650
Re: OPC client with Lazarus
« Reply #57 on: November 04, 2021, 05:53:32 pm »
@olivluca: can you please also update definition of record UA_ConnectionConfig in https://github.com/fluisgirardi/fpopen62541/blob/main/open62541.pas as suggested above ...

denny.chou

  • New Member
  • *
  • Posts: 11
Re: OPC client with Lazarus
« Reply #58 on: November 23, 2021, 10:26:51 am »
Hello, can this also be used to connect opc-da?

avra

  • Hero Member
  • *****
  • Posts: 2261
    • Additional info
Re: OPC client with Lazarus
« Reply #59 on: November 23, 2021, 10:26:18 pm »
Hello, can this also be used to connect opc-da?
Normally not, but there are OPC-UA to OPC-DA gateways which allow that.

For direct OPC-DA access you can use something like this: https://github.com/seryal/OPCComponent
ct2laz - Conversion between Lazarus and CodeTyphon
bithelpers - Bit manipulation for standard types
pasettimino - Siemens S7 PLC lib

 

TinyPortal © 2005-2018