Live streams

Local streams

Feed live samples from your own page into the engine.

Open, push, close

TypeScript
const stream = engine.live.openLocal('Line 3 press')

socket.onmessage = (msg) => {
  const s = JSON.parse(msg.data)
  stream.push({
    t: s.time,                       // any monotonic number: seconds, ms, sample index
    signals: [
      { name: 'force', unit: 'kN', value: s.force },
      { name: 'stroke', unit: 'mm', value: s.stroke },
    ],
  })
}

// Later
stream.close()
  • push takes one sample or an array of them.
  • New signal names become new columns automatically.
  • After close(), push is ignored and the connection leaves state.live.

High sample rates

At kHz rates, push blocks by column instead of one object per sample. Typed arrays are copied into the buffer in bulk: millions of samples per second, with the charts still drawing every frame.

TypeScript
// One block per message from your source: t and every signal the same length
stream.pushColumns({
  t: times,                          // Float64Array (or any array of numbers)
  columns: { force: force, stroke: stroke },
  units: { force: 'kN', stroke: 'mm' },
})
  • A signal missing from a block reads as a gap for its samples.
  • A column whose length differs from t throws a RangeError.

Plotting it

The stream appears in state.live (its id is stream.id) and is selected when it first appears, so every chart plots it. If a worksheet’s X column does not exist in the live data, the worksheet switches to t. Multi-band charts on t scroll with a window you set:

TypeScript
engine.view.setLiveWindow(30)            // seconds; null shows everything buffered
engine.datasets.toggle(stream.id)        // hide or show it like any dataset
engine.live.rowCount(stream.id)          // samples buffered now (cheap: poll it for a counter)

state.live[i].rowCount only updates on structural changes (a new signal, a status change); use live.rowCount() for a ticking counter.