Lua Transforms
Lua nodes process batches of SerialFlow frames. The current Lua contract is frame-based: your script defines process_frames(frames) and returns either frame tables or raw strings.
Lua works on frames, not lines intrinsically. For newline-delimited ASCII protocols, one frame will often correspond to one line of text. For binary or other framed protocols, frame.data contains the full payload for that frame.
The Lua Contract
Every Lua script must define process_frames(frames):
function process_frames(frames)
return frames
end
frames is a list of tables. Each frame includes:
| Field | Type | Notes |
|---|---|---|
id |
string | Frame identifier |
ts |
integer | Timestamp |
direction |
string |
"rx" or "tx" |
data |
string | Frame payload |
meta |
table | Frame metadata |
Pass Through Unchanged
Return the incoming frames as-is:
function process_frames(frames)
return frames
end
This is the default passthrough shape used by the built-in Lua examples and templates.
Update Data Or Metadata
You can mutate frame fields before returning them:
function process_frames(frames)
for _, frame in ipairs(frames) do
frame.data = string.upper(frame.data)
if frame.meta == nil then
frame.meta = {}
end
frame.meta["tag"] = "lua"
end
return frames
end
Filter Frames
To drop frames, return only the ones you want to keep:
function process_frames(frames)
local out = {}
for _, frame in ipairs(frames) do
if frame.direction == "rx" then
table.insert(out, frame)
end
end
return out
end
Returning nil is not the documented way to drop frames. Use an empty list or a filtered list instead.
Hardware-Verified Text Filter
This filter has been verified against a real CLI-connected device in our HIL flow. It passes through only frames whose payload contains the literal text error:
function process_frames(frames)
local result = {}
for _, frame in ipairs(frames) do
if string.find(frame.data, "error", 1, true) then
result[#result + 1] = frame
end
end
return result
end
On a newline-delimited text protocol, this behaves like filtering lines. For example:
-
status-okis dropped -
error-overheatpasses through
Return Raw Strings
Lua can also return raw strings instead of frame tables:
function process_frames(frames)
local out = {}
for i, frame in ipairs(frames) do
out[i] = string.upper(frame.data)
end
return out
end
When raw-string output has the same length as the input, SerialFlow preserves the original frame metadata and updates only data. When the output length changes, SerialFlow wraps the returned strings into new frames.
Error And Timeout Behavior
Lua nodes are fail-open. If a script errors, times out, or returns invalid output, SerialFlow passes the original frames through unchanged.
Editing In Studio
When you edit a Lua node in Studio and click Apply, SerialFlow validates and hot-reloads the script. If the new script is invalid, the previous script stays active.
Notes
-
Use
process_frames(frames), nottransform(data). -
Lua receives frames. If your device speaks newline-delimited text, filtering
frame.datausually feels like filtering lines. -
For binary or framed protocols,
frame.datais the full frame payload presented to Lua. -
frame.directionis a string in Lua:"rx"or"tx". -
frame.datais the payload string you usually transform. -
frame.metais where you can attach extra per-frame metadata.
Next Steps
- Core Concepts - Understand how nodes and connections work
- CLI Reference - Connect CLI devices to your pipelines