> 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/system-connectivity/industry-standards-interoperability/vda-5050-agv-integration.md).

# VDA 5050 AGV Integration

This guide describes how to use Connectware as the MQTT broker between automated guided vehicles (AGVs) that implement the VDA 5050 interface and a master control system. You configure a service commissioning file that creates the users and permissions for both sides and maps AGV state data into a Unified Namespace (UNS). A complete example file is available at the end of this guide.

## Objectives

* Understanding the VDA 5050 topic structure and which side publishes on which topic.
* Creating Connectware users and roles with least-privilege permissions for AGVs and the master control system.
* Making AGV battery and position data visible in a UNS topic hierarchy.
* Verifying the integration with an MQTT client.

## Prerequisites

To follow this guide, you will need the following:

* A running instance of Cybus Connectware.
* One or more AGVs or autonomous mobile robots (AMRs) that implement VDA 5050 version 2, and a master control system (often called fleet manager) that implements the same version. Both must have network access to the Connectware MQTT broker on port `8883` (TLS) or `1883`.
* 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), [mappings](/2-4-2/data-flows/service-commissioning-files/resources/cybus-mapping.md), and [roles](/2-4-2/data-flows/service-commissioning-files/resources/cybus-role.md)).
* It helps to be familiar with [Connecting an MQTT Client to Publish and Subscribe Data](/2-4-2/guides/machine-connectivity/gateways-generic-protocols/connecting-an-mqtt-client-to-publish-and-subscribe-data.md).

## Connectware and VDA 5050 Integration

[VDA 5050](https://github.com/VDA5050/VDA5050) is a standardized interface for the communication between AGVs and a master control system, published by the German Association of the Automotive Industry (VDA) and the VDMA Materials Handling and Intralogistics Association. The interface is broker-centric by design: AGVs and the master control never talk to each other directly. Both connect as MQTT clients to a broker and exchange JSON messages on well-defined topics.

VDA 5050 defines the topics and messages, but not the broker. Connectware fills this role:

* **Central broker**: AGVs from different manufacturers and the master control system all connect to the same Connectware instance. No vehicle-specific broker or gateway is required.
* **Governed access**: Connectware [permissions](/2-4-2/access/user-management/permissions.md) restrict each AGV to its own topic subtree, so one misconfigured vehicle cannot publish state for another.
* **Plain JSON payloads**: Unlike binary payload formats such as Sparkplug B, VDA 5050 messages are plain JSON. Connectware can read, transform, and route them with the [Rule Engine](/2-4-2/data-flows/rule-engine.md), for example to republish battery and position data into a UNS.
* **Monitoring**: You can inspect all VDA 5050 traffic live in the [Data Explorer](/2-4-2/monitoring/data-explorer.md).

This guide follows VDA 5050 version 2.1.0. The topic examples use the major version `v2`.

### VDA 5050 Topic Structure

VDA 5050 suggests the following MQTT topic structure for local brokers:

{% code lineNumbers="true" %}

```
<interfaceName>/<majorVersion>/<manufacturer>/<serialNumber>/<topic>
```

{% endcode %}

For example, the master control sends orders to the AGV with the serial number `0001` of the manufacturer `KIT` on the topic `uagv/v2/KIT/0001/order`. The interface name and the major version are subject to agreement between the AGV vendors and the master control vendor. This guide uses `uagv/v2`, which matches the example in the specification.

The subtopic names are mandatory. The following subtopics are defined:

| Subtopic         | Direction            | Content                                                                                                                 | QoS | Retained |
| ---------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------- | --- | -------- |
| `order`          | Master control → AGV | A driving order as a graph of nodes and edges, including actions to execute.                                            | 0   | No       |
| `instantActions` | Master control → AGV | Actions that the AGV executes immediately, for example pausing or starting a charging process.                          | 0   | No       |
| `state`          | AGV → Master control | The full AGV state: order progress, battery, position, errors. Sent on relevant events, at the latest every 30 seconds. | 0   | No       |
| `visualization`  | AGV → Master control | Position and velocity at a higher, integrator-defined update rate, for near real-time visualization.                    | 0   | No       |
| `connection`     | AGV → Master control | The connection state of the AGV, maintained with the MQTT last will mechanism.                                          | 1   | Yes      |
| `factsheet`      | AGV → Master control | The capabilities and parameters of the AGV, such as its physical dimensions and supported actions.                      | 0   | Yes      |

The quality of service (QoS) and retained flags in the table are the conventions that the specification mandates. The AGV and the master control set them on their own publishes; there is nothing to configure in Connectware for this.

### Connection Topic and MQTT Last Will

The `connection` topic tells the master control whether an AGV is reachable. Its payload contains a `connectionState` field with one of the following values:

| Value              | Meaning                                                                                   |
| ------------------ | ----------------------------------------------------------------------------------------- |
| `ONLINE`           | The AGV is connected to the broker.                                                       |
| `OFFLINE`          | The AGV disconnected gracefully and published this message before closing the connection. |
| `CONNECTIONBROKEN` | The connection between the AGV and the broker ended unexpectedly.                         |

The `CONNECTIONBROKEN` message is never sent by the AGV itself. When the AGV connects, it registers an MQTT last will on its `connection` topic with `connectionState: CONNECTIONBROKEN`, QoS 1, and the retained flag. If the connection drops unexpectedly, the Connectware broker publishes this last will on behalf of the AGV. Right after connecting, the AGV publishes `connectionState: ONLINE` as a retained message, so the topic always carries the current availability of the vehicle.

Because the broker publishes the last will under the identity of the AGV client, the AGV user needs write permission on its `connection` topic like on any other topic it publishes to. The permission setup in this guide includes it.

## Creating Users and Permissions

Both the AGV and the master control system authenticate against Connectware with username and password, like any other MQTT client. For more information, see [MQTT Client Authentication](/2-4-2/access/user-management/mqtt-user-authentication.md). We create the users and their roles in the service commissioning file with the [Cybus::User](/2-4-2/data-flows/service-commissioning-files/resources/cybus-user.md) and [Cybus::Role](/2-4-2/data-flows/service-commissioning-files/resources/cybus-role.md) resources.

Do not worry about copying the service commissioning file snippets together into one, the complete example file is available at the end of this guide.

### Integration Parameters

We add the manufacturer and serial number of the AGV, the passwords, and the UNS topic root as parameters, so you can set them when you install the service:

* `manufacturer` and `serialNumber`: Identify the AGV in the VDA 5050 topic structure. They must match the values that the AGV uses in its own configuration.
* `agvPassword` and `masterControlPassword`: The passwords for the two MQTT users.
* `topicRoot`: The root of the UNS topic hierarchy. Defaults to `enterprise`.

{% code lineNumbers="true" %}

```yaml
parameters:
  manufacturer:
    description: Manufacturer of the AGV as used in the VDA 5050 topic structure
    type: string
    default: KIT

  serialNumber:
    description: Serial number of the AGV as used in the VDA 5050 topic structure
    type: string
    default: '0001'

  agvPassword:
    description: Password for the MQTT user of the AGV
    type: string

  masterControlPassword:
    description: Password for the MQTT user of the master control system
    type: string

  topicRoot:
    description: Root of the UNS topic hierarchy
    type: string
    default: enterprise
```

{% endcode %}

### AGV User and Role

The AGV subscribes to its `order` and `instantActions` topics and publishes on its `state`, `visualization`, `connection`, and `factsheet` topics. The role grants exactly these permissions, restricted to the subtree of this one vehicle:

{% code lineNumbers="true" %}

```yaml
resources:
  agvRole:
    type: Cybus::Role
    properties:
      permissions:
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/order'
          operation: read
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/instantActions'
          operation: read
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/state'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/visualization'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/connection'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/factsheet'
          operation: write
          context: mqtt

  agv_kit_0001:
    type: Cybus::User
    properties:
      password: !ref agvPassword
      roles:
        - !ref agvRole
```

{% endcode %}

The resource identifier of the user becomes the username, prefixed with the [service ID](/2-4-2/data-flows/services/serviceid.md) that you assign when you install the service. For example, with the service ID `vda5050`, the AGV authenticates as `vda5050.agv_kit_0001`. If you change the `manufacturer` or `serialNumber` parameters, rename the user resource accordingly. When you operate several AGVs, add one user and one role per vehicle, so each vehicle stays restricted to its own subtree.

{% hint style="info" %}
Instead of defining AGV users in the service commissioning file, you can also let vehicles register themselves via the [Client Registry](/2-4-2/access/client-registry.md) and assign the permissions in the Admin UI. This is convenient when vehicles are commissioned one by one on the shop floor.
{% endhint %}

### Master Control User and Role

The master control system needs the opposite permissions, across all vehicles: it publishes orders and instant actions to any AGV and subscribes to everything the AGVs report. The single-level wildcard `+` matches any manufacturer and serial number:

{% code lineNumbers="true" %}

```yaml
masterControlRole:
  type: Cybus::Role
  properties:
    permissions:
      - resource: uagv/v2/+/+/order
        operation: write
        context: mqtt
      - resource: uagv/v2/+/+/instantActions
        operation: write
        context: mqtt
      - resource: uagv/v2/#
        operation: read
        context: mqtt

master_control:
  type: Cybus::User
  properties:
    password: !ref masterControlPassword
    roles:
      - !ref masterControlRole
```

{% endcode %}

## Making AGV State Visible in the UNS

The `state` message carries everything the master control needs to run the fleet, but consumers such as dashboards, historians, or an andon board usually only need a few fields. Because the payload is plain JSON, a [Cybus::Mapping](/2-4-2/data-flows/service-commissioning-files/resources/cybus-mapping.md) with a `transform` rule can extract these fields and republish them into an ISA-95-style UNS hierarchy (`<enterprise>/<site>/<area>/<line>/<cell>`).

The following abridged `state` message shows the fields used in this guide. A complete state message also contains fields such as `orderUpdateId`, `nodeStates`, `edgeStates`, `actionStates`, `driving`, `operatingMode`, `errors`, and `safetyState`:

{% code lineNumbers="true" %}

```json
{
  "headerId": 1,
  "timestamp": "2026-07-16T11:40:03.12Z",
  "version": "2.1.0",
  "manufacturer": "KIT",
  "serialNumber": "0001",
  "orderId": "order-4711",
  "batteryState": {
    "batteryCharge": 74.5,
    "charging": false
  },
  "agvPosition": {
    "positionInitialized": true,
    "x": 12.4,
    "y": 4.9,
    "theta": 1.57,
    "mapId": "hall-1"
  }
}
```

{% endcode %}

The mapping subscribes to the `state` topics of all vehicles with the named wildcards `+manufacturer` and `+serial` and reuses the matched values in the output topics as `$manufacturer` and `$serial`. Two `transform` rules extract the battery and position fields. A third mapping entry republishes the `connectionState` with the retained flag, so the UNS always shows the current availability of each vehicle:

{% code lineNumbers="true" %}

```yaml
unsMapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          topic: 'uagv/v2/+manufacturer/+serial/state'
        publish:
          topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/battery'
        rules:
          - transform:
              expression: >
                {
                  "batteryCharge": batteryState.batteryCharge,
                  "charging": batteryState.charging,
                  "timestamp": timestamp
                }
      - subscribe:
          topic: 'uagv/v2/+manufacturer/+serial/state'
        publish:
          topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/position'
        rules:
          - transform:
              expression: >
                {
                  "x": agvPosition.x,
                  "y": agvPosition.y,
                  "theta": agvPosition.theta,
                  "mapId": agvPosition.mapId,
                  "timestamp": timestamp
                }
      - subscribe:
          topic: 'uagv/v2/+manufacturer/+serial/connection'
        publish:
          topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/connection-state'
          retain: true
        rules:
          - transform:
              expression: >
                {
                  "connectionState": connectionState,
                  "timestamp": timestamp
                }
```

{% endcode %}

Adjust the site and area segments (`hamburg/intralogistics/agv-fleet`) to your own hierarchy. With the state message shown earlier, the mapping publishes the following message to `enterprise/hamburg/intralogistics/agv-fleet/KIT/0001/battery`:

{% code lineNumbers="true" %}

```json
{
  "batteryCharge": 74.5,
  "charging": false,
  "timestamp": "2026-07-16T11:40:03.12Z"
}
```

{% endcode %}

The `agvPosition` object is optional in VDA 5050. For vehicles that do not report a position, the transform output simply omits the position fields.

{% hint style="info" %}
The mapping deliberately uses the `state` topic, not the `visualization` topic. The `visualization` topic carries the same position data at a much higher, integrator-defined update rate. Running transforms on it multiplies the processing load for every vehicle. Only add a mapping on the `visualization` topic if a consumer really needs the higher update rate.
{% endhint %}

## Verifying the Integration

1. Install the service and set the parameters, including the two passwords. See [Installing Services](/2-4-2/data-flows/services/managing/installing.md).
2. Configure the AGV and the master control system with the Connectware hostname, port `8883` (TLS) or `1883`, and their usernames and passwords. Remember that the usernames are prefixed with the service ID, for example `vda5050.agv_kit_0001` and `vda5050.master_control`.
3. Open the [Data Explorer](/2-4-2/monitoring/data-explorer.md) and subscribe to `uagv/v2/#`. When the AGV connects, its retained `ONLINE` message appears on the `connection` topic, followed by `state` messages.
4. Check the UNS topics, for example `enterprise/hamburg/intralogistics/agv-fleet/KIT/0001/battery`. The extracted battery and position messages appear whenever the AGV publishes its state.

If no real vehicle is available yet, you can simulate one with an MQTT client such as `mosquitto_pub`:

{% code lineNumbers="true" %}

```bash
mosquitto_pub -h ${CONNECTWARE_HOST} -p 1883 \
  -u ${SERVICE_ID}.agv_kit_0001 -P ${AGV_PASSWORD} \
  -t uagv/v2/KIT/0001/state \
  -m '{"headerId":1,"timestamp":"2026-07-16T11:40:03.12Z","version":"2.1.0","manufacturer":"KIT","serialNumber":"0001","orderId":"","batteryState":{"batteryCharge":74.5,"charging":false},"agvPosition":{"positionInitialized":true,"x":12.4,"y":4.9,"theta":1.57,"mapId":"hall-1"}}'
```

{% endcode %}

Replace the following values:

* `${CONNECTWARE_HOST}`: The hostname or IP address of your Connectware instance.
* `${SERVICE_ID}`: The service ID that you assigned when you installed the service.
* `${AGV_PASSWORD}`: The value of the `agvPassword` parameter.

## Service Commissioning File Example

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

{% code title="vda-5050-agv-example.yml" lineNumbers="true" expandable="true" %}

```yaml
---
# ----------------------------------------------------------------------------
# Service Commissioning File
# ----------------------------------------------------------------------------
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------
# VDA 5050 AGV Integration (Example)
# ----------------------------------------------------------------------------

description: >
  Service commissioning file for using Connectware as the MQTT broker
  between VDA 5050 compliant AGVs and a master control system (Example)

metadata:
  name: VDA 5050 AGV Integration
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  manufacturer:
    description: Manufacturer of the AGV as used in the VDA 5050 topic structure
    type: string
    default: KIT

  serialNumber:
    description: Serial number of the AGV as used in the VDA 5050 topic structure
    type: string
    default: '0001'

  agvPassword:
    description: Password for the MQTT user of the AGV
    type: string

  masterControlPassword:
    description: Password for the MQTT user of the master control system
    type: string

  topicRoot:
    description: Root of the UNS topic hierarchy
    type: string
    default: enterprise

resources:
  # Permissions for one AGV: subscribe to its command topics,
  # publish on its report topics
  agvRole:
    type: Cybus::Role
    properties:
      permissions:
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/order'
          operation: read
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/instantActions'
          operation: read
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/state'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/visualization'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/connection'
          operation: write
          context: mqtt
        - resource: !sub 'uagv/v2/${manufacturer}/${serialNumber}/factsheet'
          operation: write
          context: mqtt

  # MQTT user for the AGV. The username is prefixed with the service ID,
  # for example vda5050.agv_kit_0001
  agv_kit_0001:
    type: Cybus::User
    properties:
      password: !ref agvPassword
      roles:
        - !ref agvRole

  # Permissions for the master control: publish commands to any AGV,
  # subscribe to everything the AGVs report
  masterControlRole:
    type: Cybus::Role
    properties:
      permissions:
        - resource: uagv/v2/+/+/order
          operation: write
          context: mqtt
        - resource: uagv/v2/+/+/instantActions
          operation: write
          context: mqtt
        - resource: uagv/v2/#
          operation: read
          context: mqtt

  # MQTT user for the master control system
  master_control:
    type: Cybus::User
    properties:
      password: !ref masterControlPassword
      roles:
        - !ref masterControlRole

  # Extracts battery, position, and connection state of every vehicle
  # into the UNS topic hierarchy
  unsMapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            topic: 'uagv/v2/+manufacturer/+serial/state'
          publish:
            topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/battery'
          rules:
            - transform:
                expression: >
                  {
                    "batteryCharge": batteryState.batteryCharge,
                    "charging": batteryState.charging,
                    "timestamp": timestamp
                  }
        - subscribe:
            topic: 'uagv/v2/+manufacturer/+serial/state'
          publish:
            topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/position'
          rules:
            - transform:
                expression: >
                  {
                    "x": agvPosition.x,
                    "y": agvPosition.y,
                    "theta": agvPosition.theta,
                    "mapId": agvPosition.mapId,
                    "timestamp": timestamp
                  }
        - subscribe:
            topic: 'uagv/v2/+manufacturer/+serial/connection'
          publish:
            topic: !sub '${topicRoot}/hamburg/intralogistics/agv-fleet/$manufacturer/$serial/connection-state'
            retain: true
          rules:
            - transform:
                expression: >
                  {
                    "connectionState": connectionState,
                    "timestamp": timestamp
                  }
```

{% endcode %}


---

# 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/system-connectivity/industry-standards-interoperability/vda-5050-agv-integration.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.
