> 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/migration/migrating-from-kepware-kepserverex.md).

# Migrating from Kepware KEPServerEX

This guide shows you how to migrate an existing Kepware KEPServerEX configuration to Connectware by exporting the KEPServerEX project as JSON and translating it into a [service commissioning file](/2-4-2/data-flows/service-commissioning-files.md). Because both products describe connectivity in a structured, machine-readable format, an AI assistant can do most of the translation work, while you review and verify the result. In more detail, the following topics are covered:

* Understanding how KEPServerEX concepts map to Connectware resources
* Exporting the KEPServerEX project as JSON, from the Configuration client or the Configuration API
* Translating the export into a service commissioning file with an AI assistant
* Reviewing the generated service commissioning file
* Verifying the migrated data points in the [Data Explorer](/2-4-2/monitoring/data-explorer.md)

A complete worked example, from JSON export to service commissioning file, is available at the end of this guide.

{% hint style="info" %}
Migration is not the only way to combine the two products. If you want to keep KEPServerEX in place, for example because a device is only covered by a KEPServerEX driver, Connectware can read all its data through the KEPServerEX OPC UA server interface instead. See [Connecting Legacy Devices via Kepware KEPServerEX](/2-4-2/guides/machine-connectivity/gateways-generic-protocols/connecting-legacy-devices-via-kepware-kepserverex.md).
{% endhint %}

## Prerequisites

To follow this guide, you will need the following:

* A running instance of Cybus Connectware with licenses for the connectors that replace your KEPServerEX drivers.
* Access to the KEPServerEX installation, either to the Configuration client on the Windows machine or to the Configuration API over the network.
* Network access from Connectware to the devices that KEPServerEX currently talks to. After the migration, Connectware connects to the devices directly.
* An AI assistant to translate the export. Any capable large language model (LLM) works, for example through a chat interface or an AI coding tool. [Cybus Connectware GPT](/2-4-2/tools/cybus-connectware-gpt.md) is a ChatGPT assistant that already knows the service commissioning file format.
* Basic knowledge of 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 KEPServerEX Concepts Map to Connectware

A KEPServerEX project is organized in channels, devices, and tags. A channel represents one driver and its physical interface, a device represents one controller on that channel, and tags address the data points of the device. Connectware organizes the same information in resources of a service commissioning file:

| KEPServerEX concept             | Connectware resource                                                                             | Notes                                                                                                                                                  |
| ------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Channel + device                | [Cybus::Connection](/2-4-2/data-flows/service-commissioning-files/resources/cybus-connection.md) | A connection combines the driver choice (protocol) and the device address. Create one connection per KEPServerEX device.                               |
| Tag                             | [Cybus::Endpoint](/2-4-2/data-flows/service-commissioning-files/resources/cybus-endpoint.md)     | Address, data type, and scan rate become the endpoint address properties and polling interval.                                                         |
| Tag group                       | MQTT topic hierarchy                                                                             | Tag group nesting becomes path segments in the topics of a [Cybus::Mapping](/2-4-2/data-flows/service-commissioning-files/resources/cybus-mapping.md). |
| IoT Gateway MQTT Client agent   | [Cybus::Mapping](/2-4-2/data-flows/service-commissioning-files/resources/cybus-mapping.md)       | Connectware publishes every endpoint to its integrated MQTT broker. A separate gateway plug-in is not needed.                                          |
| OPC UA server interface         | [OPC UA Server](/2-4-2/connectors/servers/opc-ua-server.md)                                      | Connectware can expose migrated data points to OPC UA clients through server resources.                                                                |
| User Manager, Security Policies | [User management](/2-4-2/access/user-management.md)                                              | Users, roles, and permissions are managed in Connectware and are not part of the service commissioning file.                                           |

### Mapping Drivers to Connectors

Each KEPServerEX channel names its driver in the `servermain.MULTIPLE_TYPES_DEVICE_DRIVER` property of the export. The following drivers have a native Connectware connector:

| KEPServerEX driver                  | Connectware connector                                                                     |
| ----------------------------------- | ----------------------------------------------------------------------------------------- |
| Modbus TCP/IP Ethernet              | [Modbus/TCP](/2-4-2/connectors/shop-floor-connectors/modbus-tcp.md)                       |
| Siemens TCP/IP Ethernet             | [Siemens SIMATIC S7](/2-4-2/connectors/shop-floor-connectors/siemens-simatic-s7.md)       |
| Siemens S7 Plus Ethernet            | [Siemens SIMATIC S7+](/2-4-2/connectors/shop-floor-connectors/siemens-simatic-s7-plus.md) |
| Allen-Bradley ControlLogix Ethernet | [EtherNet/IP](/2-4-2/connectors/shop-floor-connectors/ethernet-ip.md)                     |
| Fanuc Focas Ethernet                | [FOCAS](/2-4-2/connectors/shop-floor-connectors/focas.md)                                 |
| BACnet/IP                           | [BACnet](/2-4-2/connectors/shop-floor-connectors/bacnet.md)                               |
| OPC UA Client                       | [OPC UA Client](/2-4-2/connectors/shop-floor-connectors/opc-ua/opc-ua-client.md)          |
| OPC DA Client                       | [OPC DA](/2-4-2/connectors/shop-floor-connectors/opc-da.md)                               |
| MQTT Client                         | [MQTT](/2-4-2/connectors/enterprise-connectors/mqtt.md)                                   |

For channels whose driver has no native connector, for example aging serial drivers, keep KEPServerEX in place for those devices and connect it through its OPC UA server interface as described in [Connecting Legacy Devices via Kepware KEPServerEX](/2-4-2/guides/machine-connectivity/gateways-generic-protocols/connecting-legacy-devices-via-kepware-kepserverex.md). A migration can be partial: native connectors for the covered devices, the OPC UA route for the rest.

### What Does Not Migrate 1:1

KEPServerEX plug-ins extend the server beyond pure connectivity. Their configuration appears in the JSON export in namespaced blocks such as `_datalogger` and `_iot_gateway`, but there is no direct resource-for-resource translation. The following table lists the alternatives:

| KEPServerEX plug-in or feature | Connectware approach                                                                                                                                                                                                                 |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| DataLogger                     | Map endpoints to a database with the [SQL](/2-4-2/connectors/enterprise-connectors/sql.md), [MSSQL](/2-4-2/connectors/enterprise-connectors/mssql.md), or [InfluxDB](/2-4-2/connectors/enterprise-connectors/influxdb.md) connector. |
| Advanced Tags                  | Implement calculations and tag linking with [Rule Engine](/2-4-2/data-flows/rule-engine.md) rules, for example JSONata transformations on mappings.                                                                                  |
| Local Historian                | Store time-series data in an external database through the enterprise connectors. Connectware does not include a historian.                                                                                                          |
| Scheduler                      | Configure polling per endpoint with the `interval` property or a cron expression.                                                                                                                                                    |
| IoT Gateway REST agents        | Use the [HTTP/REST connector](/2-4-2/connectors/enterprise-connectors/http-rest.md) or the [HTTP Server](/2-4-2/connectors/servers/http-server.md).                                                                                  |
| EFM Exporter                   | No equivalent. Electronic Flow Measurement export is out of scope for Connectware.                                                                                                                                                   |
| Media-Level Redundancy         | No direct equivalent for redundant communication paths to a single device.                                                                                                                                                           |

## Exporting the KEPServerEX Project as JSON

KEPServerEX stores the complete project, including all channels, devices, tag groups, and tags, in a documented JSON structure. There are two ways to get it.

### Option 1: Save the Project as a JSON File

1. In the KEPServerEX Configuration client, select **File > Save As**.
2. Select **JSON** as the file type and save the project, for example as the `plant-floor.json` file.

Two default settings block the JSON format, both documented in the [Kepware server documentation](https://support.ptc.com/help/kepware/kepware_server/en/kepware/server/designing-project-saving-project.html):

* **Project File Encryption** is enabled by default. Encrypted projects can only be saved as `.sopf` files. Disable encryption in the project properties under **Project Properties | General** before saving as JSON.
* Projects that use the **Security Policies** plug-in can only be saved as `.opf` files. Export these projects through the Configuration API instead.

JSON project files are supported since KEPServerEX 6.0. Older 5.x installations cannot save JSON; export them through the Configuration API after an upgrade, or rebuild the configuration from the tag list.

### Option 2: Export via the Configuration API

The KEPServerEX Configuration API is a REST interface that serves the whole project as JSON. It is useful when you have no desktop access to the Windows machine, or when you want to script the export:

{% code lineNumbers="true" %}

```bash
curl -k -u ${KEPWARE_USER}:${KEPWARE_PASSWORD} \
  "https://${KEPWARE_HOST}:57512/config/v1/project?content=serialize" \
  -o plant-floor.json
```

{% endcode %}

* `${KEPWARE_HOST}` is the hostname or IP address of the KEPServerEX machine. The default Configuration API ports are 57412 (HTTP) and 57512 (HTTPS).
* `${KEPWARE_USER}` and `${KEPWARE_PASSWORD}` are credentials of a KEPServerEX user with read access to the project, for example the Administrator account.
* `-k` skips certificate verification, because the Configuration API ships with a self-signed certificate by default. Omit the flag if you have installed a trusted certificate.

The Configuration API must be enabled in the KEPServerEX settings: right-click the Administration icon in the Windows system tray and select **Settings**, then check the **Configuration API Service** section. For details, see the [Configuration API Service documentation](https://support.ptc.com/help/kepware/kepware_server/en/kepware/server/config-api-service.html).

## Translating the Export with an AI Assistant

The JSON export is self-describing: every channel names its driver, every device carries its network address, and every tag carries address, data type, and scan rate. This makes the translation to a service commissioning file a mechanical task that an AI assistant handles well, if you give it the mapping rules.

{% hint style="warning" %}
The export can contain sensitive values, for example device credentials or broker passwords from IoT Gateway agents. Remove credentials from the JSON before you paste it into an AI tool, and pass them into the service as parameters when you install it. Check the data privacy terms of the AI tool you use, and see the privacy notes for [Cybus Connectware GPT](/2-4-2/tools/cybus-connectware-gpt.md#data-privacy).
{% endhint %}

Copy the following prompt, attach or paste your JSON export, and adjust the bracketed placeholders:

{% code title="AI translation prompt" lineNumbers="true" expandable="true" %}

```
You are translating a Kepware KEPServerEX project export (JSON) into a Cybus
Connectware service commissioning file (YAML). Produce one complete, valid
service commissioning file with description, metadata, parameters,
definitions, and resources.

Structural rules:
- Create one Cybus::Connection per KEPServerEX device. Read the protocol from
  the channel property "servermain.MULTIPLE_TYPES_DEVICE_DRIVER" and the
  device address from "servermain.DEVICE_ID_STRING".
- Create one Cybus::Endpoint per tag, referencing its connection with !ref.
  Use "servermain.TAG_SCAN_RATE_MILLISECONDS" as the polling interval; if it
  is missing, fall back to "servermain.DEVICE_SCAN_MODE_RATE_MS", then 1000.
- Tags with "servermain.TAG_READ_WRITE_ACCESS": 1 get an additional write
  endpoint or a write section, read-only tags (0) only subscribe.
- Create one Cybus::Mapping that publishes every endpoint to an MQTT topic
  mirroring the KEPServerEX naming: <channel>/<device>/<tag group>/<tag>,
  lowercase kebab-case. Keeping the hierarchy identical to KEPServerEX makes
  the migration easy to validate; the topics can be remodeled later.
- Define host addresses and credentials as parameters with sensible defaults,
  never hardcoded. Do not include any credentials in the output.

Tag data types are integers ("servermain.TAG_DATA_TYPE"): 0=String,
1=Boolean, 2=Char, 3=Byte, 4=Short, 5=Word, 6=Long, 7=DWord, 8=Float,
9=Double, 13=LLong, 14=QWord.

Driver-specific rules for Modbus TCP/IP Ethernet channels
(protocol: Modbus):
- The device IP is the part of "servermain.DEVICE_ID_STRING" before the
  final dot, the port is "modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER".
- Translate tag addresses to function codes: 0xxxxx -> fc 1 (coils),
  1xxxxx -> fc 2 (discrete inputs), 3xxxxx -> fc 4 (input registers),
  4xxxxx -> fc 3 (holding registers). The register offset is the numeric
  remainder minus 1 (e.g., "400001" -> fc 3, address 0).
- Map data types: Boolean -> boolean, Short -> int16BE, Word -> uint16BE,
  Long -> int32BE, DWord -> uint32BE, Float -> floatBE, Double -> doubleBE.
  16-bit types use length 1, 32-bit types length 2, 64-bit types length 4.
  If "modbus_ethernet.DEVICE_FIRST_WORD_LOW" is true, flag every multi-
  register tag with a comment: the word order must be verified manually.

Driver-specific rules for Siemens TCP/IP Ethernet channels (protocol: S7):
- Use "servermain.DEVICE_ID_STRING" as host, port 102, and the CPU rack and
  slot from the "siemens_tcpip_ethernet.*" device properties.
- Translate tag addresses to the Connectware S7 syntax, for example
  "DB11,W0" -> address "DB11,W0" stays, but verify data type letters against
  the Connectware S7 connector documentation and flag any address you are
  not certain about with a comment.

For any channel whose driver you cannot map to a Connectware connector,
skip it and list it at the end under "Not migrated".

After the YAML, output a migration report: number of channels, devices, and
tags translated, all assumptions made, and every flagged item that needs
manual review.

[Paste or attach the KEPServerEX JSON export here.]
```

{% endcode %}

The prompt works in any capable LLM chat. With [Cybus Connectware GPT](/2-4-2/tools/cybus-connectware-gpt.md) you can shorten it, because the assistant already knows the service commissioning file format; the driver-specific translation rules are still worth including. For large projects with hundreds of tags, translate channel by channel instead of the whole project at once, and combine the results.

## Reviewing the Generated Service Commissioning File

AI-generated configuration must be reviewed before it touches production equipment. Work through this checklist:

1. Validate the file structure. The [Cybus Connectware Extension for VS Code](/2-4-2/tools/cybus-connectware-extension-vs-code.md) validates service commissioning files against the official schemas as you edit.
2. Check every connection: protocol, host, port, and device-specific options such as CPU rack and slot against the original KEPServerEX device properties.
3. Spot-check tag addresses, especially converted ones. Modbus register offsets and data type conversions are the most common source of translation errors, including off-by-one offsets and wrong word order for 32-bit values.
4. Check the polling intervals. KEPServerEX clients can override scan rates at runtime, so the exported tag scan rate is not always the rate your consumers actually used.
5. Confirm that no credentials ended up in the file and that all site-specific values are parameters.
6. Compare the endpoint count against the migration report of the AI assistant and the tag count of the original project.

## Installing the Service

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:** Connectware connects to the migrated devices directly and the connections reach the **Connected** state.

{% hint style="info" %}
For read-only validation, Connectware and KEPServerEX can usually poll the same device at the same time, which allows you to compare live values before you switch consumers over. Check the connection limits of your devices first: some PLCs only accept a small number of concurrent client connections. Remove the migrated devices from KEPServerEX once the migration is verified.
{% endhint %}

## Verifying the Data

Open the [Data Explorer](/2-4-2/monitoring/data-explorer.md) and subscribe to the topics of the migrated service. Compare the live values against the KEPServerEX Quick Client or your existing consumers:

* Every migrated tag publishes on its topic with plausible values.
* Values match between KEPServerEX and Connectware for the same data point.
* Numeric values are in the expected range. Implausible numbers on 32-bit tags indicate a wrong word order or register offset.
* Data arrives at the expected rate for polling-based connectors.

If a connection does not reach the **Connected** state, verify the host, port, and network path from Connectware to the device, and check that the device accepts an additional client connection while KEPServerEX is still connected.

## Worked Example

The following KEPServerEX export snippet describes a Modbus TCP/IP Ethernet channel with one device and three tags, using the documented property names of the JSON project format:

{% code title="plant-floor.json (excerpt)" lineNumbers="true" expandable="true" %}

```json
{
  "project": {
    "servermain.PROJECT_TITLE": "PlantFloorProject",
    "channels": [
      {
        "common.ALLTYPES_NAME": "ModbusTCP",
        "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Modbus TCP/IP Ethernet",
        "devices": [
          {
            "common.ALLTYPES_NAME": "PLC1",
            "servermain.DEVICE_ID_STRING": "<192.168.1.100>.0",
            "servermain.DEVICE_SCAN_MODE_RATE_MS": 1000,
            "modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER": 502,
            "modbus_ethernet.DEVICE_FIRST_WORD_LOW": false,
            "tags": [
              {
                "common.ALLTYPES_NAME": "MotorSpeed",
                "servermain.TAG_ADDRESS": "400001",
                "servermain.TAG_DATA_TYPE": 5,
                "servermain.TAG_READ_WRITE_ACCESS": 1,
                "servermain.TAG_SCAN_RATE_MILLISECONDS": 100
              },
              {
                "common.ALLTYPES_NAME": "Temperature",
                "servermain.TAG_ADDRESS": "400002",
                "servermain.TAG_DATA_TYPE": 8,
                "servermain.TAG_READ_WRITE_ACCESS": 0,
                "servermain.TAG_SCAN_RATE_MILLISECONDS": 1000
              },
              {
                "common.ALLTYPES_NAME": "RunningFlag",
                "servermain.TAG_ADDRESS": "000001",
                "servermain.TAG_DATA_TYPE": 1,
                "servermain.TAG_READ_WRITE_ACCESS": 0,
                "servermain.TAG_SCAN_RATE_MILLISECONDS": 100
              }
            ]
          }
        ]
      }
    ]
  }
}
```

{% endcode %}

Applying the translation rules from the prompt produces the following service commissioning file. The tag `MotorSpeed` (`400001`, Word) becomes a holding register endpoint with `fc: 3`, `address: 0`, and `dataType: uint16BE`; the Float tag `Temperature` (`400002`) occupies two registers starting at address 1; and the Boolean tag `RunningFlag` (`000001`) becomes a coil endpoint with `fc: 1`. Because `MotorSpeed` is writable in KEPServerEX, it also gets a write endpoint:

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

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

```yaml
description: >
  Service commissioning file migrated from the KEPServerEX project
  PlantFloorProject, channel ModbusTCP, device PLC1 (Example)

metadata:
  name: KEPServerEX Migration Example
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  plc1Host:
    description: IP address of the device PLC1 (from servermain.DEVICE_ID_STRING)
    type: string
    default: 192.168.1.100

  plc1Port:
    description: Modbus/TCP port of the device PLC1
    type: integer
    default: 502

definitions:
  # Topics mirror the KEPServerEX hierarchy <channel>/<device>/<tag>
  MQTT_TOPIC_PREFIX: modbustcp/plc1

resources:
  # KEPServerEX channel "ModbusTCP", device "PLC1"
  plc1Connection:
    type: Cybus::Connection
    properties:
      protocol: Modbus
      targetState: connected
      connection:
        host: !ref plc1Host
        port: !ref plc1Port

  # Tag "MotorSpeed": 400001, Word, read/write, 100 ms
  motorSpeed:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref plc1Connection
      subscribe:
        fc: 3
        address: 0
        length: 1
        dataType: uint16BE
        interval: 100

  motorSpeedWrite:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref plc1Connection
      write:
        fc: 6
        address: 0
        length: 1
        dataType: uint16BE

  # Tag "Temperature": 400002, Float, read only, 1000 ms
  temperature:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref plc1Connection
      subscribe:
        fc: 3
        address: 1
        length: 2
        dataType: floatBE
        interval: 1000

  # Tag "RunningFlag": 000001, Boolean, read only, 100 ms
  runningFlag:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref plc1Connection
      subscribe:
        fc: 1
        address: 0
        length: 1
        dataType: boolean
        interval: 100

  mapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref motorSpeed
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/motor-speed'
        - subscribe:
            topic: !sub '${MQTT_TOPIC_PREFIX}/motor-speed/set'
          publish:
            endpoint: !ref motorSpeedWrite
        - subscribe:
            endpoint: !ref temperature
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/temperature'
        - subscribe:
            endpoint: !ref runningFlag
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/running-flag'
```

{% endcode %}

For all Modbus connection and endpoint properties, see [Modbus Connection Properties](/2-4-2/connectors/shop-floor-connectors/modbus-tcp/modbusconnection.md) and [Modbus Endpoint Properties](/2-4-2/connectors/shop-floor-connectors/modbus-tcp/modbusendpoint.md).

{% hint style="info" %}
Disclaimer: Kepware, KEPServerEX, and ThingWorx are trademarks or registered trademarks of PTC Inc. or its subsidiaries in the United States and other countries.
{% 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/migration/migrating-from-kepware-kepserverex.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.
