Skip to content
Flows & automation

Script the bus — blocks or Python

Automate handshakes, polling and conditional replies. Build flows visually or in a Python-flavoured DSL, trigger them on the events you care about, and run them safely in a sandbox.

Visual blocks

Build logic as blocks — send, set, read, branch and loop — no syntax to memorise.

…or write Python

Flip to a Python-flavoured DSL and back; the blocks and code are two views of one flow.

Triggers

Run on RX match, timeout, connect or on a periodic schedule.

Sandboxed

Built-ins only, with step and wall-clock budgets — and a trust gate for external actions.

One flow, two views

Blocks and code, always in sync

Compose a flow from blocks when you want speed, or drop into code when you want precision. They're the same flow underneath, so nothing is lost switching between them.

  • Send, set, read-until, branch and loop as visual blocks
  • Switch to the Python-flavoured DSL for the same logic
  • Run log shows each step; sandboxed with step + time budgets
Build flows with AI
Omni Console — Flow editor
Edit flow Autobaud Enabled
Blocks Python Trigger: Manual only
SEND "/?!\r\n"
SET response = read_until(1500, "\n")
SET ch = response[4]
SEND ("<ACK>0" + ch + "6")
+ block
Run logclear
✓ baud negotiated → 19200
Cancel Save
Block palette

The building blocks

Every action is a block — and each block is one line of the DSL behind the scenes.

Serial actions

  • Send data
  • Send sequence
  • Read
  • Read until text
  • Read N bytes
  • Set baud rate
  • Wait
  • Beep

Logging

  • Log event
  • Print

Logic & control

  • Set variable
  • If
  • For
  • While
  • Break
  • Continue
Python-style syntax

Built-in string handling

Reshape the bytes you read with familiar, Python-style expressions — slicing, indexing and a set of built-in string functions. No imports, all sandboxed.

Text

len()upper()lower()strip()replace()find()startswith()endswith()substr()

Index & slice

response[4]response[2:6]

Convert

int()float()str()hex()ord()chr()

Match & loop

match()extract()range()
flow · python view
send("/?!\r\n")
response = read_until(1500, "\n")
# pull fields out of the reply
vendor   = upper(substr(response, 1, 3))
baud_z   = response[4]
serial   = extract(response, r"\((\d+)\)")
if startswith(response, "/"):
    send("<ACK>0" + baud_z + "6")
    log("vendor=" + vendor + " sn=" + serial)
What people automate

Flows for everyday bus work

Auto-baud handshake

Send the sign-on, read the reply, extract a byte and answer at the negotiated rate.

Periodic polling

Every few seconds, send a Modbus read and log the decoded registers.

Conditional reply

Watch for a pattern in the RX stream and respond only when it matches.

Unattended capture

On connect, start a sequence and let it run within a safe time budget.

Flow questions

Flows, answered

Is it real Python?
It's a Python-flavoured DSL — familiar syntax with a curated set of built-ins, run in a sandbox with step and wall-clock budgets. That keeps flows safe to run unattended; it is not a full Python runtime.
Blocks or code — do I have to pick?
No. The visual block graph and the DSL are two views of the same flow. Edit either; switch whenever you like.
When do flows run?
On a trigger: an RX pattern match, a timeout, on connect, or on a periodic schedule. One flow runs at a time.
Can an AI agent create flows?
Yes — over MCP, an agent can create, update and run flows, which then fire on their triggers while Omni Console is open.

Put the bus on autopilot.

Download Omni Console and build your first flow — free for 30 days.

Lifetime licenses from $39.90 · Windows & Linux · cancel anytime in trial