Import a WinCC Unified project
This guide walks through platform/tools/wincc-import, a command line tool that reads the folder a WinCC Unified Openness export produces and rebuilds the HMI on a gateway: an OPC UA connection, tags, alarms, screens, and the devices as tag type (UDT) instances. It is for the engineer migrating an existing Siemens panel. The tool was written against one export (HMI_Scadex_2026-11-01, HMI HMI_RT_NIRO, PLC S7_VN_NIRO), and that project is the one it has been run on.
Prerequisites
- The platform repository checked out, with its dependencies installed (
node_modules/.bin/tsxis used to run the tool). - The export folder from TIA Portal Openness.
- An API key with the engineer role (
--api-key scx_...), or an account's--emailand--password. See API keys. - The OPC UA driver module running on the gateway, and the PLC's OPC UA server switched on (
OPC UA_1in TIA) with the variables marked "accessible from HMI/OPC UA". - For
convertandtype-alarms: the project's tag types (CswMotor,CswMotorFreq,CswValve,CswValveAnalog,CswDigitalInput,CswAnalogInput,CswPID,CswTotalizer,CswGeneralMode,CswMode,CswAlarm) present on the gateway. They are found by name, wherever they are filed. Without them the devices stay plain tags.
node_modules/.bin/tsx tools/wincc-import/cli.ts <command> <export-folder> [options]
Commands
| Command | What it does |
|---|---|
plan | Reads the export and writes what it would create to --out. Touches no gateway. |
apply | Creates the OPC UA connection S7_VN_NIRO, its tags and their alarms. Running it again keeps what exists. On a gateway that has the project's tag types it then runs convert too (--keep-old keeps that from deleting anything). |
rebind | Points the existing OPC UA tags at the nodes the plan now names; use it after changing --namespace. Devices that are instances take their nodes from their types (and the ID and OPCUA parameters), so rebind does not reach them: change the namespace in the type. |
verify | Reads every OPC UA tag once and lists those whose quality is not Good. Run it once the PLC is online. |
convert | Replaces the motors' and valves' imported tags with instances of the tag types, alarms carried over. Needs --url. |
type-alarms | Puts the export's alarm texts onto the types and sets what each instance changes. Works from the export, not from the gateway, so alarm edits made in Scadex since convert are replaced. |
views | Builds the screens, faceplates and popups as Scadex views (screens), and makes the pages start screens. Without --url it only reports what it would build. Views that already have content are kept; --force replaces them. |
Options:
| Option | Commands | Meaning |
|---|---|---|
--url <gateway> | all but plan | The gateway |
--api-key scx_... or --email, --password | all but plan | Who the tool acts as (engineer role) |
--out <file> | plan | Where the plan goes |
--endpoint opc.tcp://10.1.2.47:4840 | apply | The PLC's OPC UA endpoint |
--namespace 3 | apply, rebind | The namespace index of the data blocks; 3 is the default |
--enable | apply | Switch the connection on at once; otherwise it is created off |
--flat | apply | No tag types: every variable stays a tag |
--keep-old | apply, convert | Make the instances, remove nothing |
--dry-run | type-alarms | Report without changing |
--family motor,pid,... | type-alarms | Only the named families |
--force, --only "Overzicht,Droge zone" | views | Replace existing views; limit to the named screens |
The command line is strict: an unknown option (--dryrun), a missing value, or an option given to a command it does nothing for (--dry-run belongs to type-alarms, and convert has none) is an error and nothing runs.
Order of operations
1. Plan
node_modules/.bin/tsx tools/wincc-import/cli.ts plan ../HMI_Scadex_2026-11-01 --out plan.json
Read the plan: the connection, the tag tree, the alarms, which blocks become which type. Nothing has touched the gateway yet.
2. Apply
node_modules/.bin/tsx tools/wincc-import/cli.ts apply ../HMI_Scadex_2026-11-01 \
--url https://app.scadex.io --api-key scx_... --endpoint opc.tcp://10.1.2.47:4840 --namespace 3
What it makes:
- Connection.
S7_VN_NIRO, an OPC UA connection to the PLC's own server, created switched off unless--enableis given. Security isnoneto start with; change it on the connection afterwards. - Tags. One tag per PLC variable the HMI used, under a folder named for the PLC that mirrors the data blocks: HMI tag
S7_VN_NIRO_P02_HP_Pomp_DB_fb_CswbecomesS7_VN_NIRO.P02_HP_Pomp_DB.fb.Cswwith node idns=3;s="P02_HP_Pomp_DB"."fb"."Csw". A structured tag (UDT_Confirm,UDT_Device_Conditions,UDT_LogEntry) is opened into one tag per member. An array element is a path segment of its own (Piping.ZoneNat[3]isPiping.ZoneNat.3). The HMI's own variables (NavMain,NavSub, ...) become memory tags underHMI, session-scoped where they say which page one person is on. TheDevice_Info_*tags are left out. - Alarms. Each of WinCC's 643 discrete alarms watches one bit of a status word, so each becomes a
bitSetalarm on that word with the bit number as the setpoint. Priorities 1 to 4 become severities 200, 500, 700 and 900. The alarm text is the alarm's name. - Devices. On a gateway that has the types,
applyrunsconvertas well (see step 4). With--flat, nothing becomes an instance.
Switch the connection on in Connections, OPC UA servers when the PLC is reachable.
3. Verify, and rebind if the namespace differs
node_modules/.bin/tsx tools/wincc-import/cli.ts verify ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_...
The namespace index is the one thing the export cannot tell. If verify reports everything as having no value while the connection shows connected, browse the connection in the dashboard to see the real index, then:
node_modules/.bin/tsx tools/wincc-import/cli.ts rebind ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_... --namespace 4
Instances are not touched by rebind: their node ids come from the type, so change the namespace there.
4. Convert devices to type instances
node_modules/.bin/tsx tools/wincc-import/cli.ts convert ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_...
How a block is classified: a data block is a motor when a motor faceplate (MotorV20) is bound to its status word, a valve when a valve faceplate (ValveV20) is, a digital input when a digital-input or detection faceplate is (or a screen script only opens the digital popup for it), an analog input with AnalogInpV20, a PID with a PID faceplate, a totalizer with FCP_Totalizer, and so on. A motor with a speed set point and feedback is a CswMotorFreq, a valve with a position pair a CswValveAnalog. The instance is named after the block without _DB (C01_Exhaust_Fan_DB becomes C01_Exhaust_Fan), at the top level, because the types build their node ids from the instance name, so every value is read from the node it was read from before.
convert makes each instance, gives its Csw the alarms the old status word has, and only then deletes the old tags, a block at a time and only if the instance's word reads Good whenever the old one did. If the gateway cannot say whether the old word reads, the old tags stay and the block is reported. It is safe to run again: it leaves alone what has been changed on an instance since (a unit, the alarms). --keep-old stops short of deleting.
convert has no dry run. Run plan first, make sure the types are the ones you mean, and consider --keep-old on the first pass.
Not carried over: history recorded against the old tags, and the alarm journal's links to them. Anything outside the tool that names an old path (a script, a view built before) has to be pointed at the instance.
5. Put the alarm texts on the types
node_modules/.bin/tsx tools/wincc-import/cli.ts type-alarms ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_... --dry-run
node_modules/.bin/tsx tools/wincc-import/cli.ts type-alarms ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_... --family motor,valve
The type's Csw member gets the alarms with {Description}: ... names, each instance's description becomes the device name that stood in front, and each instance gets only the fields that differ from the type (alarmOverrides), or a list of its own where the type cannot express them. See Model a motor as a tag type for how such templates resolve.
type-alarms rewrites from the export, not from what the gateway holds, so alarm edits made in Scadex since convert are replaced. Use --dry-run first, and --family for the families whose types you have not edited.
6. Build the screens
node_modules/.bin/tsx tools/wincc-import/cli.ts views ../HMI_Scadex_2026-11-01 --url https://app.scadex.io --api-key scx_...
The 76 WinCC screens become 12 pages and 77 parts in the folders NIRO and WinCC: the pages (Overzicht, Stappen, six Parameters pages, Natte zone, Droge zone, Hardware, Alarmen) in the Kader frame with a navigation bar, parts under WinCC/Onderdelen, and faceplates and popups under WinCC/Faceplates, redesigned because WinCC could not export their geometry. Tag reads become tag('path'), named colors their values, each I/O field a field widget, and mm:ss times a field with the duration format. The pages become start screens (Start screens).
Left out on purpose: the empty Algemeen page, the Test page, the logo, the system diagnosis control, the alarm counters per class on the navigation buttons, and the @UserName label.
Existing views with content are kept; views --force rebuilds them and --only "Overzicht,Droge zone" limits that to the named ones.
Where to go next
- Connect an S7-1500 over OPC UA for the connection the tool created.
- Tag types and Model a motor as a tag type for the
Csw*types. - Alarms for the
bitSetcondition and templates. - Screens and Templates and popups for the views it built.
- Tools for the other command line tools in the repository.