> For the complete documentation index, see [llms.txt](https://docs.cybus.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cybus.io/2-4-2/guides/machine-connectivity/plcs-industrial-controllers/connecting-a-phoenix-contact-plcnext-controller.md).

# Connecting a Phoenix Contact PLCnext Controller

This guide shows you how to read data from a Phoenix Contact PLCnext controller, such as the AXC F 2152, with the Connectware [OPC UA connector](/2-4-2/connectors/shop-floor-connectors/opc-ua/opc-ua-client.md) and map it into an ISA-95 style MQTT topic hierarchy. Every PLCnext controller ships with a built-in OPC UA server, so no additional hardware or gateway is required to make PLC variables available to Connectware. In more detail, the following topics are covered:

* Understanding how the PLCnext OPC UA server exposes variables
* Making variables OPC UA accessible in PLCnext Engineer
* Understanding the PLCnext authentication and security defaults
* Creating the [service commissioning file](/2-4-2/data-flows/service-commissioning-files.md)
* Mapping the data into an ISA-95 style MQTT topic hierarchy
* Verifying data in the [Data Explorer](/2-4-2/monitoring/data-explorer.md)

This guide focuses on the PLCnext specifics. For the general workflow of browsing an OPC UA address space and picking NodeIds, see [Using Connectware as an OPC UA Client](/2-4-2/guides/system-connectivity/industry-standards-interoperability/using-connectware-as-an-opc-ua-client.md).

A complete example file is available at the end of this guide.

## Prerequisites

To follow this guide, you will need the following:

* A running instance of Cybus Connectware.
* A Phoenix Contact PLCnext controller, for example an AXC F 2152, that is reachable over Ethernet from Connectware.
* Phoenix Contact PLCnext Engineer and access to the PLC program of the controller. For the controller-side documentation, see the [PLCnext Info Center](https://www.plcnext.help/).
* The username and password of a user configured on the controller.
* Access to the [Admin UI](/2-4-2/access/admin-ui.md) with sufficient [user permissions](/2-4-2/access/user-management.md).
* Basic knowledge of MQTT and the Connectware [services](/2-4-2/data-flows/services.md) concept (for example, [service commissioning files](/2-4-2/data-flows/service-commissioning-files.md), [connections](/2-4-2/data-flows/service-commissioning-files/resources/cybus-connection.md), and [endpoints](/2-4-2/data-flows/service-commissioning-files/resources/cybus-endpoint.md)).

## How the PLCnext OPC UA Server Exposes Variables

The PLCnext firmware includes an embedded OPC UA server, called the eUA server. It listens on the standard OPC UA port 4840, so the endpoint URL of the controller is `opc.tcp://${PLCNEXT_HOST}:4840`, where `${PLCNEXT_HOST}` is the hostname or IP address of the controller.

The eUA server publishes the variables of the IEC 61131-3 program from the Global Data Space (GDS) of the controller in the namespace `http://phoenixcontact.com/OpcUA/PLCnext/GlobalDataSpace/`. Each variable is addressed by a string NodeId of the following form:

{% code lineNumbers="true" %}

```
ns=${NAMESPACE_INDEX};s=Arp.Plc.Eclr/${PROGRAM_INSTANCE}.${VARIABLE_NAME}
```

{% endcode %}

* `${NAMESPACE_INDEX}` is the index of the GDS namespace on your controller. The index is not fixed, so read it from the namespace array of the server or from an OPC UA browser as described in [Using Connectware as an OPC UA Client](/2-4-2/guides/system-connectivity/industry-standards-interoperability/using-connectware-as-an-opc-ua-client.md).
* `${PROGRAM_INSTANCE}` is the name of the program instance in your PLCnext Engineer project.
* `${VARIABLE_NAME}` is the name of the variable. Nested paths such as function block instances and structure fields are appended with dots, for example `Arp.Plc.Eclr/MainInstance.Drive1.ActualSpeed`.

For security reasons, the variables of a PLCnext Engineer project are not visible to OPC UA clients by default. You mark the variables in PLCnext Engineer first, as described in [Making Variables Accessible in PLCnext Engineer](#making-variables-accessible-in-plcnext-engineer).

## Making Variables Accessible in PLCnext Engineer

Configure the eUA server and mark the variables in your PLCnext Engineer project:

1. Open the variable table of your program and select the **OPC** check box for each variable that Connectware should read.
2. In the **PLANT** area, open the **OPC UA** node.
3. In the **Basic settings**, set **Visibility of variables** to **Marked**. With this setting, all variables marked with the **OPC** check box become accessible through the eUA server. Alternatively, the **All** setting exposes every GDS variable without marking, which is convenient for testing but exposes more data than necessary.
4. Write the project to the controller and restart the PLC program.

For details on these settings, see [Basic OPC UA Settings](https://engineer.plcnext.help/latest/OPC_BasicSettings.htm) in the PLCnext Engineer online help.

### Authentication and Security Defaults

The PLCnext firmware enforces a secure configuration of the eUA server by default:

* **User authentication is required.** OPC UA clients authenticate with the username and password of a user configured on the controller, for example through the Web-based Management (WBM) of the controller. Anonymous sessions are rejected by default.
* **Username and password authentication requires an encrypted endpoint.** The eUA server does not accept username identity tokens on unencrypted endpoints, and the security policy `None` is disabled by default. The connection example in this guide therefore uses the message security mode `SignAndEncrypt` with the security policy `Aes128_Sha256_RsaOaep`, which the eUA server enables by default. The deprecated `Basic128Rsa15`, `Basic256`, and `Basic256Sha256` policies are disabled by default in current firmware versions.
* **Client certificates are trusted as long as the trust store is empty.** For an encrypted connection, the client presents a certificate. As long as the trust store of the eUA server is empty, the server trusts all clients. To restrict access to specific clients, add the Connectware client certificate to the trust store of the controller.

For details, see [OPC UA Security Settings](https://engineer.plcnext.help/latest/OPC_Security.htm) in the PLCnext Engineer online help.

{% hint style="danger" %}
If user authentication is disabled on the controller, the eUA server accepts anonymous sessions and enables the security policy `None`. This gives any OPC UA client on the network unrestricted access to the controller. Keep user authentication enabled in production environments.
{% endhint %}

## Choosing the Variables

This guide reads a small set of variables that is typical for machine monitoring on a packaging line. The NodeIds are project-specific: replace the namespace index and the `Arp.Plc.Eclr/${PROGRAM_INSTANCE}.${VARIABLE_NAME}` paths with the values from your own PLCnext Engineer project.

| Variable          | Data type | NodeId (project-specific)                          | Sampling interval |
| ----------------- | --------- | -------------------------------------------------- | ----------------: |
| `ConveyorRunning` | BOOL      | `ns=5;s=Arp.Plc.Eclr/MainInstance.ConveyorRunning` |           1000 ms |
| `MotorSpeed`      | REAL      | `ns=5;s=Arp.Plc.Eclr/MainInstance.MotorSpeed`      |            250 ms |
| `MotorCurrent`    | REAL      | `ns=5;s=Arp.Plc.Eclr/MainInstance.MotorCurrent`    |            250 ms |
| `PieceCounter`    | UDINT     | `ns=5;s=Arp.Plc.Eclr/MainInstance.PieceCounter`    |           1000 ms |

OPC UA subscriptions are change-driven: the server samples each variable at the `samplingInterval` and only sends a notification when the value changes. Connectware combines all endpoints with the same `publishInterval` into one OPC UA subscription, so the example uses one common publish interval. For details, see [Connectware Subscriptions](/2-4-2/connectors/shop-floor-connectors/opc-ua/opc-ua-client.md#connectware-subscriptions) and the [OPC UA endpoint properties](/2-4-2/connectors/shop-floor-connectors/opc-ua/opc-ua-client/opcuaendpoint.md).

## Writing the Service Commissioning File

The service commissioning file contains all connection and mapping details. Do not worry about copying the snippets together into one file, the complete example file is available at the end of this guide.

### Description and Metadata

These sections contain general information about the service commissioning file. Only the metadata name is required.

{% code lineNumbers="true" %}

```yaml
description: >
  Service commissioning file that reads variables from the built-in OPC UA
  server of a Phoenix Contact PLCnext controller with the OPC UA connector
  and maps them into an ISA-95 style MQTT topic hierarchy (Example)

metadata:
  name: PLCnext Controller Example
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0
```

{% endcode %}

### Parameters and Definitions

We define the network address and the credentials of the controller as parameters, so you can set them when you install the service. The default OPC UA port is 4840.

The MQTT topics in this guide follow an ISA-95 style equipment hierarchy (`<enterprise>/<site>/<area>/<line>/<work-cell>`). We define the prefix once in the `definitions` section and reuse it in every mapping with `!sub`.

{% code lineNumbers="true" %}

```yaml
parameters:
  plcnextHost:
    description: Hostname or IP address of the PLCnext controller
    type: string
    default: 192.168.1.100

  plcnextPort:
    description: Port of the PLCnext OPC UA server
    type: integer
    default: 4840

  plcnextUsername:
    description: Username of a PLCnext user with OPC UA access
    type: string
    default: ''

  plcnextPassword:
    description: Password of the PLCnext user
    type: string
    default: ''

definitions:
  MQTT_TOPIC_PREFIX: enterprise/hamburg/packaging/line-2/plc-01
```

{% endcode %}

### Cybus::Connection

The connection resource establishes the OPC UA session with the eUA server. The security options match the PLCnext defaults described in [Authentication and Security Defaults](#authentication-and-security-defaults): username and password authentication over an encrypted endpoint with the `Aes128_Sha256_RsaOaep` security policy. For all connection properties, including custom client certificates and the `connectionStrategy` retry behavior, see [OPC UA Connection Properties](/2-4-2/connectors/shop-floor-connectors/opc-ua/opc-ua-client/opcuaconnection.md).

{% code lineNumbers="true" %}

```yaml
resources:
  plcnextConnection:
    type: Cybus::Connection
    properties:
      protocol: Opcua
      targetState: connected
      connection:
        host: !ref plcnextHost
        port: !ref plcnextPort
        username: !ref plcnextUsername
        password: !ref plcnextPassword
        options:
          messageSecurityMode: SignAndEncrypt
          securityPolicy: Aes128_Sha256_RsaOaep
```

{% endcode %}

### Cybus::Endpoint

Each endpoint subscribes to one variable by its NodeId, according to the table in [Choosing the Variables](#choosing-the-variables). Remember that the NodeIds are project-specific.

{% code lineNumbers="true" %}

```yaml
conveyorRunning:
  type: Cybus::Endpoint
  properties:
    protocol: Opcua
    connection: !ref plcnextConnection
    subscribe:
      nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.ConveyorRunning
      samplingInterval: 1000
      publishInterval: 1000

motorSpeed:
  type: Cybus::Endpoint
  properties:
    protocol: Opcua
    connection: !ref plcnextConnection
    subscribe:
      nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.MotorSpeed
      samplingInterval: 250
      publishInterval: 1000

motorCurrent:
  type: Cybus::Endpoint
  properties:
    protocol: Opcua
    connection: !ref plcnextConnection
    subscribe:
      nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.MotorCurrent
      samplingInterval: 250
      publishInterval: 1000

pieceCounter:
  type: Cybus::Endpoint
  properties:
    protocol: Opcua
    connection: !ref plcnextConnection
    subscribe:
      nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.PieceCounter
      samplingInterval: 1000
      publishInterval: 1000
```

{% endcode %}

### Cybus::Mapping

The mapping publishes each endpoint on a topic of the ISA-95 hierarchy.

{% code lineNumbers="true" %}

```yaml
mapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          endpoint: !ref conveyorRunning
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/conveyor/running'
      - subscribe:
          endpoint: !ref motorSpeed
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/motor/speed'
      - subscribe:
          endpoint: !ref motorCurrent
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/motor/current'
      - subscribe:
          endpoint: !ref pieceCounter
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/production/piece-counter'
```

{% endcode %}

With this mapping, the motor speed is published on the topic `enterprise/hamburg/packaging/line-2/plc-01/motor/speed`, and every other variable follows the same pattern.

## Installing the Service Commissioning File

1. Install the service commissioning file. See [Installing Services](/2-4-2/data-flows/services/managing/installing.md).
2. Enable the service. See [Enabling Services](/2-4-2/data-flows/services/managing/enabling.md).

**Result:** The service is enabled. Connectware opens an OPC UA session with the eUA server of the controller and subscribes to the configured variables.

## Verifying the Data

Open the [Data Explorer](/2-4-2/monitoring/data-explorer.md) and subscribe to `enterprise/hamburg/packaging/line-2/plc-01/#`. Each topic carries a JSON object with the keys `timestamp` and `value`, where the timestamp is the OPC UA source timestamp set by the controller. For example, the motor speed:

{% code lineNumbers="true" %}

```json
{
  "timestamp": 1784194200354,
  "value": 87.5
}
```

{% endcode %}

Because OPC UA subscriptions are change-driven, a variable that never changes only publishes once after the subscription is established. Toggle a marked variable in the PLCnext Engineer debug mode to see an immediate update.

If the connection does not reach the **Connected** state, work through the following checks:

* Verify that the controller is reachable from Connectware on port 4840.
* Verify that the security options match the controller configuration. With the PLCnext defaults, a connection without `messageSecurityMode` and `securityPolicy` options is rejected because username and password authentication is only accepted on encrypted endpoints.
* Verify the username and password. The credentials belong to a user on the controller, not to a PLCnext Engineer or Connectware user.
* If the trust store of the eUA server is not empty, verify that it contains the Connectware client certificate.

If the connection is established but a topic stays empty, verify that the variable has the **OPC** check box selected, that **Visibility of variables** is set to **Marked**, and that the namespace index and the program instance name in the NodeId match your project.

## Service Commissioning File Example

{% file src="/files/sxpPVHcNKQs0Rd7OiyrX" %}

{% code title="plcnext-example.yml" lineNumbers="true" expandable="true" %}

```yaml
---
# ----------------------------------------------------------------------------
# Service Commissioning File
# ----------------------------------------------------------------------------
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------
# Connecting a Phoenix Contact PLCnext Controller (Example)
# ----------------------------------------------------------------------------

description: >
  Service commissioning file that reads variables from the built-in OPC UA
  server of a Phoenix Contact PLCnext controller with the OPC UA connector
  and maps them into an ISA-95 style MQTT topic hierarchy (Example)

metadata:
  name: PLCnext Controller Example
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  plcnextHost:
    description: Hostname or IP address of the PLCnext controller
    type: string
    default: 192.168.1.100

  plcnextPort:
    description: Port of the PLCnext OPC UA server
    type: integer
    default: 4840

  plcnextUsername:
    description: Username of a PLCnext user with OPC UA access
    type: string
    default: ''

  plcnextPassword:
    description: Password of the PLCnext user
    type: string
    default: ''

definitions:
  # ISA-95 style topic prefix: <enterprise>/<site>/<area>/<line>/<work-cell>
  MQTT_TOPIC_PREFIX: enterprise/hamburg/packaging/line-2/plc-01

resources:
  # Connection to the built-in OPC UA server (eUA server) of the controller.
  # With the default PLCnext security configuration, username and password
  # authentication requires an encrypted endpoint.
  plcnextConnection:
    type: Cybus::Connection
    properties:
      protocol: Opcua
      targetState: connected
      connection:
        host: !ref plcnextHost
        port: !ref plcnextPort
        username: !ref plcnextUsername
        password: !ref plcnextPassword
        options:
          messageSecurityMode: SignAndEncrypt
          securityPolicy: Aes128_Sha256_RsaOaep

  # The NodeIds below are project-specific. Replace the namespace index and
  # the Arp.Plc.Eclr/<program-instance>.<variable> paths with the values
  # from your own PLCnext Engineer project.

  # Conveyor running state (BOOL)
  conveyorRunning:
    type: Cybus::Endpoint
    properties:
      protocol: Opcua
      connection: !ref plcnextConnection
      subscribe:
        nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.ConveyorRunning
        samplingInterval: 1000
        publishInterval: 1000

  # Actual motor speed (REAL)
  motorSpeed:
    type: Cybus::Endpoint
    properties:
      protocol: Opcua
      connection: !ref plcnextConnection
      subscribe:
        nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.MotorSpeed
        samplingInterval: 250
        publishInterval: 1000

  # Actual motor current (REAL)
  motorCurrent:
    type: Cybus::Endpoint
    properties:
      protocol: Opcua
      connection: !ref plcnextConnection
      subscribe:
        nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.MotorCurrent
        samplingInterval: 250
        publishInterval: 1000

  # Produced piece counter (UDINT)
  pieceCounter:
    type: Cybus::Endpoint
    properties:
      protocol: Opcua
      connection: !ref plcnextConnection
      subscribe:
        nodeId: ns=5;s=Arp.Plc.Eclr/MainInstance.PieceCounter
        samplingInterval: 1000
        publishInterval: 1000

  mapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref conveyorRunning
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/conveyor/running'
        - subscribe:
            endpoint: !ref motorSpeed
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/motor/speed'
        - subscribe:
            endpoint: !ref motorCurrent
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/motor/current'
        - subscribe:
            endpoint: !ref pieceCounter
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/production/piece-counter'
```

{% endcode %}

{% hint style="info" %}
Disclaimer: PLCnext, PLCnext Engineer, and AXC F 2152 are trademarks or product designations of Phoenix Contact.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cybus.io/2-4-2/guides/machine-connectivity/plcs-industrial-controllers/connecting-a-phoenix-contact-plcnext-controller.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
