opcua-client · v4.3.x
Docs · Operations

Calling methods

OPC UA method calls invoke server-side procedures. The arguments and return values are positional and strongly typed; the call() API surfaces that shape directly.

An OPC UA method is a node with NodeClass::Method, attached to an object node via a HasComponent reference. Invoking it requires two NodeIds — the object the method belongs to (the receiver) and the method itself — plus a positional list of Variant-typed input arguments. The server returns a CallResult containing per-argument input status codes and a positional list of output Variant values.

Basic call

php examples/call-no-args.php
// A method with no arguments — e.g. /Server/ServerCommands/Reset
$result = $client->call(
    objectId:  'ns=2;s=Devices/PLC',
    methodId:  'ns=2;s=Devices/PLC/Reset',
);

if ($result->statusCode === 0) {
    echo "Reset accepted\n";
}
Parameters
$objectId
NodeId|string required

The object node the method belongs to. The server uses this to disambiguate when the same method NodeId is shared across multiple objects.

$methodId
NodeId|string required

The method node itself.

$inputArguments
array optional default []

Positional list of PHP values. Each value is wrapped in a Variant with the type the server declared in its InputArguments property. If auto-detect is off and you need strict control, pass Variant instances directly.

The returned CallResult:

Property Type Meaning
statusCode int Overall call status. 0 = Good.
inputArgumentResults int[] One status per input argument. All Good when overall status is Good; useful for diagnosing BadInvalidArgument.
outputArguments Variant[] The return values, in declaration order.

With arguments

php examples/call-with-args.php
// A method declared as: SetTemperature(zone: Int32, target: Double): Boolean
$result = $client->call(
    objectId:       'ns=2;s=Heating',
    methodId:       'ns=2;s=Heating/SetTemperature',
    inputArguments: [3, 22.5],
);

if ($result->statusCode === 0) {
    /** @var bool $ack */
    $ack = $result->outputArguments[0]->value;
}

The PHP type is mapped to the OPC UA BuiltinType declared by the method's InputArguments property. The client does not currently read that property automatically — when a method expects an unusual type (e.g. UInt64, a String[] array, or an ExtensionObject), pass an explicit Variant:

php explicit Variant arguments
use PhpOpcua\Client\Types\BuiltinType;
use PhpOpcua\Client\Types\Variant;

$args = [
    new Variant(BuiltinType::String, 'manual'),
    new Variant(BuiltinType::Int32, 3, dimensions: null),   // scalar
    new Variant(BuiltinType::Double, [1.0, 2.0, 3.0]),      // 1-D array
];

$result = $client->call(/* … */, inputArguments: $args);

See Types · DataValue and Variant for the array / scalar / multidimensional encoding rules.

Discovering methods

The simplest path: browse the object, filter for NodeClass::Method:

php list methods on an object
use PhpOpcua\Client\Types\NodeClass;

$methods = $client->browse(
    $objectId,
    nodeClassMask: NodeClass::Method->value,
);

foreach ($methods as $m) {
    echo "{$m->displayName->text}  ({$m->nodeId})\n";
}

To read a method's argument signature, read its InputArguments and OutputArguments properties (children with those BrowseNames). Each is an array of Argument ExtensionObjects — for now, decoded to raw bytes; extracting the field-level structure requires registering the Argument codec manually. See Extensibility · Extension object codecs.

Error handling

call() itself raises on transport / channel / session failures (see Reference · Exceptions). Semantic failures are surfaced through statusCode:

StatusCode Meaning
BadMethodInvalid $methodId is not a method on $objectId
BadArgumentsMissing Too few input arguments
BadTooManyArguments Too many input arguments
BadInvalidArgument One or more inputs failed validation — inspect inputArgumentResults
BadUserAccessDenied Session is not authorised
BadNothingToDo The method had no effect (server-defined)

Tip

A BadInvalidArgument overall status with inputArgumentResults flagging only the last entry usually means the method signature expects a type you did not pass — wrap that argument in an explicit Variant with the right BuiltinType.

What about asynchronous methods?

The library only supports the synchronous OPC UA Call service. The asynchronous variant — where a server schedules the method and returns later via a subscription — is rare in practice and not exposed here. For long-running operations on the server, prefer:

  • A synchronous call() that returns a request ID, followed by polling a status node via read().
  • A subscription on a status node that the server updates as the operation progresses. See Operations · Subscriptions.