OPC UA Write Task
Learn how to send commands to OPC UA servers with Synnax.
For task lifecycle management, see the Task Basics page.
How Commands Work
OPC UA write tasks use command channels to send values to the server:
- Command channels: Write values here to send commands to the OPC UA server
- Command time channels (
_cmd_time): Index channels storing command timestamps
OPC UA write tasks do not create separate state channels. To read back the current state, configure a read task for the same node.
Task Configuration Reference
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | - | Human-readable task name |
device | string | Yes | - | Key of the OPC UA server device |
auto_start | boolean | No | false | Automatically start task after configuration |
channels | array | Yes | - | List of output channel configurations |
Channel Configuration Reference
OPC UA Write Service Specification
Scalar Values
Writes scalar values to an OPC UA node. Suitable for control setpoints, configuration parameters, and single-value commands.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
channel | number | Yes | - | Synnax command channel key |
node_id | string | Yes | - | OPC UA NodeId (e.g., ns=2;s=Setpoint) |
enabled | boolean | No | true | Enable or disable writing to this node |
NodeId Format Examples:
- Numeric:
ns=2;i=1000 - String:
ns=2;s=ControlSetpoint - GUID:
ns=2;g=12345678-1234-1234-1234-123456789012 - Opaque:
ns=2;b=aGVsbG8=
Note: Configuring a write task creates only command channels (_cmd and
_cmd_time). If you need state feedback, configure a corresponding
read task to monitor the same nodes.
Array Values
Writes array data to an OPC UA node in bulk. Used for batch control commands or multi-value setpoints.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
channel | number | Yes | - | Synnax command channel key |
node_id | string | Yes | - | OPC UA NodeId pointing to an array variable |
enabled | boolean | No | true | Enable or disable writing to this node |
Note: The channel data type must match the array element type on the server.
Important Rules
- Direct write: Commands are written directly to the OPC UA server without state feedback channels.
- One running task per node: A node can only be controlled by one write task at a time.
- Node permissions: The OPC UA server must allow write access to the specified nodes.
- Data type matching: Ensure Synnax channel data types match the OPC UA node data types.
How-To
Configure and run task
import synnax as sy
from synnax.hardware import opcua
client = sy.Synnax()
# Retrieve OPC UA server device
dev = client.hardware.devices.retrieve(name="my_opc_server")
# Create command time index
cmd_time = client.channels.create(
name="opc_cmd_time",
is_index=True,
data_type=sy.DataType.TIMESTAMP,
retrieve_if_name_exists=True,
)
# Create command channels
setpoint_cmd = client.channels.create(
name="temperature_setpoint_cmd",
index=cmd_time.key,
data_type=sy.DataType.FLOAT32,
retrieve_if_name_exists=True,
)
valve_cmd = client.channels.create(
name="valve_control_cmd",
index=cmd_time.key,
data_type=sy.DataType.UINT8,
retrieve_if_name_exists=True,
)
# Create and configure task
task = opcua.WriteTask(
name="OPC UA Write Task",
device=dev.key,
channels=[
opcua.WriteChannel(
cmd_channel=setpoint_cmd.key,
node_id="ns=2;s=TemperatureSetpoint",
),
opcua.WriteChannel(
cmd_channel=valve_cmd.key,
node_id="ns=2;s=ValveControl",
),
],
)
client.hardware.tasks.configure(task)
# Start task and send commands
with task.run():
with client.open_writer(
start=sy.TimeStamp.now(),
channels=["temperature_setpoint_cmd", "valve_control_cmd"],
) as writer:
# Set temperature setpoint
writer.write({
"temperature_setpoint_cmd": 25.5,
})
# Open valve
writer.write({
"valve_control_cmd": 1,
})
# Close valve after delay
import time
time.sleep(2)
writer.write({
"valve_control_cmd": 0,
}) Edit task configuration
# Retrieve existing task
task = client.hardware.tasks.retrieve(name="OPC UA Write Task")
task = opcua.WriteTask(internal=task)
# Update task-level configuration
task.config.auto_start = True
# Update first channel configuration
task.config.channels[0].node_id = "ns=2;s=TemperatureSetpoint2"
# Update second channel configuration
task.config.channels[1].node_id = "ns=2;s=ValveControl2"
# Apply changes
client.hardware.tasks.configure(task) Configure and run task
import { Synnax, TimeStamp } from "@synnaxlabs/client";
const client = new Synnax();
// Retrieve OPC UA server device
const dev = await client.hardware.devices.retrieve({ name: "my_opc_server" });
// Create command time index
const cmdTime = await client.channels.create({
name: "opc_cmd_time",
isIndex: true,
dataType: "timestamp",
retrieveIfNameExists: true,
});
// Create command channels
const setpointCmd = await client.channels.create({
name: "temperature_setpoint_cmd",
index: cmdTime.key,
dataType: "float32",
retrieveIfNameExists: true,
});
const valveCmd = await client.channels.create({
name: "valve_control_cmd",
index: cmdTime.key,
dataType: "uint8",
retrieveIfNameExists: true,
});
// Create and configure task
const task = await client.hardware.tasks.create({
name: "OPC UA Write Task",
type: "opc_write",
config: JSON.stringify({
device: dev.key,
channels: [
{
channel: setpointCmd.key,
node_id: "ns=2;s=TemperatureSetpoint",
},
{
channel: valveCmd.key,
node_id: "ns=2;s=ValveControl",
},
],
}),
});
// Start task
await task.executeCommandSync("start");
// Send commands
const writer = await client.openWriter({
start: TimeStamp.now(),
channels: ["temperature_setpoint_cmd", "valve_control_cmd"],
});
// Set temperature setpoint
await writer.write({
temperature_setpoint_cmd: 25.5,
});
// Open valve
await writer.write({
valve_control_cmd: 1,
});
// Close valve after delay
await new Promise((resolve) => setTimeout(resolve, 2000));
await writer.write({
valve_control_cmd: 0,
});
// Stop task
await task.executeCommandSync("stop");
await writer.close(); Edit task configuration
// Retrieve existing task
const task = await client.hardware.tasks.retrieve({ name: "OPC UA Write Task" });
// Parse and update configuration
const config = JSON.parse(task.config);
// Update task-level configuration
config.auto_start = true;
// Update first channel configuration
config.channels[0].node_id = "ns=2;s=TemperatureSetpoint2";
// Update second channel configuration
config.channels[1].node_id = "ns=2;s=ValveControl2";
// Apply changes
await client.hardware.tasks.create({
key: task.key,
name: task.name,
type: task.type,
config: JSON.stringify(config),
});