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:
- Physical link – PROFINET, Industrial Ethernet (10/100/1000 Mbit/s), PROFIBUS-DP/FMS, or MPI.
- Transport – TCP/IP (RFC 1006 / ISO-on-TCP, port 102), or PROFIBUS FDL.
- S7 protocol layer – Siemens proprietary connection over CP 443-1 (S7-400) or CP 343-1 (S7-300), with configured TSAPs and connection resources.
- SIMATIC NET OPC Server – bridges S7 protocol to OPC items, registered as a Windows service and a COM local server.
-
COM interface –
IOPCServer,IOPCGroup,IOPCItemMgt,IOPCSyncIO,IOPCAsyncIO2,IOPCCommon. - 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
- Open Station Configurator (Start → SIMATIC → SIMATIC NET → Communication Settings → Station Configurator).
- Add an OPC Server module to slot 1 of the PC station.
- Add an IE General module (Industrial Ethernet) on a free slot and bind it to the PC's Ethernet adapter.
- Compile the station; the resulting
S7ONLINEconfiguration is consumed by the OPC server at runtime.
4.2 Configuring the S7 Connection to S7-400
- In STEP 7 / TIA Portal, open the PC station project and add an S7 connection to the S7-400 PLC.
- Set the local endpoint to the IE module of the PC station.
- Set the partner endpoint to the S7-400 CP 443-1 IP address, rack 0, slot 3 (CPU slot).
- 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 form03.xxwherexxmatches the configured S7 connection number. - Download the PC station configuration and the S7 connection to the running Simatic Net installation.
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.dllInterop.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
- Build the PC station project and download it to the local Simatic Net runtime.
- Verify the S7 connection is established – the OPC server returns
OPC_QUALITY_GOOD(0xC0) for each item on first read. - Force the
PumpStartbit from VB.NET and observe the corresponding DO on the S7-400 diagnostic buffer. - Read
TankLeveland confirm a value within the engineering range. - Read
Setpointback 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:
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) |
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_OPCaccount 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
- Simatic Net Station Configurator shows the OPC server module in slot 1 and the IE module bound to the correct network adapter.
- S7 connection is established –
Commissioningtool reports the S7-400 partner as Reachable. - DCOM permissions allow the VB.NET process to launch and access the OPC server.
- A test read of
S7:[S7_400_Conn]DB50,REAL 0returns a value with quality 0xC0 (Good). - A test write of a BOOL tag flips the corresponding DO on the S7-400, verified through the PLC's online diagnostic buffer.
- Disconnecting the Ethernet cable for 10 seconds triggers quality 0x00 on all items; reconnecting restores quality 0xC0 within the subscription update interval.
- 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.