TIA Portal Openness: Building Automated PLC Code Generators

David Krause11 min read
SiemensTIA PortalTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview: What TIA Portal Openness Actually Does

TIA Portal Openness is a Siemens-supplied programming interface (API) that exposes the internal object model of TIA Portal as a .NET class library. The API allows external applications — typically written in C# with Visual Studio — to drive TIA Portal in the same way a human engineer would: creating projects, inserting stations, configuring hardware, generating program blocks (OB, FB, FC, DB), populating tags, compiling, and even downloading to a PLC. Unlike a one-shot export, Openness operates on a live or file-based TIA Portal project and persists every change to disk.

The primary use case is engineering automation: generating dozens of identical machine programs from a template, populating I/O assignments from a spreadsheet, or — the focus of this guide — accepting a user-defined station/robot topology and emitting a complete, compilable S7-1500 project. The API is the same one used internally by Siemens tools such as the TIA Selection Tool and various customer-specific code generators.

Engineering reality check: TIA Openness is powerful but deliberately constrained. Operations that require human judgment (resolving symbolic references, choosing between conflicting hardware revisions, signing safety programs) are not exposed. Treat Openness as a fast typist that follows your script exactly — it will not second-guess a bad specification.

Supported TIA Portal Versions and API Compatibility

The Openness DLLs are version-bound. An application compiled against the V17 API will not load against a V18 or V20 installation, and vice versa. The following table summarizes the Openness package availability per major TIA Portal release:

TIA Portal Version Openness API Major Min .NET Framework Notes
V15 / V15.1 V15 4.6.1 Legacy S7-1200/1500 only
V16 V16 4.7.2 Adds WinCC Unified scripting hooks
V17 V17 4.8 Multiuser server API introduced
V18 V18 4.8 Improved TIA Portal Cloud connector
V19 V19 4.8 S7-1200 G2 support; expanded OPC UA export
V20 V20 .NET 4.8 / .NET 6 mixed Latest documented release; install path documented at the TIA Portal Openness V20 installation manual

Siemens ships matching Openness assemblies inside the TIA Portal installation media. The DLL set — Siemens.Engineering, Siemens.Engineering.Hmi, Siemens.Engineering.AddIn — must be referenced from your Visual Studio project at a path that matches the TIA Portal version you are targeting. A common deployment pitfall is referencing V17 DLLs on a build machine that only has V18 installed; TIA Portal will refuse to load the assembly at runtime with a FileLoadException citing a mismatched strong-name signature.

Architecture: How Openness Talks to TIA Portal

Openness runs in one of two modes, and the choice determines most of your coding decisions:

  1. Scripting mode (TIA Openness Scripter): A lightweight interactive console inside TIA Portal that executes C# or VB.NET against the live project. Good for prototyping, limited UI, no multi-project orchestration.
  2. External API mode: A standalone .NET application that connects to a TIA Portal instance (either local or a remote TIA Portal instance over the Openness TCP interface, default port 9050). This is the mode used for production code generators.

Object hierarchy you will touch most often:

TiaPortal
 └── Projects
      └── Project
           ├── Devices
           │    └── Device (e.g., S7-1500 CPU 1515-2 PN)
           │         └── DeviceItems (Racks, Modules, Submodules)
           ├── PlcSoftware
           │    ├── PlcBlockGroup
           │    │    ├── PlcBlock (OB, FB, FC, DB, Type)
           │    │    └── PlcBlockUserGroup
           │    ├── TagTable
           │    │    └── Tag (typed, address-bound)
           │    └── PlcSystemTagTable
           └── HmiSoftware / HmiTarget

Every node in this tree is reachable from C# through a strongly-typed interface. You traverse it with LINQ-style enumerables (e.g., project.Devices.OfType<Device>()) and mutate it with With... factory methods that return new immutable compositions.

Prerequisites

  • TIA Portal installation with the Openness option enabled — see the Siemens installation guide for the exact checkbox path (Setup → Options → TIA Portal Openness).
  • Visual Studio 2019 or 2022 with the .NET desktop development workload. Community Edition is sufficient for non-commercial use.
  • .NET Framework 4.8 (for TIA V17–V20). Targeting .NET 6/7 requires the Openness API to be wrapped — see the open-source Repsay/tia-openness-api-client Python library as a reference for cross-language bridging.
  • Siemens Openness DLLs copied locally or referenced by hint path: C:\Program Files\Siemens\Automation\Portal V20\PublicAPI\V20\.
  • Working TIA Portal license. Openness does not require a separate license, but the TIA Portal instance it drives does.
  • Solid C# foundations: generics, LINQ, async/await, XML serialization. The Siemens sample code uses these patterns heavily.

Installation and Configuration

Step-by-step commissioning of the Openness development environment:

  1. Run the TIA Portal setup as Administrator.
  2. Select Modify, then expand Options and tick TIA Portal Openness. The setup copies the Openness DLLs into the PublicAPI folder.
  3. Confirm the installation by checking for the file Siemens.Engineering.dll in PublicAPI\V20.
  4. Open Visual Studio and create a new Class Library (.NET Framework) project. Target .NET Framework 4.8, platform x64.
  5. Add references to: Siemens.Engineering.dll, Siemens.Engineering.Hmi.dll, Siemens.Engineering.AddIn.dll (optional), Siemens.Engineering.Compiler.dll (if you intend to compile).
  6. Set the Copy Local property to false for the Siemens assemblies. They are loaded at runtime from the TIA Portal install path.
  7. Sign the assembly with a strong name; Openness requires it to load external DLLs in a live TIA Portal instance.
Common failure mode: A FileNotFoundException for Siemens.Engineering at runtime almost always means the build machine is referencing one TIA version while the target machine runs a different version. Mirror the install paths exactly across dev and runtime hosts.

Building a Station-Driven PLC Code Generator

The reference architecture for a code generator that turns a user-defined station list (number of robots, number of stations, station names) into a TIA Portal project looks like this:

  1. User input layer — WinForms/WPF/Console UI collects the topology: a list of StationDef objects, each with a name, robot count, and I/O count.
  2. Code-generation engine — a C# service that translates the topology into Openness API calls.
  3. TIA Portal driver — the Openness wrapper that owns the TiaPortal instance and exposes a high-level project model.
  4. Output — a .ap20 file written to disk and opened by the user in TIA Portal for review and download.

Step 1: Open or Create a TIA Portal Project

The first Openness call a generator must make is to obtain a TiaPortal instance, then either open an existing project or create a new one. A new project skeleton is created as follows:

using Siemens.Engineering;

TiaPortal tia = new TiaPortal(TiaPortalMode.WithUserInterface);
Project project = tia.Projects.Create(
    new DirectoryInfo(@"C:\Projects\AutoGenCell1"),
    "AutoGenCell1");

If you want to script against a project that is already open in TIA Portal (typical for engineering assistants), call tia.Projects.First() or use the TiaPortal.GetFromLocalSession() helper. For unattended batch generation, use TiaPortalMode.WithoutUserInterface to suppress the TIA UI.

Step 2: Insert the PLC and Configure Hardware

A code generator that produces a topology of N stations typically creates one S7-1500 CPU and one ET 200SP station per cell. Hardware insertion uses the Device and DeviceItem hierarchy with explicit order numbers:

// Add the S7-1500 CPU 1515-2 PN (6ES7515-2AM02-0AB0)
Device plc = project.Devices.CreateWithOrder(
    OrderNumber.Parse("6ES7515-2AM02-0AB0")) as PlcDevice;

// Add a PROFINET IO system and attach the first ET 200SP head module
IioSystem pn = plc.IoControllers[0].IoSystems[0];
Device et200sp = pn.IoDevices.CreateWithOrder(
    OrderNumber.Parse("6ES7155-6AU30-0CN0"));

// Plug in 16-channel digital input module in slot 1
DeviceItem di = et200sp.DeviceItems[1].CreateWithOrder(
    OrderNumber.Parse("6ES7131-6BH01-0BA0"));

DeviceItem doModule = et200sp.DeviceItems[2].CreateWithOrder(
    OrderNumber.Parse("6ES7132-6BH01-0BA0"));

Each hardware insertion returns a DeviceItem reference that you must retain — it is the handle used later to address the I/O channels and bind them to PLC tags.

Step 3: Generate Program Blocks (FB, FC, DB, OB)

Program block generation is the heart of an automatic PLC project. The Openness API distinguishes between plain PlcBlock composition and source-file generation. The supported patterns are:

  • Composition API: Build the block entirely in C# by calling PlcBlock.Compose() with a fluent interface. Best for trivial FCs/DBs that hold only tag tables.
  • Source generation: Write the block as SCL/ST source text and feed it to the Openness compiler. This is how production code generators handle FBs with hundreds of lines of ladder or SCL.

Creating a DB and a parameter-driven FB from a station definition:

PlcBlockGroup blocks = plcSoftware.BlockGroup;

// 1) A station-specific instance DB
PlcBlock stationDb = blocks.CreateDb("DB_" + station.Name, station.StationNumber);
stationDb.AutoNumber = true;

// 2) A reusable FB (created once, instanced for every station)
if (!blocks.Contains("FB_RobotControl"))
{
    PlcBlock robotFb = blocks.CreateFb("FB_RobotControl", 100);
    robotFb.Interface.Name = "IFB_RobotControl";
    robotFb.Interface.Sections["Input"].AddMember("Start",   "Bool");
    robotFb.Interface.Sections["Input"].AddMember("Stop",    "Bool");
    robotFb.Interface.Sections["Output"].AddMember("Running", "Bool");
    robotFb.Interface.Sections["Static"].AddMember("Step",    "Int");
    // Add SCL source for the body, then call compile
}

// 3) An OB1 that instantiates the FB once per station
foreach (var st in topology.Stations)
{
    PlcBlock ob1 = plcSoftware.ObGroups[0].Blocks.Find("OB1");
    var inst = ob1.Interface.Sections["Static"].AddInstance(
        name: "inst_" + st.Name,
        typeName: "FB_RobotControl",
        dbNumber: nextFreeDb++);
}

For ladder and SCL bodies, you typically ship pre-written .scl or .awl source files alongside your generator and paste them into the block before compilation. The Openness API does not expose a visual ladder editor.

Step 4: Generate Tags and Bind to I/O

Every generated station needs a slice of the process image. A practical pattern is to allocate a contiguous bit/byte range per station (e.g., 32 bytes in, 32 bytes out) and emit a tag table with symbolic names:

PlcTagTable tagTable = plcSoftware.TagTables.Create("Tags_" + station.Name);
int baseInputByte = station.StationNumber * 32;

tagTable.Tags.Create("Station_" + station.Name + "_Start",    "Bool",   "%I" + baseInputByte + ".0");
tagTable.Tags.Create("Station_" + station.Name + "_Stop",     "Bool",   "%I" + baseInputByte + ".1");
tagTable.Tags.Create("Station_" + station.Name + "_Running",  "Bool",   "%Q" + baseInputByte + ".0");
tagTable.Tags.Create("Station_" + station.Name + "_Fault",    "Bool",   "%Q" + baseInputByte + ".1");
Address collisions are the most common source of failed compilations in generated projects. Keep a running offset counter and assert uniqueness before calling Tags.Create.

Step 5: Compile and Persist

Compiling the generated software validates the project without requiring a live PLC:

plcSoftware.Compiler.CheckConsistency(out CompilerResult result);
if (result.HasErrors)
{
    foreach (var msg in result.Messages)
        Console.WriteLine($"[{msg.Severity}] {msg.Path}: {msg.Text}");
}
project.Save();
project.Close();

Calling Save writes the project to its directory. You can then open the resulting .ap20 in TIA Portal for engineer review, online diagnostics, and download to the real CPU.

Verification: Confirming the Generated Project Loads

After the generator finishes, validate the result with these checks:

  1. Open the .ap20 in TIA Portal manually. The project tree should show your generated devices, blocks, and tag tables.
  2. Run Project → Compile → Software (rebuild all) in the TIA Portal UI. A successful compile confirms the generator did not leave dangling references.
  3. Open the generated OB1 and verify the FB instances match the station list from your input.
  4. Open the tag table and check that the absolute addresses do not overlap between stations.
  5. If you have a SIMATIC S7-PLCSIM Advanced license, download the project to a simulated S7-1500 and exercise the first station to confirm runtime behavior.

Troubleshooting Matrix

Symptom Likely Root Cause Remediation
FileNotFoundException for Siemens.Engineering.dll at startup Mismatched TIA Portal version on dev vs. runtime host Match the PublicAPI path; do not copy Siemens assemblies locally
TiaPortalException: Another TIA Portal instance is running Generator attempted WithUserInterface mode while TIA Portal is already open Switch to WithoutUserInterface or close the UI first
Compiler reports "Address X is already used" Tag generator reused an I/O offset Introduce a central AddressAllocator that hands out non-overlapping ranges
Generated block is empty after creation Used Compose but never called Compile or assigned source text Provide SCL source and call plcSoftware.Compiler.CheckConsistency
External app hangs on first Openness call UAC elevation mismatch between TIA Portal and your generator Run both as Administrator or both as standard user — never mix
Project opens but devices missing Hardware order number typo or unsupported revision Validate order numbers against the TIA Selection Tool catalog

Best Practices for Production Generators

  • Keep generators stateless. Take a topology model as input and produce a project as output. Persist nothing in the generator's own memory between runs.
  • Use a template project. Master the layout (HMI tags, security settings, multi-user server URLs) in a hand-built .ap20 and have the generator open and modify that template, rather than building everything from scratch.
  • Compile twice. Compile after the skeleton is in place, again after every block is generated, and a final time before save. Early errors are far cheaper to diagnose.
  • Log everything. Emit a CSV or JSON report listing every device, block, tag, and its allocated address. The report is invaluable for engineer sign-off.
  • Version your generator alongside the TIA Portal version it targets. A single binary tied to a single TIA Portal version is far easier to support than a multi-version matrix.
  • Engineer-in-the-loop. Always leave the final review pass to a human. Openness will happily produce a project that compiles but does not match the mechanical reality.

FAQ

Do I need to know C# to use TIA Portal Openness?

Yes, for the External API mode. C# is the primary supported language because Openness is a .NET API. The TIA Openness Scripter also accepts VB.NET, but every production reference, sample, and Siemens Knowledge Base article targets C#.

Can Openness generate programs for S7-1200 as well as S7-1500?

Yes. Both S7-1200 (firmware 4.0 and above) and S7-1500 CPUs are supported. WinAC and ET 200SP CPUs are also valid targets. Older S7-300/400 controllers are not exposed through the Openness API.

Is the Openness API free?

Yes. The Openness DLLs ship with the TIA Portal installation media. A valid TIA Portal license activates the TIA Portal instance that Openness drives, but no separate Openness license is required.

Can I use Python or another non-.NET language with TIA Openness?

Direct calls are not supported, but cross-language bridges exist. The open-source Repsay/tia-openness-api-client project on GitHub demonstrates a Python wrapper that talks to a C# Openness shim. Plan for an extra process boundary and JSON-RPC or named-pipe marshalling.

Where do I find the official Siemens documentation?

Start with Siemens Support entry 109792902, which indexes the Openness manual, the "Introduction and Demo Application" paper, and the installation guide. The V20-specific install path is documented at the TIA Portal Openness V20 installation page.

Back to blog