Graph Editor · Node wiki

// Node wiki

Graph Editor

The reference for every node in the graph editor — what each one does, its inputs and outputs, and when to reach for it. New here? Start with the hands-on quick start.

New here · ~10 min

Quick start

From an empty app to a live RPM bar that reacts to data — no sim required. Seven short steps, on its own page.

Reference

Browse the nodes

Every node explained, grouped by what it does — plus the full channel reference.

Reference · searchable

Expressions

The expression language on its own page — every function with an example, searchable by category.

Reference

Properties

Make your dashboard tweakable — expose parameters and compose the settings page players get, on its own page.

Setup · 2 min

USB screens: the driver

Put a dashboard on the USB screen of your wheel — the one-time Windows driver change, step by step, and the blank-screen checklist.

Reference

Node wiki

Every node, grouped by what it does. Each entry shows the node as it looks in the editor — inputs on the left, outputs on the right — plus what it computes and when to use it.

▸

Reading a node

÷Math
in1in2
out

Anatomy

A node has a header (name + an operator glyph where relevant), input sockets down the left edge, and output sockets down the right. Each socket has a type, shown by its colour. Drag from an output to an input to wire them — types must be compatible. A thin top stripe marks the node's category.

in a value the node consumes · out a value it produces · display widgets are sinks (inputs only).

▸

Socket types

Six types, colour-coded everywhere (the same hues the editor uses):

number boolean string color vector table any

Categories (the toolbar chips) use their own hues: Data · Compute · Logic · UI Elements · Assets · Doc.

  • number ↔ boolean connect freely (a boolean reads as 1/0; a number is false only when 0).
  • vector never auto-converts to/from number — use Make Vec2 / Split Vec2.
  • A few display inputs (like Text's value) are polymorphic — they accept any type and format it.
  • A wire is rejected if the types are incompatible, if it loops a node to itself, or if it would create a cycle.
▸

Data sources

◈Input
carsrpm speed…

Input

The single source of live sim data. Outputs one socket per telemetry channel — the full iRacing v5 feed: engine & fluids, per-wheel tyres (temp / wear / pressure), suspension & dampers, attitude, force feedback, weather, lap & timing, flags & session state, standings, pit & strategy, push-to-pass and more — 228 channels grouped into collapsible categories — collapsed by default, with a search box at the top to filter by name. There's exactly one Input per graph.

It also exposes the whole multi-car field as a green cars table output (in the Race category) — one row per car: position, class position, name, number, class, pit status, and two ready-made gaps: gap_to_leader_s (to the leader of that car's class — correct in multi-class racing, so a GT3 isn't timed against an LMP) and gap_to_ego_s (signed, to your car). For a standings, wire it straight into a Table Row (sort by position, display gap_to_leader_s). For a relative, route it through a Focus first (pivot on is_player, sort by gap_to_ego_s).

ref see every channel, its format and meaning in the Channel reference

out every telemetry channel (+ your math channels) · cars (table)

Freshness dot. Most channels refresh live every frame. A few only update around a pit stop — tyre cold pressures, tyre-set inventory, fast-repair counts — and carry a small orange dot. (Identity & car-setup values such as car id or fuel capacity refresh on car/track change.) Wire a pit-frozen channel to a live gauge and it'll look stuck between stops — that's expected.
◇Mock Telemetry

Mock Telemetry editable

A design-time control surface that feeds the Input node while you build — so your gauges come alive without a live session. Same categorised, searchable channel picker as Input, but each row is a setter instead of an output. It has no sockets: it writes the mock feed the Input node reads.

Manual — set any channel by hand (slider + field for numbers & booleans, a text box for strings like track or driver name). Play — load a real lap or an .ibt file and scrub / loop it to animate every channel at once. Presets — save & reload named setups, reusable across dashboards.

Game selector — Any / iRacing / AC. Pick the sim you're building for and the mock behaves like its connector: channels that game doesn't provide are greyed out (“not sent”) and your dashboard receives the real wire value — 0 or empty — exactly as it would live. Channels marked with a ⚠ warning are approximations on that game (hover for the detail). Applies to Manual and Play, so replaying an iRacing lap with AC selected shows what an AC session would look like. iRacing provides every channel; Any lifts all restrictions.

out nothing wired — it drives the editor preview via the Input node

Always there, one instance. You don't add or delete the Mock node — it's present by default at every level of the graph (each page and every dive-in show the same node). Edit it anywhere and it changes everywhere; its setup is global and carries across all your dashboards. Drag it wherever suits you.
Editor-only. The Mock node is inert when a dashboard runs live (main app, a device, or a secondary screen) — there the Input node reads the real sim.
#Number
out

Const: Number · Bool · String · Color editable

A fixed value you type into the node — a number, a true/false toggle, a text string, or a colour from a picker. Use them as thresholds, labels, fallbacks, and tints (the 5000 max in the quick start is a Number const).

out the constant (number / boolean / string / color)

⊹Make Vec2
xy
out

Vec2: Make · Split · Const vector

Make Vec2 packs two numbers into a vector; Split Vec2 unpacks one back into x/y; Const Vec2 is a fixed vector you edit inline. Vectors carry 2-D things like position or size.

Make x,y → out (vector) · Split in (vector) → x,y · Const → out (vector)

⤢Transform
xy rotationscale…

Transform editable

A position/rotation/scale source. Outputs x, y, rotation, scaleX, scaleY and a normalized anchor (9 presets). Wire it into an asset to place or scale the whole widget.

out x, y, rotation, scaleX, scaleY, anchorX, anchorY (number)

⌖Focus
table
table

Focus editable

A generic window-around-a-pivot transform: table in → table out (same columns). It sorts the table, finds the pivot row, and returns 2·window+1 rows centred on it. This is how you build a relative — but it's generic (works on any table: the sectors around the active sector, etc.).

  • on (pivot) — the boolean column that marks the row to centre on. For a relative: is_player (your car).
  • sort by + ↑/↓ — the column that orders the window. For a relative: gap_to_ego_s, descending (ahead on top).
  • window — how many rows each side of the pivot.

Edges: the pivot is always the middle row. If it's near the top or bottom of the field (you're leading, or last), the missing side is filled with blank rows — Focus never wraps around to the other end. Pivot not found in the table → all blank.

Feed the output into a Table Row inside a ForEach (count = 2·window+1) to render each row.

in table (table) · out table (same columns, windowed)

☰Table Row
tableindex
namegap_s… per column

Table Row editable

The workhorse of the table nodes. It takes a table (from Input's cars, or a Focus), optionally sorts it, picks the row at index, and exposes one output socket per column — each typed to match. Wire the column you want straight into a display.

  • index — the row to pick (0 = first after sorting). Set it in Properties for a fixed row, or wire the index socket (e.g. from a ForEach) — the wire wins when connected.
  • sort by — a dropdown of the connected table's columns (or (unsorted) for its natural order), plus an ↑/↓ direction.
  • The output sockets appear automatically once a table is connected — they mirror that table's schema. Connect nothing and the node shows “Connect a table”.

To render a full table, drop Table Row inside a ForEach block and wire the loop index in — each iteration is one row. The number of rows is just the ForEach count — wire a constant (e.g. 10 for a top-10), and offset each row's Y by index × rowHeight.

in table (table) · index (number) · out one socket per column of the upstream table, typed per column

▸

Math & numbers

Several are operator-select: one node with a dropdown that picks the operation. All output a single out (number).

+−×÷Math
in1in2
out

Math operator-select

Arithmetic on two numbers. Choose the operation from the node's op dropdown:

  • + add — in1 + in2
  • − sub — in1 − in2
  • × mul — in1 × in2
  • ÷ div — in1 ÷ in2 (÷ 0 → 0)
  • % mod — remainder of in1 ÷ in2 (% 0 → 0)
  • ^ pow — in1 raised to the power in2

in in1, in2 · out out (number)

Vec2 mode. Wire a vector into an input and + − × ÷ switch to component-wise vector math (the output becomes a vector too). % and ^ stay scalar.
sincos / sin
in
out

Trig (cos / sin) operator-select

Trigonometric function of an angle in radians. Choose via the op dropdown:

  • cos — cosine, output in [−1, 1]
  • sin — sine, output in [−1, 1]

in in (radians) · out out (number)

maxmin / max
in1in2
out

min / max (extremum) operator-select

The smaller or larger of two numbers. Choose via the op dropdown:

  • min — the smaller of in1, in2
  • max — the larger of in1, in2

in in1, in2 · out out (number)

⌊⌋round…
in
out

round / floor / ceil (rounding) operator-select

Convert a number to a whole integer. Choose via the op dropdown:

  • round — nearest integer (halves go up)
  • floor — round down, toward −∞
  • ceil — round up, toward +∞

in in · out out (number)

⊓Clamp
inminmax
out

Clamp

Constrains a value to stay within [min, max].

in in, min, max · out out

|x|Abs / Sqrt
in
out

Abs · Sqrt

Abs gives the magnitude (drops the sign); Sqrt the square root (negatives clamp to 0).

in in · out out

⟿Lerp
abt
out

Lerp

Linear interpolation between a and b by t (clamped 0–1). t=0 → a, t=1 → b.

in a, b, t · out out

↦Remap
infrom…to…
out

Remap

Rescales a value from one range to another — e.g. RPM 0–8000 into 0–1, or a pedal 0–1 into 0–100%.

in in, fromMin, fromMax, toMin, toMax · out out

▸

Color

⟿Lerp Color
abt
out

Lerp Color

Blends two colours by t — a smooth two-colour crossfade.

in a, b (color), t (number) · out out (color)

▦Ramp Color
tstops…
out

Ramp Color editable

Maps a 0–1 input through an editable multi-stop gradient — perfect for RPM shift lights or a temperature scale. Add/move colour stops inline. The blend between stops is set by a dropdown:

  • block — hard steps, no blend (each stop's colour holds until the next)
  • linear — straight RGB blend between adjacent stops
  • perceptual — blends in OKLab so mid-tones stay vivid (no grey dip)
  • smooth — linear blend eased at each stop (smoothstep)
  • cubic — one smooth curve through all stops, no corners

in t (0–1) + per-stop offset/color · out out (color)

▸

Text, time & expressions

⏱Format Time
input
out

Format Time

Turns a number of seconds into a readable time string. Pick the format from the mode dropdown (a live preview shows the result):

  • MM:SS.mmm — lap time, e.g. 1:23.456
  • SS.mmm — seconds only, e.g. 23.456 (sectors)
  • H:MM:SS — race / session time, e.g. 1:23:45
  • ±SS.mmm — signed delta, e.g. +0.567 / −1.234 (gaps)

in input (seconds) · out out (string)

ƒExpression
vars…
out

Expression editable

A mini wrangler — a small program over telemetry, powerful enough to replace most node chains on its own. Write one or more statements separated by ;, and the node grows the sockets it needs:

  • Bare names become input sockets — rpm / rpmMax adds ports rpm and rpmMax.
  • name = … is a local (no socket): ratio = rpm / rpmMax;
  • @channel reads telemetry directly, no wire: @gear, @speed_kmh.
  • $name = … adds a named output: $shift = ratio > 0.95. Outputs exist only through $ — a program with no $ has no output socket (the node shows a hint instead).
  • Components read & write vectors (.x .y) and colours (.r .g .b .a, 0–255): $dir.x = vel.x * 2.
  • Whole colours & text: $c = mixcolor(a, b, t) makes a colour output, $label = "P" + str(@position) a text output.
  • State & time: prev, rising, pulse, blink, elapsed… let one expression do what the Changed / Pulse / Blink nodes do.

The editor has live syntax colouring and autocomplete (functions, PI/E, and @channels). Full grammar, every function with an example, recipes and colour key on the expression language page (searchable by category) — also one click away from the node's Properties panel.

in one socket per bare variable (number / vector / colour) · out one per $name (number / vector / colour / text)

▸

Expression language

The Expression node runs a tiny, sandboxed language over telemetry — multi-statement, with named inputs/outputs ($name), direct channel reads (@channel), vector/colour components, text, and stateful time functions (blink, pulse, prev…).

The full reference now lives on its own page — grammar, types, every function with an example, recipes, and a search box with category filters to find the right function fast (French search terms work too).

Reference · searchable

Expression language

~40 functions across Math, Trig, Exp & logs, Interpolation, Colour, Text, State & time.

Practice

Recipes

Shift light, gear label, held warnings, needle sweep — ready-to-paste programs.

▸

Logic & control

&&Logic
in1in2
out

Logic operator-select

Boolean algebra and numeric comparisons in one node — choose the operation from the op dropdown. The output is always a boolean; the inputs adapt to the operator.

Boolean ops — boolean inputs:

  • && and — true when both inputs are true
  • || or — true when at least one input is true
  • ! not — inverts a single input (one socket: in)

Comparisons — number inputs:

  • == eq — equal · != neq — not equal
  • < lt — less than · <= lte — less or equal
  • > gt — greater than · >= gte — greater or equal

in in1, in2 (just in for !) · out out (boolean)

Sockets follow the operator. Switching op re-shapes the inputs live — boolean for && || !, number for the comparisons — so a wire may need redoing when you switch between the two groups.
?If
condthenelse
out

If

Branches between two values by a condition: outputs then when true, otherwise else. Polymorphic — pick the value type (Number, String, Boolean, Color, Vector) in Properties, or just wire then/else and the sockets adapt. Replaces the old If Color node.

in cond (boolean), then, else (value type) · out out (value type)

⇄Switch
inputfallback
out

Switch editable

Maps a number to a string via a list of cases — e.g. gear 0→"R" 1→"N" 2→"1"…. Emits the fallback if no case matches.

in input (number), fallback (string) · out out (string)

↻ForEach
count
indexcount

ForEach block

Repeats the nodes inside the block once per iteration — e.g. a row of N shift-light LEDs from one network. Drops a begin node (giving index and count) and an end marker.

in count · out index, count (number, on the begin node)

ΔChanged
in
out (1 frame)

Changed operator-select

Fires true for exactly one frame when the input changes — the event detector. Pick the edge from the op dropdown:

  • rising — the value went up (a boolean turning on counts: 0 → 1)
  • falling — the value went down
  • any — any change, either direction

Booleans are accepted directly (off = 0, on = 1). Typical use: feed a Pulse to stretch the one-frame event into a visible reaction.

in in (number or boolean) · out out (boolean, 1 frame)

⎍Pulse
triggerduration (s)
out

Pulse

When trigger turns on, the output stays true for duration seconds, then drops back. Triggering again while the pulse is running restarts the timer (the reaction is prolonged).

in trigger (boolean), duration (seconds, default 5) · out out (boolean)

▸

Display widgets

The sinks: each is a widget on the canvas. They have inputs but no outputs. Any input can be wired (live) or set as a static value in the Properties panel.

TText
valuefillColor

Text

A text label. Its value is polymorphic — wire a number, string, etc., and format it (number, time) in Properties. The Style section offers a 25-font library (racing display, futurist, LCD, sans, mono) plus "Import font…" to load your own .ttf / .otf / .woff / .woff2 — imported fonts are embedded in the .slxd, so the dashboard renders identically on any machine.

in value (any), fillColor (color), effects

▢Rect
fillColorstroke…

Rect

A rectangle — solid or with a linear gradient and strokes. Great as a backdrop, panel, or status block.

in fillColor or gradient stops, stroke width/color, effects

◯Ellipse
fillColorstartsweepratio

Ellipse

A circle, ellipse, arc or ring. Same wirable fill as the Rect (solid fillColor, or gradient angle + per-stop sockets), plus Figma-style arc controls: start (degrees, 0 = 3 o'clock, clockwise), sweep (degrees, 0–360) and ratio (inner radius 0–1 — a ring when > 0). Wire sweep from a 0–360 value and you have a circular gauge; add ratio for a donut. Strokes and effects are wirable like the Rect (inside/outside strokes fall back to center on an arc).

in fillColor or gradient stops, start / sweep / ratio, stroke width/color, effects

▣Image
opacity

Image

An image — a logo, car silhouette, or custom gauge face. Source and scale set in Properties. The node can also hold an image set: add more images ("+ Add" on the node or in Properties — the picker accepts multiple files at once) and an index socket appears — wire a number to pick which image shows (floored and clamped to 0…N−1). Perfect for flags, gear states or weather icons driven by telemetry; one image visible at a time.

in index (number, with an image set), opacity (number), effects

∿Track map
strokeColorlabelsmarkers…

Track map

Draws a map of the circuit. It auto-records the racing line from the car's GPS (lat / lon) as you drive — SimHub-style — then renders that outline. On top of the trace it plots live car positions as dots: your car and the other cars, each placed along the recorded line. Add an optional start / finish line and per-car labels. Before a trace exists it shows a dashed placeholder.

The trace records itself the first time you run a clean lap on track (out-laps and the garage are ignored), and is saved with the dashboard — one shape per circuit. It needs GPS channels: iRacing provides them ; Assetto Corsa does not yet feed lat / lon, so the trace won't record there.

Everything below is in the Properties panel, grouped into collapsible sections:

  • Trace — the circuit line's colour and width.
  • Your car — toggle the marker, set its colour and size.
  • Other cars — toggle them, set size, and either a single colour or Colour by class (a cycled palette, one hue per class present — for multi-class fields).
  • Labels — draw a text label on each dot, taken from a wired table column (Input's cars or a Focus), matched by car_number. Pick the column and a text colour.
  • Start / finish — toggle the line and set its colour.

The Track map sockets block on the node exposes the markers + start/finish params as wirable inputs (show / colour / size for your car & others, colour-by-class, start-finish colour), alongside the trace strokeColor / strokeWidth and the labels table. A wired socket wins over its Properties value — so you can drive e.g. your car's colour from a flag, or pulse its size.

in trace (strokeColor, strokeWidth) · car markers (your car + others: show / colour / size, colour-by-class) · labels (table, joined by car_number) · start/finish colour · transform (x, y, rotation, scale, anchor) · no outputs (draws on the canvas)

▦Table
table

Table

Renders a whole table in one widget. Wire a table — Input's cars, or the output of a Focus — and it draws the full grid: header + one row per record. This is the one-node alternative to laying out many Table Rows + Text widgets by hand. Unwired, it shows a dashed placeholder.

Everything below is in the Properties panel:

  • Header — show / hide the column-name row.
  • Row height, Size, Text & Header colour — the base look. Columns split the widget width evenly; numbers align right, everything else left.
  • Row lines / Col lines — separators, with a shared colour + width. Padding insets the cell text.
  • Columns — tick which columns to show and reorder them ↑/↓ (from the connected table's schema); All resets to every column.

The Style sockets block on the node exposes most of these as wirable inputs — header on/off, row/cell sizes, text & header colour, separators and outer border. A wired socket wins over its Properties value, so you can drive e.g. a border colour from a state. Columns, conditional formatting, alignment and font stay in Properties (no socket).

Conditional formatting formulas

Add rules to colour cells from the data — like a spreadsheet. Each rule is an Expr formula evaluated per record; when it's true, the rule's style applies. Pick a target (the Whole row, or one column) and set a background, text colour and/or bold. Rules stack — later ones win.

  • car_class == 3 · target car_class · background red — flag the GT3 class.
  • is_player == 1 · target Whole row · highlight — your own row.
  • gap_to_ego_s > 25 and car_class != 3 · target name · blue text — a backmarker, computed on the fly (no extra column needed).

Formulas see the table's numeric and boolean columns as variables (booleans read as 1 / 0). A formula that doesn't parse simply doesn't fire, so a half-typed rule is harmless.

in table (table) · Style sockets (header, row height, cell padding, font size, text/header colour, row/column lines + colour/width, outer border + colour/width) · no outputs (draws on the canvas)

▸

Subgraphs & assets

▥Asset
inputs…x, y…
outputs…

Asset instance

A reusable widget — a packaged sub-network with typed inputs and outputs (like a function or component). Make one by selecting nodes and pressing Ctrl+G, or drop a built-in (like Bar or Shift Lights Row) from the +Assets chip. Assets can nest, and each instance can override inputs and styling.

in the asset's inputs + transform (x, y, rotation, scale, anchor) · out the asset's outputs

Restructure a group after the fact. Right-click a node (or a selection) and pick Move into group ▸ to push it inside a group at the current level, or — once you've dived into a group — Move to parent level to pull it back out. Wires that cross the new boundary are handled for you: connections to the outside become Inputs / Outputs ports on the group, and a wire that just fed the group boundary is re-routed straight through. Works on groups (made with Ctrl+G); to edit a published asset's body, dive in and edit it there.
⇥In / Out
params…

Subgraph Inputs & Outputs

Found inside an asset's body: Inputs exposes the asset's parameters as outputs to wire from; Outputs collects its results. Created automatically — you don't add them from the menu.

Inputs → out per parameter · Outputs ← in per result

▸

Annotations

✎Note / Frame

Note · Frame

Documentation, not computation. A Note is a free-floating text label; a Frame is a titled box that groups nodes and moves them together. Neither affects the result — they keep a graph tidy.

no inputs · no outputs · visual only

▸

Channel reference

Every value the Input node can output — the full iRacing v5 feed, 238 channels. Drag from a socket to wire one into the graph, or read it inside an Expression with @name. The format is the socket type (number / boolean / string) plus its unit; Games says on which sims the value actually works.

number boolean string pit-frozen session connect / car change game availability
Freshness. Most channels refresh every frame. A orange dot marks pit values — they travel live but freeze away from the pits (cold pressures, tyre-set inventory, fast-repair, pit-service commands). A session tag marks values that only change on connect or a car / track change (identity, car setup, shift points). Wire a pit-frozen channel to a live gauge and it'll look stuck between stops — that's expected.
Games. is the reference feed — every channel below is provided. marks what the Assetto Corsa connector (standard shared memory) really fills in; * means the value is approximated or derived on AC — hover the tag for the detail. A channel without an AC tag reads as zero / empty while playing Assetto Corsa. The column is derived from the connector code; values flagged here but never verified in-game may still surprise — report anything off.

Lap & timing 6

ChannelTypeUnitWhat it isGames
lap number—Lap
lap_time numbersLap time
best_lap_time numbersBest lap time
delta numbersDelta
last_sector_time_s numbersLast sector time
race_laps number—Race laps

Speed 1

ChannelTypeUnitWhat it isGames
speed_kmh numberkm/hSpeed

Engine & fluids 21

ChannelTypeUnitWhat it isGames
rpm numberrpmEngine RPM
rpm_shift_first session numberrpmRPM first shift
rpm_shift_last session numberrpmRPM last shift
rpm_shift_blink session numberrpmRPM shift critical
gear number—Gear (number)
gear_label string—Gear
oil_temp_c number°COil temp
oil_pressure_bar numberbarOil pressure
oil_level_l numberLOil level
water_temp_c number°CWater temp
water_level_l numberLWater level
manifold_pressure_bar numberbarManifold pressure
voltage_v numberVBattery voltage
rpm_shift_shift session numberrpmRPM shift point
warn_water_temp boolean—Water temp warning
warn_fuel_pressure boolean—Fuel pressure warning
warn_oil_pressure boolean—Oil pressure warning
warn_engine_stalled boolean—Engine stalled warning
warn_pit_limiter boolean—Pit limiter warning
warn_rev_limiter boolean—Rev limiter warning
warn_oil_temp boolean—Oil temp warning

Fuel 6

ChannelTypeUnitWhat it isGames
fuel_level numberLFuel remaining
fuel_capacity_l session numberLFuel tank capacity
fuel_used_per_lap numberLFuel per lap
fuel_level_pct number%Fuel remaining %
fuel_use_per_hour_kgh numberkg/hFuel use per hour
fuel_pressure_bar numberbarFuel pressure

Driver inputs 8

ChannelTypeUnitWhat it isGames
throttle_pct number%Throttle
brake_pct number%Brake
clutch_pct number%Clutch
throttle_raw number—Throttle raw
brake_raw number—Brake raw
clutch_raw number—Clutch raw
handbrake_raw number—Handbrake raw
driver_marker boolean—Driver marker

Force feedback 12

ChannelTypeUnitWhat it isGames
ffb_torque_nm numberNmFFB torque
ffb_torque_pct number%FFB torque %
ffb_torque_pct_signed number%FFB torque signed
ffb_torque_pct_signed_stops number%FFB torque signed (stops)
ffb_damper_pct number%FFB damper
ffb_intensity_pct number%FFB intensity
ffb_smoothing_pct number%FFB smoothing
ffb_limiter_pct number%FFB limiter
ffb_max_force_nm numberNmFFB max force
ffb_peak_force_nm numberNmFFB peak force
ffb_use_linear boolean—FFB linear
ffb_enabled boolean—FFB enabled

Position & standings 6

ChannelTypeUnitWhat it isGames
position number—Overall position
class_position number—Class position *
sector_index number—Current sector
lap_distance_pct number—Lap distance
lat number°GPS latitude
lon number°GPS longitude

Track & surface 5

ChannelTypeUnitWhat it isGames
track_surface string—Track location *
track_surface_material string—Surface material
in_garage boolean—In garage
in_pit_stall boolean—In pit stall *
on_pit_road boolean—On pit road *

Weather 14

ChannelTypeUnitWhat it isGames
air_temp_c number°CAir temp
track_temp_c number°CTrack temp
wetness string—Track wetness
declared_wet boolean—Declared wet
precipitation_pct number%Precipitation
humidity_pct number%Humidity
wind_dir_rad numberradWind direction
wind_vel_ms numberm/sWind speed
fog_pct number%Fog
skies string—Skies
solar_altitude_rad numberradSolar altitude
solar_azimuth_rad numberradSolar azimuth
air_density_kgm3 numberkg/m³Air density
air_pressure_pa numberPaAir pressure

Driver aids 5

ChannelTypeUnitWhat it isGames
tc_active boolean—TC active
abs_active boolean—ABS active
pit_limiter_active boolean—Pit limiter active
drs_available boolean—DRS available
drs_active boolean—DRS active

Driver controls 10

Raw dial values. In-car adjustment dials (irsdk dc* family) — no per-car interpretation: a TC / ABS "level" is 1-based on most GT3s, engine_map is a map index. Dials the car doesn't have read 0.
ChannelTypeUnitWhat it isGames
brake_bias_pct number%Brake bias
abs_level number—ABS level
tc_level number—TC level
tc2_level number—TC2 level
engine_map number—Engine map
throttle_shape number—Throttle shape
fuel_mixture number—Fuel mixture
engine_braking number—Engine braking
anti_roll_front number—Anti-roll front
anti_roll_rear number—Anti-roll rear

Push-to-pass / hybrid 6

ChannelTypeUnitWhat it isGames
p2p_count number—P2P count
p2p_status boolean—P2P active
push_to_pass boolean—Push-to-pass
push_to_talk boolean—Push-to-talk
manual_boost boolean—Manual boost
manual_no_boost boolean—Manual no-boost

Race, flags & session state 8

ChannelTypeUnitWhat it isGames
flag string—Flag
session_phase string—Session phase *
session_time_s numbersSession time
time_of_day_s numbersTime of day
time_remain_s numbersTime remaining
laps_remain number—Laps remaining
joker_laps_remain number—Joker laps remaining
on_joker_lap boolean—On joker lap

Penalties & incidents 7

ChannelTypeUnitWhat it isGames
incidents_personal numberxIncidents (personal)
incidents_team numberxIncidents (team)
incidents_driver numberxIncidents (driver)
weight_penalty_kg numberkgWeight penalty
power_adjust_pct number%Power adjust
tow_time_s numbersTow time
fast_repairs_used number—Fast repairs used

Pit & strategy 25

ChannelTypeUnitWhat it isGames
pit_pitstop_active boolean—Pitstop active *
pit_pits_open boolean—Pits open
pit_repair_left_s numbersRepair left
pit_opt_repair_left_s numbersOptional repair left
pit_fast_repair_available number—Fast repairs available
pit_cmd_fuel_add_kg numberkgFuel to add
pit_cmd_fuel_auto_fill_active boolean—Fuel auto-fill active
pit_cmd_fuel_auto_fill_enabled boolean—Fuel auto-fill enabled
pit_cmd_fuel_fill boolean—Fuel fill requested
pit_cmd_fast_repair boolean—Fast repair requested
pit_cmd_tire_change_lf number—Change tire LF
pit_cmd_tire_change_rf number—Change tire RF
pit_cmd_tire_change_lr number—Change tire LR
pit_cmd_tire_change_rr number—Change tire RR
pit_cmd_cold_press_lf_pa numberPaRequested pressure LF
pit_cmd_cold_press_rf_pa numberPaRequested pressure RF
pit_cmd_cold_press_lr_pa numberPaRequested pressure LR
pit_cmd_cold_press_rr_pa numberPaRequested pressure RR
pit_cmd_windshield_tearoff boolean—Windshield tearoff
pit_cmd_service_fuel_l numberLService fuel
pit_cmd_service_press_lf_kpa numberkPaService pressure LF
pit_cmd_service_press_rf_kpa numberkPaService pressure RF
pit_cmd_service_press_lr_kpa numberkPaService pressure LR
pit_cmd_service_press_rr_kpa numberkPaService pressure RR
pit_cmd_service_compound number—Service compound

Session & car setup 14

ChannelTypeUnitWhat it isGames
on_track boolean—On track
delta_valid boolean—Delta valid
car_id session string—Car ID
track_name session string—Track name
driver_name session string—Driver name
session_num session number—Session number
session_time_total_s session numbersSession duration
session_laps_total session number—Session laps
is_race session boolean—Is race
car_class session number—Car class
dry_tire_set_limit session number—Dry tire set limit
steering_max_angle_rad session numberradSteering max angle
steering_max_force_nm session numberNmSteering max force
player_car_idx session number—Player car index

Physics & chassis 9

ChannelTypeUnitWhat it isGames
steering_angle numberradSteering angle
accel_long_g numbergLongitudinal acceleration
accel_lat_g numbergLateral acceleration
accel_vert_g numbergVertical acceleration
ride_height_front_m numbermFront ride height
ride_height_rear_m numbermRear ride height
velocity_x_ms numberm/sVelocity X
velocity_y_ms numberm/sVelocity Y
velocity_z_ms numberm/sVelocity Z

Attitude (pitch / roll / yaw) 7

ChannelTypeUnitWhat it isGames
pitch_rad numberradPitch
roll_rad numberradRoll
yaw_rad numberradYaw
yaw_north_rad numberradYaw vs north
pitch_rate numberrad/sPitch rate
roll_rate numberrad/sRoll rate
yaw_rate numberrad/sYaw rate

Suspension 8

ChannelTypeUnitWhat it isGames
brake_line_press_lf_bar numberbarBrake line press LF
brake_line_press_rf_bar numberbarBrake line press RF
brake_line_press_lr_bar numberbarBrake line press LR
brake_line_press_rr_bar numberbarBrake line press RR
ride_height_lf_m numbermRide height LF
ride_height_rf_m numbermRide height RF
ride_height_lr_m numbermRide height LR
ride_height_rr_m numbermRide height RR

Dampers 8

ChannelTypeUnitWhat it isGames
shock_vel_lf_mm_s numbermm/sShock speed FL
shock_vel_rf_mm_s numbermm/sShock speed FR
shock_vel_lr_mm_s numbermm/sShock speed RL
shock_vel_rr_mm_s numbermm/sShock speed RR
shock_defl_lf_mm numbermmShock position FL
shock_defl_rf_mm numbermmShock position FR
shock_defl_lr_mm numbermmShock position RL
shock_defl_rr_mm numbermmShock position RR

Tyres 33

ChannelTypeUnitWhat it isGames
tire_compound number—Tire compound
tire_temp_lf_left_c number°CTire temp LF (left)
tire_temp_lf_mid_c number°CTire temp LF (mid)
tire_temp_lf_right_c number°CTire temp LF (right)
tire_temp_rf_left_c number°CTire temp RF (left)
tire_temp_rf_mid_c number°CTire temp RF (mid)
tire_temp_rf_right_c number°CTire temp RF (right)
tire_temp_lr_left_c number°CTire temp LR (left)
tire_temp_lr_mid_c number°CTire temp LR (mid)
tire_temp_lr_right_c number°CTire temp LR (right)
tire_temp_rr_left_c number°CTire temp RR (left)
tire_temp_rr_mid_c number°CTire temp RR (mid)
tire_temp_rr_right_c number°CTire temp RR (right)
tire_wear_lf_left_pct number%Tire wear LF (left)
tire_wear_lf_mid_pct number%Tire wear LF (mid)
tire_wear_lf_right_pct number%Tire wear LF (right)
tire_wear_rf_left_pct number%Tire wear RF (left)
tire_wear_rf_mid_pct number%Tire wear RF (mid)
tire_wear_rf_right_pct number%Tire wear RF (right)
tire_wear_lr_left_pct number%Tire wear LR (left)
tire_wear_lr_mid_pct number%Tire wear LR (mid)
tire_wear_lr_right_pct number%Tire wear LR (right)
tire_wear_rr_left_pct number%Tire wear RR (left)
tire_wear_rr_mid_pct number%Tire wear RR (mid)
tire_wear_rr_right_pct number%Tire wear RR (right)
tire_cold_press_lf_kpa numberkPaCold pressure LF
tire_cold_press_rf_kpa numberkPaCold pressure RF
tire_cold_press_lr_kpa numberkPaCold pressure LR
tire_cold_press_rr_kpa numberkPaCold pressure RR
tire_odo_lf_m numbermTire odometer LF
tire_odo_rf_m numbermTire odometer RF
tire_odo_lr_m numbermTire odometer LR
tire_odo_rr_m numbermTire odometer RR

Tyre sets 18

ChannelTypeUnitWhat it isGames
tire_sets_total_available number—Sets available (total)
tire_sets_total_used number—Sets used (total)
tire_sets_left_available number—Left available
tire_sets_left_used number—Left used
tire_sets_right_available number—Right available
tire_sets_right_used number—Right used
tire_sets_front_available number—Front available
tire_sets_front_used number—Front used
tire_sets_rear_available number—Rear available
tire_sets_rear_used number—Rear used
tire_sets_corner_available_lf number—Available LF
tire_sets_corner_available_rf number—Available RF
tire_sets_corner_available_lr number—Available LR
tire_sets_corner_available_rr number—Available RR
tire_sets_corner_used_lf number—Used LF
tire_sets_corner_used_rf number—Used RF
tire_sets_corner_used_lr number—Used LR
tire_sets_corner_used_rr number—Used RR

Meta & connection 1

ChannelTypeUnitWhat it isGames
_ws_connected boolean—Engine connection
Appendix · For contributors

Under the hood

A brief look at how the graph is stored and evaluated. Skip this if you're just building dashboards.

▸

Data model & evaluation

The body / layout split

A graph is two concentric parts. The body is the eval contract — nodes and wires, no visuals. The layout holds positions, notes and frames. Because positions live only in layout, moving a node never changes the body — evaluation and asset signatures are drag-stable.

Graph = {
  body:   { nodes: StructuralNode[], wires: Wire[] },           // eval contract — no visuals
  layout: { nodes: Record<id, {x,y,…}>, notes, frames },        // visual state only
}

How it evaluates

Each engine tick, evalGraphCore reads the body only and: (1) topologically sorts the nodes (a cycle throws — which is why cyclic wires are rejected at draw time); (2) handles any ForEach block by partitioning into pre / loop / post zones and running the loop once per iteration; (3) evaluates each node via a tiny dispatcher into the registry; (4) collects the resolved inputs of every display node; (5) re-orders by document order for correct stacking. The result feeds the renderer.

The registry — adding a node

Every node kind is one NodeDef entry colocating its kind, label, category, Zod schema, build() factory, eval(), and socket-type resolver. The goal: adding a node = one entry in registry/primitives.ts or registry/non-primitives.ts (+ a React component), nothing else.

Code lives in software/simlogix/ui/src/features/advanced-editor/graph/. The folder's own summary.md tracks change history and links the design specs.