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.
ByteString type input in PHP
it is good to know!
Best regards
Please Log in or Create an account to join the conversation.
- novotnypetr
- Topic Author
- Offline
- Senior Member
- Posts: 5
- Thank you received: 1
I must apologize, your solution from July 14th is functional and the code fragment which I sent on July 15th is working. (The problem "BadTypeMismatch" was in binary data structure.)
Thank you!
Best regards
Please Log in or Create an account to join the conversation.
In order to be able to troubleshoot, I will need Wireshark capture ( kb.opclabs.com/Collecting_information_for_troubleshooting ) of what is happening when you run your PHP/QuickOCP program, and, if possible, a similar capture of what is happening with some other UA client that *does* work - if you have that. That is actually my question now too - do you have such client?
One of the reasons could be that with the way it is done now, the argument will be passed as array of bytes, which is not precisely the same as ByteString. However, AFAIK, compliant UA servers are required to treat them the same. But this is just a guess, there can be other reasons too.
Best regards
Please Log in or Create an account to join the conversation.
- novotnypetr
- Topic Author
- Offline
- Senior Member
- Posts: 5
- Thank you received: 1
thank you for the answer, but it still doesn't work.
The code is now:
$fileContent = $this->getFileStream(); //binary data
$length = strlen($fileContent);
$bytes = [];
for ( $i = 0; $i < $length; $i++ ) {
$bytes[] = ord($fileContent{$i});
}
$inputs = [
0 => 1, //0 = target: production level, 1 = target: preparation level
1 => 1, //Write machine part of the program: 0 = no, 1 = yes
2 => 1, //Write robot part of the program: 0 = no, 1 = yes
3 => 1, //Write freely configurable page part of the program: 0 = no, 1 = yes
4 => $bytes //ByteString - Zipped program file to download
];
$typeFullNames = [
0 => 'System.UInt16',
1 => 'System.UInt16',
2 => 'System.UInt16',
3 => 'System.UInt16',
4 => 'System.Byte[]'
];
$callArguments1 = new \COM("OpcLabs.EasyOpc.UA.OperationModel.UACallArguments");
$callArguments1->EndpointDescriptor->UrlString = $this->opcUaUrl;
$callArguments1->NodeDescriptor->NodeId->ExpandedText = "ns=2;i=399860";
$callArguments1->MethodNodeDescriptor->NodeId->ExpandedText = "ns=2;i=399790";
$callArguments1->InputArguments = $inputs;
$callArguments1->InputTypeFullNames = $typeFullNames;
$arguments = [
0 => $callArguments1
];
$outputs = $opcUaClient->CallMultipleMethods($arguments);
Returning error message:
*** Failure Opc.UA.ServiceResult=0x80740000: OPC UA service result - {BadTypeMismatch}. The value supplied for the attribute is not of the same type as the attribute's value. [...]
Best regards
Please Log in or Create an account to join the conversation.
We do not provide paid support/consultations.
As you recognized, the issue here is that the type of the method's last input parameter needs to be correctly specified. That would be easy to do in QuickOPC for .NET, because it is possible to simply use the Type object that represents the right type (in C#, it would be typeof(byte[]) ). Unfortunately in COM tools (such as PHP), it is not directly possible to create/refer to .NET type objects, and that is one of the reason why the TypeCode-s are used; but then, they are limited and only allow scalars and not arrays.
But, I still think there is a way to do it. There are two parts to this:
1. You need to use CallMultipleMethods (as opposed to CallMethod) - even if you are making just one method call. The reason for it is that the CallMethod is an extremely simplified API with just a few arguments (and this limited functionality). It is a wrapper around CallMultipleMethods which constructs the right parameters for it. By using CallMultipleMethods , you get access to all options available. An example for this method is here: opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...Call%20multiple%20methods.html . There is no PHP example but there are examples in other COM tools; I believe that should be enough.
2. Instead of using the UACallArguments.InputTypeCodes array, which suffers from the same limitation, you would use the UACallArguments.InputTypeFullNames array (opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...uments~InputTypeFullNames.html ). You need to give an array of strings, and each string will be the full .NET type name. In your example, the strings will be "System.UInt16", "System.UInt16", "System.UInt16", "System.UInt16", "System.Byte[]". Notice the angle brackets in the last element, which make it into an array type.
I have not tested this, but it should work.
Best regards
Please Log in or Create an account to join the conversation.
- novotnypetr
- Topic Author
- Offline
- Senior Member
- Posts: 5
- Thank you received: 1
this part of code executes the method:
$fileContent = $this->getFileStream(); //binary data
$length = strlen($fileContent);
$bytes = [];
for ( $i = 0; $i < $length; $i++ ) {
$bytes[] = ord($fileContent{$i});
}
$inputs = [
0 => 1, //0 = target: production level, 1 = target: preparation level
1 => 1, //Write machine part of the program: 0 = no, 1 = yes
2 => 1, //Write robot part of the program: 0 = no, 1 = yes
3 => 1, //Write freely configurable page part of the program: 0 = no, 1 = yes
4 => $bytes //ByteString - Zipped program file to download
];
$typeCodes = [
0 => 8, // TypeCode.UInt16
1 => 8, // TypeCode.UInt16
2 => 8, // TypeCode.UInt16
3 => 8, // TypeCode.UInt16
//4 => 6 //intentionally omitted because there is not type code for ByteString
];
$opcUaClient->CallMethod(
$this->opcUaUrl,
"ns=2;i=399860",
"ns=2;i=399790",
$inputs,
$typeCodes
);
ByteString is 4th parameter as array of integers, so it is the same approach as in your example.
(Calling another method without byte string parameter work without problems, so the problem must be in the parameter.)
The error message is:
Source: OpcLabs.EasyOpcUA
Description: OPC UA service result - {BadInvalidArgument}. One or more arguments are invalid.
+ The method descriptor used was: NodeId="ns=2;i=399790".
+ The node descriptor used was: NodeId="ns=2;i=399860".
+ The client method called (or event/callback invoked) was 'CallMultipleMethods[1]'.
Is it possible to order an on-line consultation at your company? Maybe it will be faster to find a solution.
Best regards
Please Log in or Create an account to join the conversation.
I currently do not have a PHP example with method call and a ByteString, but we have an example of that with Write: opclabs.doc-that.com/files/onlinedocs/QuickOpc/Latest/User%2...%20Write%20a%20ByteString.html . It looks like this:
// This example shows how to write a value into a single node that is of type ByteString.
$Values[0] = 11;
$Values[1] = 22;
$Values[2] = 33;
$Values[3] = 44;
$Values[4] = 55;
// Instantiate the client object
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
// Modify value of a node
try
{
$Client->WriteValue(
"opcua.demo-this.com:51211/UA/SampleServer", //or "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
"nsu=http://test.org/UA/Data/ ;i=10230",
$Values);
}
catch (com_exception $e)
{
printf("*** Failure: %s\n", $e->getMessage());
}
Does a similar approach work with method call? If not, what is the error your are getting?
Best regards/S pozdravem
Please Log in or Create an account to join the conversation.
- novotnypetr
- Topic Author
- Offline
- Senior Member
- Posts: 5
- Thank you received: 1
in PHP project I need to call a method with a parameter of ByteString type (method for downloading programme to the machine from binary file). How to make this ByteString input parameter in PHP? Do you have any example code?
I tried various variants of array of bytes, but nothing works.
Best regards
Please Log in or Create an account to join the conversation.