Siemens Comfort HMI SQL Logging: OPC UA vs S7NetPlus Comparison

David Krause15 min read
HMI / SCADASiemensTechnical 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

Overview

Siemens Comfort panels (TP1200 Comfort, TP1500 Comfort, TP2200 Comfort, TP1900 Comfort) include a built-in CSV logging workflow that writes historical tags to the panel's SD card and can copy the resulting files to a remote share. When the destination is a relational database such as Microsoft SQL Server, however, the panel itself cannot run a custom OPC client or insert rows into a database directly; an external Windows service or scheduled task is required on a separate PC. This reference compares the three architectures that engineers most commonly evaluate for that bridge:

  1. Siemens SIMATIC HMI Options+ CSV export, with a downstream ETL process that loads the CSV files into SQL Server.
  2. An OPC UA client written in C# against the OPC Foundation .NET Standard stack, polling or subscribing to tags exposed by WinCC Runtime on the Comfort panel.
  3. A direct S7 communication client using the S7NetPlus library to read DBs, Merkers, and process tags from the S7-1200 or S7-1500 PLC that the panel is displaying.

The objective of this document is to give the controls engineer a side-by-side comparison of the three approaches, with concrete C# code, a SQL Server target schema, licensing caveats, and a verification checklist that you can run on the bench before deploying to production.

Architecture Options

Option 1 - CSV Export with HMI Options+

SIMATIC WinCC on the Comfort panel writes process values to a CSV file on the SD card of the panel using a historical tag or logging tag. Once the file is closed, Options+ can copy it to a remote SMB share and delete it from the local card only if the copy completes successfully. A second process on the PC ingests the CSV into SQL Server using BULK INSERT or a small ETL script.

This is the only path that survives total network outages between the panel and the PC: while the network is down, the panel still writes to its SD card. The trade-off is the latency of the data appearing in the database (file rotation interval plus network recovery plus ETL run interval).

Option 2 - OPC UA Client Polling the Panel

The Comfort panel exposes an OPC UA server (built into WinCC Runtime). A C# application on a separate PC uses the OPC Foundation .NET Standard client library to open a session and either poll specific NodeIds on a timer or subscribe to data changes. Each change is written as a row to SQL Server.

The advantage is uniformity of access: the same client can read HMI tags, PLC tags (if forwarded), and even energy counters without needing direct S7 access. The disadvantages are the dependency on network availability (lost samples during outage unless buffered on disk), the OPC Foundation licensing model for commercial distribution, and the requirement that the PC hosting the client must be available.

Option 3 - S7NetPlus Direct PLC Read

S7NetPlus is a managed .NET library that speaks the S7 communication protocol directly. It does not require the Comfort panel at all; it reads tags from the S7-1200 / S7-1500 CPU that the panel is connected to. It is published under the MIT license and is free for commercial use. A C# application polls the PLC at a fixed interval (for example, every 1 s) and inserts the values into SQL Server.

This is the simplest path if you do not need to read HMI-internal computed tags, only PLC process tags. The Comfort panel becomes purely a display device; the data acquisition runs independently.

Option Comparison

Criterion HMI Options+ CSV OPC UA Client (WinCC) S7NetPlus
Source of truth WinCC Runtime historical WinCC Runtime tags S7 CPU DB / Merker / PEW
Network outage behaviour Buffers locally on SD card Loses samples until reconnect Loses samples until reconnect
Polling interval floor Tag cycle (250 ms typical) Subscription push or 250 ms 50-200 ms typical
Database load pattern Batched BULK INSERT One INSERT per change event One INSERT per poll cycle
License cost Bundled with WinCC/Comfort OPC Foundation commercial terms MIT, free
Panel-side configuration Configure historical tag Activate OPC UA server None
Required skills WinCC, SMB, T-SQL C#, OPC UA, T-SQL C#, T-SQL
External PC required Yes (ETL) Yes (client) Yes (client)
Survives PC reboot Yes, until SD fills No, samples lost No, samples lost
Can read non-PLC tags Yes (HMI variables) Yes No

Topology and Data Flow

S7-1200/1500 PLC TP1200 Comfort WinCC Runtime + OPC UA PC: C# Service OPC UA / S7NetPlus PC: SQL Server dbo.ProcessValues table PROFINET Option A: OPC UA Option B: CSV ETL INSERT

Topology note: the Comfort panel sits between the PLC and the PC for Option A and Option B. For Option C (S7NetPlus direct), the PC talks to the PLC and bypasses the panel for data; the panel remains a pure HMI.

Prerequisites

  • Siemens Comfort panel with WinCC Comfort/Advanced V16 or later (OPC UA server requires TIA Portal V14 SP1 or later for full security profiles).
  • S7-1200 (firmware V4.2 or later) or S7-1500 CPU with PUT/GET enabled if S7NetPlus will read directly.
  • Windows 10/11 or Windows Server 2016+ PC dedicated to the data service.
  • .NET 6 or .NET 8 desktop runtime installed on the PC.
  • Microsoft SQL Server 2017 or later (Express edition is acceptable for sub-10 GB logging databases).
  • For Option A: OPC Foundation .NET Standard NuGet package OPCFoundation.NetStandard.Opc.Ua.Client version 1.4.x or later.
  • For Option C: NuGet package S7netplus version 0.12.0 or later.

SQL Server Target Schema

Define a single table that all three options can write to. Use a clustered columnstore index only if your row volume exceeds 50 million per year; otherwise the rowstore clustered index on the time key is sufficient.

CREATE TABLE dbo.ProcessValues (
    LogId        BIGINT IDENTITY(1,1) NOT NULL,
    TagName      NVARCHAR(128) NOT NULL,
    TagValue     SQL_VARIANT NOT NULL,
    Quality      SMALLINT NOT NULL,
    SourceTime   DATETIME2(3) NOT NULL,
    IngestTime   DATETIME2(3) NOT NULL
        CONSTRAINT DF_ProcessValues_IngestTime DEFAULT SYSUTCDATETIME(),
    SourceKind   NVARCHAR(16) NOT NULL, -- 'OPCUA', 'S7NET', 'CSV'
    CONSTRAINT PK_ProcessValues PRIMARY KEY CLUSTERED (SourceTime, TagName)
);
CREATE NONCLUSTERED INDEX IX_ProcessValues_TagName_Time
    ON dbo.ProcessValues (TagName, SourceTime DESC);

The composite primary key on (SourceTime, TagName) gives you natural deduplication for re-ingested CSV files and prevents a single bad poll from corrupting history.

Option A - OPC UA Client Implementation

Activating the OPC UA Server on the Comfort Panel

In TIA Portal, on the Comfort panel project, open Runtime settings > OPC and enable the OPC UA server. Define a user (for example opcuser) with anonymous-read disabled. Note the server endpoint URL; the default is opc.tcp://<panel-ip>:4840.

C# Client Skeleton

using Opc.Ua;
using Opc.Ua.Client;
using System.Data.SqlClient;

var cfg = new ApplicationConfiguration();
cfg.ApplicationName = "ComfortLogger";
cfg.ApplicationType = ApplicationType.Client;
cfg.CertificateValidator = new CertificateValidator();
cfg.CertificateValidator.TrustedPeerCertificates.StoreType = CertificateStoreType.Directory;
cfg.CertificateValidator.TrustedPeerCertificates.StorePath = @"%CommonApplicationData%\OPC Foundation\Certificates";
await cfg.LoadApplicationConfigurationAsync(false);

var endpoint = CoreClientUtils.SelectEndpoint(
    "opc.tcp://192.168.0.50:4840", useSecurity: false);
var session = await Session.Create(cfg, endpoint, false, "ComfortLogger", 60000, null, null);

var subscription = new Subscription(session.DefaultSubscription) {
    PublishingInterval = 1000
};
var item = new MonitoredItem {
    StartNodeId = new NodeId("ns=4;s=HMI_Tag_Pressure", 4),
    AttributeId = Attributes.Value,
    SamplingInterval = 500
};
item.Notification += OnValueChange;
subscription.AddItem(item);
session.AddSubscription(subscription);
subscription.Create();

async void OnValueChange(MonitoredItem mi, MonitoredItemNotificationEventArgs e) {
    foreach (var v in mi.DequeueValues()) {
        if (StatusCode.IsGood(v.StatusCode)) {
            using var cn = new SqlConnection("Server=.;Database=Plant;Integrated Security=true;");
            await cn.OpenAsync();
            using var cmd = new SqlCommand(@"INSERT INTO dbo.ProcessValues
                (TagName, TagValue, Quality, SourceTime, SourceKind)
                VALUES (@n, @v, @q, @t, 'OPCUA')", cn);
            cmd.Parameters.AddWithValue("@n", mi.StartNodeId.ToString());
            cmd.Parameters.AddWithValue("@v", v.Value);
            cmd.Parameters.AddWithValue("@q", (short)v.StatusCode.Code);
            cmd.Parameters.AddWithValue("@t", v.SourceTimestamp);
            await cmd.ExecuteNonQueryAsync();
        }
    }
}

Subscription versus Polling

Subscriptions are preferred when the panel supports them with cyclic continuous tag acquisition in WinCC. Polling on a System.Timers.Timer at 1000 ms is acceptable for slow-changing tags (temperatures, levels). The Notification path is more efficient because the panel pushes only when the value changes within the configured deadband.

Option B - CSV via HMI Options+

Configuring the Logging Tag

On the Comfort panel, in the historical data configuration, set:

  • Acquisition cycle: 1000 ms (matches the field device update).
  • Logging mode: cyclic log with file rotation every 60 minutes or 50000 events, whichever comes first.
  • Storage path: /media/simatic/CF/Logs/ on the SD card.

Configuring Options+ File Transfer

In SIMATIC HMI Options+, create a transfer task for the path above that copies completed files to \\PC01\Ingest\Comfort\ and deletes them on success. Confirm the SMB share is reachable from the panel by browsing to it from the panel's Service Center.

SQL Server ETL

CREATE TABLE dbo.Staging_CSV (
    TagName  NVARCHAR(128),
    [Time]   DATETIME2(3),
    Value    NVARCHAR(64),
    Quality  NVARCHAR(16)
);

BULK INSERT dbo.Staging_CSV
FROM 'C:\Ingest\Comfort\ProcessLog_20250115.csv'
WITH (FORMAT = 'CSV', FIRSTROW = 2, FIELDTERMINATOR = ';', ROWTERMINATOR = '\n');

INSERT INTO dbo.ProcessValues (TagName, TagValue, Quality, SourceTime, SourceKind)
SELECT TagName, CAST(Value AS SQL_VARIANT),
       CASE Quality WHEN 'Good' THEN 192 ELSE 0 END,
       [Time], 'CSV'
FROM dbo.Staging_CSV s
WHERE NOT EXISTS (
    SELECT 1 FROM dbo.ProcessValues p
    WHERE p.TagName = s.TagName AND p.SourceTime = s.[Time]
);
TRUNCATE TABLE dbo.Staging_CSV;

Wrap the steps above in a stored procedure scheduled every minute via SQL Server Agent. A PowerShell watcher can also fire on file system change events; SQL Agent is simpler to audit.

Option C - S7NetPlus Implementation

PLC Configuration

On the S7-1200/1500, enable Permit access with PUT/GET communication from remote partner in Properties > Protection > Connection mechanisms. If the CPU is in V14 or later with optimized block access, mark the DBs as non-optimized or create a non-optimized shadow DB that S7NetPlus can read.

C# Client with Timer-Based Polling

using S7.Net;
using System.Data.SqlClient;
using System.Timers;

var plc = new Plc(CpuType.S71500, "192.168.0.10", 0, 1);
plc.Open();

var tags = new (string Name, DataItem Item, string Type)[] {
    ("DB1.REAL0",  new DataItem { DataType = DataType.Real,  DB = 1,  StartByteAdr = 0  }, "Real"),
    ("DB1.INT4",   new DataItem { DataType = DataType.Int,   DB = 1,  StartByteAdr = 4  }, "Int"),
    ("DB1.BOOL10", new DataItem { DataType = DataType.Bool,  DB = 1,  StartByteAdr = 10 }, "Bool")
};

var timer = new System.Timers.Timer(1000);
timer.Elapsed += async (_, _) => {
    try {
        var values = plc.ReadMultipleVars(tags.Select(t => t.Item).ToList());
        using var cn = new SqlConnection("Server=.;Database=Plant;Integrated Security=true;");
        await cn.OpenAsync();
        for (int i = 0; i < values.Length; i++) {
            using var cmd = new SqlCommand(@"INSERT INTO dbo.ProcessValues
                (TagName, TagValue, Quality, SourceTime, SourceKind)
                VALUES (@n, @v, 192, @t, 'S7NET')", cn);
            cmd.Parameters.AddWithValue("@n", tags[i].Name);
            cmd.Parameters.AddWithValue("@v", values[i]);
            cmd.Parameters.AddWithValue("@t", DateTime.UtcNow);
            await cmd.ExecuteNonQueryAsync();
        }
    } catch (Exception ex) {
        Logger.Warn(ex, "Poll cycle failed; will retry next tick");
    }
};
timer.Start();

Why the PLC and Not the Panel?

Reading PLC tags directly with S7NetPlus bypasses the Comfort panel entirely for data acquisition. The Comfort panel continues to act as a display. The PLC remains the source of truth; if the panel fails, the data service continues logging. The polling timer does not need to be coordinated with WinCC acquisition cycles.

Licensing Analysis

Library / Tool License Commercial use without membership
S7netplus (NuGet) MIT Yes, free, no source disclosure
OPCFoundation.NetStandard.Opc.Ua.Client (NuGet binary) MIT-style binary distribution Binary use permitted
OPCFoundation.NetStandard.Opc.Ua.Client (source code) GPL 2.0 for non-members Modifications to the library itself must be GPL if distributed; private internal use is unrestricted
SIMATIC HMI Options+ Bundled with TIA Portal licence Yes with valid TIA licence

If you only consume the NuGet binaries and never modify or redistribute the OPC Foundation source, the GPL obligations do not attach to your own application code. Once you distribute an application that contains a modified version of the OPC Foundation library, the GPL requires you to provide the modified source to your recipients under the same GPL. Confirm your obligations directly with the OPC Foundation before shipping.

For most internal factory-automation deployments the practical conclusion is:

  • If you do not redistribute the binary outside your company and you do not modify the OPC Foundation source, GPL has no practical effect.
  • If you sell a product that embeds a modified OPC Foundation client, join the OPC Foundation or rewrite the affected client portions.
  • If you want zero license entanglement, S7NetPlus under MIT is the cleanest path.

Handling Network and PC Outages

The discussion thread raises the legitimate concern that a polled or subscribed client loses samples during a network outage. Three mitigation strategies are commonly used:

  1. Local spool on the PC: when the SQL Server insert fails, append the row to a SQLite or flat-file spool. A background task retries the spool until it drains. This bounds the data-loss window to the local disk size of the PC.
  2. Timestamp from the source: always insert using SOURCE_TIMESTAMP from the OPC UA notification or the S7 PLC clock, not the PC clock. This prevents timestamp drift during network delay.
  3. CSV fallback on the panel: keep the Options+ CSV logging enabled as a cold backup. If the PC is offline for more than X hours, restore the gap from the SD card logs.

Spool Table Example

CREATE TABLE dbo.Spool_Outbox (
    SpoolId BIGINT IDENTITY PRIMARY KEY,
    TagName NVARCHAR(128), TagValue SQL_VARIANT,
    Quality SMALLINT, SourceTime DATETIME2(3), SourceKind NVARCHAR(16)
);
-- Background retry job:
MERGE dbo.ProcessValues AS tgt
USING (SELECT TOP 5000 * FROM dbo.Spool_Outbox ORDER BY SpoolId) AS src
ON tgt.TagName = src.TagName AND tgt.SourceTime = src.SourceTime
WHEN NOT MATCHED THEN
    INSERT (TagName, TagValue, Quality, SourceTime, SourceKind)
    VALUES (src.TagName, src.TagValue, src.Quality, src.SourceTime, src.SourceKind);
DELETE FROM dbo.Spool_Outbox
WHERE SpoolId IN (SELECT TOP 5000 SpoolId FROM dbo.Spool_Outbox ORDER BY SpoolId);

Verification Checklist

Before signing off the system, run each item below and capture evidence in the commissioning report.

  1. Disconnect the network between the panel and the PC for 10 minutes; reconnect; verify that no rows are duplicated in dbo.ProcessValues and that no SourceKind is missing from the outage window.
  2. Set a PLC tag to a known value (for example DB1.REAL0 = 12.345), trigger one poll, query SELECT * FROM dbo.ProcessValues WHERE TagName = 'DB1.REAL0' ORDER BY SourceTime DESC TOP 1 and confirm the value.
  3. Force a SQL Server outage by stopping the service. Verify that the spool file grows. Restart SQL Server and confirm the spool drains to zero within 5 minutes.
  4. Disable the OPC UA server on the panel. Verify that the client logs a connection error, retries with exponential backoff, and recovers when the server is re-enabled.
  5. Verify the CSV ETL by copying a known CSV file into the ingest share and confirming that SELECT COUNT(*) FROM dbo.ProcessValues WHERE SourceKind = 'CSV' increases by exactly the row count in the file.
  6. Run a stress test at 10 Hz for 1 hour. Confirm SQL Server CPU stays below 40 percent and the row count matches expectation (36000 ± 0.1 percent).
  7. Audit the licence folder of the deployed service: the OPC UA binary license file must reference MIT for binary distribution; the SPDX header in any custom modifications must be GPL 2.0 if applicable.

Troubleshooting Matrix

Symptom Likely Cause Diagnostic Fix
OPC UA session fails with BadCertificateUntrusted PC certificate not trusted by panel Check %CommonApplicationData%\OPC Foundation\Certificates\Rejected Copy PC cert into panel's TrustedClients store
Values always show stale data WinCC tag acquisition set to On demand Inspect tag properties in WinCC Set acquisition to Cyclic continuous
Subscription events arrive late Sampling interval larger than publishing interval Lower SamplingInterval on MonitoredItem Set SamplingInterval = PublishingInterval / 2
S7NetPlus throws WrongNumberOfBytesException Optimized block access blocks absolute addressing Check DB properties in TIA Portal Set DB to standard (non-optimized) or use symbolic addressing
SQL Server inserts fail with duplicate key Re-ingested CSV after retry SELECT rows where duplicate Use MERGE or NOT EXISTS pattern shown above
SD card fills up Network down, options+ cannot copy Options+ log shows copy failures Reduce logging cycle or expand SD card
CSV row timestamp drifts by hours Panel timezone vs UTC mismatch Compare panel time and PC time Standardise on UTC in TIA Portal

Performance Sizing

If you log N tags at a cycle of T seconds for H hours per day, the daily row count is:

rows_per_day = N * (H * 3600 / T)

Example: 200 tags at 1 s for 24 hours gives 200 * 86400 = 17.28 million rows per day. With an average row width of 80 bytes including indexes, that is approximately 1.4 GB per day. SQL Server Standard can absorb this with batched inserts and a daily partition switch; Express (10 GB limit) requires partitioning or downsampling.

For 1 Hz polling, batch inserts inside a single transaction every 5 seconds to reduce log flushes:

var sw = new StringBuilder();
sw.Append("INSERT INTO dbo.ProcessValues (TagName, TagValue, Quality, SourceTime, SourceKind) VALUES ");
for (int i = 0; i < batch.Count; i++) {
    sw.Append(i == 0 ? "(" : ",(");
    sw.Append($"@n{i},@v{i},192,@t{i},'S7NET')");
}

Use SqlBulkCopy for batches above 1000 rows.

Field Commissioning Notes

  • Always configure the panel's OPC UA server with a dedicated user; do not enable anonymous access in production.
  • When using S7NetPlus, never poll faster than the PLC's OB1 cycle. S7-1200 OB1 is typically 100 ms; S7-1500 can be 1 ms but the connection resources are still finite.
  • Set the Windows service recovery options to restart on failure. For polling-based options, an exponential backoff of 1 s, 2 s, 4 s, 8 s up to 60 s prevents a tight loop when the network is down.
  • Include a watchdog row inserted every minute with a synthetic tag name such as _watchdog_pc; an alert queries for missing rows to detect silent service failures.
  • For long-term archiving, partition dbo.ProcessValues by month on SourceTime; sliding-window partitions keep the clustered index manageable.

Which option is best for a brand-new Siemens Comfort panel project with a budget for one Windows PC?

Use S7NetPlus (MIT-licensed C# client) polling the S7-1200/1500 directly at 1 s intervals, writing to SQL Server via batched inserts. It avoids OPC Foundation licensing, bypasses the panel for data acquisition so a panel failure does not stop logging, and requires no WinCC historical configuration.

Can the Comfort panel itself write directly to SQL Server without a PC?

No. Comfort panels run WinCC Comfort/Advanced and cannot host a general-purpose .NET application or ODBC client against SQL Server. A separate Windows host is required for any database-side work, regardless of which data path you choose.

Does pulling data with OPC UA conflict with WinCC tag acquisition mode settings?

Yes. If the tag is set to On demand, OPC UA reads return stale values because the tag only refreshes when displayed. Set the tag's acquisition mode to Cyclic continuous in WinCC with an acquisition cycle equal to or faster than the OPC UA publishing interval.

Is the OPCFoundation NuGet package safe to use in commercial software without an OPC Foundation membership?

The compiled binaries distributed on NuGet carry a permissive license that allows commercial use without modification. If you modify the OPC Foundation client source itself and redistribute it, the GPL 2.0 obligations attach and you must either join the OPC Foundation or provide the modified source under GPL. Always confirm with the OPC Foundation before shipping a redistributed product.

How do I avoid losing samples when the PC or network goes down?

For polled or subscribed options, add a local spool (SQLite or SQL Server outbox table) that buffers failed inserts and is retried by a background job. Use the source PLC or OPC UA timestamp, not the PC clock. Keep the CSV via Options+ logging enabled as a cold backup so the panel's SD card captures the gap until the PC is back.

Back to blog