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
- Typecasting using Genericdata in Delphi
Typecasting using Genericdata in Delphi
So, it's up to you to decode the byte array - doing so actually falls outside of our product's scope. But it should be quite easy. I myself was doing Object Pascal/Delphi programming only many years ago, but I believe that in principle you will use one of the functions like CopyMemory to either
- Copy the whole array to a 'record' which you will define and that will have the right structure. In this case, care needs to be made about record packing/field alignment (docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/He...n/compdirsalignfields_xml.html )
- Do it repeatedly and copy just parts of the byte array to the "target" variables individually.
In both cases, if types with more than one byte in length are involved, additional consideration is whether the endianness is the same between the returned structure, and the one used in Delphi (which is "little endian" on Intel/AMD processors). If it is not the same, the byte order will need to be swapped as well.
Best regards
Please Log in or Create an account to join the conversation.
As far as I know the server is exposing the variable as an array of bytes. It just transfers the array from PLC to the client without any knowledge of the content.
Best regards,
Moien
Please Log in or Create an account to join the conversation.
First, I have a question. What leads you to believe that that the solution should involve the GenericData? It might, or it might not. It depends. Let me explain:
If the server supports OPC UA complex data types and the variable you read is of such complex data type, then it is passed as array of bytes on the wire, but QuickOPC has feature to decode it into its fields automatically - based on the "metadata" that it gets from the same server. This is the GenericData thing.
Or, the server may be truly exposing the variable *only* as an array/strring of Bytes. In such case the decoding needs to be done "manually".
Do you know which of these two cases are we dealing with?
Regards
Please Log in or Create an account to join the conversation.
I am again here but this time with a new topic. We had lots of challenges regarding the previous topic. Hopefully, this one is more easygoing.
I am reading the values from PLC using Read function. These values are all defined in just one Array in Byte format which I get directly from OPC UA Server.
I have to write the values of this Single Array from PLC into multiple variables inside my Delphi application. I know the orders and types of variables inside delphi definde in an array of record as "OPCServerItemArray". In other words, as an example the first variable in my "OPCServerItemArray" is a Real variable with 4 Bytes and the corresponding value from the PLC is the entry of the first 4 Bytes of the array which comes from PLC (Bytes[0..3]). The second variable in "OPCServerItemArray" is a DateTime variable (8 Bytes) and the corresponding variable from PLC Array is the entries of Bytes[4..11] and so on. How can I do Typecasting using Genericdata?
I coppied part of my code here:
Procedure TOPCClient.ReadAllItems;
var
ReadVar_vonSPS : Array of Byte;
AttributeSPSData : UAAttributeData;
I: Integer;
ItemRead : Boolean;
Name : String;
OPCUAResult: _UAAttributeDataResult;
OPCUAResults: OleVariant;
J,K: Cardinal;
begin
SetLength(ReadOPCUAArguments,Length(OPCServerItemArray)-NoV_DB100);
try
if (Connected) then begin
AttributeSPSData := OPCUAClientSPS.Read(Url_String,'nsu=Siemens1' + ';s=' + S0);
ReadVar_vonSPS := AttributeSPSData.Value;
for I := 0 to NoV_DB100-1 do begin
OPCServerItemArray[I].Value := //??? Typecasting using GenericData --> ReadVar_vonSPS
OPCServerItemArray[I].ItemQuality := AttributeSPSData.StatusCode;
OPCServerItemArray[I].TimeStamp := AttributeSPSData.ServerTimestamplocal;
end;
if (FirstCylyle) then begin
for J := NoV_DB100 to Length(OPCServerItemArray)-1 do begin
Name := OPCServerItemArray[J].Source + '.' + OPCServerItemArray[J].ItemName;
ReadOPCUAArguments[J-NoV_DB100] := CoUAReadArguments.Create;
ReadOPCUAArguments[J-NoV_DB100].ReadParameters.MaximumAge := 100;
ReadOPCUAArguments[J-NoV_DB100].EndpointDescriptor.UrlString := Url_String;
ReadOPCUAArguments[J-NoV_DB100].NodeDescriptor.NodeId.ExpandedText := 'nsu='+ nsu + ';s=Local Items.' + Name;
end;
OPCUAArguments := VarArrayCreate([0, Length(OPCServerItemArray)-NoV_DB100-1], varVariant);
for I := 0 to Length(OPCServerItemArray)-NoV_DB100-1 do begin
OPCUAArguments[I] := ReadOPCUAArguments[I];
end;
FirstCylyle := False;
end;
// Perform the operation
TVarData(OPCUAResults).VType := varArray or varVariant;
TVarData(OPCUAResults).VArray := PVarArray(OPCUAClientRead.ReadMultiple( //OPVLabs 2019.1 Version
PSafeArray(TVarData(OPCUAArguments).VArray)));
// Writing the results in Delphi internal Array
for K := VarArrayLowBound(OPCUAResults, 1) to VarArrayHighBound(OPCUAResults, 1) do
begin
OPCUAResult := IInterface(OPCUAResults[K]) as _UAAttributeDataResult;
OPCServerItemArray[NoV_DB100+K].Value := OPCUAResult.AttributeData.value;
OPCServerItemArray[NoV_DB100+K].ItemQuality := OPCUAResult.AttributeData.StatusCode;
OPCServerItemArray[NoV_DB100+K].TimeStamp := OPCUAResult.AttributeData.ServerTimestamplocal;
end;
end else begin
Meldung(0,'TOPCClient.ReadAllItems: (Not connected to the OPC UA Server!)');
end;
except
on E: Exception do begin
Meldung(0,'TOPCClient.ReadAllItems - Exception: ' + E.Message);
end;
end;
end;
Moien
Please Log in or Create an account to join the conversation.
- Forum
- Discussions
- QuickOPC-Classic in .NET
- Reading, Writing, Subscriptions, Property Access
- Typecasting using Genericdata in Delphi