WinCC Unified Automatic Report Printing via CUPS on MTP Panels

David Krause11 min read
HMI / SCADASiemensTutorial / How-to
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

End-of-cycle report printing on a Siemens Unified Comfort Panel such as the MTP700 running WinCC Unified V18 requires bridging three subsystems: the WinCC Unified report engine, the on-device CUPS (Common UNIX Printing System) spool, and the panel's JavaScript runtime that orchestrates the workflow. The WinCC Unified JavaScript object model does not expose a CUPS binding, so the print submission has to be delegated to the standard lp command (or a headless LibreOffice invocation) launched through the StartProgram runtime method. This reference documents a field-proven configuration: trigger the report at cycle end, locate the timestamped PDF on the local file system, push it to a pre-provisioned CUPS queue, and raise a WinCC alarm if the job never reaches the printer.

Architectural constraint: the WinCC Unified JSOM does not surface CUPS as a class. Any attempt to instantiate a Cups() wrapper or call cups.printFile() from a Unified script will fail at parse time. Treat the lp binary as the only supported bridge to the print spool.

Prerequisites

Item Specification Notes
HMI hardware SIMATIC MTP700 (Unified Comfort) 6AV2 128-3GB06-0AX0 or equivalent 7" generation
HMI firmware / runtime WinCC Unified V18 (TIA Portal V18) Runtime version must match engineering build
PLC SIMATIC S7-1200 (CPU 1214C / 1215C / 1217C) Any firmware V4.x that pairs with TIA V18
Printer Brother HLL8260CDW (or HLL5100DN) – factory-provisioned on the Unified image Custom drivers are not installable on the panel; pick a model from the Siemens-approved peripheral list
Spooler CUPS pre-installed on the Unified Linux base Visible in the HMI Control Panel → Printers
Office pipeline LibreOffice headless on the HMI image (optional path) Required only if the report is generated as .xlsx / .ods
Network Printer reachable on the panel's plant network (static IP recommended) DHCP leases that change break the CUPS queue

Confirm TIA Portal V18 and the Unified runtime update are both on the same service pack. Mixing, for example, TIA V18 Update 2 with runtime V18 GA has been observed to break the StartProgram permission profile.

CUPS Architecture and Queue Provisioning

CUPS on the Unified Comfort Panel behaves exactly like a Linux desktop install: a local daemon (cupsd) listens on the loopback socket, queues are defined in /etc/cups/printers.conf, and jobs are submitted through the lp / lpr binaries. The crucial difference is that the panel image ships with a whitelist of printer models. Adding an arbitrary driver is not supported; the printer must appear in the HMI's Control Panel → Printers → Add dialog. The Brother HLL8260CDW and HLL5100DN are two of the pre-validated models and are reliable choices for production cells.

Once a printer is added, capture the exact queue name – CUPS is case-sensitive and the queue name embedded in scripts must match byte-for-byte. The fastest way to confirm the queue name from the HMI desktop is:

  1. Open Control Panel → Printers.
  2. Right-click the Brother device and select Properties.
  3. Copy the Queue Name field (for example HLL8260CDW or HLL5100DN).
  4. Validate by running lpstat -p -d from a shell; the queue should appear in the output.

For more details on the lp command options, refer to the CUPS lp man page and the CUPS documentation set.

Triggering Report Generation at Cycle End

Reports in WinCC Unified are template-driven objects that render to .pdf (and optionally .xlsx) on a schedule or on demand. For a deterministic cycle-end trigger, configure the report with the Event-based output mode and bind a PLC tag (for example "DB_Cycle.CycleDone") as the trigger bit. The Siemens Industry Online Support portal hosts the TIA Portal V18 help package, which documents the report configuration tree under Reports → Output → Trigger.

Configure the report's storage path on the panel's local file system – for example:

/media/simatic/report_archive/

The default naming pattern appends a timestamp. A typical filename rendered at the end of cycle 4729 is:

Report_CycleSummary_20240118_143207_4729.pdf

Note the underscore separators – they are what the JavaScript parser relies on to extract the cycle number and the wall-clock time.

Resolving the Timestamped PDF Path

The JSOM exposes the local file system through HMIRuntime.FileSystem. Use readdir against the report directory, sort by modified descending, and pick the most recent PDF. A robust pattern that handles the race between report write and read is to wait until the file size is stable across two consecutive samples (an unlocked PDF is still growing during the render phase).

// Locate the newest PDF in the report directory
const dir = "/media/simatic/report_archive";
const items = HMIRuntime.FileSystem.readdir(dir);
let newest = null;
let newestMtime = 0;

for (const f of items) {
  if (!f.toLowerCase().endsWith(".pdf")) continue;
  const full = `${dir}/${f}`;
  const st = HMIRuntime.FileSystem.stat(full);
  if (st.mtimeMs > newestMtime) {
    newestMtime = st.mtimeMs;
    newest = full;
  }
}

if (!newest) {
  HMIRuntime.Tags.SysFct.SetTagValue("Print_Alarm", true);
  HMIRuntime.Trace("Report lookup failed: no PDF in " + dir);
  return;
}

For deterministic lookup (useful when the report name includes the cycle number passed from the PLC), parse the filename and match on a regex:

const cycle = HMIRuntime.Tags.SysFct.GetTagValue("DB_Cycle.CurrentCycle");
const re = new RegExp(`CycleSummary_.*_${cycle}\.pdf$`);
const match = items.find(f => re.test(f));

Invoking lp via StartProgram

StartProgram is the only public JSOM entry point that can spawn a child process from a Unified runtime script. The signature is:

HMIRuntime.StartProgram(
  program: string,      // absolute path or command in PATH
  args:   string,       // single command-line string
  mode:   number,       // 0 = wait for completion, 1 = detached
  timeout: number       // ms; 0 = no timeout
);

The job-blocking mode (mode = 0) returns a numeric status that maps to the lp exit code. CUPS returns 0 on a successful enqueue and a non-zero value if the queue is paused, the printer is offline, or the file is unreadable. Capture that return code and route it to a tag that the alarm logic will read.

// Submit the PDF to the CUPS queue
const printer = "HLL8260CDW";          // MUST match the CUPS queue name
const title   = `Cycle_${cycle}_Report`;
const cmd     = `/usr/bin/lp`;
const args    = `-d ${printer} -t "${title}" -n 1 "${newest}"`;

let rc;
try {
  rc = HMIRuntime.StartProgram(cmd, args, 0, 15000);
} catch (e) {
  HMIRuntime.Trace("StartProgram threw: " + e);
  rc = -1;
}

HMIRuntime.Tags.SysFct.SetTagValue("Print_RC", rc);
if (rc !== 0) {
  HMIRuntime.Tags.SysFct.SetTagValue("Print_Alarm", true);
  HMIRuntime.Trace(`lp failed rc=${rc} file=${newest}`);
}

Relevant lp options to consider:

Option Meaning When to use
-d <queue> Destination queue Always required; value is the CUPS queue name
-n <count> Number of copies Production reports are usually 1; shop-floor travelers may need 2–3
-t <title> Job title shown in the queue Embed cycle ID for traceability
-o sides=two-sided-long-edge Duplex Required for ISO 9001 traveler documents
-o media=A4 Force paper size Prevents tray-fallback surprises
-o job-priority=100 Priority (1–100) Bump alarm reports above routine logs

Alternative Path: LibreOffice Headless Print

When the report template is bound to an Excel-style layout (multi-sheet .xlsx) and the destination printer's driver does not consume the raw file well, route the document through soffice in headless mode. The command line is:

soffice --headless --norestore --nologo \
        --convert-to pdf:"calc_pdf_Export" \
        --outdir /tmp /media/simatic/report_archive/Report.xlsx

Then submit the intermediate PDF to lp as shown above. The whole pipeline can be wrapped in a single shell script invoked from StartProgram:

/usr/bin/sh /home/admin/scripts/print_report.sh "${newest}" "${printer}"

Headless soffice does not display the LibreOffice splash on the HMI screen, which is essential for an operator-facing panel. It does, however, hold a license lockfile at ~/.config/libreoffice; if two reports fire in the same second the second invocation will block. Add a 250 ms sleep between calls or queue them through a single at job.

Alarm Handling for Print Failures

Three independent failure modes must surface as discrete alarms so that maintenance can route to the right discipline (network, mechanical, or software):

Failure Detection Alarm tag Recommended priority
Report file not found readdir returned no PDF within 30 s of trigger Alarm_Print_NoFile Warning
CUPS enqueue rejected lp returned non-zero exit code Alarm_Print_Queue Warning
Job stuck in queue Queue depth > 0 with no progress for > 60 s (lpstat -o cross-check) Alarm_Print_Stuck Error
Printer hardware fault (paper, toner, offline) CUPS printer-state-reasons flag Alarm_Print_Hardware Error

A polled watchdog tag named Print_Heartbeat should be set to true on every successful print and auto-cleared by an external timer after 120 s. If a follow-up print never toggles the heartbeat, an Inactive alarm fires, which catches the silent case where the report job completes but the operator never sees the printed sheet.

For an additional layer of robustness, schedule a cron-driven shell job on the panel that runs lpstat -p HLL8260CDW -o every 30 seconds, parses the state, and writes the result back to a WinCC tag via the SIMATIC Runtime ODK interface – this is a heavier integration and is only justified on high-reliability lines.

Verification Procedure

  1. Static check: from the HMI desktop, run lpstat -p -d. The Brother queue should be listed as idle and marked as the default destination.
  2. Manual smoke test: open a terminal and execute lp -d HLL8260CDW /media/simatic/report_archive/<any>.pdf. The printer must produce one page within five seconds.
  3. Script-level test: trigger the report from the HMI's Report control manually and confirm the job title appears in lpq.
  4. Alarm test: power-cycle the printer, retrigger a report, and confirm Alarm_Print_Queue raises within the script timeout (15 s).
  5. End-to-end test: run a full S7-1200 cycle, verify the PDF appears in the archive directory, the printer emits a sheet, and the Print_Heartbeat tag toggles to true in TIA's online tag view.
  6. Long-run soak: repeat step 5 for 100 consecutive cycles. Inspect CUPS access_log for repeated printer-error entries that would indicate an intermittent queue or driver issue.

Troubleshooting Matrix

Symptom Likely cause Diagnostic Corrective action
Script never fires Event-bound report trigger bit never sets Watch DB_Cycle.CycleDone in TIA online Verify the PLC code raises the bit for at least one scan after the cycle ends
StartProgram throws permission error Unified runtime user lacks lp exec rights Check audit.log for denied execve Re-image the panel with the Siemens "Print Server" option enabled in ProSave
Job sits in queue, never prints Printer offline or IP changed lpstat -p HLL8260CDW -l Assign a static IP on the printer and re-ping from the panel
PDF prints as blank pages File was still being written when lp opened it Compare file size between two polls 2 s apart Add the size-stability guard shown in the Resolving the Timestamped PDF Path section
Garbled characters in printed text Embedded font missing on the HMI image Open the PDF in the on-device viewer Switch the report template to a font that ships with the panel (Liberation Sans, DejaVu Sans)
Alarms raise but no actual failure False positive from StartProgram timeout on a slow first print Compare Print_RC tag value to lp exit codes Increase the StartProgram timeout to 30 000 ms for the first job after a long idle
Only the first cycle of the shift prints CUPS queue paused after a recoverable error and never resumed cupsenable HLL8260CDW output Add cupsenable to a startup script or invoke it from the alarm-clear handler

Limitations and Field Notes

  • No direct CUPS binding. The Unified JavaScript object model exposes neither the CUPS spooler nor the lp binary. All print submissions must go through StartProgram and rely on the operating system's PATH resolution.
  • Whitelisted printers only. Custom PPDs and third-party drivers cannot be added to a Unified Comfort Panel. Pick a printer from the Siemens-approved peripheral list; the Brother HLL8260CDW and HLL5100DN are confirmed to work in production.
  • Filename parsing brittleness. The default timestamp format includes a seconds field. If your cycle time is shorter than one second (rare on a discrete line but possible in test rigs), consider switching the report to millisecond precision and updating the regex accordingly.
  • Locale on the HMI. lp will print date and number formats using the panel's locale. A European panel printing English reports will invert commas and dots on number fields. Set the report template to a fixed-culture format string before relying on printed numeric values.
  • Security. StartProgram runs with the Unified runtime user's privileges. Do not pass untrusted cycle IDs or filenames into the args string without sanitization – a malformed cycle tag containing a shell metacharacter will be executed. Use a strict regex whitelist on the cycle number and the filename before composing args.
  • Audit trail. The access_log under /var/log/cups/ is the canonical record of every job. Mirror it to a network share for compliance with FDA 21 CFR Part 11 or similar regulated environments.

FAQ

Does WinCC Unified V18 expose a CUPS object in the JavaScript API?

No. The JSOM does not include a CUPS class, and there is no public roadmap item to add one. The supported bridge is the HMIRuntime.StartProgram method calling the lp binary directly.

Which printers are validated for use with an MTP700 Unified Comfort Panel?

Only models that appear in the HMI's Control Panel → Printers → Add dialog can be added, because custom drivers cannot be installed. The Brother HLL8260CDW and HLL5100DN are field-validated monochrome/color laser options that print correctly via CUPS out of the box.

How do I select the most recent timestamped PDF after a report runs?

Use HMIRuntime.FileSystem.readdir on the report directory, filter for .pdf, and pick the entry with the highest mtime. For deterministic matching when the cycle number is known, parse the filename with a regex like CycleSummary_.*_<cycle>\.pdf$. Always confirm the file size is stable across two polls to avoid reading a half-rendered PDF.

Why does my lp call return non-zero even though the page eventually prints?

The most common cause is an insufficient StartProgram timeout. The first job after a long idle triggers a CUPS warm-up that can exceed 15 s. Increase the timeout argument to 30 000 ms, or split the call into an enqueue (fast) and a watchdog that polls lpstat separately.

Can I print an Excel-style report directly without converting to PDF first?

Yes – use LibreOffice in headless mode: soffice --headless --convert-to pdf:"calc_pdf_Export" --outdir /tmp <xlsx>, then submit the resulting PDF to lp. Wrap both steps in a shell script invoked from StartProgram to keep the script body short and to avoid the LibreOffice single-instance lockfile.

Back to blog