Disclaimer: This is an independent third-party tool. It is not an official Siemens product and is not affiliated with, sponsored by, or endorsed by Siemens. It is provided "as is" and does not replace official engineering, diagnostic, or safety procedures.
A read-only black box for investigating intermittent faults in Siemens S7-300/400 systems.
s7trace continuously polls a focused set of PLC addresses and records their
history in a portable SQLite database. It can stay on site for hours, days, or
weeks until a rare fault happens again. When it does, you investigate the actual
sequence of events before, during, and after the failure—not an operator's
recollection or a normal-looking online snapshot taken too late.
The engineer does not have to remain on site. The s7trace server stays next to
the PLC on an industrial PC or service laptop, while the same small executable
acts as a remote CLI. From another office or another city you can check whether
data is fresh, change a diagnostic set, perform a one-off read, add an event
note, and query the history without opening a remote desktop session or creating
a second connection to the PLC.
This is not a SCADA package and not another visualization stack. Its narrower job is to provide the evidence that is usually missing when an intermittent industrial fault has to be explained.
s7traceis currently intended for Siemens S7-300/400 PLCs. It is read-only by design and never writes values to PLC memory.
Intermittent faults tend to disappear before an engineer reaches the machine. They may occur once a week, only at night, or only under a rare combination of states. By the time somebody connects STEP 7, the current values are normal, diagnostic buffers are limited, and reproducing the condition on production equipment may be impossible or unsafe.
Without continuous recording, the investigation becomes guesswork:
- Which signal changed first?
- Was it a cause or a consequence?
- How long did the intermediate state last?
- Has the same transition sequence occurred before?
- What were the neighbouring mechanisms doing at that moment?
With s7trace, you select only the signals relevant to the current hypotheses,
choose their polling periods, start a named dataset, and leave the recorder
running. When the problem returns, the complete timeline is still in SQLite.
This is especially useful for remote support. A short site visit may be enough
to place the recorder safely in the controls network; the rest of the
investigation can happen through compact CLI commands. The on-site server owns
the only PLC connection. Remote clients talk to s7trace, never directly to the
CPU.
About a decade ago I saw a process historian on a site for the first time and immediately understood how I wanted to work from then on. I used STEP 7 Analyzer, iba, and later the free Telegraf → InfluxDB → Grafana stack. Continuous monitoring repeatedly gave me the evidence needed to solve the most difficult and elusive faults.
The arrival of capable LLMs changed the two most labour-intensive parts of that workflow. There is no longer a good reason to copy hundreds of addresses by hand, nor to inspect every time-series manually.
I export the original STEP 7 project with another tool I created,
awl-text-sync. I discuss the
symptoms and possible causes with an LLM, review a minimal set of diagnostic
tags, and leave s7trace collecting until the fault appears again. The LLM can
then help construct SQL queries, compare transitions, calculate durations, and
test hypotheses against the recorded database.
The engineer talks to one LLM agent throughout the investigation. The agent combines two different views of the same machine:
- the static view—program logic, symbols, DB layouts, and cross-references
exported from the STEP 7 project by
awl-text-sync; - the runtime view—current status, selected signals, event notes, and
recorded history obtained through the remote
s7traceCLI.
The key point is that the agent does not infer the machine state from the program alone. It can compare what the project says should happen with what the recorder proves did happen. The engineer remains responsible for the hypothesis, tag selection, safety, and final decision.
The LLM does not replace the controls engineer and receives no ability to
control the PLC. It helps read the program, design the observation, and analyse
recorded evidence. Configuration changes go through typed s7trace commands,
history is exposed through bounded read-only SQL, and only the server owns the
PLC connection.
- Continuous polling of one or more S7-300/400 PLCs.
- Thematic metric sets for a drive, conveyor, handshake, sequence, or fault.
- Independent polling groups with different periods.
- Change history, poll cycles, and diagnostic events in SQLite.
- Live tag and set changes without restarting the server.
- One-off typed and raw reads for address diagnostics.
- Timestamped notes that align operator observations with PLC data.
- Visibility into bad tags, stale polling, and queue state.
- Compact JSON/JSONL output for scripts and LLM agents.
- Full remote operation through the CLI and a durable command queue.
- A small native Windows control window for set state and polling freshness.
SQLite is deliberate: one file holds configuration, history, events, and queue state. It is easy to copy, archive, inspect with standard tools, or give to an LLM agent under read-only access.
On Windows, the server includes a deliberately small local panel for checking metric sets, active and bad tag counts, effective polling rate, and data age. It can enable or disable a selected set and adjust a single poll group's period. The CLI remains the full local and remote engineering interface.
- Export the STEP 7 project with
awl-text-sync. - Describe the symptoms and identify signals that distinguish the main hypotheses.
- Add the PLC, polling groups, and diagnostic tags to
s7trace. - Leave the server on site and operate the recording remotely through the CLI.
- Wait for the fault to recur.
- Query SQLite for event boundaries, transition order, durations, and similar episodes.
- Verify the conclusion against the PLC program and the physical process.
Do not record everything merely because it is available. A small signal set chosen to separate concrete hypotheses puts less load on the PLC and produces a far clearer investigation.
A stable Rust toolchain is required:
cargo build --releaseThe main binary is written to target/release/s7trace (s7trace.exe on
Windows). The build also produces s7mock, a mock PLC server used for testing.
# Server, SQLite database, HTTP CLI transport, and Windows control window
s7trace --db s7trace.db server
# Headless, with the CLI transport bound to localhost only
s7trace --db s7trace.db server --noui --http-bind 127.0.0.1:7707Port 7707 is the default CLI transport port. The server is the only process
that polls PLCs and writes the live database; action commands are serialized
through its durable queue.
The two roles are intentionally separated. Only s7trace server must remain on
site. The engineer needs the same executable and uses -r to route commands to
that server:
# Check the recorder from another city
s7trace -r s7trace-site.example status
# Return current problems in an LLM-friendly format
s7trace -r s7trace-site.example sql --format jsonl \
"SELECT * FROM v_tag_status WHERE bad = 1"
# Enable a prepared diagnostic set
s7trace -r s7trace-site.example set-enable intermittent_fault
# Put an operator report on the same timeline as the PLC samples
s7trace -r s7trace-site.example note "The stop occurred again" \
--plc line1 --dataset incident_2026_07Set S7TRACE_SERVER to avoid repeating -r; use S7TRACE_PORT or
--server-port for a non-default port. A bare host, host:port, and a full
http://host:port URL are accepted.
Do not expose port 7707 directly to the public Internet. Use a VPN or another
protected private network and enable S7TRACE_TOKEN.
The addresses below are examples. Replace them with values reviewed for your PLC.
# Define a PLC and a 100 ms polling group
s7trace -r 127.0.0.1 plc-add --name line1 \
--host 192.168.0.50:102 --rack 0 --slot 2
s7trace -r 127.0.0.1 poll-group-add --name fast --period-ms 100
# Create a focused set and add a validated tag
s7trace -r 127.0.0.1 set-create --plc line1 --name intermittent_fault
s7trace -r 127.0.0.1 tag-add --plc line1 --name Motor.Speed \
--address DB1.DBW0 --type i16 --poll-group fast --set intermittent_fault
# Start a named investigation dataset
s7trace -r 127.0.0.1 collection-start --plc line1 \
--dataset incident_2026_07 --set intermittent_fault
s7trace -r 127.0.0.1 statusTags can also be imported from a small YAML-shaped signal file:
signals:
- name: Motor.Speed
address: DB1.DBW0
type: i16
- name: Conveyor.Running
address: DB1.DBX10.0
type: bools7trace -r 127.0.0.1 tag-import --plc line1 --file signals.yaml \
--set intermittent_fault --poll-group fast --validateQuery a running remote server:
s7trace -r 127.0.0.1 sql --format jsonl \
"SELECT * FROM v_tag_status WHERE bad = 1"Inspect a stopped or copied database offline:
s7trace --local-db --db s7trace.db sql \
"SELECT name, last_value_i FROM tag"The sql command accepts read-only SELECT, WITH, and PRAGMA statements,
applies a row limit, and has a timeout. This is a practical boundary for LLM
tools: ask the agent to inspect the schema and construct narrow queries instead
of dumping the entire time-series into its context.
Run s7trace --help for all commands and s7trace <command> --help for one
command's exact options.
Possible next step: I am considering a small chart workflow in which a CLI command requests a time window and a chosen set of tags, then opens a local web view containing the resulting plots. This is a roadmap idea, not a feature in the current release; configuration, collection, and analysis are CLI/SQL-driven today.
Although s7trace never writes PLC memory, cyclic reads still consume CPU
communication resources. Begin with a small number of tags and conservative
periods, watch the status, and expand gradually. Be particularly careful with
old or already heavily loaded controllers.
If port 7707 is reachable beyond localhost, set the same S7TRACE_TOKEN value
for the server and every client. When the variable is unset or empty,
authentication is disabled.
# Server process
S7TRACE_TOKEN=change-me s7trace --db s7trace.db server
# Remote client process
S7TRACE_TOKEN=change-me s7trace -r s7trace-site.example statusDo not publish production SQLite databases. They may contain equipment names, program structure, PLC addresses, timestamps, and process data.
- The per-PLC actor owns the PLC connection and serializes all reads.
- SQLite stores configuration, history, events, and command state.
- The CLI is the interface for both engineers and LLM agents.
- Metric sets define focused groups of signals.
- Datasets separate one investigation from another.
A single SQLite file holds every domain: the topology and configuration that
define what is recorded, the recorded history and events, and the durable
command queue. The read-only views along the bottom are the practical entry
points for the sql command.
See docs/architecture.md for implementation details.
docs/concept.md— design principles and scope.docs/architecture.md— data flow and components.docs/server-ui.md— native Windows control window.docs/cli-ergonomics.md— proposed CLI improvements.docs/spike-multiread-chunking.md— S7 multi-read batching and PDU constraints.migrations/0001_initial.sql— initial SQLite schema embedded in the binary.
This began as my own field troubleshooting tool and is published for engineers
who find the same workflow useful. Interfaces and the database schema may still
change. The default S7 backend uses the vendored pure-Rust turbos7 client; a
native Snap7 dependency is not required for the normal build.
Some repository scripts can use a separately obtained local Snap7 server to
simulate a PLC during development. The snap7/ directory is ignored, Snap7 is
not bundled or distributed with s7trace, and it is not required at runtime.
s7trace is released under the MIT License. The vendored turbos7
dependency retains its upstream dual-license declaration; see
Third-party notices.
