Python Script
Runs Python against the message. It is the general-purpose node — where you compute, reshape, decide and filter when no purpose-built node fits.
Type: python · Category: Transform · Ports: one input · one output


When to use it
- Computing something from several inputs — a rate, an average, an OEE figure
- Reshaping a payload before a database write or an API call
- Filtering: return
Noneand the branch ends
Reach for something else when
For a per-item transformation over an array, Batch Transform runs the items in parallel. For a database write, use the SQL node rather than system.db — only the node gets store-and-forward.
Settings
| Setting | Key | Default | Purpose |
|---|---|---|---|
| Code | code | — | The transform function. |
| Timeout | timeout | 60 s | Fail the node after this long. |
Example — computing OEE from a tag read
# Supported modules: system, math, json, datetime
# Globals: payload (data), message (metadata)
import datetime
def transform(payload, message):
"""
:param payload: the primary data object from the previous node
:param message: the full message, including metadata and context
:return: the value passed to the next node
"""
speed = system.tag.read("Line1/Filler/Motor1/Speed")
if speed["quality"] != "Good":
return None # returning None ends this branch
target = payload[0]["targetRate"] # from the SQL node upstream
run_minutes = payload[0]["runMinutes"]
availability = run_minutes / 60.0
performance = speed["value"] / target if target else 0.0
return {
"line": "LINE1",
"availability": round(availability, 4),
"performance": round(performance, 4),
"oee": round(availability * performance, 4),
"timestamp": datetime.datetime.now(datetime.timezone.utc).isoformat(),
}
Gotchas
- Returning
Noneends the branch. This is the cleanest filter there is — but a downstream Join waiting on that branch will wait forever, so filter before a split, not between split and join. - Set the timeout shorter than whatever is waiting. A node still running when the caller has given up is pure cost.