Discovering Siemens S7 PLCs OPC UA LDS, PROFINET DCP, and C#

David Krause14 min read
Industrial NetworkingSiemensTechnical 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

Discovering Siemens S7 PLCs: OPC UA LDS, PROFINET DCP, and C# Patterns

Auto-discovery of Siemens S7-1200 and S7-1500 controllers is a routine commissioning task, but the underlying mechanism changes dramatically depending on whether you rely on the OPC UA Local Discovery Server (LDS), a PROFINET DCP broadcast, the legacy S7 discovery frame, or a custom C# client. This reference consolidates the activation steps on the PLC side, the network prerequisites (subnets, broadcast domains, MAC forwarding), the registration flow into an LDS, and the integration patterns you can apply to build a plug-and-play tool without TIA Portal.

Constraint before any discovery can succeed: The S7-1200/S7-1500 OPC UA server is disabled by factory default. A controller in its out-of-the-box state is invisible to OPC UA Local Discovery. You must enable the server in the device configuration and download the project before any LDS, GDS, or third-party client can resolve the endpoint.

1. Discovery Mechanisms Compared

Four distinct mechanisms can locate a Siemens S7 PLC on a Layer 2 network. Each has a different scope, transport, and required configuration on the PLC.

Mechanism Transport Scope PLC-side activation Typical client
OPC UA Local Discovery Server (LDS) UDP multicast 224.0.0.252 port 5353 (mDNS-like) and TCP 4840 Local subnet OPC UA server enabled, port 4840 open OPC Foundation LDS, custom UA client
PROFINET DCP Ethernet multicast 01:0E:CF:00:00:00 Local Layer 2 segment PROFINET interface enabled (default on) TIA Portal, PRONETA, custom DCP scanner
S7 primary/secondary discovery ISO-on-TCP (TCP port 102) rack/slot request Routable with directed broadcast PUT/GET or S7 communication permitted LibNoDave, Snap7, S7NetPlus
Siemens Primary Setup Tool / S7-Diagnostics UDP/MAC broadcast Local subnet MAC reachable Siemens automation tool, TIA "Accessible devices"

The "find accessible devices" function in TIA Portal is essentially a MAC-address broadcast sweep across the local segment; it does not require any application-level server to be enabled. That is why a factory-fresh CPU still shows up in TIA even before OPC UA is configured. OPC UA discovery is application-layer and only works once the server is running.

2. OPC UA Local Discovery Server (LDS) Architecture

The OPC UA LDS, published by the OPC Foundation, is a stand-alone Windows service that maintains a registry of OPC UA servers on the local machine. The official binary and source are distributed through the OPC Foundation's developer samples page:

OPC Foundation Local Discovery Server (LDS)

The architecture follows Part 100 of the OPC UA specification. Each OPC UA server registers itself with the LDS over a local loopback call to a well-known endpoint (opc.tcp://localhost:4840). Once registered, the server is reachable through:

  • FindServersOnNetwork - sent as a UDP datagram to 224.0.0.252 on port 5353; LDS instances respond with the registered servers' discovery URLs.
  • GetEndpoints - directed TCP call to opc.tcp://<host>:4840 using the URL returned in step one.

The LDS only sees servers registered on the same host by default. To aggregate servers from multiple machines (including PLCs), you must run an LDS on each host that runs a server, or use the Global Discovery Server (GDS) for cross-subnet federation. The LDS binary does not crawl the network itself; the PLC's OPC UA stack has to push its registration, not be polled.

Multicast routing: The 224.0.0.252 discovery address is link-local by default. Routers typically do not forward multicast between subnets. Plan your LDS scope to match the Layer 2 broadcast domain or configure PIM/DVMRP if cross-subnet discovery is required.

3. Activating OPC UA Server on S7-1200 and S7-1500

Before any client (LDS, custom C#, or third-party SCADA) can see a Siemens PLC, the OPC UA server must be turned on inside the project. The procedure differs slightly between firmware generations.

3.1 S7-1500 / ET 200SP CPU

  1. Open the device configuration of the CPU in TIA Portal.
  2. Navigate to Properties > General > OPC UA.
  3. Tick Activate OPC UA server.
  4. Select the desired port (default 4840) and security policy. For lab discovery leave None enabled; for production use at least Basic256Sha256 with signed-and-encrypted.
  5. Define authentication: anonymous, username/password, or certificate-based. Siemens firmware V2.6 and above supports server certificates generated directly from TIA.
  6. Configure runtime measures such as minimum sampling interval, max monitored items, and max subscriptions to bound server load.
  7. Compile and download to the CPU.

3.2 S7-1200 (firmware V4.4 and above)

  1. Open the device configuration of the S7-1200 CPU.
  2. Under Properties > OPC UA Server enable the server.
  3. Limit the server to specific DBs or use the default "all accessible symbols" model. V4.4 supports read/write; subscriptions require V4.5 or later.
  4. Set the port (4840 default) and security policies.
  5. Download the project.

The firmware-dependent limits are documented in the Siemens function manuals for OPC UA on S7-1200 and S7-1500. Always cross-check the limits table for your specific CPU order number (e.g., 6ES7515-2AM02-0AB0 vs. 6ES7515-2AM02-0AB1) because OPC UA capability sometimes differs between MLFB revisions.

4. Registering the PLC's OPC UA Server with an LDS

Once the PLC's OPC UA server is enabled, the LDS registration question depends on where the LDS is running.

4.1 LDS on the same Windows host as the SCADA/HMI

If your C# application and the LDS service both run on the same PC, registration of local servers is automatic when the server starts and calls RegisterServer. This is the typical SCADA pattern.

4.2 LDS discovering servers on a Siemens PLC

A Siemens S7 CPU does not embed the OPC Foundation LDS. The PLC's UA stack registers itself with the LDS only if:

  • The LDS is reachable from the PLC's network at opc.tcp://<LDS-host>:4840, and
  • The PLC's OPC UA configuration has been told the LDS URL via the Discovery section in TIA Portal (CPU > Properties > OPC UA > Discovery).

Procedure to push a Siemens CPU's UA server to an LDS:

  1. In TIA Portal open the CPU properties > OPC UA > Discovery.
  2. Enter the LDS server URL, e.g., opc.tcp://192.168.0.50:4840.
  3. Choose a registration interval (default 60 s). The PLC will periodically push its discovery URL to the LDS.
  4. Compile and download the project.
  5. On the LDS host, verify the registration with the OPC Foundation's LDS console or by calling FindServersOnNetwork from any UA client.
Many PLCs, one LDS: If you have multiple S7-1500 CPUs, configure the same LDS URL on every CPU. The LDS will list each server under its own endpoint URL. There is no limit imposed by Siemens on the number of registrations beyond the LDS host's own capacity.

5. GDS Commissioning for Cross-Subnet Discovery

Where the LDS handles local subnet aggregation, the OPC UA Global Discovery Server (GDS) pushes and pulls server registrations across routable networks. Siemens includes a GDS push plug-in as part of TIA Portal from V16 upwards. The high-level commissioning flow:

  1. Stand up a GDS instance (e.g., the OPC Foundation's open-source UA-.NETStandard GDS sample or a commercial GDS).
  2. In TIA Portal open the CPU properties > OPC UA > GDS and enable Use GDS.
  3. Provide the GDS endpoint URL and a trust list (root CA) the PLC can validate.
  4. Download to the PLC; it will register and pull its server certificate from the GDS.
  5. Clients query the GDS over TCP (not multicast), so discovery works across routed networks.

GDS adds certificate lifecycle management, push of trust lists, and a directory service. For an air-gapped plant with a single subnet, LDS is sufficient. For multi-site, multi-subnet deployments, GDS is the only practical federated option.

6. PROFINET DCP Discovery (MAC Broadcast)

The "find accessible devices" button in TIA Portal triggers a PROFINET DCP IdentifyAll multicast. The frame is sent to the reserved Ethernet multicast address 01-0E-CF-00-00-00. Every PROFINET device on the segment is required to respond with its name-of-station, IP, and MAC. This is why even a brand-new CPU with no project responds.

If you are writing a C# discovery tool without TIA, you can use the SharpProfinet open-source stack or build a minimal DCP requester. The minimal DCP IdentifyAll frame layout is:

Offset Length (bytes) Field Value
0 6 Dest MAC 01:0E:CF:00:00:00
6 6 Src MAC Sender's MAC
12 2 EtherType 0x8892 (PROFINET)
14 4 PN frame ID 0xFEFE (DCP)
18 n PDU payload ServiceID 0x04 IdentifyAll

Once you have the IP, switch to TCP/102 and use the S7 protocol for further fingerprinting (firmware version, module order number, serial number). This combination - DCP to find, S7 to identify - is the most robust plug-and-play pattern that works on a default S7 CPU with no OPC UA configured.

7. S7 Native Discovery Without OPC UA

The legacy S7 communication stack (ISO-on-TCP, port 102) supports an unknown CPU discovery sequence. The classic library implementations:

Library Language Discovery call Notes
Snap7 C/C++/.NET wrapper Cli_ConnectTo() with target IP Industrial-grade; actively maintained
libnodave C/Java daveConnect() Older; still works on most S7-300/400 and S7-1200/1500
S7NetPlus C# Plc.Connect() Modern .NET, async API
node-s7 Node.js conn.Connect() Node integration

To enumerate possible rack/slot combinations you issue a CPU function group request. The S7-1500 typically responds at rack 0, slot 1; S7-1200 at rack 0, slot 1; ET 200SP at rack 0, slot 1 as well. The discovery can be reduced to a sweep of plausible rack/slot pairs at TCP/102:

for (int rack = 0; rack <= 0; rack++)
  for (int slot = 1; slot <= 4; slot++)
    if (TryS7Connect(ip, rack, slot, out cpuInfo))
      yield return cpuInfo;

Once connected, read system status list (SSL) 0x0011 (module identification) and 0x0012 (firmware version). This gives you the order number (MLFB), serial, and firmware without any project on the PLC side, as long as PUT/GET is permitted in the CPU security settings.

Security gate: From firmware V4.x onwards S7-1200 and S7-1500 block PUT/GET by default. Enable Permit access with PUT/GET from remote partner in the CPU protection settings or use the OPC UA server route instead.

8. C# Plug-and-Play Discovery Pattern

A robust C# discovery tool combines three phases: DCP multicast, S7 identification, and OPC UA endpoint retrieval. The skeleton below is intentionally framework-agnostic and uses Pylogix-style logic translated to C#; the original library targets EtherNet/IP but the pattern applies.

8.1 Phase 1 - L2 sweep with raw socket

using System.Net.Sockets;
using System.Net;
using PacketDotNet;

var client = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Raw);
client.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.10"), 0));
client.EnableBroadcast = true;

var eth = new EthernetPacket(
    PhysicalAddress.Parse("01-0E-CF-00-00-00"),
    PhysicalAddress.Parse("00-1B-1B-00-00-01"))
{ Type = EthernetType.Profinet };
var pn  = new ProfinetPacket(ProfiNetServiceType.DcpIdentifyAll);
eth.PayloadPacket = pn;
client.Send(eth.Bytes());

8.2 Phase 2 - S7 fingerprint via TCP/102

using S7.Net;

var plc = new Plc(CpuType.S71500, "192.168.0.20", 0, 1);
plc.Open();
var info = new {
    OrderNumber = plc.GetOrderCode(),
    Firmware     = plc.GetCpuInfo().FirmwareVersion
};
plc.Close();

8.3 Phase 3 - OPC UA discovery via LDS

using Opc.Ua;
using Opc.Ua.Client;

var discovery = new DiscoveryClient(new Uri("opc.tcp://localhost:4840"));
var servers = await discovery.FindServersOnNetworkAsync(
    0,                       // startingRecordId
    0,                       // maxRecordsToReturn
    new[] { "" },            // serverCapabilityFilter
    null);                   // applicationUri

foreach (var s in servers)
{
    var endpointUrl = s.DiscoveryUrls[0];   // e.g. opc.tcp://192.168.0.20:4840
    var endpoint   = await DiscoveryClient.GetEndpointsAsync(endpointUrl);
    // pick endpoint by security policy and consume
}

The phases can run concurrently. DCP finishes in milliseconds, S7 fingerprinting takes a few hundred ms per PLC, and OPC UA FindServers waits for the next multicast cycle (up to 60 s if the LDS only refreshes once per minute). Cache the result keyed by MAC or IP for 30 s to avoid hammering the network on repeated scans.

9. Cross-Subnet Considerations

Layer 2 broadcast-based mechanisms (DCP, S7 UDP broadcast, mDNS-like UA discovery) do not cross routed subnets. To extend discovery across VLANs you have three options:

  1. Directed broadcast - some L3 devices forward UDP/102 broadcasts if explicitly configured. Modern enterprise routers block this by default.
  2. L3 relay - PROFINet discovery agents (PRONETA, Siemens Primary Setup Tool) can be placed on each subnet, registered to a central server, and queried individually.
  3. Routed UA discovery - use a GDS or run LDS on each subnet and federate results over an OPC UA client that connects to each LDS.

If you must scan across subnets from a single host, configure a static route on each intermediate router so the discovery packets reach the target subnet. Most industrial routers (Scalance, Cisco IE, Hirschmann) require per-interface helper-address entries to forward UDP/102 broadcasts. Make sure the firewall permits UDP/102, TCP/102, UDP/5353, and TCP/4840 between the scanner and the PLC subnet.

Trap: A common field error is to assume that because Ping crosses the subnet, so will discovery. Ping uses ICMP echo, which is unicast and routable. PROFINET DCP and the OPC UA multicast discovery are not. Always verify with a packet capture (Wireshark on the PLC subnet) before declaring discovery broken.

10. Troubleshooting Matrix

Symptom Likely cause Verification Fix
PLC invisible in TIA "accessible devices" Different VLAN / firewall Wireshark capture on PLC port Add helper-address or open firewall
LDS returns no servers OPC UA server not activated on CPU Check CPU properties > OPC UA Enable server, download project
LDS only shows local PC's servers PLC not configured with LDS URL Check CPU > OPC UA > Discovery URL Enter LDS URL, download
C# S7 connect fails PUT/GET disabled in CPU security TIA > CPU properties > Protection Enable PUT/GET or use OPC UA
DCP responses missing Managed switch filtering multicast Show MAC table, IGMP snooping config Disable IGMP snooping or add static entry
FindServersOnNetwork timeout LDS not running or wrong port Test-NetConnection <host> -Port 4840 Start LDS service, open firewall
Discovery works from laptop but not from SCADA VM Virtual NIC not on correct VLAN ipconfig /all, switch port VLAN Tag VM NIC to PLC VLAN

11. Verification Checklist

  1. From the SCADA host run opc.tcp://<PLC>:4840 against the CPU's OPC UA port using UA Expert or a custom client. If it connects, the PLC server is active and reachable.
  2. Run the LDS console; the PLC's endpoint URL must appear in the registry within one registration interval.
  3. From a packet capture on the PLC port, confirm the CPU is sending DCP Identify responses (PROFINET frames with EtherType 0x8892).
  4. With S7NetPlus, read the order number and firmware. The values must match the MLFB label on the CPU.
  5. Issue a directed S7 read on a known tag (e.g., DB1.DBD0) - success confirms PUT/GET is open and the slot/rack mapping is correct.
  6. Re-run the C# discovery app from a different subnet. If it fails, switch to GDS or place an LDS on the target subnet.

12. Field-Proven Recommendations

  • Treat OPC UA as the future-proof path: enable the server on every S7-1500 you deploy, push the LDS URL once, and let discovery be config-driven.
  • Keep DCP as a fallback for green-field commissioning when projects are not yet on the CPU.
  • For mixed-vendor fleets, run an LDS on each operator station; aggregate at the SCADA layer rather than at the network layer.
  • Lock down discovery from the operator network with VLAN ACLs; PROFINET DCP and OPC UA multicast are noisy and an attacker can fingerprint devices trivially.
  • Document the discovery interval, LDS URL, and GDS root CA in the plant's network register so future maintenance engineers don't break the chain.

Frequently Asked Questions

Why does my brand-new Siemens S7-1200 not show up in the OPC UA Local Discovery Server?

Because OPC UA server is disabled by factory default. Open the CPU in TIA Portal, enable OPC UA Server under device properties, configure the port (default 4840), and download the project. Until that is done, the LDS cannot register the CPU because the server never starts.

How do I make a Siemens S7-1500 push its OPC UA endpoint to an LDS running on a Windows host?

In TIA Portal open the CPU's OPC UA properties and enter the LDS URL under Discovery, e.g., opc.tcp://192.168.0.50:4840. The CPU will periodically register itself with that LDS. The LDS must be running and reachable on TCP/4840 from the PLC subnet.

Can I find a Siemens PLC on the network without TIA Portal?

Yes. Use a PROFINET DCP multicast on MAC 01-0E-CF-00-00-00 with EtherType 0x8892 to enumerate devices on the local Layer 2 segment. Then connect to each device on TCP/102 and read the order number via the S7 protocol. This works on factory-fresh CPUs without any OPC UA configuration.

Why does FindServersOnNetwork return nothing when I call it from a custom C# client?

The OPC UA discovery multicast uses 224.0.0.252 on UDP/5353 and is link-local. Routers do not forward it. The LDS must run on the same Layer 2 segment as the client, or you must use a GDS over TCP. Also confirm the firewall allows UDP/5353 inbound and outbound.

What is the difference between LDS and GDS for Siemens PLC discovery?

The LDS aggregates OPC UA servers on a single host or local subnet using multicast discovery. The GDS is a federated directory service that operates over routable TCP, manages certificates, and can push trust lists to multiple PLCs at once. Use LDS for a single subnet, GDS when you have multiple subnets or need certificate lifecycle management.

Does PROFINET DCP discovery work across VLANs or routed subnets?

No. DCP is a Layer 2 multicast frame and is dropped at routed boundaries. To extend discovery you must place a PROFINET-aware tool (PRONETA, Siemens Primary Setup Tool) on each subnet, configure a directed broadcast and helper-address on the L3 device, or use OPC UA over a GDS instead.

Back to blog