Simatic Net VB.NET OPC Client Integration: Setup Guide

David Krause15 min read
Data AcquisitionSiemensTechnical Reference
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

1. Simatic Net OPC Communication Architecture

Siemens SIMATIC NET PC Software exposes S7 controllers to VB.NET clients through one or more OPC server components bundled with the package. The current generation (SIMATIC NET PC Software V18 / V19 / V20) ships three OPC interfaces relevant to .NET developers:

  • OPC DA 3.0 Server (opcsvr.exe) – the Classic COM Data Access server reached from VB.NET through Runtime Callable Wrappers (RCWs).
  • OPC DA 2.05a Server – backward-compatible profile for legacy DA 2 clients.
  • OPC UA Server – modern binary/HTTP endpoint, accessible from .NET Framework 4.6+ or .NET 6+ without COM.

The Classic OPC DA path is the focus of this reference because the integration scenario is anchored in COM-based interop with VB.NET. The communication chain has six layers:

  1. Physical link – PROFINET, Industrial Ethernet (10/100/1000 Mbit/s), PROFIBUS-DP/FMS, or MPI.
  2. Transport – TCP/IP (RFC 1006 / ISO-on-TCP, port 102), or PROFIBUS FDL.
  3. S7 protocol layer – Siemens proprietary connection over CP 443-1 (S7-400) or CP 343-1 (S7-300), with configured TSAPs and connection resources.
  4. SIMATIC NET OPC Server – bridges S7 protocol to OPC items, registered as a Windows service and a COM local server.
  5. COM interfaceIOPCServer, IOPCGroup, IOPCItemMgt, IOPCSyncIO, IOPCAsyncIO2, IOPCCommon.
  6. VB.NET RCW layer – primary interop assembly (PIA) or custom RCW mapping the COM v-table to managed objects.

VB.NET can participate at layer 5 (full COM control, maximum flexibility) or layer 6 (managed wrapper, faster development). Both approaches are detailed below.

2. OPC Foundation Components and APIs

The OPC Foundation publishes the canonical interfaces that any Classic OPC client (including a Simatic Net OPC client written in VB.NET) must consume. Two API paths are available:

2.1 OPC Core Components (RCW path)

OPC Foundation supplies a set of Runtime Callable Wrappers (RCWs) bundled in the OPC Core Components redistributable. These wrappers expose every published specification (DA 2.05a, DA 3.0, AE 1.10, HDA 1.20, DX 1.0) as .NET-callable interfaces. They are free, vendor-neutral, and the lowest-level path into a COM-based OPC server.

Drawbacks: significant COM interop code must be hand-written in VB.NET. Memory management of IntPtr buffers, SafeHandle wrappers, and Marshal.ReleaseComObject calls fall on the developer.

2.2 OPC .NET API (managed path)

The OPC Foundation also distributes an OPC .NET API for Foundation members. It is a unified managed layer that abstracts both COM (DA 2, DA 3) and SOAP/XML servers, with sample clients in C# and VB.NET. The .NET API requires .NET Framework 2.0 or later. It does not have the status of a full OPC specification – it is an implementation provided as a convenience, but it is the recommended managed path for production VB.NET clients when membership credentials are available.

Reference: OPC Foundation – What is OPC? and the OPC Classic specifications index.

3. Prerequisites

Component Requirement Notes
Operating system Windows 10 / 11 (64-bit) or Windows Server 2016 / 2019 / 2022 Simatic Net V19+ requires 64-bit; 32-bit requires explicit install
SIMATIC NET PC Software V18.0 / V19.0 / V20.0 OPC DA server and configuration tools (Station Configurator, Commissioning)
STEP 7 / TIA Portal V5.6 / V17 / V18 (matching S7-400 project) Required for PC station configuration and S7 connection
S7-400 PLC CPU 41x PN/DP, CPU 41x H, CPU 41x F/FH CP 443-1 / CP 443-1 Advanced required for Ethernet S7 communication
.NET Framework 4.6.2 minimum (4.8 recommended) Visual Studio 2010 / 2015 / 2019 / 2022 supported
OPC Core Components Latest redistributable (3.00.x) Install before referencing OPC PIAs
User rights Local Administrator for configuration; standard user for runtime DCOM launch/activation rights must be granted

4. Simatic Net OPC Server Configuration

The Simatic Net OPC Server is configured through the Station Configurator and the SIMATIC NET Commissioning tool. The PC station must mirror the STEP 7 / TIA configuration of the S7-400 connection.

4.1 Defining the OPC Server in the PC Station

  1. Open Station Configurator (Start → SIMATIC → SIMATIC NET → Communication Settings → Station Configurator).
  2. Add an OPC Server module to slot 1 of the PC station.
  3. Add an IE General module (Industrial Ethernet) on a free slot and bind it to the PC's Ethernet adapter.
  4. Compile the station; the resulting S7ONLINE configuration is consumed by the OPC server at runtime.

4.2 Configuring the S7 Connection to S7-400

  1. In STEP 7 / TIA Portal, open the PC station project and add an S7 connection to the S7-400 PLC.
  2. Set the local endpoint to the IE module of the PC station.
  3. Set the partner endpoint to the S7-400 CP 443-1 IP address, rack 0, slot 3 (CPU slot).
  4. Define the TSAPs: local (e.g. 10.01) and partner (e.g. 03.01). For an S7-400 with CP 443-1, the partner TSAP typically has the form 03.xx where xx matches the configured S7 connection number.
  5. Download the PC station configuration and the S7 connection to the running Simatic Net installation.
DCOM Configuration: For local clients no DCOM edits are required. For remote clients, configure dcomcnfg to grant the OPC server launch and activation rights to the client user, and open TCP port 135 plus the OPC server's dynamic range. The Microsoft KB article Configuring a machine to host COM components documents the procedure.

5. Tag Addressing in the Simatic Net OPC Namespace

The OPC DA server exposes S7 memory areas as items with a hierarchical item ID. The most common syntaxes are:

Memory Area Item ID Format Example
Data Block (DB) S7:[connection_name]DB<n>,BYTE <offset> S7:[S7_Conn_1]DB10,BYTE 0
Bit in DB S7:[connection_name]DB<n>,X <byte>.<bit> S7:[S7_Conn_1]DB10,X 0.0
Word / INT / REAL S7:[connection_name]DB<n>,WORD/DINT/REAL <offset> S7:[S7_Conn_1]DB20,REAL 4
Process inputs (PE) S7:[connection_name]PE<byte> S7:[S7_Conn_1]PE0
Process outputs (PA) S7:[connection_name]PA<byte> S7:[S7_Conn_1]PA0
Merker / flags (M) S7:[connection_name]MB/MW/MD <offset> S7:[S7_Conn_1]MW10
Timers / Counters S7:[connection_name]T<n> / C<n> S7:[S7_Conn_1]T5
Symbolic (after upload) S7:[connection_name]SYM:<symbol> S7:[S7_Conn_1]SYM:"TankLevel"

The byte offset is zero-based. A REAL occupies 4 bytes, an INT/DINT 4 bytes, and a BOOL 1 bit. Multi-DB reads and writes are composed by the client in OPC group definitions.

6. VB.NET Client Implementation – RCW Approach

The RCW path gives the most control and is recommended when the Simatic Net server runs locally and the client is a long-lived Windows service or HMI application. References required in the VB.NET project:

  • Interop.OpcRcw.Comn.dll
  • Interop.OpcRcw.Da.dll

Both ship with the OPC Core Components redistributable. Import them with Imports OpcRcw.Comn and Imports OpcRcw.Da.

6.1 Connect to the Simatic Net OPC Server

Imports OpcRcw.Comn
Imports OpcRcw.Da
Imports System.Runtime.InteropServices

Module SimaticNetClient

    ' Simatic Net OPC DA 3.0 ProgID and CLSID
    Private Const SERVER_PROG_ID As String = "OPC.SimaticNet"
    Private Const DA3_CLSID As String = "{75D00BBB-DDA5-11D1-B7B3-006008B5B4F7}"

    Public Function ConnectToServer() As IOPCServer
        Dim type As Type = Type.GetTypeFromProgID(SERVER_PROG_ID)
        If type Is Nothing Then
            Throw New InvalidOperationException(
                "Simatic Net OPC server not registered. Run Station Configurator.")
        End If
        Dim srv As Object = Activator.CreateInstance(type)
        Return CType(srv, IOPCServer)
    End Function

End Module

6.2 Add an OPC Group with a Subscription

Public Function AddSubscription(server As IOPCServer, _
                                updateRateMs As Integer, _
                                ByRef group As IOPCGroupStateMgt, _
                                ByRef groupHandle As Integer) As Integer
    Dim active As Integer = 1
    Dim biasTime As Integer = 0
    Dim deadband As Single = 0.0F
    Dim LCID As Integer = System.Globalization.CultureInfo.CurrentCulture.LCID
    Dim name As String = "VBNetGroup"

    Return server.AddGroup(name, active, updateRateMs, _
                           0, biasTime, deadband, LCID, _
                           groupHandle, updateRateMs, group, _
                           IID.IID_IOPCGroupStateMgt)
End Function

6.3 Add Items (S7-400 Tags) to the Group

Public Sub AddTags(group As IOPCItemMgt, ParamArray itemIds() As String)
    Dim n As Integer = itemIds.Length
    Dim itemDefs(n - 1) As OPCITEMDEF
    Dim clientHandles(n - 1) As Integer
    For i As Integer = 0 To n - 1
        itemDefs(i).szItemID = itemIds(i)
        itemDefs(i).szAccessPath = ""
        itemDefs(i).bActive = 1
        itemDefs(i).hServer = 0
        itemDefs(i).dwBlobSize = 0
        itemDefs(i).pBlob = IntPtr.Zero
        itemDefs(i).vtRequestedDataType = VarEnum.VT_EMPTY
        clientHandles(i) = i + 1
    Next

    Dim results(n - 1) As IntPtr
    group.AddItems(n, itemDefs, results)

    For i As Integer = 0 To n - 1
        Dim addResult As OPCITEMRESULT = _
            Marshal.PtrToStructure(results(i), GetType(OPCITEMRESULT))
        If addResult.hResult <> S_OK Then
            Throw New COMException("AddItems failed for " & itemIds(i), _
                                   addResult.hResult)
        End If
        Marshal.FreeCoTaskMem(results(i))
    Next
End Sub

6.4 Synchronous Read

Public Function ReadTags(group As IOPCSyncIO, _
                         ParamArray clientHandles() As Integer) _
                         As Object()
    Dim n As Integer = clientHandles.Length
    Dim pErrors As IntPtr
    Dim pValues As IntPtr
    Dim pQualities As IntPtr
    Dim pTimestamps As IntPtr

    group.Read(OPCDATASOURCE.OPC_DS_DEVICE, n, clientHandles, _
               pValues, pQualities, pTimestamps, pErrors)

    Dim values(n - 1) As Object
    For i As Integer = 0 To n - 1
        Dim item As OPCITEMSTATE = Marshal.PtrToStructure( _
            IntPtr.Add(pValues, i * Marshal.SizeOf(GetType(OPCITEMSTATE))), _
            GetType(OPCITEMSTATE))
        values(i) = Marshal.GetObjectForNativeVariant(item.vDataValue)
    Next

    Marshal.FreeCoTaskMem(pValues)
    Marshal.FreeCoTaskMem(pErrors)
    Return values
End Function

6.5 Asynchronous Read with Callback

Asynchronous I/O offloads the read from the calling thread to the COM apartment. Simatic Net OPC fires IOPCDataCallback when the group completes the cycle.

Public Class AsyncHandler
    Implements IOPCDataCallback

    Public Sub OnDataChange(dwTransid As Integer, hGroup As Integer, _
                            hrMasterquality As Integer, hrMastererror As Integer, _
                            dwCount As Integer, phClientItems As IntPtr, _
                            pvValues As IntPtr, pwQualities As IntPtr, _
                            pftTimeStamps As IntPtr, pErrors As IntPtr) _
            Implements IOPCDataCallback.OnDataChange

        For i As Integer = 0 To dwCount - 1
            Dim clientHandle As Integer = Marshal.ReadInt32( _
                IntPtr.Add(phClientItems, i * 4))
            Dim state As OPCITEMSTATE = Marshal.PtrToStructure( _
                IntPtr.Add(pvValues, i * Marshal.SizeOf(GetType(OPCITEMSTATE))), _
                GetType(OPCITEMSTATE))
            Console.WriteLine("Tag {0} = {1} (Q={2})", _
                              clientHandle, state.vDataValue, state.wQuality)
        Next
    End Sub

    Public Sub OnReadComplete(dwTransid As Integer, hGroup As Integer, _
                              hrMasterquality As Integer, hrMastererror As Integer, _
                              dwCount As Integer, phClientItems As IntPtr, _
                              pvValues As IntPtr, pwQualities As IntPtr, _
                              pftTimeStamps As IntPtr, pErrors As IntPtr) _
            Implements IOPCDataCallback.OnReadComplete
        ' Handle async read complete similarly
    End Sub

    Public Sub OnCancelComplete(dwTransid As Integer, hGroup As Integer) _
            Implements IOPCDataCallback.OnCancelComplete
    End Sub
End Class

6.6 Synchronous Write

Public Sub WriteTags(group As IOPCSyncIO, _
                     handles() As Integer, values() As Object)
    Dim n As Integer = handles.Length
    Dim pErrors As IntPtr
    group.Write(n, handles, values, pErrors)

    For i As Integer = 0 To n - 1
        Dim hr As Integer = Marshal.ReadInt32(IntPtr.Add(pErrors, i * 4))
        If hr <> S_OK Then
            Throw New COMException("Write failed at index " & i, hr)
        End If
    Next
    Marshal.FreeCoTaskMem(pErrors)
End Sub

7. VB.NET Client Implementation – OPC .NET API

The OPC Foundation .NET API (downloadable by Foundation members) packages the COM interop into a managed assembly. Reference OpcNetApi.dll and OpcNetApi.Com.dll, then import Opc and Opc.Da.

Imports Opc
Imports Opc.Da

Module NetApiClient

    Public Sub ConnectAndRead()
        Dim server As New Server(Opc.Specification.COM_DA_20)
        Dim url As URL = New URL("opcda://localhost/OPC.SimaticNet")
        server.Connect(url)

        Dim browser As Opc.Da.Browser = New Opc.Da.Browser(server)
        Dim leaves As Opc.Da.Item() = browser.Browse(ItemIdentifier.Root, _
            Nothing, Nothing, True)

        Dim subscription As Subscription = server.CreateSubscription(500)
        subscription.State.Active = True

        Dim items(leaves.Length - 1) As Item
        For i As Integer = 0 To leaves.Length - 1
            items(i) = New Item()
            items(i).ItemName = leaves(i).ItemName
            items(i).ClientHandle = i
            items(i).Active = True
        Next
        subscription.AddItems(items)

        AddHandler subscription.DataChanged, AddressOf OnChanged
        Console.ReadLine()
        server.Disconnect()
    End Sub

    Private Sub OnChanged(sender As Object, e As DataChangedEventArgs)
        For Each val As ItemValueResult In e.Values
            Console.WriteLine("{0} = {1}", val.Item.ItemName, val.Value)
        Next
    End Sub

End Module

This approach eliminates Marshal.ReleaseComObject discipline, handles subscription state transitions, and provides typed ItemValueResult objects rather than raw IntPtr buffers.

8. Reading and Writing an S7-400 Process Variable End-to-End

Assume the S7-400 contains a function block controlling a tank level. DB50 holds the process image, where DB50.DBD0 is the measured level in REAL format and DB50.DBX10.0 is the pump start command.

8.1 Tag List

S7 Symbol OPC Item ID VB.NET Type Direction
TankLevel S7:[S7_400_Conn]DB50,REAL 0 Single Read
PumpStart S7:[S7_400_Conn]DB50,X 10.0 Boolean Read/Write
Setpoint S7:[S7_400_Conn]DB50,REAL 20 Single Write

8.2 Verification Procedure

  1. Build the PC station project and download it to the local Simatic Net runtime.
  2. Verify the S7 connection is established – the OPC server returns OPC_QUALITY_GOOD (0xC0) for each item on first read.
  3. Force the PumpStart bit from VB.NET and observe the corresponding DO on the S7-400 diagnostic buffer.
  4. Read TankLevel and confirm a value within the engineering range.
  5. Read Setpoint back from the PLC to confirm the write committed.

9. Integration with Process Simulation and Historian Layers

Beyond direct S7-400 reads, the Simatic Net OPC server frequently acts as the bridge between control hardware and upper-layer platforms such as Honeywell UniSim Design (dynamic process simulation) and OSIsoft PI System (time-series historian). The architecture is:

S7-400 PLC + CP 443-1 SIMATIC NET OPC DA / UA VB.NET Client (this app) UniSim Design (process model) OSIsoft PI Server (historian) HMI / Reports SQL / Web

The VB.NET application reads measured values from S7-400 via Simatic Net, drives a UniSim model with operator setpoints, and forwards process values to PI using its OPC interface or a dedicated PI OPC DA Interface. The historian then exposes long-term trends back to dashboards.

10. Error Handling and Common Fault Codes

HRESULT Name Likely Cause Remediation
0x00000000 S_OK Success
0x80004005 E_FAIL Generic COM failure Check Simatic Net service, station configuration
0xC0040004 OPC_E_NOTFOUND Item ID does not exist in server Browse server; verify connection name in item path
0xC0040007 OPC_E_INVALIDHANDLE Stale client handle Re-add item; check group cleanup
0xC0040006 OPC_E_INVALIDITEMID Malformed tag path Validate syntax against addressing table
0xC004000C OPC_E_DEADBANDNOTSUPPORTED Non-zero deadband on Analog tag with no EU range Set deadband = 0 in subscription
0xC0040010 OPC_S_CLAMP Returned value clamped to EU limits Informational; check tag scaling
0x00000005 E_ACCESSDENIED DCOM launch/activation denied Grant user rights in dcomcnfg
0x800401F3 CO_E_OBJNOTCONNECTED Proxy disconnected Reconnect; check network
0x8001011F COR_E_OBJECTDISPOSED Group removed but still referenced Call Marshal.ReleaseComObject on cleanup

10.1 Item Quality Codes

Quality Byte Meaning
0xC0 Good – value valid
0xC8 Good – local override
0x40 Uncertain – value below/above EU range
0x00 Bad – communication failure (S7 link down)
0x18 Bad – no connection to S7-400 CP
0x1C Bad – device failure (CP 443-1 error)
Connection-loss detection: register a subscription and watch for items transitioning to OPC_QUALITY_BAD (0x00–0x1C range). This is the only reliable signal from the Simatic Net server that the S7 link is down; do not rely on TCP keepalive alone.

11. Performance, Sizing and Tuning

Parameter Default Recommendation Impact
Group update rate 100 ms 250–500 ms for trending, 100 ms for control loops Higher rates multiply CPU load on Simatic Net and S7-400 CP
Max items per group Unlimited (theoretical) 200–500 for S7-400 / CP 443-1; up to 2000 for CP 443-1 Advanced Reduces PDU count, improves throughput
Deadband (analog) 0% 0.5–1% for trending, 0% for control Suppresses redundant callbacks
Async vs sync reads Sync Async for continuous, sync for on-demand Async avoids blocking VB.NET UI thread
Connection count 1 Multiple connections to load-balance tags across CPs Distributes S7 partner resource usage
Apartment model STA STA mandatory for OPC DA callbacks MTA causes RPC_E_WRONG_THREAD errors

Throughput rule of thumb: a single S7 connection to a CP 443-1 sustains roughly 3000 item updates/second at 100 ms update rate, dropping to 1500/s at 50 ms. Above this, transition to CP 443-1 Extended or split across multiple PC station connections.

12. Security Considerations

  • Run as a dedicated Windows user: do not embed domain admin credentials in the VB.NET service. Create a SVC_SIMATICNET_OPC account with Log on as service rights only.
  • Restrict the OPC server with the Simatic Net Security Configuration tool: limit which clients may add groups, browse, or write.
  • Use OPC UA for new deployments: UA supports authentication (certificates), transport encryption (TLS 1.2/1.3), and runs on a single configurable port – eliminating the DCOM attack surface. The Simatic Net OPC UA server in V18+ is the recommended path for any new VB.NET client.
  • Firewall rules: open TCP 102 (ISO-on-TCP) only between the VB.NET host and the S7-400 CP; block all other inbound traffic.
  • Audit writes: the VB.NET application should log every successful OPC write with timestamp, user, tag, and previous/new value to support GMP/21 CFR Part 11-style traceability.

13. Verification Checklist

  1. Simatic Net Station Configurator shows the OPC server module in slot 1 and the IE module bound to the correct network adapter.
  2. S7 connection is established – Commissioning tool reports the S7-400 partner as Reachable.
  3. DCOM permissions allow the VB.NET process to launch and access the OPC server.
  4. A test read of S7:[S7_400_Conn]DB50,REAL 0 returns a value with quality 0xC0 (Good).
  5. A test write of a BOOL tag flips the corresponding DO on the S7-400, verified through the PLC's online diagnostic buffer.
  6. Disconnecting the Ethernet cable for 10 seconds triggers quality 0x00 on all items; reconnecting restores quality 0xC0 within the subscription update interval.
  7. The VB.NET application survives a client-side disconnect by cleanly releasing COM objects and reconnecting within 5 seconds.

14. Frequently Asked Questions

Which OPC interface should my new VB.NET client use: DA 3.0 RCW or the OPC .NET API?

For new projects on .NET Framework 4.6.2 or later, prefer OPC UA (Simatic Net V18+ ships a UA server) – it removes COM/DCOM entirely. If OPC Classic is mandatory, use the OPC .NET API when your organization is an OPC Foundation member; it eliminates manual Marshal.ReleaseComObject calls. Otherwise, the RCW approach (Core Components) is free and gives full control.

The OPC server returns OPC_E_NOTFOUND for every tag – what is wrong?

The connection name in the item path (between square brackets, e.g. S7:[S7_400_Conn]) must match an S7 connection name defined in the PC station configuration. Verify the name in STEP 7 / TIA, re-download the station, and confirm the OPC server has reloaded the configuration (restart the OPC server service if necessary).

What is the maximum number of items per S7-400 connection?

The CP 443-1 supports up to 64 active S7 connections with a combined throughput of approximately 3000 tag updates/second per connection. Practical single-client item count is around 2000 active items per CP before latency rises; split groups across multiple CP 443-1 Advanced modules for larger tag lists.

How do I detect that the S7-400 link has dropped without polling?

Subscribe to the items and inspect the quality field on each callback. A transition to OPC_QUALITY_BAD (any sub-code from 0x00 to 0x1F) signals an S7 connection failure. Pair this with the OPC server's IOPCServer.GetStatus to confirm the local server is still healthy and only the S7 link has dropped.

Can the VB.NET client run on the same PC as the Simatic Net OPC server?

Yes – and it is the recommended topology for performance and DCOM-free operation. Local COM calls use the fast LPC channel rather than RPC, and no DCOM permissions need to be granted. The OPC.SimaticNet ProgID resolves to the local COM local server.

Does OPC DA support arrays or structs for reading 100 contiguous REALs from a DB?

OPC DA reads/writes scalar values per item. To move 100 REALs, the recommended approach is to define 100 individual OPC items at byte offsets 0, 4, 8, … 396 – or to switch to OPC UA, where Read/Write services natively support multi-dimensional arrays and structured types in a single call.

Back to blog