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.
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.252on port5353; LDS instances respond with the registered servers' discovery URLs. -
GetEndpoints - directed TCP call to
opc.tcp://<host>:4840using 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.
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
- Open the device configuration of the CPU in TIA Portal.
- Navigate to Properties > General > OPC UA.
- Tick Activate OPC UA server.
- 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. - Define authentication: anonymous, username/password, or certificate-based. Siemens firmware V2.6 and above supports server certificates generated directly from TIA.
- Configure runtime measures such as minimum sampling interval, max monitored items, and max subscriptions to bound server load.
- Compile and download to the CPU.
3.2 S7-1200 (firmware V4.4 and above)
- Open the device configuration of the S7-1200 CPU.
- Under Properties > OPC UA Server enable the server.
- 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.
- Set the port (4840 default) and security policies.
- 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:
- In TIA Portal open the CPU properties > OPC UA > Discovery.
- Enter the LDS server URL, e.g.,
opc.tcp://192.168.0.50:4840. - Choose a registration interval (default 60 s). The PLC will periodically push its discovery URL to the LDS.
- Compile and download the project.
- On the LDS host, verify the registration with the OPC Foundation's LDS console or by calling
FindServersOnNetworkfrom any UA client.
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:
- Stand up a GDS instance (e.g., the OPC Foundation's open-source UA-.NETStandard GDS sample or a commercial GDS).
- In TIA Portal open the CPU properties > OPC UA > GDS and enable Use GDS.
- Provide the GDS endpoint URL and a trust list (root CA) the PLC can validate.
- Download to the PLC; it will register and pull its server certificate from the GDS.
- 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.
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:
- Directed broadcast - some L3 devices forward UDP/102 broadcasts if explicitly configured. Modern enterprise routers block this by default.
- L3 relay - PROFINet discovery agents (PRONETA, Siemens Primary Setup Tool) can be placed on each subnet, registered to a central server, and queried individually.
- 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.
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
- From the SCADA host run
opc.tcp://<PLC>:4840against the CPU's OPC UA port using UA Expert or a custom client. If it connects, the PLC server is active and reachable. - Run the LDS console; the PLC's endpoint URL must appear in the registry within one registration interval.
- From a packet capture on the PLC port, confirm the CPU is sending DCP Identify responses (PROFINET frames with EtherType
0x8892). - With S7NetPlus, read the order number and firmware. The values must match the MLFB label on the CPU.
- 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. - 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.